Chromium Code Reviews| Index: ash/rotator/screen_rotation_animator.cc |
| diff --git a/ash/rotator/screen_rotation_animator.cc b/ash/rotator/screen_rotation_animator.cc |
| index 05e48f879fdda24920c895cb2c5292da333d2f5b..ddfb4caac459c570a8b0f5afa171ab50c34de882 100644 |
| --- a/ash/rotator/screen_rotation_animator.cc |
| +++ b/ash/rotator/screen_rotation_animator.cc |
| @@ -4,16 +4,13 @@ |
| #include "ash/rotator/screen_rotation_animator.h" |
| -#include <string> |
| -#include <utility> |
| -#include <vector> |
| - |
| #include "ash/ash_switches.h" |
| #include "ash/display/window_tree_host_manager.h" |
| #include "ash/public/cpp/shell_window_ids.h" |
| #include "ash/rotator/screen_rotation_animation.h" |
| #include "ash/rotator/screen_rotation_animator_observer.h" |
| #include "ash/shell.h" |
| +#include "ash/utility/transformer_util.h" |
| #include "base/command_line.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/metrics/histogram_macros.h" |
| @@ -21,9 +18,9 @@ |
| #include "cc/output/copy_output_request.h" |
| #include "cc/output/copy_output_result.h" |
| #include "ui/aura/window.h" |
| +#include "ui/compositor/callback_layer_animation_observer.h" |
| #include "ui/compositor/layer.h" |
| #include "ui/compositor/layer_animation_element.h" |
| -#include "ui/compositor/layer_animation_observer.h" |
| #include "ui/compositor/layer_animation_sequence.h" |
| #include "ui/compositor/layer_animator.h" |
| #include "ui/compositor/layer_owner.h" |
| @@ -77,6 +74,11 @@ aura::Window* GetRootWindow(int64_t display_id) { |
| display_id); |
| } |
| +aura::Window* GetScreenRotationContainer(int64_t display_id) { |
| + return GetRootWindow(display_id) |
| + ->GetChildById(kShellWindowId_ScreenRotationContainer); |
| +} |
| + |
| // Returns true if the rotation between |initial_rotation| and |new_rotation| is |
| // 180 degrees. |
| bool Is180DegreeFlip(display::Display::Rotation initial_rotation, |
| @@ -90,78 +92,49 @@ int GetInitialDegrees(display::Display::Rotation initial_rotation, |
| return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); |
| } |
| -// A LayerAnimationObserver that will destroy the contained LayerTreeOwner |
| -// when notified that a layer animation has ended or was aborted. |
| -class LayerCleanupObserver : public ui::LayerAnimationObserver { |
| - public: |
| - // Takes WeakPtr of ScreenRotationAnimator. |this| may outlive the |animator_| |
| - // instance and the |animator_| isn't detaching itself as an observer when |
| - // being destroyed. However, ideally, when |animator_| is destroying, |
| - // deleting |old_layer_tree_owner_| will trigger OnLayerAnimationAborted and |
| - // delete |this| before |animator_| deleted. |
| - explicit LayerCleanupObserver(base::WeakPtr<ScreenRotationAnimator> animator); |
| - ~LayerCleanupObserver() override; |
| - |
| - // ui::LayerAnimationObserver: |
| - void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override; |
| - void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override; |
| - void OnLayerAnimationScheduled( |
| - ui::LayerAnimationSequence* sequence) override {} |
| - |
| - protected: |
| - // ui::LayerAnimationObserver: |
| - bool RequiresNotificationWhenAnimatorDestroyed() const override { |
| - return true; |
| - } |
| - void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override; |
| - void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override; |
| - |
| - private: |
| - base::WeakPtr<ScreenRotationAnimator> animator_; |
| - |
| - // The LayerAnimationSequence that |this| has been attached to. Defaults to |
| - // nullptr. |
| - ui::LayerAnimationSequence* sequence_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(LayerCleanupObserver); |
| -}; |
| - |
| -LayerCleanupObserver::LayerCleanupObserver( |
| - base::WeakPtr<ScreenRotationAnimator> animator) |
| - : animator_(animator), sequence_(nullptr) {} |
| - |
| -LayerCleanupObserver::~LayerCleanupObserver() { |
| - // We must eplicitly detach from |sequence_| because we return true from |
| - // RequiresNotificationWhenAnimatorDestroyed. |
| - if (sequence_) |
| - sequence_->RemoveObserver(this); |
| +void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) { |
| + // Add the cloned/copied layer tree into the root, so it will be rendered. |
| + root_window->layer()->Add(layer); |
| + root_window->layer()->StackAtTop(layer); |
| } |
| -void LayerCleanupObserver::OnLayerAnimationEnded( |
| - ui::LayerAnimationSequence* sequence) { |
| - if (animator_) |
| - animator_->ProcessAnimationQueue(); |
| - |
| - delete this; |
| +// The Callback will be invoked when all animation sequences have |
| +// finished. |observer| will be destroyed after invoking the Callback if it |
| +// returns true. |
| +bool AnimationEndedCallback( |
| + base::WeakPtr<ScreenRotationAnimator> animator, |
| + const ui::CallbackLayerAnimationObserver& observer) { |
| + if (animator) |
| + animator->ProcessAnimationQueue(); |
| + return true; |
| } |
| -void LayerCleanupObserver::OnLayerAnimationAborted( |
| - ui::LayerAnimationSequence* sequence) { |
| - if (animator_) |
| - animator_->ProcessAnimationQueue(); |
| - |
| - delete this; |
| +// Creates a Transform for the old layer in screen rotation animation. |
| +gfx::Transform CreateScreenRotationOldLayerTransformForDisplay( |
| + display::Display::Rotation new_rotation, |
| + display::Display::Rotation old_rotation, |
| + const display::Display& display) { |
| + gfx::Transform inverse; |
| + CHECK(CreateRotationTransform(old_rotation, new_rotation, display) |
| + .GetInverse(&inverse)); |
| + return inverse; |
| } |
| -void LayerCleanupObserver::OnAttachedToSequence( |
| - ui::LayerAnimationSequence* sequence) { |
| - sequence_ = sequence; |
| +// The |request_id| changed since last copy request, which means a |
| +// new rotation stated, we need to ignore this copy result. |
| +bool IgnoreCopyResult(int64_t request_id, int64_t current_request_id) { |
| + DCHECK(request_id <= current_request_id); |
| + return request_id < current_request_id; |
| } |
| -void LayerCleanupObserver::OnDetachedFromSequence( |
| - ui::LayerAnimationSequence* sequence) { |
| - DCHECK_EQ(sequence, sequence_); |
| - sequence_ = nullptr; |
| +// In the following cases, abort rotation: |
| +// 1) if the display was removed, |
| +// 2) the copy request has been canceled or failed. It would fail if, |
| +// for examples: a) The layer is removed from the compositor and destroye |
| +// before committing the request to the compositor. b) The compositor is |
| +// shutdown. |
| +bool AbortRotation(int64_t display_id, cc::CopyOutputResult* result) { |
| + return !IsDisplayIdValid(display_id) || result->IsEmpty(); |
| } |
| class ScreenRotationAnimationMetricsReporter |
| @@ -187,6 +160,10 @@ ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) |
| metrics_reporter_( |
| base::MakeUnique<ScreenRotationAnimationMetricsReporter>()), |
| disable_animation_timers_for_test_(false), |
| + has_switch_ash_enable_smooth_screen_rotation_(false), |
| + screen_rotation_container_layer_( |
| + GetScreenRotationContainer(display_id_)->layer()), |
|
oshima
2017/04/14 04:54:26
use root_window_ to get the rotation container.
wutao
2017/04/14 07:48:28
Done.
|
| + root_window_(GetRootWindow(display_id_)), |
| weak_factory_(this) {} |
| ScreenRotationAnimator::~ScreenRotationAnimator() { |
| @@ -203,133 +180,159 @@ ScreenRotationAnimator::~ScreenRotationAnimator() { |
| void ScreenRotationAnimator::StartRotationAnimation( |
| std::unique_ptr<ScreenRotationRequest> rotation_request) { |
| - if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| - switches::kAshEnableSmoothScreenRotation)) { |
| - RequestCopyRootLayerAndAnimateRotation(std::move(rotation_request)); |
| + if (has_switch_ash_enable_smooth_screen_rotation_) { |
| + std::unique_ptr<cc::CopyOutputRequest> copy_output_request = |
| + cc::CopyOutputRequest::CreateRequest( |
| + CreateAfterCopyCallbackBeforeRotation(std::move(rotation_request))); |
| + RequestCopyScreenRotationContainerLayer(std::move(copy_output_request)); |
| + screen_rotation_state_ = COPY_REQUESTED; |
| } else { |
| - CreateOldLayerTree(); |
| - AnimateRotation(std::move(rotation_request)); |
| + StartSlowAnimation(std::move(rotation_request)); |
| } |
| } |
| -void ScreenRotationAnimator::RequestCopyRootLayerAndAnimateRotation( |
| +void ScreenRotationAnimator::StartSlowAnimation( |
| std::unique_ptr<ScreenRotationRequest> rotation_request) { |
| - std::unique_ptr<cc::CopyOutputRequest> copy_output_request = |
| - cc::CopyOutputRequest::CreateRequest( |
| - CreateAfterCopyCallback(std::move(rotation_request))); |
| - ui::Layer* layer = GetRootWindow(display_id_)->layer(); |
| - copy_output_request->set_area(gfx::Rect(layer->size())); |
| - layer->RequestCopyOfOutput(std::move(copy_output_request)); |
| + CreateOldLayerTree(); |
| + SetRotation(rotation_request->new_rotation, rotation_request->old_rotation, |
| + rotation_request->source); |
| + AnimateRotation(std::move(rotation_request)); |
| +} |
| + |
| +void ScreenRotationAnimator::SetRotation( |
| + display::Display::Rotation new_rotation, |
| + display::Display::Rotation old_rotation, |
| + display::Display::RotationSource source) { |
| + Shell::Get()->display_manager()->SetDisplayRotation(display_id_, new_rotation, |
| + source); |
| + const display::Display display = |
| + Shell::Get()->display_manager()->GetDisplayForId(display_id_); |
| + old_layer_tree_owner_->root()->SetTransform( |
| + CreateScreenRotationOldLayerTransformForDisplay(new_rotation, |
| + old_rotation, display)); |
| +} |
| + |
| +void ScreenRotationAnimator::RequestCopyScreenRotationContainerLayer( |
| + std::unique_ptr<cc::CopyOutputRequest> copy_output_request) { |
| + copy_output_request->set_area( |
| + gfx::Rect(screen_rotation_container_layer_->size())); |
| + screen_rotation_container_layer_->RequestCopyOfOutput( |
| + std::move(copy_output_request)); |
| +} |
| - screen_rotation_state_ = COPY_REQUESTED; |
| +ScreenRotationAnimator::CopyCallback |
| +ScreenRotationAnimator::CreateAfterCopyCallbackBeforeRotation( |
| + std::unique_ptr<ScreenRotationRequest> rotation_request) { |
| + return base::Bind(&ScreenRotationAnimator:: |
| + OnScreenRotationContainerLayerCopiedBeforeRotation, |
| + weak_factory_.GetWeakPtr(), |
| + base::Passed(&rotation_request)); |
| } |
| ScreenRotationAnimator::CopyCallback |
| -ScreenRotationAnimator::CreateAfterCopyCallback( |
| +ScreenRotationAnimator::CreateAfterCopyCallbackAfterRotation( |
| std::unique_ptr<ScreenRotationRequest> rotation_request) { |
| - return base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation, |
| + return base::Bind(&ScreenRotationAnimator:: |
| + OnScreenRotationContainerLayerCopiedAfterRotation, |
| weak_factory_.GetWeakPtr(), |
| base::Passed(&rotation_request)); |
| } |
| -void ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation( |
| +void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation( |
| std::unique_ptr<ScreenRotationRequest> rotation_request, |
| std::unique_ptr<cc::CopyOutputResult> result) { |
| - DCHECK(rotation_request->id <= rotation_request_id_); |
| - // The |rotation_request_id_| changed since last copy request, which means a |
| - // new rotation stated, we need to ignore this copy result. |
| - if (rotation_request->id < rotation_request_id_) |
| + if (IgnoreCopyResult(rotation_request->id, rotation_request_id_)) |
| return; |
| + if (AbortRotation(display_id_, result.get())) { |
| + ProcessAnimationQueue(); |
| + return; |
| + } |
| - // In the following cases, abort rotation: |
| - // 1) if the display was removed, |
| - // 2) the copy request has been canceled or failed. It would fail if, |
| - // for examples: a) The layer is removed from the compositor and destroye |
| - // before committing the request to the compositor. b) The compositor is |
| - // shutdown. |
| - if (!IsDisplayIdValid(display_id_) || result->IsEmpty()) { |
| + old_layer_tree_owner_ = CopyLayerTree(std::move(result)); |
| + SetRotation(rotation_request->new_rotation, rotation_request->old_rotation, |
| + rotation_request->source); |
| + std::unique_ptr<cc::CopyOutputRequest> copy_output_request = |
| + cc::CopyOutputRequest::CreateRequest( |
| + CreateAfterCopyCallbackAfterRotation(std::move(rotation_request))); |
| + RequestCopyScreenRotationContainerLayer(std::move(copy_output_request)); |
| +} |
| + |
| +void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation( |
| + std::unique_ptr<ScreenRotationRequest> rotation_request, |
| + std::unique_ptr<cc::CopyOutputResult> result) { |
| + if (IgnoreCopyResult(rotation_request->id, rotation_request_id_)) |
| + return; |
| + if (AbortRotation(display_id_, result.get())) { |
| ProcessAnimationQueue(); |
| return; |
| } |
| - CopyOldLayerTree(std::move(result)); |
| + new_layer_tree_owner_ = CopyLayerTree(std::move(result)); |
| AnimateRotation(std::move(rotation_request)); |
| } |
| void ScreenRotationAnimator::CreateOldLayerTree() { |
| - old_layer_tree_owner_ = ::wm::RecreateLayers(GetRootWindow(display_id_)); |
| + old_layer_tree_owner_ = ::wm::RecreateLayers(root_window_); |
| + AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root()); |
| } |
| -void ScreenRotationAnimator::CopyOldLayerTree( |
| +std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree( |
| std::unique_ptr<cc::CopyOutputResult> result) { |
| cc::TextureMailbox texture_mailbox; |
| std::unique_ptr<cc::SingleReleaseCallback> release_callback; |
| result->TakeTexture(&texture_mailbox, &release_callback); |
| DCHECK(texture_mailbox.IsTexture()); |
| - aura::Window* root_window = GetRootWindow(display_id_); |
| - gfx::Rect rect(root_window->layer()->size()); |
| + gfx::Rect rect(root_window_->layer()->size()); |
| std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>(); |
| copy_layer->SetBounds(rect); |
| copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback), |
| rect.size()); |
| - old_layer_tree_owner_ = |
| - base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer)); |
| + |
| + AddLayerAtTopOfWindowLayers(root_window_, copy_layer.get()); |
| + return base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer)); |
| } |
| void ScreenRotationAnimator::AnimateRotation( |
| std::unique_ptr<ScreenRotationRequest> rotation_request) { |
| screen_rotation_state_ = ROTATING; |
| - |
| - aura::Window* root_window = GetRootWindow(display_id_); |
| - std::unique_ptr<LayerCleanupObserver> old_layer_cleanup_observer( |
| - new LayerCleanupObserver(weak_factory_.GetWeakPtr())); |
| - ui::Layer* old_root_layer = old_layer_tree_owner_->root(); |
| - old_root_layer->set_name("ScreenRotationAnimator:old_layer_tree"); |
| - // Add the cloned layer tree in to the root, so it will be rendered. |
| - root_window->layer()->Add(old_root_layer); |
| - root_window->layer()->StackAtTop(old_root_layer); |
| - |
| - const gfx::Rect original_screen_bounds = root_window->GetTargetBounds(); |
| - |
| - const int rotation_factor = GetRotationFactor( |
| - GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); |
| - |
| + const int rotation_factor = GetRotationFactor(rotation_request->old_rotation, |
| + rotation_request->new_rotation); |
| const int old_layer_initial_rotation_degrees = GetInitialDegrees( |
| - GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); |
| - |
| + rotation_request->old_rotation, rotation_request->new_rotation); |
| const base::TimeDelta duration = |
| base::TimeDelta::FromMilliseconds(kRotationDurationInMs); |
| - |
| const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; |
| - |
| - Shell::Get()->display_manager()->SetDisplayRotation( |
| - display_id_, rotation_request->new_rotation, rotation_request->source); |
| - |
| - const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds(); |
| + const gfx::Rect rotated_screen_bounds = root_window_->GetTargetBounds(); |
| const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, |
| rotated_screen_bounds.height() / 2); |
| - ui::Layer* screen_rotation_container_layer = |
| - root_window->GetChildById(kShellWindowId_ScreenRotationContainer) |
| - ->layer(); |
| - std::unique_ptr<ScreenRotationAnimation> current_layer_screen_rotation = |
| + ui::Layer* new_root_layer; |
| + if (new_layer_tree_owner_ && has_switch_ash_enable_smooth_screen_rotation_) { |
| + // Make the current layers invisible if the copy request after rotation is |
| + // succeesful. |
| + screen_rotation_container_layer_->SetOpacity(0.0f); |
| + new_root_layer = new_layer_tree_owner_->root(); |
| + } else { |
| + new_root_layer = screen_rotation_container_layer_; |
| + } |
| + |
| + std::unique_ptr<ScreenRotationAnimation> new_layer_screen_rotation = |
| base::MakeUnique<ScreenRotationAnimation>( |
| - screen_rotation_container_layer, kRotationDegrees * rotation_factor, |
| + new_root_layer, kRotationDegrees * rotation_factor, |
| 0 /* end_degrees */, 0.0f, |
| - screen_rotation_container_layer->opacity() /* target_opacity */, |
| - pivot, duration, tween_type); |
| + new_root_layer->opacity() /* target_opacity */, pivot, duration, |
| + tween_type); |
| - ui::LayerAnimator* current_layer_animator = |
| - screen_rotation_container_layer->GetAnimator(); |
| - current_layer_animator->set_preemption_strategy( |
| + ui::LayerAnimator* new_layer_animator = new_root_layer->GetAnimator(); |
| + new_layer_animator->set_preemption_strategy( |
| ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
| - std::unique_ptr<ui::LayerAnimationSequence> current_layer_animation_sequence = |
| + std::unique_ptr<ui::LayerAnimationSequence> new_layer_animation_sequence = |
| base::MakeUnique<ui::LayerAnimationSequence>( |
| - std::move(current_layer_screen_rotation)); |
| - current_layer_animator->StartAnimation( |
| - current_layer_animation_sequence.release()); |
| + std::move(new_layer_screen_rotation)); |
| + ui::Layer* old_root_layer = old_layer_tree_owner_->root(); |
| + const gfx::Rect original_screen_bounds = old_root_layer->GetTargetBounds(); |
| // The old layer will also be transformed into the new orientation. We will |
| // translate it so that the old layer's center point aligns with the new |
| // orientation's center point and use that center point as the pivot for the |
| @@ -354,29 +357,45 @@ void ScreenRotationAnimator::AnimateRotation( |
| std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence = |
| base::MakeUnique<ui::LayerAnimationSequence>( |
| std::move(old_layer_screen_rotation)); |
| - // Add an observer so that the cloned layers can be cleaned up with the |
| - // animation completes/aborts. |
| - old_layer_animation_sequence->AddObserver( |
| - old_layer_cleanup_observer.release()); |
| + |
| // In unit test, we can use ash::test::ScreenRotationAnimatorTestApi to |
| // control the animation. |
| - if (disable_animation_timers_for_test_) |
| + if (disable_animation_timers_for_test_) { |
| + if (new_layer_tree_owner_) |
| + new_layer_animator->set_disable_timer_for_test(true); |
| old_layer_animator->set_disable_timer_for_test(true); |
| + } |
| old_layer_animation_sequence->SetAnimationMetricsReporter( |
| metrics_reporter_.get()); |
| + |
| + // Add an observer so that the cloned/copied layers can be cleaned up with the |
| + // animation completes/aborts. |
| + ui::CallbackLayerAnimationObserver* observer = |
| + new ui::CallbackLayerAnimationObserver( |
| + base::Bind(&AnimationEndedCallback, weak_factory_.GetWeakPtr())); |
| + if (new_layer_tree_owner_) |
| + new_layer_animator->AddObserver(observer); |
| + new_layer_animator->StartAnimation(new_layer_animation_sequence.release()); |
| + old_layer_animator->AddObserver(observer); |
| old_layer_animator->StartAnimation(old_layer_animation_sequence.release()); |
| + observer->SetActive(); |
| } |
| void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, |
| display::Display::RotationSource source) { |
| - if (GetCurrentScreenRotation(display_id_) == new_rotation) |
| + const display::Display::Rotation current_rotation = |
| + GetCurrentScreenRotation(display_id_); |
| + if (current_rotation == new_rotation) |
| return; |
| + has_switch_ash_enable_smooth_screen_rotation_ = |
| + base::CommandLine::ForCurrentProcess()->HasSwitch( |
|
oshima
2017/04/14 04:54:26
initialize it in ctor
wutao
2017/04/14 07:48:28
Done. I also need to add a setter for test so that
|
| + switches::kAshEnableSmoothScreenRotation); |
| + |
| rotation_request_id_++; |
| std::unique_ptr<ScreenRotationRequest> rotation_request = |
| - base::MakeUnique<ScreenRotationRequest>(rotation_request_id_, |
| - new_rotation, source); |
| - |
| + base::MakeUnique<ScreenRotationRequest>( |
| + rotation_request_id_, current_rotation, new_rotation, source); |
| switch (screen_rotation_state_) { |
| case IDLE: |
| case COPY_REQUESTED: |
| @@ -404,7 +423,10 @@ void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( |
| void ScreenRotationAnimator::ProcessAnimationQueue() { |
| screen_rotation_state_ = IDLE; |
| + if (IsDisplayIdValid(display_id_)) |
| + screen_rotation_container_layer_->SetOpacity(1.0f); |
| old_layer_tree_owner_.reset(); |
| + new_layer_tree_owner_.reset(); |
| if (last_pending_request_ && IsDisplayIdValid(display_id_)) { |
| display::Display::Rotation new_rotation = |
| last_pending_request_->new_rotation; |
| @@ -424,13 +446,14 @@ void ScreenRotationAnimator::set_disable_animation_timers_for_test( |
| } |
| void ScreenRotationAnimator::StopAnimating() { |
| - GetRootWindow(display_id_) |
| - ->GetChildById(kShellWindowId_ScreenRotationContainer) |
| - ->layer() |
| - ->GetAnimator() |
| - ->StopAnimating(); |
| + // |old_layer_tree_owner_| new_layer_tree_owner_| could be nullptr if another |
| + // the rotation request comes before the copy request finished. |
| if (old_layer_tree_owner_) |
| old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); |
| + if (new_layer_tree_owner_) |
| + new_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); |
| + if (IsDisplayIdValid(display_id_)) |
| + screen_rotation_container_layer_->SetOpacity(1.0f); |
| } |
| } // namespace ash |