Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(774)

Side by Side Diff: ash/rotator/screen_rotation_animator.cc

Issue 2790583004: Add second copy request after screen rotation to flatten the layers in animation. (Closed)
Patch Set: Add a copy request after screen rotation to flatten the layers in animation. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698