blob: aaadcdb64169539b07e0630bdc9d7c56cfe586e1 [file] [log] [blame]
bruthig37f9cad02015-03-12 22:28:501// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ash/rotator/screen_rotation_animator.h"
6
James Cookb0bf8e82017-04-09 17:01:447#include "ash/ash_switches.h"
oshimae2818922015-07-28 01:18:528#include "ash/display/window_tree_host_manager.h"
wutao33576082017-04-14 18:51:109#include "ash/public/cpp/shell_window_ids.h"
bruthig37f9cad02015-03-12 22:28:5010#include "ash/rotator/screen_rotation_animation.h"
wutao6ddafa32017-03-18 03:10:0811#include "ash/rotator/screen_rotation_animator_observer.h"
bruthig37f9cad02015-03-12 22:28:5012#include "ash/shell.h"
wutao6d394112017-04-20 02:17:3513#include "ash/utility/transformer_util.h"
bruthig37f9cad02015-03-12 22:28:5014#include "base/command_line.h"
ratsunnybd5087e2016-12-17 05:19:2515#include "base/memory/ptr_util.h"
wutao3f08f812017-03-25 03:06:3316#include "base/metrics/histogram_macros.h"
bruthig37f9cad02015-03-12 22:28:5017#include "base/time/time.h"
wutao2c0ca182017-04-06 22:40:5418#include "cc/output/copy_output_request.h"
19#include "cc/output/copy_output_result.h"
bruthig37f9cad02015-03-12 22:28:5020#include "ui/aura/window.h"
wutao6d394112017-04-20 02:17:3521#include "ui/compositor/callback_layer_animation_observer.h"
bruthig37f9cad02015-03-12 22:28:5022#include "ui/compositor/layer.h"
wutao3f08f812017-03-25 03:06:3323#include "ui/compositor/layer_animation_element.h"
bruthig37f9cad02015-03-12 22:28:5024#include "ui/compositor/layer_animation_sequence.h"
25#include "ui/compositor/layer_animator.h"
26#include "ui/compositor/layer_owner.h"
27#include "ui/compositor/layer_tree_owner.h"
oshimaf84b0da722016-04-27 19:47:1928#include "ui/display/display.h"
rjkroege72f8154f2016-10-29 00:49:0229#include "ui/display/manager/display_manager.h"
rjkroege259c01882016-08-30 19:29:5030#include "ui/display/manager/managed_display_info.h"
bruthig37f9cad02015-03-12 22:28:5031#include "ui/gfx/animation/tween.h"
bruthig37f9cad02015-03-12 22:28:5032#include "ui/gfx/geometry/point.h"
33#include "ui/gfx/geometry/rect.h"
34#include "ui/gfx/geometry/rect_f.h"
35#include "ui/gfx/transform.h"
36#include "ui/gfx/transform_util.h"
37#include "ui/wm/core/window_util.h"
38
39namespace ash {
40
41namespace {
42
bruthigaff7d0f2015-09-01 17:46:5543// The number of degrees that the rotation animations animate through.
44const int kRotationDegrees = 20;
bruthig37f9cad02015-03-12 22:28:5045
bruthig2ce3f232015-04-02 15:21:3546// The time it takes for the rotation animations to run.
bruthig37f9cad02015-03-12 22:28:5047const int kRotationDurationInMs = 250;
48
wutao6ddafa32017-03-18 03:10:0849// The rotation factors.
50const int kCounterClockWiseRotationFactor = 1;
51const int kClockWiseRotationFactor = -1;
52
wutao6ddafa32017-03-18 03:10:0853display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) {
skycb4be5b2017-04-06 17:52:4554 return Shell::Get()
bruthig37f9cad02015-03-12 22:28:5055 ->display_manager()
56 ->GetDisplayInfo(display_id)
jonrossd01de7f2015-04-23 19:52:0057 .GetActiveRotation();
bruthig37f9cad02015-03-12 22:28:5058}
59
wutao6ddafa32017-03-18 03:10:0860bool IsDisplayIdValid(int64_t display_id) {
skycb4be5b2017-04-06 17:52:4561 return Shell::Get()->display_manager()->IsDisplayIdValid(display_id);
wutao6ddafa32017-03-18 03:10:0862}
63
64// 180 degree rotations should animate clock-wise.
65int GetRotationFactor(display::Display::Rotation initial_rotation,
66 display::Display::Rotation new_rotation) {
67 return (initial_rotation + 3) % 4 == new_rotation
68 ? kCounterClockWiseRotationFactor
69 : kClockWiseRotationFactor;
70}
71
72aura::Window* GetRootWindow(int64_t display_id) {
skycb4be5b2017-04-06 17:52:4573 return Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId(
74 display_id);
wutao6ddafa32017-03-18 03:10:0875}
76
wutao6d394112017-04-20 02:17:3577aura::Window* GetScreenRotationContainer(aura::Window* root_window) {
78 return root_window->GetChildById(kShellWindowId_ScreenRotationContainer);
79}
80
bruthig37f9cad02015-03-12 22:28:5081// Returns true if the rotation between |initial_rotation| and |new_rotation| is
82// 180 degrees.
oshimaf84b0da722016-04-27 19:47:1983bool Is180DegreeFlip(display::Display::Rotation initial_rotation,
84 display::Display::Rotation new_rotation) {
bruthig37f9cad02015-03-12 22:28:5085 return (initial_rotation + 2) % 4 == new_rotation;
86}
87
wutao6ddafa32017-03-18 03:10:0888// Returns the initial degrees the old layer animation to begin with.
89int GetInitialDegrees(display::Display::Rotation initial_rotation,
90 display::Display::Rotation new_rotation) {
91 return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90);
92}
93
wutao6d394112017-04-20 02:17:3594void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) {
95 // Add the cloned/copied layer tree into the root, so it will be rendered.
96 root_window->layer()->Add(layer);
97 root_window->layer()->StackAtTop(layer);
bruthig37f9cad02015-03-12 22:28:5098}
99
wutao6d394112017-04-20 02:17:35100void AddLayerBelowWindowLayer(aura::Window* root_window,
101 ui::Layer* top_layer,
102 ui::Layer* layer) {
103 // Add the cloned/copied layer tree into the root, so it will be rendered.
104 root_window->layer()->Add(layer);
105 root_window->layer()->StackBelow(layer, top_layer);
bruthig37f9cad02015-03-12 22:28:50106}
107
wutao6d394112017-04-20 02:17:35108// The Callback will be invoked when all animation sequences have
109// finished. |observer| will be destroyed after invoking the Callback if it
110// returns true.
111bool AnimationEndedCallback(
112 base::WeakPtr<ScreenRotationAnimator> animator,
113 const ui::CallbackLayerAnimationObserver& observer) {
114 if (animator)
115 animator->ProcessAnimationQueue();
116 return true;
bruthig37f9cad02015-03-12 22:28:50117}
118
wutao6d394112017-04-20 02:17:35119// Creates a Transform for the old layer in screen rotation animation.
120gfx::Transform CreateScreenRotationOldLayerTransformForDisplay(
121 display::Display::Rotation old_rotation,
122 display::Display::Rotation new_rotation,
123 const display::Display& display) {
124 gfx::Transform inverse;
125 CHECK(CreateRotationTransform(old_rotation, new_rotation, display)
126 .GetInverse(&inverse));
127 return inverse;
bruthig37f9cad02015-03-12 22:28:50128}
129
wutao6d394112017-04-20 02:17:35130// The |request_id| changed since last copy request, which means a
131// new rotation stated, we need to ignore this copy result.
132bool IgnoreCopyResult(int64_t request_id, int64_t current_request_id) {
133 DCHECK(request_id <= current_request_id);
134 return request_id < current_request_id;
135}
136
wutao6d394112017-04-20 02:17:35137// Creates a black mask layer and returns the |layer_owner|.
138std::unique_ptr<ui::LayerOwner> CreateBlackMaskLayerOwner(
139 const gfx::Rect& rect) {
140 std::unique_ptr<ui::Layer> black_mask_layer =
141 base::MakeUnique<ui::Layer>(ui::LAYER_SOLID_COLOR);
142 black_mask_layer->SetBounds(rect);
143 black_mask_layer->SetColor(SK_ColorBLACK);
144 std::unique_ptr<ui::LayerOwner> black_mask_layer_owner =
145 base::MakeUnique<ui::LayerOwner>();
146 black_mask_layer_owner->SetLayer(std::move(black_mask_layer));
147 return black_mask_layer_owner;
bruthig37f9cad02015-03-12 22:28:50148}
149
wutao3f08f812017-03-25 03:06:33150class ScreenRotationAnimationMetricsReporter
151 : public ui::AnimationMetricsReporter {
152 public:
wutao883ea6f2017-05-16 19:40:51153 ScreenRotationAnimationMetricsReporter() = default;
154 ~ScreenRotationAnimationMetricsReporter() override = default;
wutao3f08f812017-03-25 03:06:33155
156 void Report(int value) override {
157 UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value);
158 }
159
160 private:
161 DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter);
162};
163
wutao6ddafa32017-03-18 03:10:08164} // namespace
jonross7351feb2015-04-23 22:10:26165
wutao6ddafa32017-03-18 03:10:08166ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id)
167 : display_id_(display_id),
wutao4a485532017-04-11 00:04:28168 screen_rotation_state_(IDLE),
wutao88733df2017-04-13 19:39:06169 rotation_request_id_(0),
wutao3f08f812017-03-25 03:06:33170 metrics_reporter_(
171 base::MakeUnique<ScreenRotationAnimationMetricsReporter>()),
wutao6ddafa32017-03-18 03:10:08172 disable_animation_timers_for_test_(false),
wutaob161bf22017-04-26 16:55:03173 has_switch_ash_disable_smooth_screen_rotation_(
wutao6d394112017-04-20 02:17:35174 base::CommandLine::ForCurrentProcess()->HasSwitch(
wutaob161bf22017-04-26 16:55:03175 switches::kAshDisableSmoothScreenRotation)),
wutao6d394112017-04-20 02:17:35176 root_window_(GetRootWindow(display_id_)),
177 screen_rotation_container_layer_(
178 GetScreenRotationContainer(root_window_)->layer()),
wutao6ddafa32017-03-18 03:10:08179 weak_factory_(this) {}
180
wutao3f08f812017-03-25 03:06:33181ScreenRotationAnimator::~ScreenRotationAnimator() {
wutao6d394112017-04-20 02:17:35182 // To prevent a call to |AnimationEndedCallback()| from calling a method on
183 // the |animator_|.
wutao3f08f812017-03-25 03:06:33184 weak_factory_.InvalidateWeakPtrs();
185
186 // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in
187 // order to make sure |metrics_reporter_| outlives the attached animation
188 // sequence.
189 old_layer_tree_owner_.reset();
190 metrics_reporter_.reset();
191}
wutao6ddafa32017-03-18 03:10:08192
wutao2c0ca182017-04-06 22:40:54193void ScreenRotationAnimator::StartRotationAnimation(
194 std::unique_ptr<ScreenRotationRequest> rotation_request) {
wutao6d394112017-04-20 02:17:35195 const display::Display::Rotation current_rotation =
196 GetCurrentScreenRotation(display_id_);
197 if (current_rotation == rotation_request->new_rotation) {
198 // We need to call |ProcessAnimationQueue()| to prepare for next rotation
199 // request.
wutao2c0ca182017-04-06 22:40:54200 ProcessAnimationQueue();
201 return;
202 }
203
wutao6d394112017-04-20 02:17:35204 rotation_request->old_rotation = current_rotation;
wutaob161bf22017-04-26 16:55:03205 if (has_switch_ash_disable_smooth_screen_rotation_) {
206 StartSlowAnimation(std::move(rotation_request));
207 } else {
wutao6d394112017-04-20 02:17:35208 std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
209 cc::CopyOutputRequest::CreateRequest(
210 CreateAfterCopyCallbackBeforeRotation(std::move(rotation_request)));
211 RequestCopyScreenRotationContainerLayer(std::move(copy_output_request));
212 screen_rotation_state_ = COPY_REQUESTED;
wutao6d394112017-04-20 02:17:35213 }
214}
215
216void ScreenRotationAnimator::StartSlowAnimation(
217 std::unique_ptr<ScreenRotationRequest> rotation_request) {
218 CreateOldLayerTreeForSlowAnimation();
219 SetRotation(rotation_request->old_rotation, rotation_request->new_rotation,
220 rotation_request->source);
wutao2c0ca182017-04-06 22:40:54221 AnimateRotation(std::move(rotation_request));
222}
223
wutao6d394112017-04-20 02:17:35224void ScreenRotationAnimator::SetRotation(
225 display::Display::Rotation old_rotation,
226 display::Display::Rotation new_rotation,
227 display::Display::RotationSource source) {
wutaoeb552052017-05-10 22:35:29228 // Allow compositor locks to extend timeout, so that screen rotation only
229 // takes output copy after contents are properlly resized, such as wallpaper
230 // and ARC apps.
231 ui::Compositor* compositor = root_window_->layer()->GetCompositor();
232 compositor->set_allow_locks_to_extend_timeout(true);
wutao6d394112017-04-20 02:17:35233 Shell::Get()->display_manager()->SetDisplayRotation(display_id_, new_rotation,
234 source);
wutaoeb552052017-05-10 22:35:29235 compositor->set_allow_locks_to_extend_timeout(false);
wutao6d394112017-04-20 02:17:35236 const display::Display display =
237 Shell::Get()->display_manager()->GetDisplayForId(display_id_);
238 old_layer_tree_owner_->root()->SetTransform(
239 CreateScreenRotationOldLayerTransformForDisplay(old_rotation,
240 new_rotation, display));
wutao2c0ca182017-04-06 22:40:54241}
242
wutao6d394112017-04-20 02:17:35243void ScreenRotationAnimator::RequestCopyScreenRotationContainerLayer(
244 std::unique_ptr<cc::CopyOutputRequest> copy_output_request) {
245 copy_output_request->set_area(
246 gfx::Rect(screen_rotation_container_layer_->size()));
247 screen_rotation_container_layer_->RequestCopyOfOutput(
248 std::move(copy_output_request));
249}
250
251ScreenRotationAnimator::CopyCallback
252ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation(
253 std::unique_ptr<ScreenRotationRequest> rotation_request) {
254 return base::Bind(&ScreenRotationAnimator::
255 OnScreenRotationContainerLayerCopiedBeforeRotation,
256 weak_factory_.GetWeakPtr(),
257 base::Passed(&rotation_request));
258}
259
260ScreenRotationAnimator::CopyCallback
261ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation(
262 std::unique_ptr<ScreenRotationRequest> rotation_request) {
263 return base::Bind(&ScreenRotationAnimator::
264 OnScreenRotationContainerLayerCopiedAfterRotation,
265 weak_factory_.GetWeakPtr(),
266 base::Passed(&rotation_request));
267}
268
269void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation(
270 std::unique_ptr<ScreenRotationRequest> rotation_request,
271 std::unique_ptr<cc::CopyOutputResult> result) {
272 if (IgnoreCopyResult(rotation_request->id, rotation_request_id_))
273 return;
wutaob161bf22017-04-26 16:55:03274 // Abort rotation and animation if the display was removed.
275 if (!IsDisplayIdValid(display_id_)) {
276 ProcessAnimationQueue();
277 return;
278 }
279 // Abort animation and set the rotation to target rotation when the copy
280 // request has been canceled or failed. It would fail if, for examples: a) The
281 // layer is removed from the compositor and destroye before committing the
282 // request to the compositor. b) The compositor is shutdown.
283 if (result->IsEmpty()) {
284 Shell::Get()->display_manager()->SetDisplayRotation(
285 display_id_, rotation_request->new_rotation, rotation_request->source);
wutao6d394112017-04-20 02:17:35286 ProcessAnimationQueue();
287 return;
288 }
289
290 old_layer_tree_owner_ = CopyLayerTree(std::move(result));
291 AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());
292 SetRotation(rotation_request->old_rotation, rotation_request->new_rotation,
293 rotation_request->source);
294 std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
295 cc::CopyOutputRequest::CreateRequest(
296 CreateAfterCopyCallbackAfterRotation(std::move(rotation_request)));
297 RequestCopyScreenRotationContainerLayer(std::move(copy_output_request));
298}
299
300void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation(
301 std::unique_ptr<ScreenRotationRequest> rotation_request,
302 std::unique_ptr<cc::CopyOutputResult> result) {
303 if (IgnoreCopyResult(rotation_request->id, rotation_request_id_))
304 return;
wutaob161bf22017-04-26 16:55:03305 // In the following cases, abort animation:
306 // 1) if the display was removed,
307 // 2) the copy request has been canceled or failed. It would fail if,
308 // for examples: a) The layer is removed from the compositor and destroye
309 // before committing the request to the compositor. b) The compositor is
310 // shutdown.
311 if (!IsDisplayIdValid(display_id_) || result->IsEmpty()) {
wutao6d394112017-04-20 02:17:35312 ProcessAnimationQueue();
313 return;
314 }
315
316 new_layer_tree_owner_ = CopyLayerTree(std::move(result));
317 AddLayerBelowWindowLayer(root_window_, old_layer_tree_owner_->root(),
318 new_layer_tree_owner_->root());
319 AnimateRotation(std::move(rotation_request));
320}
321
322void ScreenRotationAnimator::CreateOldLayerTreeForSlowAnimation() {
323 old_layer_tree_owner_ = ::wm::RecreateLayers(root_window_);
324 // |screen_rotation_container_layer_| needs update after |RecreateLayers()|.
325 screen_rotation_container_layer_ =
326 GetScreenRotationContainer(root_window_)->layer();
327 AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());
328}
329
330std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree(
wutao2c0ca182017-04-06 22:40:54331 std::unique_ptr<cc::CopyOutputResult> result) {
332 cc::TextureMailbox texture_mailbox;
333 std::unique_ptr<cc::SingleReleaseCallback> release_callback;
334 result->TakeTexture(&texture_mailbox, &release_callback);
335 DCHECK(texture_mailbox.IsTexture());
336
wutao6d394112017-04-20 02:17:35337 const gfx::Rect rect(screen_rotation_container_layer_->size());
wutao2c0ca182017-04-06 22:40:54338 std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>();
339 copy_layer->SetBounds(rect);
340 copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback),
341 rect.size());
wutao6d394112017-04-20 02:17:35342 return base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer));
wutao2c0ca182017-04-06 22:40:54343}
344
wutao6ddafa32017-03-18 03:10:08345void ScreenRotationAnimator::AnimateRotation(
346 std::unique_ptr<ScreenRotationRequest> rotation_request) {
wutao4a485532017-04-11 00:04:28347 screen_rotation_state_ = ROTATING;
wutao6d394112017-04-20 02:17:35348 const int rotation_factor = GetRotationFactor(rotation_request->old_rotation,
349 rotation_request->new_rotation);
wutao6ddafa32017-03-18 03:10:08350 const int old_layer_initial_rotation_degrees = GetInitialDegrees(
wutao6d394112017-04-20 02:17:35351 rotation_request->old_rotation, rotation_request->new_rotation);
bruthigaff7d0f2015-09-01 17:46:55352 const base::TimeDelta duration =
353 base::TimeDelta::FromMilliseconds(kRotationDurationInMs);
bruthigaff7d0f2015-09-01 17:46:55354 const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN;
wutao6d394112017-04-20 02:17:35355 const gfx::Rect rotated_screen_bounds = root_window_->GetTargetBounds();
bruthig37f9cad02015-03-12 22:28:50356 const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
357 rotated_screen_bounds.height() / 2);
358
wutao6d394112017-04-20 02:17:35359 ui::Layer* new_root_layer;
wutaob161bf22017-04-26 16:55:03360 if (!new_layer_tree_owner_ ||
361 has_switch_ash_disable_smooth_screen_rotation_) {
362 new_root_layer = screen_rotation_container_layer_;
363 } else {
wutao6d394112017-04-20 02:17:35364 new_root_layer = new_layer_tree_owner_->root();
365 // Add a black mask layer on top of |screen_rotation_container_layer_|.
366 black_mask_layer_owner_ = CreateBlackMaskLayerOwner(
367 gfx::Rect(screen_rotation_container_layer_->size()));
368 AddLayerBelowWindowLayer(root_window_, new_root_layer,
369 black_mask_layer_owner_->layer());
wutao6d394112017-04-20 02:17:35370 }
371
372 std::unique_ptr<ScreenRotationAnimation> new_layer_screen_rotation =
wutao33576082017-04-14 18:51:10373 base::MakeUnique<ScreenRotationAnimation>(
wutao6d394112017-04-20 02:17:35374 new_root_layer, kRotationDegrees * rotation_factor,
375 0 /* end_degrees */, new_root_layer->opacity(),
376 new_root_layer->opacity() /* target_opacity */, pivot, duration,
377 tween_type);
bruthig37f9cad02015-03-12 22:28:50378
wutao6d394112017-04-20 02:17:35379 ui::LayerAnimator* new_layer_animator = new_root_layer->GetAnimator();
380 new_layer_animator->set_preemption_strategy(
wutao33576082017-04-14 18:51:10381 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
wutao6d394112017-04-20 02:17:35382 std::unique_ptr<ui::LayerAnimationSequence> new_layer_animation_sequence =
wutao33576082017-04-14 18:51:10383 base::MakeUnique<ui::LayerAnimationSequence>(
wutao6d394112017-04-20 02:17:35384 std::move(new_layer_screen_rotation));
bruthig37f9cad02015-03-12 22:28:50385
wutao6d394112017-04-20 02:17:35386 ui::Layer* old_root_layer = old_layer_tree_owner_->root();
387 const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds();
bruthig37f9cad02015-03-12 22:28:50388 // The old layer will also be transformed into the new orientation. We will
389 // translate it so that the old layer's center point aligns with the new
390 // orientation's center point and use that center point as the pivot for the
391 // rotation animation.
392 gfx::Transform translate_transform;
393 translate_transform.Translate(
394 (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2,
395 (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2);
wutao6ddafa32017-03-18 03:10:08396 old_root_layer->SetTransform(translate_transform);
bruthig37f9cad02015-03-12 22:28:50397
wutao33576082017-04-14 18:51:10398 std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation =
ratsunnybd5087e2016-12-17 05:19:25399 base::MakeUnique<ScreenRotationAnimation>(
wutao6ddafa32017-03-18 03:10:08400 old_root_layer, old_layer_initial_rotation_degrees * rotation_factor,
bruthigaff7d0f2015-09-01 17:46:55401 (old_layer_initial_rotation_degrees - kRotationDegrees) *
402 rotation_factor,
wutao6ddafa32017-03-18 03:10:08403 old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration,
404 tween_type);
bruthig37f9cad02015-03-12 22:28:50405
wutao33576082017-04-14 18:51:10406 ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator();
407 old_layer_animator->set_preemption_strategy(
bruthig37f9cad02015-03-12 22:28:50408 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
wutao33576082017-04-14 18:51:10409 std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence =
410 base::MakeUnique<ui::LayerAnimationSequence>(
411 std::move(old_layer_screen_rotation));
wutao6d394112017-04-20 02:17:35412
wutao6ddafa32017-03-18 03:10:08413 // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to
414 // control the animation.
wutao6d394112017-04-20 02:17:35415 if (disable_animation_timers_for_test_) {
416 if (new_layer_tree_owner_)
417 new_layer_animator->set_disable_timer_for_test(true);
wutao33576082017-04-14 18:51:10418 old_layer_animator->set_disable_timer_for_test(true);
wutao6d394112017-04-20 02:17:35419 }
wutao33576082017-04-14 18:51:10420 old_layer_animation_sequence->SetAnimationMetricsReporter(
421 metrics_reporter_.get());
wutao33576082017-04-14 18:51:10422
wutao6d394112017-04-20 02:17:35423 // Add an observer so that the cloned/copied layers can be cleaned up with the
424 // animation completes/aborts.
425 ui::CallbackLayerAnimationObserver* observer =
426 new ui::CallbackLayerAnimationObserver(
427 base::Bind(&AnimationEndedCallback, weak_factory_.GetWeakPtr()));
428 if (new_layer_tree_owner_)
429 new_layer_animator->AddObserver(observer);
430 new_layer_animator->StartAnimation(new_layer_animation_sequence.release());
431 old_layer_animator->AddObserver(observer);
432 old_layer_animator->StartAnimation(old_layer_animation_sequence.release());
433 observer->SetActive();
bruthigf57a7bba2015-04-24 21:19:31434}
435
oshimaf84b0da722016-04-27 19:47:19436void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation,
437 display::Display::RotationSource source) {
wutao6d394112017-04-20 02:17:35438 // |rotation_request_id_| is used to skip stale requests. Before the layer
439 // CopyOutputResult callback called, there could have new rotation request.
440 // Increases |rotation_request_id_| for each new request and in the callback,
441 // we compare the |rotation_request.id| and |rotation_request_id_| to
442 // determine the stale status.
wutao88733df2017-04-13 19:39:06443 rotation_request_id_++;
wutao6ddafa32017-03-18 03:10:08444 std::unique_ptr<ScreenRotationRequest> rotation_request =
wutao88733df2017-04-13 19:39:06445 base::MakeUnique<ScreenRotationRequest>(rotation_request_id_,
446 new_rotation, source);
wutao4a485532017-04-11 00:04:28447 switch (screen_rotation_state_) {
448 case IDLE:
wutao88733df2017-04-13 19:39:06449 case COPY_REQUESTED:
wutao4a485532017-04-11 00:04:28450 StartRotationAnimation(std::move(rotation_request));
451 break;
452 case ROTATING:
453 last_pending_request_ = std::move(rotation_request);
454 // The pending request will be processed when the
wutao6d394112017-04-20 02:17:35455 // |AnimationEndedCallback()| should be called after |StopAnimating()|.
wutao4a485532017-04-11 00:04:28456 StopAnimating();
457 break;
wutao6ddafa32017-03-18 03:10:08458 }
459}
460
461void ScreenRotationAnimator::AddScreenRotationAnimatorObserver(
462 ScreenRotationAnimatorObserver* observer) {
463 screen_rotation_animator_observers_.AddObserver(observer);
464}
465
466void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver(
467 ScreenRotationAnimatorObserver* observer) {
468 screen_rotation_animator_observers_.RemoveObserver(observer);
469}
470
wutao6ddafa32017-03-18 03:10:08471void ScreenRotationAnimator::ProcessAnimationQueue() {
wutao4a485532017-04-11 00:04:28472 screen_rotation_state_ = IDLE;
wutao6d394112017-04-20 02:17:35473 if (IsDisplayIdValid(display_id_) && black_mask_layer_owner_)
474 root_window_->layer()->Remove(black_mask_layer_owner_->layer());
wutao6ddafa32017-03-18 03:10:08475 old_layer_tree_owner_.reset();
wutao6d394112017-04-20 02:17:35476 new_layer_tree_owner_.reset();
477 black_mask_layer_owner_.reset();
wutao6ddafa32017-03-18 03:10:08478 if (last_pending_request_ && IsDisplayIdValid(display_id_)) {
wutao6d394112017-04-20 02:17:35479 StartRotationAnimation(std::move(last_pending_request_));
wutao6ddafa32017-03-18 03:10:08480 return;
481 }
482
wutao6d394112017-04-20 02:17:35483 // This is only used in test to notify animator observer.
wutao6ddafa32017-03-18 03:10:08484 for (auto& observer : screen_rotation_animator_observers_)
485 observer.OnScreenRotationAnimationFinished(this);
486}
487
wutao6ddafa32017-03-18 03:10:08488void ScreenRotationAnimator::StopAnimating() {
wutao6d394112017-04-20 02:17:35489 // |old_layer_tree_owner_| new_layer_tree_owner_| could be nullptr if another
490 // the rotation request comes before the copy request finished.
wutao33576082017-04-14 18:51:10491 if (old_layer_tree_owner_)
492 old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
wutao6d394112017-04-20 02:17:35493 if (new_layer_tree_owner_)
494 new_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
495 if (IsDisplayIdValid(display_id_) && black_mask_layer_owner_)
496 root_window_->layer()->Remove(black_mask_layer_owner_->layer());
bruthig37f9cad02015-03-12 22:28:50497}
498
499} // namespace ash