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/common/ash_switches.h" |
12 #include "ash/display/window_tree_host_manager.h" | 12 #include "ash/display/window_tree_host_manager.h" |
13 #include "ash/public/cpp/shell_window_ids.h" | 13 #include "ash/public/cpp/shell_window_ids.h" |
14 #include "ash/rotator/screen_rotation_animation.h" | 14 #include "ash/rotator/screen_rotation_animation.h" |
15 #include "ash/rotator/screen_rotation_animator_observer.h" | 15 #include "ash/rotator/screen_rotation_animator_observer.h" |
16 #include "ash/shell.h" | 16 #include "ash/shell.h" |
17 #include "base/command_line.h" | 17 #include "base/command_line.h" |
18 #include "base/memory/ptr_util.h" | 18 #include "base/memory/ptr_util.h" |
19 #include "base/metrics/histogram_macros.h" | 19 #include "base/metrics/histogram_macros.h" |
20 #include "base/time/time.h" | 20 #include "base/time/time.h" |
21 #include "cc/output/copy_output_request.h" | 21 #include "cc/output/copy_output_request.h" |
22 #include "cc/output/copy_output_result.h" | 22 #include "cc/output/copy_output_result.h" |
23 #include "ui/aura/window.h" | 23 #include "ui/aura/window.h" |
24 #include "ui/compositor/callback_layer_animation_observer.h" | |
24 #include "ui/compositor/layer.h" | 25 #include "ui/compositor/layer.h" |
25 #include "ui/compositor/layer_animation_element.h" | 26 #include "ui/compositor/layer_animation_element.h" |
26 #include "ui/compositor/layer_animation_observer.h" | |
27 #include "ui/compositor/layer_animation_sequence.h" | 27 #include "ui/compositor/layer_animation_sequence.h" |
28 #include "ui/compositor/layer_animator.h" | 28 #include "ui/compositor/layer_animator.h" |
29 #include "ui/compositor/layer_owner.h" | 29 #include "ui/compositor/layer_owner.h" |
30 #include "ui/compositor/layer_tree_owner.h" | 30 #include "ui/compositor/layer_tree_owner.h" |
31 #include "ui/display/display.h" | 31 #include "ui/display/display.h" |
32 #include "ui/display/manager/display_manager.h" | 32 #include "ui/display/manager/display_manager.h" |
33 #include "ui/display/manager/managed_display_info.h" | 33 #include "ui/display/manager/managed_display_info.h" |
34 #include "ui/gfx/animation/tween.h" | 34 #include "ui/gfx/animation/tween.h" |
35 #include "ui/gfx/geometry/point.h" | 35 #include "ui/gfx/geometry/point.h" |
36 #include "ui/gfx/geometry/rect.h" | 36 #include "ui/gfx/geometry/rect.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
70 return (initial_rotation + 3) % 4 == new_rotation | 70 return (initial_rotation + 3) % 4 == new_rotation |
71 ? kCounterClockWiseRotationFactor | 71 ? kCounterClockWiseRotationFactor |
72 : kClockWiseRotationFactor; | 72 : kClockWiseRotationFactor; |
73 } | 73 } |
74 | 74 |
75 aura::Window* GetRootWindow(int64_t display_id) { | 75 aura::Window* GetRootWindow(int64_t display_id) { |
76 return Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId( | 76 return Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId( |
77 display_id); | 77 display_id); |
78 } | 78 } |
79 | 79 |
80 aura::Window* GetScreenRotationContainer(aura::Window* root_window) { | |
81 return root_window->GetChildById(kShellWindowId_ScreenRotationContainer); | |
82 } | |
83 | |
84 aura::Window* GetScreenRotationContainer(int64_t display_id) { | |
85 return GetScreenRotationContainer(GetRootWindow(display_id)); | |
86 } | |
87 | |
80 // Returns true if the rotation between |initial_rotation| and |new_rotation| is | 88 // Returns true if the rotation between |initial_rotation| and |new_rotation| is |
81 // 180 degrees. | 89 // 180 degrees. |
82 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, | 90 bool Is180DegreeFlip(display::Display::Rotation initial_rotation, |
83 display::Display::Rotation new_rotation) { | 91 display::Display::Rotation new_rotation) { |
84 return (initial_rotation + 2) % 4 == new_rotation; | 92 return (initial_rotation + 2) % 4 == new_rotation; |
85 } | 93 } |
86 | 94 |
87 // Returns the initial degrees the old layer animation to begin with. | 95 // Returns the initial degrees the old layer animation to begin with. |
88 int GetInitialDegrees(display::Display::Rotation initial_rotation, | 96 int GetInitialDegrees(display::Display::Rotation initial_rotation, |
89 display::Display::Rotation new_rotation) { | 97 display::Display::Rotation new_rotation) { |
90 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); | 98 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); |
91 } | 99 } |
92 | 100 |
93 // A LayerAnimationObserver that will destroy the contained LayerTreeOwner | 101 void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) { |
94 // when notified that a layer animation has ended or was aborted. | 102 // Add the cloned/copied layer tree into the root, so it will be rendered. |
95 class LayerCleanupObserver : public ui::LayerAnimationObserver { | 103 root_window->layer()->Add(layer); |
96 public: | 104 root_window->layer()->StackAtTop(layer); |
97 // Takes WeakPtr of ScreenRotationAnimator. |this| may outlive the |animator_| | |
98 // instance and the |animator_| isn't detaching itself as an observer when | |
99 // being destroyed. However, ideally, when |animator_| is destroying, | |
100 // deleting |old_layer_tree_owner_| will trigger OnLayerAnimationAborted and | |
101 // delete |this| before |animator_| deleted. | |
102 explicit LayerCleanupObserver(base::WeakPtr<ScreenRotationAnimator> animator); | |
103 ~LayerCleanupObserver() override; | |
104 | |
105 // ui::LayerAnimationObserver: | |
106 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override; | |
107 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override; | |
108 void OnLayerAnimationScheduled( | |
109 ui::LayerAnimationSequence* sequence) override {} | |
110 | |
111 protected: | |
112 // ui::LayerAnimationObserver: | |
113 bool RequiresNotificationWhenAnimatorDestroyed() const override { | |
114 return true; | |
115 } | |
116 void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override; | |
117 void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override; | |
118 | |
119 private: | |
120 base::WeakPtr<ScreenRotationAnimator> animator_; | |
121 | |
122 // The LayerAnimationSequence that |this| has been attached to. Defaults to | |
123 // nullptr. | |
124 ui::LayerAnimationSequence* sequence_; | |
125 | |
126 DISALLOW_COPY_AND_ASSIGN(LayerCleanupObserver); | |
127 }; | |
128 | |
129 LayerCleanupObserver::LayerCleanupObserver( | |
130 base::WeakPtr<ScreenRotationAnimator> animator) | |
131 : animator_(animator), sequence_(nullptr) {} | |
132 | |
133 LayerCleanupObserver::~LayerCleanupObserver() { | |
134 // We must eplicitly detach from |sequence_| because we return true from | |
135 // RequiresNotificationWhenAnimatorDestroyed. | |
136 if (sequence_) | |
137 sequence_->RemoveObserver(this); | |
138 } | 105 } |
139 | 106 |
140 void LayerCleanupObserver::OnLayerAnimationEnded( | 107 // The Callback will be invoked when all animation sequences have |
141 ui::LayerAnimationSequence* sequence) { | 108 // finished. |observer| will be destroyed after invoking the Callback if it |
142 if (animator_) | 109 // returns true. |
143 animator_->ProcessAnimationQueue(); | 110 bool AnimationEndedCallback( |
144 | 111 base::WeakPtr<ScreenRotationAnimator> animator, |
145 delete this; | 112 const ui::CallbackLayerAnimationObserver& observer) { |
113 if (animator) | |
114 animator->ProcessAnimationQueue(); | |
115 return true; | |
146 } | 116 } |
147 | 117 |
148 void LayerCleanupObserver::OnLayerAnimationAborted( | 118 // Round near zero value to zero. |
149 ui::LayerAnimationSequence* sequence) { | 119 void RoundNearZero(gfx::Transform* transform) { |
150 if (animator_) | 120 const float kEpsilon = 0.001f; |
151 animator_->ProcessAnimationQueue(); | 121 SkMatrix44& matrix = transform->matrix(); |
152 | 122 for (int x = 0; x < 4; ++x) { |
153 delete this; | 123 for (int y = 0; y < 4; ++y) { |
124 if (std::abs(SkMScalarToFloat(matrix.get(x, y))) < kEpsilon) | |
125 matrix.set(x, y, SkFloatToMScalar(0.0f)); | |
126 } | |
127 } | |
154 } | 128 } |
155 | 129 |
156 void LayerCleanupObserver::OnAttachedToSequence( | 130 void TransformLayerToOldRotation( |
157 ui::LayerAnimationSequence* sequence) { | 131 ui::Layer* layer, |
158 sequence_ = sequence; | 132 const int64_t display_id, |
159 } | 133 const display::Display::Rotation& new_rotation, |
134 const display::Display::Rotation& old_rotation) { | |
135 const display::Display display = | |
136 Shell::Get()->display_manager()->GetDisplayForId(display_id); | |
160 | 137 |
161 void LayerCleanupObserver::OnDetachedFromSequence( | 138 const int rotation_changed = ((new_rotation - old_rotation) + 4) % 4; |
162 ui::LayerAnimationSequence* sequence) { | 139 float one_pixel = 1.0f / display.device_scale_factor(); |
163 DCHECK_EQ(sequence, sequence_); | 140 gfx::Transform transform; |
164 sequence_ = nullptr; | 141 switch (rotation_changed) { |
142 case 0: | |
143 break; | |
144 case 1: | |
145 transform.Rotate(270); | |
146 transform.Translate(-display.bounds().height() + one_pixel, 0); | |
147 break; | |
148 case 2: | |
149 transform.Rotate(180); | |
150 transform.Translate(-display.bounds().width() + one_pixel, | |
151 -display.bounds().height() + one_pixel); | |
152 break; | |
153 case 3: | |
154 transform.Rotate(90); | |
155 transform.Translate(0, -display.bounds().width() + one_pixel); | |
156 break; | |
157 } | |
158 | |
159 RoundNearZero(&transform); | |
160 layer->SetTransform(transform); | |
oshima
2017/04/07 20:48:56
Can you refactor and reuse CreateRotationTransform
wutao
2017/04/10 08:01:07
It is not exactly the same. It is an inverse trans
| |
165 } | 161 } |
166 | 162 |
167 class ScreenRotationAnimationMetricsReporter | 163 class ScreenRotationAnimationMetricsReporter |
168 : public ui::AnimationMetricsReporter { | 164 : public ui::AnimationMetricsReporter { |
169 public: | 165 public: |
170 ScreenRotationAnimationMetricsReporter() {} | 166 ScreenRotationAnimationMetricsReporter() {} |
171 ~ScreenRotationAnimationMetricsReporter() override {} | 167 ~ScreenRotationAnimationMetricsReporter() override {} |
172 | 168 |
173 void Report(int value) override { | 169 void Report(int value) override { |
174 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); | 170 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); |
(...skipping 21 matching lines...) Expand all Loading... | |
196 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in | 192 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in |
197 // order to make sure |metrics_reporter_| outlives the attached animation | 193 // order to make sure |metrics_reporter_| outlives the attached animation |
198 // sequence. | 194 // sequence. |
199 old_layer_tree_owner_.reset(); | 195 old_layer_tree_owner_.reset(); |
200 metrics_reporter_.reset(); | 196 metrics_reporter_.reset(); |
201 } | 197 } |
202 | 198 |
203 void ScreenRotationAnimator::StartRotationAnimation( | 199 void ScreenRotationAnimator::StartRotationAnimation( |
204 std::unique_ptr<ScreenRotationRequest> rotation_request) { | 200 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
205 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 201 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
206 switches::kAshEnableSmoothScreenRotation)) { | 202 switches::kAshEnableSmoothScreenRotation)) { |
oshima
2017/04/07 20:48:56
you may cache this value.
wutao
2017/04/10 08:01:07
Done.
| |
207 RequestCopyRootLayerAndAnimateRotation(std::move(rotation_request)); | 203 std::unique_ptr<cc::CopyOutputRequest> copy_output_request = |
204 cc::CopyOutputRequest::CreateRequest( | |
205 CreateAfterCopyCallbackBeforeRotation(std::move(rotation_request))); | |
206 RequestCopyScreenRotationContainerLayer(std::move(copy_output_request)); | |
208 } else { | 207 } else { |
209 CreateOldLayerTree(); | 208 StartSlowAnimation(std::move(rotation_request)); |
210 AnimateRotation(std::move(rotation_request)); | |
211 } | 209 } |
212 } | 210 } |
213 | 211 |
214 void ScreenRotationAnimator::RequestCopyRootLayerAndAnimateRotation( | 212 void ScreenRotationAnimator::StartSlowAnimation( |
215 std::unique_ptr<ScreenRotationRequest> rotation_request) { | 213 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
216 std::unique_ptr<cc::CopyOutputRequest> copy_output_request = | 214 CreateOldLayerTree(); |
217 cc::CopyOutputRequest::CreateRequest( | 215 SetRotation(rotation_request->new_rotation, rotation_request->old_rotation, |
218 CreateAfterCopyCallback(std::move(rotation_request))); | 216 rotation_request->source); |
219 ui::Layer* layer = GetRootWindow(display_id_)->layer(); | 217 AnimateRotation(std::move(rotation_request)); |
218 } | |
219 | |
220 void ScreenRotationAnimator::SetRotation( | |
221 const display::Display::Rotation& new_rotation, | |
222 const display::Display::Rotation& old_rotation, | |
223 const display::Display::RotationSource& source) { | |
224 Shell::Get()->display_manager()->SetDisplayRotation(display_id_, new_rotation, | |
225 source); | |
226 TransformLayerToOldRotation(old_layer_tree_owner_->root(), display_id_, | |
227 new_rotation, old_rotation); | |
228 } | |
229 | |
230 void ScreenRotationAnimator::RequestCopyScreenRotationContainerLayer( | |
231 std::unique_ptr<cc::CopyOutputRequest> copy_output_request) { | |
232 ui::Layer* layer = GetScreenRotationContainer(display_id_)->layer(); | |
oshima
2017/04/07 20:48:56
since the container will never change, you should
wutao
2017/04/10 08:01:07
Done.
| |
220 copy_output_request->set_area(gfx::Rect(layer->size())); | 233 copy_output_request->set_area(gfx::Rect(layer->size())); |
221 layer->RequestCopyOfOutput(std::move(copy_output_request)); | 234 layer->RequestCopyOfOutput(std::move(copy_output_request)); |
222 } | 235 } |
223 | 236 |
224 ScreenRotationAnimator::CopyCallback | 237 ScreenRotationAnimator::CopyCallback |
225 ScreenRotationAnimator::CreateAfterCopyCallback( | 238 ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation( |
226 std::unique_ptr<ScreenRotationRequest> rotation_request) { | 239 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
227 return base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation, | 240 return base::Bind(&ScreenRotationAnimator:: |
241 OnScreenRotationContainerLayerCopiedBeforeRotation, | |
228 weak_factory_.GetWeakPtr(), | 242 weak_factory_.GetWeakPtr(), |
229 base::Passed(&rotation_request)); | 243 base::Passed(&rotation_request)); |
230 } | 244 } |
231 | 245 |
232 void ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation( | 246 ScreenRotationAnimator::CopyCallback |
247 ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation( | |
248 std::unique_ptr<ScreenRotationRequest> rotation_request) { | |
249 return base::Bind(&ScreenRotationAnimator:: | |
250 OnScreenRotationContainerLayerCopiedAfterRotation, | |
251 weak_factory_.GetWeakPtr(), | |
252 base::Passed(&rotation_request)); | |
253 } | |
254 | |
255 void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation( | |
233 std::unique_ptr<ScreenRotationRequest> rotation_request, | 256 std::unique_ptr<ScreenRotationRequest> rotation_request, |
234 std::unique_ptr<cc::CopyOutputResult> result) { | 257 std::unique_ptr<cc::CopyOutputResult> result) { |
235 // If display was removed, should abort rotation. | 258 // If display was removed, should abort rotation. |
236 if (!IsDisplayIdValid(display_id_)) { | 259 if (!IsDisplayIdValid(display_id_)) { |
237 ProcessAnimationQueue(); | 260 ProcessAnimationQueue(); |
238 return; | 261 return; |
239 } | 262 } |
240 | 263 |
241 // Fall back to recreate layers solution when the copy request has been | 264 // Fall back to recreate layers solution when the copy request has been |
242 // canceled or failed. It would fail if, for examples: a) The layer is removed | 265 // canceled or failed. It would fail if, for examples: a) The layer is removed |
243 // from the compositor and destroyed before committing the request to the | 266 // from the compositor and destroyed before committing the request to the |
244 // compositor. b) The compositor is shutdown. | 267 // compositor. b) The compositor is shutdown. |
oshima
2017/04/07 20:48:56
do we have to continue under these conditions? Can
wutao
2017/04/10 08:01:07
Yes, we can
| |
245 if (result->IsEmpty()) | 268 if (result->IsEmpty()) { |
246 CreateOldLayerTree(); | 269 StartSlowAnimation(std::move(rotation_request)); |
247 else | 270 } else { |
248 CopyOldLayerTree(std::move(result)); | 271 old_layer_tree_owner_ = CopyLayerTree(std::move(result)); |
272 SetRotation(rotation_request->new_rotation, rotation_request->old_rotation, | |
273 rotation_request->source); | |
274 std::unique_ptr<cc::CopyOutputRequest> copy_output_request = | |
275 cc::CopyOutputRequest::CreateRequest( | |
276 CreateAfterCopyCallbackAfterRotation(std::move(rotation_request))); | |
277 RequestCopyScreenRotationContainerLayer(std::move(copy_output_request)); | |
278 } | |
279 } | |
280 | |
281 void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation( | |
282 std::unique_ptr<ScreenRotationRequest> rotation_request, | |
283 std::unique_ptr<cc::CopyOutputResult> result) { | |
284 // If display was removed, should abort rotation. | |
285 if (!IsDisplayIdValid(display_id_)) { | |
286 ProcessAnimationQueue(); | |
287 return; | |
288 } | |
289 | |
290 // If copy request has been canceled or failed, use the real layers for | |
291 // animation. | |
oshima
2017/04/07 20:48:56
ditto
wutao
2017/04/10 08:01:07
Abort here.
| |
292 if (!result->IsEmpty()) | |
293 new_layer_tree_owner_ = CopyLayerTree(std::move(result)); | |
249 AnimateRotation(std::move(rotation_request)); | 294 AnimateRotation(std::move(rotation_request)); |
250 } | 295 } |
251 | 296 |
252 void ScreenRotationAnimator::CreateOldLayerTree() { | 297 void ScreenRotationAnimator::CreateOldLayerTree() { |
253 old_layer_tree_owner_ = ::wm::RecreateLayers(GetRootWindow(display_id_)); | 298 aura::Window* root_window = GetRootWindow(display_id_); |
299 old_layer_tree_owner_ = ::wm::RecreateLayers(root_window); | |
300 AddLayerAtTopOfWindowLayers(root_window, old_layer_tree_owner_->root()); | |
254 } | 301 } |
255 | 302 |
256 void ScreenRotationAnimator::CopyOldLayerTree( | 303 std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree( |
257 std::unique_ptr<cc::CopyOutputResult> result) { | 304 std::unique_ptr<cc::CopyOutputResult> result) { |
258 cc::TextureMailbox texture_mailbox; | 305 cc::TextureMailbox texture_mailbox; |
259 std::unique_ptr<cc::SingleReleaseCallback> release_callback; | 306 std::unique_ptr<cc::SingleReleaseCallback> release_callback; |
260 result->TakeTexture(&texture_mailbox, &release_callback); | 307 result->TakeTexture(&texture_mailbox, &release_callback); |
261 DCHECK(texture_mailbox.IsTexture()); | 308 DCHECK(texture_mailbox.IsTexture()); |
262 | 309 |
263 aura::Window* root_window = GetRootWindow(display_id_); | 310 aura::Window* root_window = GetRootWindow(display_id_); |
264 gfx::Rect rect(root_window->layer()->size()); | 311 gfx::Rect rect(root_window->layer()->size()); |
265 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>(); | 312 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>(); |
266 copy_layer->SetBounds(rect); | 313 copy_layer->SetBounds(rect); |
267 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback), | 314 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback), |
268 rect.size()); | 315 rect.size()); |
269 old_layer_tree_owner_ = | 316 |
270 base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer)); | 317 AddLayerAtTopOfWindowLayers(root_window, copy_layer.get()); |
318 return base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer)); | |
271 } | 319 } |
272 | 320 |
273 void ScreenRotationAnimator::AnimateRotation( | 321 void ScreenRotationAnimator::AnimateRotation( |
274 std::unique_ptr<ScreenRotationRequest> rotation_request) { | 322 std::unique_ptr<ScreenRotationRequest> rotation_request) { |
275 aura::Window* root_window = GetRootWindow(display_id_); | 323 const int rotation_factor = GetRotationFactor(rotation_request->old_rotation, |
276 std::unique_ptr<LayerCleanupObserver> old_layer_cleanup_observer( | 324 rotation_request->new_rotation); |
277 new LayerCleanupObserver(weak_factory_.GetWeakPtr())); | |
278 ui::Layer* old_root_layer = old_layer_tree_owner_->root(); | |
279 old_root_layer->set_name("ScreenRotationAnimator:old_layer_tree"); | |
280 // Add the cloned layer tree in to the root, so it will be rendered. | |
281 root_window->layer()->Add(old_root_layer); | |
282 root_window->layer()->StackAtTop(old_root_layer); | |
283 | |
284 const gfx::Rect original_screen_bounds = root_window->GetTargetBounds(); | |
285 | |
286 const int rotation_factor = GetRotationFactor( | |
287 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); | |
288 | |
289 const int old_layer_initial_rotation_degrees = GetInitialDegrees( | 325 const int old_layer_initial_rotation_degrees = GetInitialDegrees( |
290 GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); | 326 rotation_request->old_rotation, rotation_request->new_rotation); |
291 | |
292 const base::TimeDelta duration = | 327 const base::TimeDelta duration = |
293 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); | 328 base::TimeDelta::FromMilliseconds(kRotationDurationInMs); |
294 | |
295 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; | 329 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; |
296 | 330 aura::Window* root_window = GetRootWindow(display_id_); |
297 Shell::Get()->display_manager()->SetDisplayRotation( | |
298 display_id_, rotation_request->new_rotation, rotation_request->source); | |
299 | |
300 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds(); | 331 const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds(); |
301 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, | 332 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, |
302 rotated_screen_bounds.height() / 2); | 333 rotated_screen_bounds.height() / 2); |
303 | 334 |
304 ui::Layer* screen_rotation_container_layer = | 335 ui::Layer* new_root_layer; |
305 root_window->GetChildById(kShellWindowId_ScreenRotationContainer) | 336 if (new_layer_tree_owner_ && |
306 ->layer(); | 337 base::CommandLine::ForCurrentProcess()->HasSwitch( |
307 std::unique_ptr<ScreenRotationAnimation> current_layer_screen_rotation = | 338 switches::kAshEnableSmoothScreenRotation)) { |
339 // Make the current layers invisible if the copy request after rotation is | |
340 // succeesful. | |
341 GetScreenRotationContainer(root_window)->layer()->SetOpacity(0.0f); | |
342 new_root_layer = new_layer_tree_owner_->root(); | |
343 } else { | |
344 new_root_layer = GetScreenRotationContainer(root_window)->layer(); | |
345 } | |
346 | |
347 std::unique_ptr<ScreenRotationAnimation> new_layer_screen_rotation = | |
308 base::MakeUnique<ScreenRotationAnimation>( | 348 base::MakeUnique<ScreenRotationAnimation>( |
309 screen_rotation_container_layer, kRotationDegrees * rotation_factor, | 349 new_root_layer, kRotationDegrees * rotation_factor, |
310 0 /* end_degrees */, 0.0f, | 350 0 /* end_degrees */, 0.0f, |
311 screen_rotation_container_layer->opacity() /* target_opacity */, | 351 new_root_layer->opacity() /* target_opacity */, pivot, duration, |
312 pivot, duration, tween_type); | 352 tween_type); |
313 | 353 |
314 ui::LayerAnimator* current_layer_animator = | 354 ui::LayerAnimator* new_layer_animator = new_root_layer->GetAnimator(); |
315 screen_rotation_container_layer->GetAnimator(); | 355 new_layer_animator->set_preemption_strategy( |
316 current_layer_animator->set_preemption_strategy( | |
317 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); | 356 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
318 std::unique_ptr<ui::LayerAnimationSequence> current_layer_animation_sequence = | 357 std::unique_ptr<ui::LayerAnimationSequence> new_layer_animation_sequence = |
319 base::MakeUnique<ui::LayerAnimationSequence>( | 358 base::MakeUnique<ui::LayerAnimationSequence>( |
320 std::move(current_layer_screen_rotation)); | 359 std::move(new_layer_screen_rotation)); |
321 current_layer_animator->StartAnimation( | |
322 current_layer_animation_sequence.release()); | |
323 | 360 |
361 ui::Layer* old_root_layer = old_layer_tree_owner_->root(); | |
362 const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds(); | |
324 // The old layer will also be transformed into the new orientation. We will | 363 // The old layer will also be transformed into the new orientation. We will |
325 // translate it so that the old layer's center point aligns with the new | 364 // translate it so that the old layer's center point aligns with the new |
326 // orientation's center point and use that center point as the pivot for the | 365 // orientation's center point and use that center point as the pivot for the |
327 // rotation animation. | 366 // rotation animation. |
328 gfx::Transform translate_transform; | 367 gfx::Transform translate_transform; |
329 translate_transform.Translate( | 368 translate_transform.Translate( |
330 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2, | 369 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2, |
331 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); | 370 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); |
332 old_root_layer->SetTransform(translate_transform); | 371 old_root_layer->SetTransform(translate_transform); |
333 | 372 |
334 std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation = | 373 std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation = |
335 base::MakeUnique<ScreenRotationAnimation>( | 374 base::MakeUnique<ScreenRotationAnimation>( |
336 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, | 375 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, |
337 (old_layer_initial_rotation_degrees - kRotationDegrees) * | 376 (old_layer_initial_rotation_degrees - kRotationDegrees) * |
338 rotation_factor, | 377 rotation_factor, |
339 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, | 378 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, |
340 tween_type); | 379 tween_type); |
341 | 380 |
342 ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator(); | 381 ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator(); |
343 old_layer_animator->set_preemption_strategy( | 382 old_layer_animator->set_preemption_strategy( |
344 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); | 383 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
345 std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence = | 384 std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence = |
346 base::MakeUnique<ui::LayerAnimationSequence>( | 385 base::MakeUnique<ui::LayerAnimationSequence>( |
347 std::move(old_layer_screen_rotation)); | 386 std::move(old_layer_screen_rotation)); |
348 // Add an observer so that the cloned layers can be cleaned up with the | 387 |
349 // animation completes/aborts. | |
350 old_layer_animation_sequence->AddObserver( | |
351 old_layer_cleanup_observer.release()); | |
352 // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to | 388 // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to |
353 // control the animation. | 389 // control the animation. |
354 if (disable_animation_timers_for_test_) | 390 if (disable_animation_timers_for_test_) { |
391 if (new_layer_tree_owner_) | |
392 new_layer_animator->set_disable_timer_for_test(true); | |
355 old_layer_animator->set_disable_timer_for_test(true); | 393 old_layer_animator->set_disable_timer_for_test(true); |
394 } | |
356 old_layer_animation_sequence->SetAnimationMetricsReporter( | 395 old_layer_animation_sequence->SetAnimationMetricsReporter( |
357 metrics_reporter_.get()); | 396 metrics_reporter_.get()); |
397 | |
398 // Add an observer so that the cloned/copied layers can be cleaned up with the | |
399 // animation completes/aborts. | |
400 ui::CallbackLayerAnimationObserver* observer = | |
401 new ui::CallbackLayerAnimationObserver( | |
402 base::Bind(&AnimationEndedCallback, weak_factory_.GetWeakPtr())); | |
403 if (new_layer_tree_owner_) { | |
404 new_layer_animator->AddObserver(observer); | |
405 new_layer_animator->StartAnimation(new_layer_animation_sequence.release()); | |
406 } | |
407 old_layer_animator->AddObserver(observer); | |
358 old_layer_animator->StartAnimation(old_layer_animation_sequence.release()); | 408 old_layer_animator->StartAnimation(old_layer_animation_sequence.release()); |
409 observer->SetActive(); | |
359 | 410 |
360 rotation_request.reset(); | 411 rotation_request.reset(); |
361 } | 412 } |
362 | 413 |
363 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, | 414 void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, |
364 display::Display::RotationSource source) { | 415 display::Display::RotationSource source) { |
365 if (GetCurrentScreenRotation(display_id_) == new_rotation) | 416 const display::Display::Rotation current_rotation = |
417 GetCurrentScreenRotation(display_id_); | |
418 if (current_rotation == new_rotation) | |
366 return; | 419 return; |
367 | 420 |
368 std::unique_ptr<ScreenRotationRequest> rotation_request = | 421 std::unique_ptr<ScreenRotationRequest> rotation_request = |
369 base::MakeUnique<ScreenRotationRequest>(new_rotation, source); | 422 base::MakeUnique<ScreenRotationRequest>(current_rotation, new_rotation, |
423 source); | |
370 | 424 |
371 if (is_rotating_) { | 425 if (is_rotating_) { |
372 last_pending_request_ = std::move(rotation_request); | 426 last_pending_request_ = std::move(rotation_request); |
373 // The pending request will be processed when the | 427 // The pending request will be processed when the |
374 // OnLayerAnimation(Ended|Aborted) methods should be called after | 428 // OnLayerAnimation(Ended|Aborted) methods should be called after |
375 // StopAnimating(). | 429 // StopAnimating(). |
376 StopAnimating(); | 430 StopAnimating(); |
377 } else { | 431 } else { |
378 is_rotating_ = true; | 432 is_rotating_ = true; |
379 StartRotationAnimation(std::move(rotation_request)); | 433 StartRotationAnimation(std::move(rotation_request)); |
380 } | 434 } |
381 } | 435 } |
382 | 436 |
383 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver( | 437 void ScreenRotationAnimator::AddScreenRotationAnimatorObserver( |
384 ScreenRotationAnimatorObserver* observer) { | 438 ScreenRotationAnimatorObserver* observer) { |
385 screen_rotation_animator_observers_.AddObserver(observer); | 439 screen_rotation_animator_observers_.AddObserver(observer); |
386 } | 440 } |
387 | 441 |
388 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( | 442 void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( |
389 ScreenRotationAnimatorObserver* observer) { | 443 ScreenRotationAnimatorObserver* observer) { |
390 screen_rotation_animator_observers_.RemoveObserver(observer); | 444 screen_rotation_animator_observers_.RemoveObserver(observer); |
391 } | 445 } |
392 | 446 |
393 void ScreenRotationAnimator::ProcessAnimationQueue() { | 447 void ScreenRotationAnimator::ProcessAnimationQueue() { |
394 is_rotating_ = false; | 448 is_rotating_ = false; |
449 StopAnimating(); | |
395 old_layer_tree_owner_.reset(); | 450 old_layer_tree_owner_.reset(); |
451 new_layer_tree_owner_.reset(); | |
396 if (last_pending_request_ && IsDisplayIdValid(display_id_)) { | 452 if (last_pending_request_ && IsDisplayIdValid(display_id_)) { |
397 std::unique_ptr<ScreenRotationRequest> rotation_request = | 453 std::unique_ptr<ScreenRotationRequest> rotation_request = |
398 std::move(last_pending_request_); | 454 std::move(last_pending_request_); |
399 Rotate(rotation_request->new_rotation, rotation_request->source); | 455 Rotate(rotation_request->new_rotation, rotation_request->source); |
400 rotation_request.reset(); | 456 rotation_request.reset(); |
401 return; | 457 return; |
402 } | 458 } |
403 | 459 |
404 for (auto& observer : screen_rotation_animator_observers_) | 460 for (auto& observer : screen_rotation_animator_observers_) |
405 observer.OnScreenRotationAnimationFinished(this); | 461 observer.OnScreenRotationAnimationFinished(this); |
406 } | 462 } |
407 | 463 |
408 void ScreenRotationAnimator::set_disable_animation_timers_for_test( | 464 void ScreenRotationAnimator::set_disable_animation_timers_for_test( |
409 bool disable_timers) { | 465 bool disable_timers) { |
410 disable_animation_timers_for_test_ = disable_timers; | 466 disable_animation_timers_for_test_ = disable_timers; |
411 } | 467 } |
412 | 468 |
413 void ScreenRotationAnimator::StopAnimating() { | 469 void ScreenRotationAnimator::StopAnimating() { |
414 GetRootWindow(display_id_) | 470 // |old_layer_tree_owner_| new_layer_tree_owner_| could be nullptr if the |
415 ->GetChildById(kShellWindowId_ScreenRotationContainer) | 471 // copy request after screen rotation was canceled or failed. |
416 ->layer() | 472 if (old_layer_tree_owner_) |
417 ->GetAnimator() | 473 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); |
418 ->StopAnimating(); | 474 if (new_layer_tree_owner_) { |
419 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); | 475 GetScreenRotationContainer(display_id_)->layer()->SetOpacity(1.0f); |
476 new_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); | |
477 } | |
420 } | 478 } |
421 | 479 |
422 } // namespace ash | 480 } // namespace ash |
OLD | NEW |