screen_rotation_animator.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  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
  3. // found in the LICENSE file.
  4. #include "ash/rotator/screen_rotation_animator.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "ash/public/cpp/metrics_util.h"
  8. #include "ash/public/cpp/shell_window_ids.h"
  9. #include "ash/rotator/screen_rotation_animation.h"
  10. #include "ash/rotator/screen_rotation_animator_observer.h"
  11. #include "ash/shell.h"
  12. #include "ash/utility/layer_util.h"
  13. #include "ash/utility/transformer_util.h"
  14. #include "base/bind.h"
  15. #include "base/command_line.h"
  16. #include "base/metrics/histogram_macros.h"
  17. #include "base/threading/sequenced_task_runner_handle.h"
  18. #include "base/time/time.h"
  19. #include "components/viz/common/frame_sinks/copy_output_request.h"
  20. #include "components/viz/common/frame_sinks/copy_output_result.h"
  21. #include "ui/aura/window.h"
  22. #include "ui/base/class_property.h"
  23. #include "ui/compositor/animation_throughput_reporter.h"
  24. #include "ui/compositor/callback_layer_animation_observer.h"
  25. #include "ui/compositor/compositor.h"
  26. #include "ui/compositor/layer.h"
  27. #include "ui/compositor/layer_animation_element.h"
  28. #include "ui/compositor/layer_animation_sequence.h"
  29. #include "ui/compositor/layer_animator.h"
  30. #include "ui/compositor/layer_owner.h"
  31. #include "ui/compositor/layer_tree_owner.h"
  32. #include "ui/compositor/scoped_animation_duration_scale_mode.h"
  33. #include "ui/display/display.h"
  34. #include "ui/display/manager/display_manager.h"
  35. #include "ui/display/manager/managed_display_info.h"
  36. #include "ui/display/screen.h"
  37. #include "ui/gfx/animation/tween.h"
  38. #include "ui/gfx/geometry/point.h"
  39. #include "ui/gfx/geometry/rect.h"
  40. #include "ui/gfx/geometry/size_f.h"
  41. #include "ui/gfx/geometry/transform.h"
  42. #include "ui/gfx/geometry/transform_util.h"
  43. #include "ui/wm/core/window_util.h"
  44. DEFINE_UI_CLASS_PROPERTY_TYPE(ash::ScreenRotationAnimator*)
  45. namespace ash {
  46. namespace {
  47. // The number of degrees that the rotation animations animate through.
  48. const int kRotationDegrees = 20;
  49. // The time it takes for the rotation animations to run.
  50. const int kRotationDurationInMs = 250;
  51. // The rotation factors.
  52. const int kCounterClockWiseRotationFactor = 1;
  53. const int kClockWiseRotationFactor = -1;
  54. constexpr char kRotationAnimationSmoothness[] =
  55. "Ash.Rotation.AnimationSmoothness";
  56. // A property key to store the ScreenRotationAnimator of the window; Used for
  57. // screen rotation.
  58. DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(ScreenRotationAnimator,
  59. kScreenRotationAnimatorKey,
  60. nullptr)
  61. display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) {
  62. return Shell::Get()
  63. ->display_manager()
  64. ->GetDisplayInfo(display_id)
  65. .GetActiveRotation();
  66. }
  67. // 180 degree rotations should animate clock-wise.
  68. int GetRotationFactor(display::Display::Rotation initial_rotation,
  69. display::Display::Rotation new_rotation) {
  70. return (initial_rotation + 3) % 4 == new_rotation
  71. ? kCounterClockWiseRotationFactor
  72. : kClockWiseRotationFactor;
  73. }
  74. aura::Window* GetScreenRotationContainer(aura::Window* root_window) {
  75. return root_window->GetChildById(kShellWindowId_ScreenAnimationContainer);
  76. }
  77. // Returns true if the rotation between |initial_rotation| and |new_rotation| is
  78. // 180 degrees.
  79. bool Is180DegreeFlip(display::Display::Rotation initial_rotation,
  80. display::Display::Rotation new_rotation) {
  81. return (initial_rotation + 2) % 4 == new_rotation;
  82. }
  83. // Returns the initial degrees the old layer animation to begin with.
  84. int GetInitialDegrees(display::Display::Rotation initial_rotation,
  85. display::Display::Rotation new_rotation) {
  86. return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90);
  87. }
  88. void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) {
  89. // Add the cloned/copied layer tree into the root, so it will be rendered.
  90. root_window->layer()->Add(layer);
  91. root_window->layer()->StackAtTop(layer);
  92. }
  93. void AddLayerBelowWindowLayer(aura::Window* root_window,
  94. ui::Layer* top_layer,
  95. ui::Layer* layer) {
  96. // Add the cloned/copied layer tree into the root, so it will be rendered.
  97. root_window->layer()->Add(layer);
  98. root_window->layer()->StackBelow(layer, top_layer);
  99. }
  100. // The Callback will be invoked when all animation sequences have
  101. // finished. |observer| will be destroyed after invoking the Callback if it
  102. // returns true.
  103. bool AnimationEndedCallback(
  104. base::WeakPtr<ScreenRotationAnimator> animator,
  105. const ui::CallbackLayerAnimationObserver& observer) {
  106. if (animator)
  107. animator->ProcessAnimationQueue();
  108. return true;
  109. }
  110. // Creates a Transform for the old layer in screen rotation animation.
  111. gfx::Transform CreateScreenRotationOldLayerTransformForDisplay(
  112. display::Display::Rotation old_rotation,
  113. display::Display::Rotation new_rotation,
  114. const display::Display& display) {
  115. gfx::Transform inverse;
  116. CHECK(CreateRotationTransform(old_rotation, new_rotation,
  117. gfx::SizeF(display.size()))
  118. .GetInverse(&inverse));
  119. return inverse;
  120. }
  121. // The |request_id| changed since last copy request, which means a
  122. // new rotation stated, we need to ignore this copy result.
  123. bool IgnoreCopyResult(int64_t request_id, int64_t current_request_id) {
  124. DCHECK(request_id <= current_request_id);
  125. return request_id < current_request_id;
  126. }
  127. bool RootWindowChangedForDisplayId(aura::Window* root_window,
  128. int64_t display_id) {
  129. return root_window != Shell::GetRootWindowForDisplayId(display_id);
  130. }
  131. // Creates a mask layer and returns the |mask_layer_tree_owner|.
  132. std::unique_ptr<ui::LayerTreeOwner> CreateMaskLayerTreeOwner(
  133. const gfx::Rect& rect) {
  134. std::unique_ptr<ui::Layer> mask_layer =
  135. std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR);
  136. mask_layer->SetBounds(rect);
  137. mask_layer->SetColor(SK_ColorBLACK);
  138. return std::make_unique<ui::LayerTreeOwner>(std::move(mask_layer));
  139. }
  140. } // namespace
  141. // static
  142. ScreenRotationAnimator* ScreenRotationAnimator::GetForRootWindow(
  143. aura::Window* root_window) {
  144. auto* animator = root_window->GetProperty(kScreenRotationAnimatorKey);
  145. if (!animator) {
  146. animator = new ScreenRotationAnimator(root_window);
  147. root_window->SetProperty(kScreenRotationAnimatorKey, animator);
  148. }
  149. return animator;
  150. }
  151. // static
  152. void ScreenRotationAnimator::SetScreenRotationAnimatorForTest(
  153. aura::Window* root_window,
  154. std::unique_ptr<ScreenRotationAnimator> animator) {
  155. root_window->SetProperty(kScreenRotationAnimatorKey, std::move(animator));
  156. }
  157. ScreenRotationAnimator::ScreenRotationAnimator(aura::Window* root_window)
  158. : root_window_(root_window),
  159. screen_rotation_state_(IDLE),
  160. rotation_request_id_(0),
  161. disable_animation_timers_for_test_(false) {}
  162. ScreenRotationAnimator::~ScreenRotationAnimator() {
  163. // To prevent a call to |AnimationEndedCallback()| from calling a method on
  164. // the |animator_|.
  165. weak_factory_.InvalidateWeakPtrs();
  166. }
  167. void ScreenRotationAnimator::StartRotationAnimation(
  168. std::unique_ptr<ScreenRotationRequest> rotation_request) {
  169. const display::Display::Rotation current_rotation =
  170. GetCurrentScreenRotation(rotation_request->display_id);
  171. if (current_rotation == rotation_request->new_rotation) {
  172. // We need to call |ProcessAnimationQueue()| to prepare for next rotation
  173. // request.
  174. ProcessAnimationQueue();
  175. return;
  176. }
  177. rotation_request->old_rotation = current_rotation;
  178. if (DisplayConfigurationController::ANIMATION_SYNC ==
  179. rotation_request->mode) {
  180. StartSlowAnimation(std::move(rotation_request));
  181. } else {
  182. current_async_rotation_request_ = ScreenRotationRequest(*rotation_request);
  183. RequestCopyScreenRotationContainerLayer(
  184. std::make_unique<viz::CopyOutputRequest>(
  185. viz::CopyOutputRequest::ResultFormat::RGBA,
  186. viz::CopyOutputRequest::ResultDestination::kNativeTextures,
  187. CreateAfterCopyCallbackBeforeRotation(
  188. std::move(rotation_request))));
  189. screen_rotation_state_ = COPY_REQUESTED;
  190. }
  191. }
  192. void ScreenRotationAnimator::StartSlowAnimation(
  193. std::unique_ptr<ScreenRotationRequest> rotation_request) {
  194. CreateOldLayerTreeForSlowAnimation();
  195. SetRotation(rotation_request->display_id, rotation_request->old_rotation,
  196. rotation_request->new_rotation, rotation_request->source);
  197. AnimateRotation(std::move(rotation_request));
  198. }
  199. void ScreenRotationAnimator::SetRotation(
  200. int64_t display_id,
  201. display::Display::Rotation old_rotation,
  202. display::Display::Rotation new_rotation,
  203. display::Display::RotationSource source) {
  204. // Reset the current request because its rotation must be applied if any.
  205. current_async_rotation_request_.reset();
  206. // Allow compositor locks to extend timeout, so that screen rotation only
  207. // takes output copy after contents are properlly resized, such as wallpaper
  208. // and ARC apps.
  209. ui::Compositor* compositor = root_window_->layer()->GetCompositor();
  210. compositor->SetAllowLocksToExtendTimeout(true);
  211. Shell::Get()->display_manager()->SetDisplayRotation(display_id, new_rotation,
  212. source);
  213. compositor->SetAllowLocksToExtendTimeout(false);
  214. const display::Display display =
  215. Shell::Get()->display_manager()->GetDisplayForId(display_id);
  216. old_layer_tree_owner_->root()->SetTransform(
  217. CreateScreenRotationOldLayerTransformForDisplay(old_rotation,
  218. new_rotation, display));
  219. }
  220. void ScreenRotationAnimator::RequestCopyScreenRotationContainerLayer(
  221. std::unique_ptr<viz::CopyOutputRequest> copy_output_request) {
  222. ui::Layer* screen_rotation_container_layer =
  223. GetScreenRotationContainer(root_window_)->layer();
  224. copy_output_request->set_area(
  225. gfx::Rect(screen_rotation_container_layer->size()));
  226. copy_output_request->set_result_task_runner(
  227. base::SequencedTaskRunnerHandle::Get());
  228. screen_rotation_container_layer->RequestCopyOfOutput(
  229. std::move(copy_output_request));
  230. }
  231. ScreenRotationAnimator::CopyCallback
  232. ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation(
  233. std::unique_ptr<ScreenRotationRequest> rotation_request) {
  234. return base::BindOnce(&ScreenRotationAnimator::
  235. OnScreenRotationContainerLayerCopiedBeforeRotation,
  236. weak_factory_.GetWeakPtr(),
  237. std::move(rotation_request));
  238. }
  239. ScreenRotationAnimator::CopyCallback
  240. ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation(
  241. std::unique_ptr<ScreenRotationRequest> rotation_request) {
  242. return base::BindOnce(&ScreenRotationAnimator::
  243. OnScreenRotationContainerLayerCopiedAfterRotation,
  244. weak_factory_.GetWeakPtr(),
  245. std::move(rotation_request));
  246. }
  247. void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation(
  248. std::unique_ptr<ScreenRotationRequest> rotation_request,
  249. std::unique_ptr<viz::CopyOutputResult> result) {
  250. if (IgnoreCopyResult(rotation_request->id, rotation_request_id_))
  251. return;
  252. // Abort rotation and animation if the display was removed or the
  253. // |root_window| was changed for |display_id|.
  254. if (RootWindowChangedForDisplayId(root_window_,
  255. rotation_request->display_id)) {
  256. ProcessAnimationQueue();
  257. return;
  258. }
  259. // Abort animation and set the rotation to target rotation when the copy
  260. // request has been canceled or failed. It would fail if, for examples: a) The
  261. // layer is removed from the compositor and destroyed before committing the
  262. // request to the compositor. b) The compositor is shutdown.
  263. if (result->IsEmpty()) {
  264. Shell::Get()->display_manager()->SetDisplayRotation(
  265. rotation_request->display_id, rotation_request->new_rotation,
  266. rotation_request->source);
  267. ProcessAnimationQueue();
  268. return;
  269. }
  270. old_layer_tree_owner_ = CopyLayerTree(std::move(result));
  271. AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());
  272. // TODO(oshima): We need a better way to control animation and other
  273. // activities during system wide animation.
  274. animation_scale_mode_ =
  275. std::make_unique<ui::ScopedAnimationDurationScaleMode>(
  276. ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
  277. for (auto& observer : screen_rotation_animator_observers_)
  278. observer.OnScreenCopiedBeforeRotation();
  279. SetRotation(rotation_request->display_id, rotation_request->old_rotation,
  280. rotation_request->new_rotation, rotation_request->source);
  281. RequestCopyScreenRotationContainerLayer(
  282. std::make_unique<viz::CopyOutputRequest>(
  283. viz::CopyOutputRequest::ResultFormat::RGBA,
  284. viz::CopyOutputRequest::ResultDestination::kNativeTextures,
  285. CreateAfterCopyCallbackAfterRotation(std::move(rotation_request))));
  286. }
  287. void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation(
  288. std::unique_ptr<ScreenRotationRequest> rotation_request,
  289. std::unique_ptr<viz::CopyOutputResult> result) {
  290. animation_scale_mode_.reset();
  291. if (IgnoreCopyResult(rotation_request->id, rotation_request_id_)) {
  292. NotifyAnimationFinished(/*canceled=*/true);
  293. return;
  294. }
  295. // In the following cases, abort animation:
  296. // 1) if the display was removed,
  297. // 2) if the |root_window| was changed for |display_id|,
  298. // 3) the copy request has been canceled or failed. It would fail if,
  299. // for examples: a) The layer is removed from the compositor and destroyed
  300. // before committing the request to the compositor. b) The compositor is
  301. // shutdown.
  302. if (RootWindowChangedForDisplayId(root_window_,
  303. rotation_request->display_id) ||
  304. result->IsEmpty()) {
  305. ProcessAnimationQueue();
  306. return;
  307. }
  308. new_layer_tree_owner_ = CopyLayerTree(std::move(result));
  309. AddLayerBelowWindowLayer(root_window_, old_layer_tree_owner_->root(),
  310. new_layer_tree_owner_->root());
  311. AnimateRotation(std::move(rotation_request));
  312. }
  313. void ScreenRotationAnimator::CreateOldLayerTreeForSlowAnimation() {
  314. old_layer_tree_owner_ = ::wm::RecreateLayers(root_window_);
  315. AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());
  316. }
  317. std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree(
  318. std::unique_ptr<viz::CopyOutputResult> result) {
  319. gfx::Size layer_size =
  320. GetScreenRotationContainer(root_window_)->layer()->size();
  321. std::unique_ptr<ui::Layer> copy_layer =
  322. CreateLayerFromCopyOutputResult(std::move(result), layer_size);
  323. DCHECK_EQ(copy_layer->size(),
  324. GetScreenRotationContainer(root_window_)->layer()->size());
  325. // TODO(crbug.com/1040279): This is a workaround and should be removed once
  326. // the issue is fixed.
  327. copy_layer->SetFillsBoundsOpaquely(false);
  328. return std::make_unique<ui::LayerTreeOwner>(std::move(copy_layer));
  329. }
  330. void ScreenRotationAnimator::AnimateRotation(
  331. std::unique_ptr<ScreenRotationRequest> rotation_request) {
  332. screen_rotation_state_ = ROTATING;
  333. const int rotation_factor = GetRotationFactor(rotation_request->old_rotation,
  334. rotation_request->new_rotation);
  335. const int old_layer_initial_rotation_degrees = GetInitialDegrees(
  336. rotation_request->old_rotation, rotation_request->new_rotation);
  337. const base::TimeDelta duration = base::Milliseconds(kRotationDurationInMs);
  338. const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN;
  339. const gfx::Rect rotated_screen_bounds = root_window_->GetTargetBounds();
  340. const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
  341. rotated_screen_bounds.height() / 2);
  342. ui::Layer* screen_rotation_container_layer =
  343. GetScreenRotationContainer(root_window_)->layer();
  344. ui::Layer* new_root_layer;
  345. if (!new_layer_tree_owner_) {
  346. new_root_layer = screen_rotation_container_layer;
  347. } else {
  348. new_root_layer = new_layer_tree_owner_->root();
  349. // Add a black mask layer on top of |screen_rotation_container_layer|.
  350. mask_layer_tree_owner_ = CreateMaskLayerTreeOwner(
  351. gfx::Rect(screen_rotation_container_layer->size()));
  352. AddLayerBelowWindowLayer(root_window_, new_root_layer,
  353. mask_layer_tree_owner_->root());
  354. }
  355. std::unique_ptr<ScreenRotationAnimation> new_layer_screen_rotation =
  356. std::make_unique<ScreenRotationAnimation>(
  357. new_root_layer, kRotationDegrees * rotation_factor,
  358. 0 /* end_degrees */, new_root_layer->opacity(),
  359. new_root_layer->opacity() /* target_opacity */, pivot, duration,
  360. tween_type);
  361. ui::LayerAnimator* new_layer_animator = new_root_layer->GetAnimator();
  362. new_layer_animator->set_preemption_strategy(
  363. ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
  364. std::unique_ptr<ui::LayerAnimationSequence> new_layer_animation_sequence =
  365. std::make_unique<ui::LayerAnimationSequence>(
  366. std::move(new_layer_screen_rotation));
  367. ui::Layer* old_root_layer = old_layer_tree_owner_->root();
  368. const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds();
  369. // The old layer will also be transformed into the new orientation. We will
  370. // translate it so that the old layer's center point aligns with the new
  371. // orientation's center point and use that center point as the pivot for the
  372. // rotation animation.
  373. gfx::Transform translate_transform;
  374. translate_transform.Translate(
  375. (rotated_screen_bounds.width() - original_screen_bounds.width()) / 2,
  376. (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2);
  377. old_root_layer->SetTransform(translate_transform);
  378. std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation =
  379. std::make_unique<ScreenRotationAnimation>(
  380. old_root_layer, old_layer_initial_rotation_degrees * rotation_factor,
  381. (old_layer_initial_rotation_degrees - kRotationDegrees) *
  382. rotation_factor,
  383. old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration,
  384. tween_type);
  385. ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator();
  386. old_layer_animator->set_preemption_strategy(
  387. ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
  388. std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence =
  389. std::make_unique<ui::LayerAnimationSequence>(
  390. std::move(old_layer_screen_rotation));
  391. // In unit tests, we can use ash::ScreenRotationAnimatorTestApi to control the
  392. // animation.
  393. if (disable_animation_timers_for_test_) {
  394. if (new_layer_tree_owner_)
  395. new_layer_animator->set_disable_timer_for_test(true);
  396. old_layer_animator->set_disable_timer_for_test(true);
  397. }
  398. ui::AnimationThroughputReporter reporter(
  399. old_layer_animator,
  400. metrics_util::ForSmoothness(base::BindRepeating([](int smoothness) {
  401. UMA_HISTOGRAM_PERCENTAGE(kRotationAnimationSmoothness, smoothness);
  402. })));
  403. // Add an observer so that the cloned/copied layers can be cleaned up with the
  404. // animation completes/aborts.
  405. ui::CallbackLayerAnimationObserver* observer =
  406. new ui::CallbackLayerAnimationObserver(base::BindRepeating(
  407. &AnimationEndedCallback, weak_factory_.GetWeakPtr()));
  408. if (new_layer_tree_owner_)
  409. new_layer_animation_sequence->AddObserver(observer);
  410. new_layer_animator->StartAnimation(new_layer_animation_sequence.release());
  411. old_layer_animation_sequence->AddObserver(observer);
  412. old_layer_animator->StartAnimation(old_layer_animation_sequence.release());
  413. observer->SetActive();
  414. }
  415. void ScreenRotationAnimator::Rotate(
  416. display::Display::Rotation new_rotation,
  417. display::Display::RotationSource source,
  418. DisplayConfigurationController::RotationAnimation mode) {
  419. // |rotation_request_id_| is used to skip stale requests. Before the layer
  420. // CopyOutputResult callback called, there could have new rotation request.
  421. // Increases |rotation_request_id_| for each new request and in the callback,
  422. // we compare the |rotation_request.id| and |rotation_request_id_| to
  423. // determine the stale status.
  424. rotation_request_id_++;
  425. const int64_t display_id =
  426. display::Screen::GetScreen()->GetDisplayNearestWindow(root_window_).id();
  427. std::unique_ptr<ScreenRotationRequest> rotation_request =
  428. std::make_unique<ScreenRotationRequest>(rotation_request_id_, display_id,
  429. new_rotation, source, mode);
  430. target_rotation_ = new_rotation;
  431. if (mode == DisplayConfigurationController::ANIMATION_SYNC)
  432. current_async_rotation_request_.reset();
  433. switch (screen_rotation_state_) {
  434. case IDLE:
  435. DCHECK(!current_async_rotation_request_);
  436. [[fallthrough]];
  437. case COPY_REQUESTED:
  438. if (current_async_rotation_request_ &&
  439. !RootWindowChangedForDisplayId(
  440. root_window_, current_async_rotation_request_->display_id)) {
  441. Shell::Get()->display_manager()->SetDisplayRotation(
  442. current_async_rotation_request_->display_id,
  443. current_async_rotation_request_->new_rotation,
  444. current_async_rotation_request_->source);
  445. current_async_rotation_request_.reset();
  446. }
  447. StartRotationAnimation(std::move(rotation_request));
  448. break;
  449. case ROTATING:
  450. last_pending_request_ = std::move(rotation_request);
  451. // The pending request will be processed when the
  452. // |AnimationEndedCallback()| should be called after |StopAnimating()|.
  453. StopAnimating();
  454. break;
  455. }
  456. }
  457. void ScreenRotationAnimator::AddObserver(
  458. ScreenRotationAnimatorObserver* observer) {
  459. screen_rotation_animator_observers_.AddObserver(observer);
  460. }
  461. void ScreenRotationAnimator::RemoveObserver(
  462. ScreenRotationAnimatorObserver* observer) {
  463. screen_rotation_animator_observers_.RemoveObserver(observer);
  464. }
  465. void ScreenRotationAnimator::ProcessAnimationQueue() {
  466. screen_rotation_state_ = IDLE;
  467. old_layer_tree_owner_.reset();
  468. new_layer_tree_owner_.reset();
  469. mask_layer_tree_owner_.reset();
  470. current_async_rotation_request_.reset();
  471. if (last_pending_request_ &&
  472. !RootWindowChangedForDisplayId(root_window_,
  473. last_pending_request_->display_id)) {
  474. StartRotationAnimation(std::move(last_pending_request_));
  475. return;
  476. }
  477. NotifyAnimationFinished(/*canceled=*/false);
  478. }
  479. bool ScreenRotationAnimator::IsRotating() const {
  480. return screen_rotation_state_ != IDLE;
  481. }
  482. display::Display::Rotation ScreenRotationAnimator::GetTargetRotation() const {
  483. return target_rotation_;
  484. }
  485. void ScreenRotationAnimator::StopAnimating() {
  486. // |old_layer_tree_owner_| new_layer_tree_owner_| could be nullptr if another
  487. // the rotation request comes before the copy request finished.
  488. if (old_layer_tree_owner_)
  489. old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
  490. if (new_layer_tree_owner_)
  491. new_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
  492. mask_layer_tree_owner_.reset();
  493. }
  494. void ScreenRotationAnimator::NotifyAnimationFinished(bool canceled) {
  495. for (auto& observer : screen_rotation_animator_observers_)
  496. observer.OnScreenRotationAnimationFinished(this, canceled);
  497. }
  498. } // namespace ash