OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/rotator/screen_rotation_animator.h" | 5 #include "ash/rotator/screen_rotation_animator.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <utility> | 8 #include <utility> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "ash/common/ash_switches.h" | |
11 #include "ash/display/window_tree_host_manager.h" | 12 #include "ash/display/window_tree_host_manager.h" |
12 #include "ash/rotator/screen_rotation_animation.h" | 13 #include "ash/rotator/screen_rotation_animation.h" |
13 #include "ash/rotator/screen_rotation_animator_observer.h" | 14 #include "ash/rotator/screen_rotation_animator_observer.h" |
14 #include "ash/shell.h" | 15 #include "ash/shell.h" |
15 #include "base/command_line.h" | 16 #include "base/command_line.h" |
16 #include "base/memory/ptr_util.h" | 17 #include "base/memory/ptr_util.h" |
17 #include "base/metrics/histogram_macros.h" | 18 #include "base/metrics/histogram_macros.h" |
18 #include "base/time/time.h" | 19 #include "base/time/time.h" |
20 #include "cc/output/copy_output_request.h" | |
21 #include "cc/output/copy_output_result.h" | |
19 #include "ui/aura/window.h" | 22 #include "ui/aura/window.h" |
23 #include "ui/compositor/callback_layer_animation_observer.h" | |
20 #include "ui/compositor/layer.h" | 24 #include "ui/compositor/layer.h" |
21 #include "ui/compositor/layer_animation_element.h" | 25 #include "ui/compositor/layer_animation_element.h" |
22 #include "ui/compositor/layer_animation_observer.h" | 26 #include "ui/compositor/layer_animation_observer.h" |
23 #include "ui/compositor/layer_animation_sequence.h" | 27 #include "ui/compositor/layer_animation_sequence.h" |
24 #include "ui/compositor/layer_animator.h" | 28 #include "ui/compositor/layer_animator.h" |
25 #include "ui/compositor/layer_owner.h" | 29 #include "ui/compositor/layer_owner.h" |
26 #include "ui/compositor/layer_tree_owner.h" | 30 #include "ui/compositor/layer_tree_owner.h" |
27 #include "ui/display/display.h" | 31 #include "ui/display/display.h" |
28 #include "ui/display/manager/display_manager.h" | 32 #include "ui/display/manager/display_manager.h" |
29 #include "ui/display/manager/managed_display_info.h" | 33 #include "ui/display/manager/managed_display_info.h" |
(...skipping 12 matching lines...) Expand all Loading... | |
42 // The number of degrees that the rotation animations animate through. | 46 // The number of degrees that the rotation animations animate through. |
43 const int kRotationDegrees = 20; | 47 const int kRotationDegrees = 20; |
44 | 48 |
45 // The time it takes for the rotation animations to run. | 49 // The time it takes for the rotation animations to run. |
46 const int kRotationDurationInMs = 250; | 50 const int kRotationDurationInMs = 250; |
47 | 51 |
48 // The rotation factors. | 52 // The rotation factors. |
49 const int kCounterClockWiseRotationFactor = 1; | 53 const int kCounterClockWiseRotationFactor = 1; |
50 const int kClockWiseRotationFactor = -1; | 54 const int kClockWiseRotationFactor = -1; |
51 | 55 |
52 // Aborts the active animations of the layer, and recurses upon its child | 56 // The delegate root layer name. |
53 // layers. | 57 const std::string kDelegateRootLayerName = "DelegateRootLayer"; |
54 void AbortAnimations(ui::Layer* layer) { | 58 // The old root layer name. |
55 for (ui::Layer* child_layer : layer->children()) | 59 const std::string kOldRootLayerName = "ScreenRotationAnimator:old_layer_tree"; |
56 AbortAnimations(child_layer); | 60 // The new root layer name. |
57 layer->GetAnimator()->AbortAllAnimations(); | 61 const std::string kNewRootLayerName = "ScreenRotationAnimator:new_layer_tree"; |
58 } | |
59 | 62 |
60 display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) { | 63 display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) { |
61 return Shell::GetInstance() | 64 return Shell::GetInstance() |
62 ->display_manager() | 65 ->display_manager() |
63 ->GetDisplayInfo(display_id) | 66 ->GetDisplayInfo(display_id) |
64 .GetActiveRotation(); | 67 .GetActiveRotation(); |
65 } | 68 } |
66 | 69 |
67 bool IsDisplayIdValid(int64_t display_id) { | 70 bool IsDisplayIdValid(int64_t display_id) { |
68 return Shell::GetInstance()->display_manager()->IsDisplayIdValid(display_id); | 71 return Shell::GetInstance()->display_manager()->IsDisplayIdValid(display_id); |
69 } | 72 } |
70 | 73 |
71 // 180 degree rotations should animate clock-wise. | 74 // 180 degree rotations should animate clock-wise. |
72 int GetRotationFactor(display::Display::Rotation initial_rotation, | 75 int GetRotationFactor(display::Display::Rotation initial_rotation, |
73 display::Display::Rotation new_rotation) { | 76 display::Display::Rotation new_rotation) { |
74 return (initial_rotation + 3) % 4 == new_rotation | 77 return (initial_rotation + 3) % 4 == new_rotation |
75 ? kCounterClockWiseRotationFactor | 78 ? kCounterClockWiseRotationFactor |
76 : kClockWiseRotationFactor; | 79 : kClockWiseRotationFactor; |
77 } | 80 } |
78 | 81 |
79 aura::Window* GetRootWindow(int64_t display_id) { | 82 aura::Window* GetRootWindow(int64_t display_id) { |
80 return Shell::GetInstance() | 83 return Shell::GetInstance() |
81 ->window_tree_host_manager() | 84 ->window_tree_host_manager() |
82 ->GetRootWindowForDisplayId(display_id); | 85 ->GetRootWindowForDisplayId(display_id); |
83 } | 86 } |
84 | 87 |
88 ui::Layer* GetChildLayerByName(ui::Layer* parent, const std::string& name) { | |
89 for (ui::Layer* child_layer : parent->children()) { | |
90 if (child_layer->name() == name) | |
91 return child_layer; | |
92 } | |
93 NOTREACHED(); | |
94 return nullptr; | |
95 } | |
96 | |
85 // Returns true if the rotation between |initial_rotation| and |new_rotation| is | 97 // Returns true if the rotation between |initial_rotation| and |new_rotation| is |
86 // 180 degrees. | 98 // 180 degrees. |
87 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, | 99 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, |
88 display::Display::Rotation new_rotation) { | 100 display::Display::Rotation new_rotation) { |
89 return (initial_rotation + 2) % 4 == new_rotation; | 101 return (initial_rotation + 2) % 4 == new_rotation; |
90 } | 102 } |
91 | 103 |
92 // Returns the initial degrees the old layer animation to begin with. | 104 // Returns the initial degrees the old layer animation to begin with. |
93 int GetInitialDegrees(display::Display::Rotation initial_rotation, | 105 int GetInitialDegrees(display::Display::Rotation initial_rotation, |
94 display::Display::Rotation new_rotation) { | 106 display::Display::Rotation new_rotation) { |
95 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); | 107 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); |
96 } | 108 } |
97 | 109 |
98 // A LayerAnimationObserver that will destroy the contained LayerTreeOwner | |
99 // when notified that a layer animation has ended or was aborted. | |
100 class LayerCleanupObserver : public ui::LayerAnimationObserver { | |
101 public: | |
102 // Takes WeakPtr of ScreenRotationAnimator. |this| may outlive the |animator_| | |
103 // instance and the |animator_| isn't detaching itself as an observer when | |
104 // being destroyed. However, ideally, when |animator_| is destroying, | |
105 // deleting |old_layer_tree_owner_| will trigger OnLayerAnimationAborted and | |
106 // delete |this| before |animator_| deleted. | |
107 explicit LayerCleanupObserver(base::WeakPtr<ScreenRotationAnimator> animator); | |
108 ~LayerCleanupObserver() override; | |
109 | |
110 // ui::LayerAnimationObserver: | |
111 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override; | |
112 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override; | |
113 void OnLayerAnimationScheduled( | |
114 ui::LayerAnimationSequence* sequence) override {} | |
115 | |
116 protected: | |
117 // ui::LayerAnimationObserver: | |
118 bool RequiresNotificationWhenAnimatorDestroyed() const override { | |
119 return true; | |
120 } | |
121 void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override; | |
122 void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override; | |
123 | |
124 private: | |
125 base::WeakPtr<ScreenRotationAnimator> animator_; | |
126 | |
127 // The LayerAnimationSequence that |this| has been attached to. Defaults to | |
128 // nullptr. | |
129 ui::LayerAnimationSequence* sequence_; | |
130 | |
131 DISALLOW_COPY_AND_ASSIGN(LayerCleanupObserver); | |
132 }; | |
133 | |
134 LayerCleanupObserver::LayerCleanupObserver( | |
135 base::WeakPtr<ScreenRotationAnimator> animator) | |
136 : animator_(animator), sequence_(nullptr) {} | |
137 | |
138 LayerCleanupObserver::~LayerCleanupObserver() { | |
139 // We must eplicitly detach from |sequence_| because we return true from | |
140 // RequiresNotificationWhenAnimatorDestroyed. | |
141 if (sequence_) | |
142 sequence_->RemoveObserver(this); | |
143 } | |
144 | |
145 void LayerCleanupObserver::OnLayerAnimationEnded( | |
146 ui::LayerAnimationSequence* sequence) { | |
147 if (animator_) | |
148 animator_->ProcessAnimationQueue(); | |
149 | |
150 delete this; | |
151 } | |
152 | |
153 void LayerCleanupObserver::OnLayerAnimationAborted( | |
154 ui::LayerAnimationSequence* sequence) { | |
155 if (animator_) | |
156 animator_->ProcessAnimationQueue(); | |
157 | |
158 delete this; | |
159 } | |
160 | |
161 void LayerCleanupObserver::OnAttachedToSequence( | |
162 ui::LayerAnimationSequence* sequence) { | |
163 sequence_ = sequence; | |
164 } | |
165 | |
166 void LayerCleanupObserver::OnDetachedFromSequence( | |
167 ui::LayerAnimationSequence* sequence) { | |
168 DCHECK_EQ(sequence, sequence_); | |
169 sequence_ = nullptr; | |
170 } | |
171 | |
172 class ScreenRotationAnimationMetricsReporter | 110 class ScreenRotationAnimationMetricsReporter |
173 : public ui::AnimationMetricsReporter { | 111 : public ui::AnimationMetricsReporter { |
174 public: | 112 public: |
175 ScreenRotationAnimationMetricsReporter() {} | 113 ScreenRotationAnimationMetricsReporter() {} |
176 ~ScreenRotationAnimationMetricsReporter() override {} | 114 ~ScreenRotationAnimationMetricsReporter() override {} |
177 | 115 |
178 void Report(int value) override { | 116 void Report(int value) override { |
179 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); | 117 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); |
180 } | 118 } |
181 | 119 |
182 private: | 120 private: |
183 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); | 121 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); |
184 }; | 122 }; |
185 | 123 |
124 void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) { | |
125 // Add the cloned layer tree in to the root, so it will be rendered. | |
126 root_window->layer()->Add(layer); | |
127 root_window->layer()->StackAtTop(layer); | |
128 } | |
129 | |
130 bool AnimationEndedCallback( | |
131 base::WeakPtr<ScreenRotationAnimator> animator, | |
132 const ui::CallbackLayerAnimationObserver& observer) { | |
133 if (animator) | |
134 animator->ProcessAnimationQueue(); | |
135 return true; | |
136 } | |
137 | |
138 // Round near zero value to zero. | |
139 void RoundNearZero(gfx::Transform* transform) { | |
140 const float kEpsilon = 0.001f; | |
141 SkMatrix44& matrix = transform->matrix(); | |
142 for (int x = 0; x < 4; ++x) { | |
143 for (int y = 0; y < 4; ++y) { | |
144 if (std::abs(SkMScalarToFloat(matrix.get(x, y))) < kEpsilon) | |
145 matrix.set(x, y, SkFloatToMScalar(0.0f)); | |
146 } | |
147 } | |
148 } | |
149 | |
150 void TransformLayerToOldRotation( | |
151 ui::Layer* layer, | |
152 const int64_t display_id, | |
153 const display::Display::Rotation& new_rotation, | |
154 const display::Display::Rotation& old_rotation) { | |
155 const display::Display display = | |
156 Shell::GetInstance()->display_manager()->GetDisplayForId(display_id); | |
157 | |
158 const int rotation_changed = ((new_rotation - old_rotation) + 4) % 4; | |
159 float one_pixel = 1.0f / display.device_scale_factor(); | |
160 gfx::Transform transform; | |
161 switch (rotation_changed) { | |
162 case 0: | |
163 break; | |
164 case 1: | |
165 transform.Rotate(270); | |
166 transform.Translate(-display.bounds().height() + one_pixel, 0); | |
167 break; | |
168 case 2: | |
169 transform.Rotate(180); | |
170 transform.Translate(-display.bounds().width() + one_pixel, | |
171 -display.bounds().height() + one_pixel); | |
172 break; | |
173 case 3: | |
174 transform.Rotate(90); | |
175 transform.Translate(0, -display.bounds().width() + one_pixel); | |
176 break; | |
177 } | |
178 | |
179 RoundNearZero(&transform); | |
180 layer->SetTransform(transform); | |
181 } | |
182 | |
186 } // namespace | 183 } // namespace |
187 | 184 |
188 struct ScreenRotationAnimator::ScreenRotationRequest { | 185 struct ScreenRotationAnimator::ScreenRotationRequest { |
189 ScreenRotationRequest(display::Display::Rotation to_rotation, | 186 ScreenRotationRequest(const display::Display::Rotation& from_rotation, |
190 display::Display::RotationSource from_source) | 187 const display::Display::Rotation& to_rotation, |
191 : new_rotation(to_rotation), source(from_source) {} | 188 const display::Display::RotationSource& from_source) |
189 : old_rotation(from_rotation), | |
190 new_rotation(to_rotation), | |
191 source(from_source) {} | |
192 display::Display::Rotation old_rotation; | |
192 display::Display::Rotation new_rotation; | 193 display::Display::Rotation new_rotation; |
193 display::Display::RotationSource source; | 194 display::Display::RotationSource source; |
194 }; | 195 }; |
195 | 196 |
196 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) | 197 ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) |
197 : display_id_(display_id), | 198 : display_id_(display_id), |
198 is_rotating_(false), | 199 is_rotating_(false), |
199 metrics_reporter_( | 200 metrics_reporter_( |
200 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), | 201 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), |
201 disable_animation_timers_for_test_(false), | 202 disable_animation_timers_for_test_(false), |
202 weak_factory_(this) {} | 203 weak_factory_(this) {} |
203 | 204 |
204 ScreenRotationAnimator::~ScreenRotationAnimator() { | 205 ScreenRotationAnimator::~ScreenRotationAnimator() { |
205 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from | 206 // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from |
206 // calling a method on the |animator_|. | 207 // calling a method on the |animator_|. |
207 weak_factory_.InvalidateWeakPtrs(); | 208 weak_factory_.InvalidateWeakPtrs(); |
208 | 209 |
209 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in | 210 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in |
210 // order to make sure |metrics_reporter_| outlives the attached animation | 211 // order to make sure |metrics_reporter_| outlives the attached animation |
211 // sequence. | 212 // sequence. |
212 old_layer_tree_owner_.reset(); | 213 old_layer_tree_owner_.reset(); |
213 metrics_reporter_.reset(); | 214 metrics_reporter_.reset(); |
214 } | 215 } |
215 | 216 |
217 void ScreenRotationAnimator::StartRotationAnimation( | |
218 std::unique_ptr<ScreenRotationRequest> rotation_request) { | |
219 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
220 switches::kAshEnableSmoothScreenRotation)) { | |
221 const cc::CopyOutputRequest::CopyOutputRequestCallback callback = | |
222 base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation, | |
223 weak_factory_.GetWeakPtr(), base::Passed(&rotation_request)); | |
224 RequestCopyRootLayerByName(kDelegateRootLayerName, callback); | |
225 } else { | |
226 StartSlowAnimation(std::move(rotation_request)); | |
227 } | |
228 } | |
229 | |
230 void ScreenRotationAnimator::SetRotation( | |
231 const display::Display::Rotation& new_rotation, | |
232 const display::Display::Rotation& old_rotation, | |
233 const display::Display::RotationSource& source) { | |
234 Shell::GetInstance()->display_manager()->SetDisplayRotation( | |
235 display_id_, new_rotation, source); | |
236 TransformLayerToOldRotation(old_layer_tree_owner_->root(), display_id_, | |
237 new_rotation, old_rotation); | |
238 } | |
239 | |
240 void ScreenRotationAnimator::StartSlowAnimation( | |
241 std::unique_ptr<ScreenRotationRequest> rotation_request) { | |
242 CreateOldLayerTree(); | |
243 SetRotation(rotation_request->new_rotation, rotation_request->old_rotation, | |
244 rotation_request->source); | |
245 AnimateRotation(std::move(rotation_request)); | |
246 } | |
247 | |
248 void ScreenRotationAnimator::RequestCopyRootLayerByName( | |
249 const std::string& layer_name, | |
250 const cc::CopyOutputRequest::CopyOutputRequestCallback& callback) { | |
251 std::unique_ptr<cc::CopyOutputRequest> copy_output_request = | |
252 cc::CopyOutputRequest::CreateRequest(callback); | |
253 ui::Layer* layer = | |
254 GetChildLayerByName(GetRootWindow(display_id_)->layer(), layer_name); | |
255 gfx::Rect rect(layer->size()); | |
256 copy_output_request->set_area(rect); | |
257 layer->RequestCopyOfOutput(std::move(copy_output_request)); | |
258 } | |
259 | |
260 void ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation( | |
261 std::unique_ptr<ScreenRotationRequest> rotation_request, | |
262 std::unique_ptr<cc::CopyOutputResult> result) { | |
263 // If copy request does not succeed or canceled, fall back to recreate layers | |
264 // solution. | |
265 if (result->IsEmpty() || result->size().IsEmpty() || !result->HasTexture()) { | |
danakj
2017/03/31 19:32:30
I don't think you need to check size() or HasTextu
wutao
2017/04/07 06:59:11
Acknowledged.
| |
266 StartSlowAnimation(std::move(rotation_request)); | |
267 } else { | |
268 old_layer_tree_owner_ = CopyLayerTree(kOldRootLayerName, std::move(result)); | |
269 | |
270 SetRotation(rotation_request->new_rotation, rotation_request->old_rotation, | |
271 rotation_request->source); | |
272 | |
273 const cc::CopyOutputRequest::CopyOutputRequestCallback callback = | |
274 base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedAfterRotation, | |
275 weak_factory_.GetWeakPtr(), base::Passed(&rotation_request)); | |
276 RequestCopyRootLayerByName(kDelegateRootLayerName, callback); | |
danakj
2017/03/31 19:32:30
Why not do both of these copies at the same time i
wutao
2017/04/07 06:59:11
Talked offline, The two requests are on the same l
| |
277 } | |
278 } | |
279 | |
280 void ScreenRotationAnimator::OnRootLayerCopiedAfterRotation( | |
281 std::unique_ptr<ScreenRotationRequest> rotation_request, | |
282 std::unique_ptr<cc::CopyOutputResult> result) { | |
283 if (!result->IsEmpty() && !result->size().IsEmpty() && result->HasTexture()) | |
danakj
2017/03/31 19:32:30
same about size and HasTexture
wutao
2017/04/07 06:59:11
Acknowledged.
| |
284 new_layer_tree_owner_ = CopyLayerTree(kNewRootLayerName, std::move(result)); | |
285 AnimateRotation(std::move(rotation_request)); | |
286 } | |
287 | |
288 void ScreenRotationAnimator::CreateOldLayerTree() { | |
289 aura::Window* root_window = GetRootWindow(display_id_); | |
290 old_layer_tree_owner_ = ::wm::RecreateLayers(root_window); | |
291 old_layer_tree_owner_->root()->set_name(kOldRootLayerName); | |
292 AddLayerAtTopOfWindowLayers(root_window, old_layer_tree_owner_->root()); | |
293 } | |
294 | |
295 std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree( | |
296 const std::string& layer_name, | |
297 std::unique_ptr<cc::CopyOutputResult> result) { | |
298 cc::TextureMailbox texture_mailbox; | |
299 std::unique_ptr<cc::SingleReleaseCallback> release_callback; | |
300 result->TakeTexture(&texture_mailbox, &release_callback); | |
301 DCHECK(texture_mailbox.IsTexture()); | |
302 | |
303 aura::Window* root_window = GetRootWindow(display_id_); | |
304 gfx::Rect rect(root_window->layer()->size()); | |
305 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>(); | |
306 copy_layer->SetBounds(rect); | |
307 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback), | |
308 rect.size()); | |
309 | |
310 copy_layer->set_name(layer_name); | |
311 AddLayerAtTopOfWindowLayers(root_window, copy_layer.get()); | |
312 return base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer)); | |
313 } | |
314 | |
216 void ScreenRotationAnimator::AnimateRotation( | 315 void ScreenRotationAnimator::AnimateRotation( |
217 std::unique_ptr<ScreenRotationRequest> rotation_request) { | 316 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
218 aura::Window* root_window = GetRootWindow(display_id_); | 317 const int rotation_factor = GetRotationFactor(rotation_request->old_rotation, |
219 | 318 rotation_request->new_rotation); |
220 const gfx::Rect original_screen_bounds = root_window->GetTargetBounds(); | |
221 | |
222 const int rotation_factor = GetRotationFactor( | |
223 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); | |
224 | |
225 const int old_layer_initial_rotation_degrees = GetInitialDegrees( | 319 const int old_layer_initial_rotation_degrees = GetInitialDegrees( |
226 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); | 320 rotation_request->old_rotation, rotation_request->new_rotation); |
227 | |
228 const base::TimeDelta duration = | 321 const base::TimeDelta duration = |
229 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); | 322 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); |
230 | |
231 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; | 323 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; |
232 | 324 aura::Window* root_window = GetRootWindow(display_id_); |
233 std::unique_ptr<ui::LayerTreeOwner> old_layer_tree = | |
234 ::wm::RecreateLayers(root_window); | |
235 old_layer_tree->root()->set_name("ScreenRotationAnimator:old_layer_tree"); | |
236 | |
237 // Add the cloned layer tree in to the root, so it will be rendered. | |
238 root_window->layer()->Add(old_layer_tree->root()); | |
239 root_window->layer()->StackAtTop(old_layer_tree->root()); | |
240 | |
241 old_layer_tree_owner_ = std::move(old_layer_tree); | |
242 std::unique_ptr<LayerCleanupObserver> old_layer_cleanup_observer( | |
243 new LayerCleanupObserver(weak_factory_.GetWeakPtr())); | |
244 | |
245 Shell::GetInstance()->display_manager()->SetDisplayRotation( | |
246 display_id_, rotation_request->new_rotation, rotation_request->source); | |
247 | |
248 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds(); | 325 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds(); |
249 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, | 326 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, |
250 rotated_screen_bounds.height() / 2); | 327 rotated_screen_bounds.height() / 2); |
251 | 328 |
252 ui::Layer* old_root_layer = old_layer_tree_owner_->root(); | 329 // Make the current layers invisible. |
253 // We must animate each non-cloned child layer individually because the cloned | 330 if (new_layer_tree_owner_) { |
254 // layer was added as a child to |root_window|'s layer so that it will be | 331 GetChildLayerByName(root_window->layer(), kDelegateRootLayerName) |
255 // rendered. | 332 ->SetOpacity(0.0f); |
256 // TODO(bruthig): Add a NOT_DRAWN layer in between the root_window's layer and | |
257 // its current children so that we only need to initiate two | |
258 // LayerAnimationSequences. One for the new layers and one for the old layer. | |
259 for (ui::Layer* child_layer : root_window->layer()->children()) { | |
260 // Skip the cloned layer because it has a different animation. | |
261 if (child_layer == old_root_layer) | |
262 continue; | |
263 | |
264 std::unique_ptr<ScreenRotationAnimation> screen_rotation = | |
265 base::MakeUnique<ScreenRotationAnimation>( | |
266 child_layer, kRotationDegrees * rotation_factor, | |
267 0 /* end_degrees */, child_layer->opacity(), | |
268 1.0f /* target_opacity */, pivot, duration, tween_type); | |
269 | |
270 ui::LayerAnimator* animator = child_layer->GetAnimator(); | |
271 animator->set_preemption_strategy( | |
272 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); | |
273 std::unique_ptr<ui::LayerAnimationSequence> animation_sequence = | |
274 base::MakeUnique<ui::LayerAnimationSequence>( | |
275 std::move(screen_rotation)); | |
276 animator->StartAnimation(animation_sequence.release()); | |
277 } | 333 } |
278 | 334 |
335 // Add an observer so that the copied layers can be cleaned up with the | |
336 // animation completes/aborts. | |
337 ui::CallbackLayerAnimationObserver* observer = | |
338 new ui::CallbackLayerAnimationObserver( | |
339 base::Bind(&AnimationEndedCallback, weak_factory_.GetWeakPtr())); | |
340 | |
341 ui::Layer* new_root_layer; | |
342 if (new_layer_tree_owner_ && | |
343 base::CommandLine::ForCurrentProcess()->HasSwitch( | |
344 switches::kAshEnableSmoothScreenRotation)) { | |
345 new_root_layer = new_layer_tree_owner_->root(); | |
346 } else { | |
347 new_root_layer = | |
348 GetChildLayerByName(root_window->layer(), kDelegateRootLayerName); | |
349 } | |
350 | |
351 std::unique_ptr<ScreenRotationAnimation> current_layer_screen_rotation = | |
352 base::MakeUnique<ScreenRotationAnimation>( | |
353 new_root_layer, kRotationDegrees * rotation_factor, | |
354 0 /* end_degrees */, 0.0f, | |
355 new_root_layer->opacity() /* target_opacity */, pivot, duration, | |
356 tween_type); | |
357 | |
358 ui::LayerAnimator* current_layer_animator = new_root_layer->GetAnimator(); | |
359 current_layer_animator->set_preemption_strategy( | |
360 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); | |
361 std::unique_ptr<ui::LayerAnimationSequence> current_layer_animation_sequence = | |
362 base::MakeUnique<ui::LayerAnimationSequence>( | |
363 std::move(current_layer_screen_rotation)); | |
364 | |
365 ui::Layer* old_root_layer = old_layer_tree_owner_->root(); | |
366 const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds(); | |
279 // The old layer will also be transformed into the new orientation. We will | 367 // The old layer will also be transformed into the new orientation. We will |
280 // translate it so that the old layer's center point aligns with the new | 368 // translate it so that the old layer's center point aligns with the new |
281 // orientation's center point and use that center point as the pivot for the | 369 // orientation's center point and use that center point as the pivot for the |
282 // rotation animation. | 370 // rotation animation. |
283 gfx::Transform translate_transform; | 371 gfx::Transform translate_transform; |
284 translate_transform.Translate( | 372 translate_transform.Translate( |
285 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2, | 373 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2, |
286 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); | 374 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); |
287 old_root_layer->SetTransform(translate_transform); | 375 old_root_layer->SetTransform(translate_transform); |
288 | 376 |
289 std::unique_ptr<ScreenRotationAnimation> screen_rotation = | 377 std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation = |
290 base::MakeUnique<ScreenRotationAnimation>( | 378 base::MakeUnique<ScreenRotationAnimation>( |
291 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, | 379 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, |
292 (old_layer_initial_rotation_degrees - kRotationDegrees) * | 380 (old_layer_initial_rotation_degrees - kRotationDegrees) * |
293 rotation_factor, | 381 rotation_factor, |
294 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, | 382 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, |
295 tween_type); | 383 tween_type); |
296 | 384 |
297 ui::LayerAnimator* animator = old_root_layer->GetAnimator(); | 385 ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator(); |
298 animator->set_preemption_strategy( | 386 old_layer_animator->set_preemption_strategy( |
299 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); | 387 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
300 std::unique_ptr<ui::LayerAnimationSequence> animation_sequence = | 388 std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence = |
301 base::MakeUnique<ui::LayerAnimationSequence>(std::move(screen_rotation)); | 389 base::MakeUnique<ui::LayerAnimationSequence>( |
302 // Add an observer so that the cloned layers can be cleaned up with the | 390 std::move(old_layer_screen_rotation)); |
303 // animation completes/aborts. | 391 |
304 animation_sequence->AddObserver(old_layer_cleanup_observer.release()); | |
305 // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to | |
306 // control the animation. | |
307 if (disable_animation_timers_for_test_) | 392 if (disable_animation_timers_for_test_) |
308 animator->set_disable_timer_for_test(true); | 393 old_layer_animator->set_disable_timer_for_test(true); |
309 animation_sequence->SetAnimationMetricsReporter(metrics_reporter_.get()); | 394 old_layer_animation_sequence->SetAnimationMetricsReporter( |
310 animator->StartAnimation(animation_sequence.release()); | 395 metrics_reporter_.get()); |
311 | 396 |
397 current_layer_animator->AddObserver(observer); | |
398 old_layer_animator->AddObserver(observer); | |
399 current_layer_animator->StartAnimation( | |
400 current_layer_animation_sequence.release()); | |
401 old_layer_animator->StartAnimation(old_layer_animation_sequence.release()); | |
402 observer->SetActive(); | |
312 rotation_request.reset(); | 403 rotation_request.reset(); |
313 } | 404 } |
314 | 405 |
315 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, | 406 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, |
316 display::Display::RotationSource source) { | 407 display::Display::RotationSource source) { |
317 if (GetCurrentScreenRotation(display_id_) == new_rotation) | 408 const display::Display::Rotation current_rotation = |
409 GetCurrentScreenRotation(display_id_); | |
410 if (current_rotation == new_rotation) | |
318 return; | 411 return; |
319 | 412 |
320 std::unique_ptr<ScreenRotationRequest> rotation_request = | 413 std::unique_ptr<ScreenRotationRequest> rotation_request = |
321 base::MakeUnique<ScreenRotationRequest>(new_rotation, source); | 414 base::MakeUnique<ScreenRotationRequest>(current_rotation, new_rotation, |
415 source); | |
322 | 416 |
323 if (is_rotating_) { | 417 if (is_rotating_) { |
324 last_pending_request_ = std::move(rotation_request); | 418 last_pending_request_ = std::move(rotation_request); |
325 // The pending request will be processed when the | 419 // The pending request will be processed when the |
326 // OnLayerAnimation(Ended|Aborted) methods should be called after | 420 // OnLayerAnimation(Ended|Aborted) methods should be called after |
327 // StopAnimating(). | 421 // StopAnimating(). |
328 StopAnimating(); | 422 StopAnimating(); |
329 } else { | 423 } else { |
330 is_rotating_ = true; | 424 is_rotating_ = true; |
331 AnimateRotation(std::move(rotation_request)); | 425 StartRotationAnimation(std::move(rotation_request)); |
332 } | 426 } |
333 } | 427 } |
334 | 428 |
335 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver( | 429 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver( |
336 ScreenRotationAnimatorObserver* observer) { | 430 ScreenRotationAnimatorObserver* observer) { |
337 screen_rotation_animator_observers_.AddObserver(observer); | 431 screen_rotation_animator_observers_.AddObserver(observer); |
338 } | 432 } |
339 | 433 |
340 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( | 434 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( |
341 ScreenRotationAnimatorObserver* observer) { | 435 ScreenRotationAnimatorObserver* observer) { |
342 screen_rotation_animator_observers_.RemoveObserver(observer); | 436 screen_rotation_animator_observers_.RemoveObserver(observer); |
343 } | 437 } |
344 | 438 |
345 void ScreenRotationAnimator::ProcessAnimationQueue() { | 439 void ScreenRotationAnimator::ProcessAnimationQueue() { |
346 is_rotating_ = false; | 440 is_rotating_ = false; |
441 StopAnimating(); | |
347 old_layer_tree_owner_.reset(); | 442 old_layer_tree_owner_.reset(); |
443 new_layer_tree_owner_.reset(); | |
348 if (last_pending_request_ && IsDisplayIdValid(display_id_)) { | 444 if (last_pending_request_ && IsDisplayIdValid(display_id_)) { |
349 std::unique_ptr<ScreenRotationRequest> rotation_request = | 445 std::unique_ptr<ScreenRotationRequest> rotation_request = |
350 std::move(last_pending_request_); | 446 std::move(last_pending_request_); |
351 Rotate(rotation_request->new_rotation, rotation_request->source); | 447 Rotate(rotation_request->new_rotation, rotation_request->source); |
352 rotation_request.reset(); | 448 rotation_request.reset(); |
353 return; | 449 return; |
354 } | 450 } |
355 | 451 |
356 for (auto& observer : screen_rotation_animator_observers_) | 452 for (auto& observer : screen_rotation_animator_observers_) |
357 observer.OnScreenRotationAnimationFinished(this); | 453 observer.OnScreenRotationAnimationFinished(this); |
358 } | 454 } |
359 | 455 |
360 void ScreenRotationAnimator::set_disable_animation_timers_for_test( | 456 void ScreenRotationAnimator::set_disable_animation_timers_for_test( |
361 bool disable_timers) { | 457 bool disable_timers) { |
362 disable_animation_timers_for_test_ = disable_timers; | 458 disable_animation_timers_for_test_ = disable_timers; |
363 } | 459 } |
364 | 460 |
365 void ScreenRotationAnimator::StopAnimating() { | 461 void ScreenRotationAnimator::StopAnimating() { |
366 aura::Window* root_window = GetRootWindow(display_id_); | 462 GetChildLayerByName(GetRootWindow(display_id_)->layer(), |
367 for (ui::Layer* child_layer : root_window->layer()->children()) { | 463 kDelegateRootLayerName) |
368 if (child_layer == old_layer_tree_owner_->root()) | 464 ->SetOpacity(1.0f); |
369 continue; | |
370 | |
371 child_layer->GetAnimator()->StopAnimating(); | |
372 } | |
373 | |
374 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); | 465 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); |
466 // |new_layer_tree_owner_| could be nullptr if the second copy request failed | |
467 // or canceled. | |
468 if (new_layer_tree_owner_) | |
469 new_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); | |
375 } | 470 } |
376 | 471 |
377 } // namespace ash | 472 } // namespace ash |
OLD | NEW |