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 102b8d0e7b3082f7ff25656d2f1243ecad206e22..a111c245f13596a3a0137ddaed664bd1e327168d 100644 |
| --- a/ash/rotator/screen_rotation_animator.cc |
| +++ b/ash/rotator/screen_rotation_animator.cc |
| @@ -8,6 +8,7 @@ |
| #include <utility> |
| #include <vector> |
| +#include "ash/common/ash_switches.h" |
| #include "ash/display/window_tree_host_manager.h" |
| #include "ash/rotator/screen_rotation_animation.h" |
| #include "ash/rotator/screen_rotation_animator_observer.h" |
| @@ -16,7 +17,10 @@ |
| #include "base/memory/ptr_util.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/time/time.h" |
| +#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" |
| @@ -49,13 +53,12 @@ const int kRotationDurationInMs = 250; |
| const int kCounterClockWiseRotationFactor = 1; |
| const int kClockWiseRotationFactor = -1; |
| -// Aborts the active animations of the layer, and recurses upon its child |
| -// layers. |
| -void AbortAnimations(ui::Layer* layer) { |
| - for (ui::Layer* child_layer : layer->children()) |
| - AbortAnimations(child_layer); |
| - layer->GetAnimator()->AbortAllAnimations(); |
| -} |
| +// The delegate root layer name. |
| +const std::string kDelegateRootLayerName = "DelegateRootLayer"; |
| +// The old root layer name. |
| +const std::string kOldRootLayerName = "ScreenRotationAnimator:old_layer_tree"; |
| +// The new root layer name. |
| +const std::string kNewRootLayerName = "ScreenRotationAnimator:new_layer_tree"; |
| display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) { |
| return Shell::GetInstance() |
| @@ -82,6 +85,15 @@ aura::Window* GetRootWindow(int64_t display_id) { |
| ->GetRootWindowForDisplayId(display_id); |
| } |
| +ui::Layer* GetChildLayerByName(ui::Layer* parent, const std::string& name) { |
| + for (ui::Layer* child_layer : parent->children()) { |
| + if (child_layer->name() == name) |
| + return child_layer; |
| + } |
| + NOTREACHED(); |
| + return nullptr; |
| +} |
| + |
| // Returns true if the rotation between |initial_rotation| and |new_rotation| is |
| // 180 degrees. |
| bool Is180DegreeFlip(display::Display::Rotation initial_rotation, |
| @@ -95,100 +107,89 @@ 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 { |
| +class ScreenRotationAnimationMetricsReporter |
| + : public ui::AnimationMetricsReporter { |
| 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; |
| + ScreenRotationAnimationMetricsReporter() {} |
| + ~ScreenRotationAnimationMetricsReporter() override {} |
| + |
| + void Report(int value) override { |
| + UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); |
| } |
| - 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); |
| + DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); |
| }; |
| -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 LayerCleanupObserver::OnLayerAnimationEnded( |
| - ui::LayerAnimationSequence* sequence) { |
| - if (animator_) |
| - animator_->ProcessAnimationQueue(); |
| - |
| - delete this; |
| -} |
| - |
| -void LayerCleanupObserver::OnLayerAnimationAborted( |
| - ui::LayerAnimationSequence* sequence) { |
| - if (animator_) |
| - animator_->ProcessAnimationQueue(); |
| - |
| - delete this; |
| +void AddLayerAtTopOfWindowLayers(aura::Window* root_window, ui::Layer* layer) { |
| + // Add the cloned layer tree in to the root, so it will be rendered. |
| + root_window->layer()->Add(layer); |
| + root_window->layer()->StackAtTop(layer); |
| } |
| -void LayerCleanupObserver::OnAttachedToSequence( |
| - ui::LayerAnimationSequence* sequence) { |
| - sequence_ = sequence; |
| +bool AnimationEndedCallback( |
| + base::WeakPtr<ScreenRotationAnimator> animator, |
| + const ui::CallbackLayerAnimationObserver& observer) { |
| + if (animator) |
| + animator->ProcessAnimationQueue(); |
| + return true; |
| } |
| -void LayerCleanupObserver::OnDetachedFromSequence( |
| - ui::LayerAnimationSequence* sequence) { |
| - DCHECK_EQ(sequence, sequence_); |
| - sequence_ = nullptr; |
| +// Round near zero value to zero. |
| +void RoundNearZero(gfx::Transform* transform) { |
| + const float kEpsilon = 0.001f; |
| + SkMatrix44& matrix = transform->matrix(); |
| + for (int x = 0; x < 4; ++x) { |
| + for (int y = 0; y < 4; ++y) { |
| + if (std::abs(SkMScalarToFloat(matrix.get(x, y))) < kEpsilon) |
| + matrix.set(x, y, SkFloatToMScalar(0.0f)); |
| + } |
| + } |
| } |
| -class ScreenRotationAnimationMetricsReporter |
| - : public ui::AnimationMetricsReporter { |
| - public: |
| - ScreenRotationAnimationMetricsReporter() {} |
| - ~ScreenRotationAnimationMetricsReporter() override {} |
| - |
| - void Report(int value) override { |
| - UMA_HISTOGRAM_PERCENTAGE("Ash.Rotation.AnimationSmoothness", value); |
| +void TransformLayerToOldRotation( |
| + ui::Layer* layer, |
| + const int64_t display_id, |
| + const display::Display::Rotation& new_rotation, |
| + const display::Display::Rotation& old_rotation) { |
| + const display::Display display = |
| + Shell::GetInstance()->display_manager()->GetDisplayForId(display_id); |
| + |
| + const int rotation_changed = ((new_rotation - old_rotation) + 4) % 4; |
| + float one_pixel = 1.0f / display.device_scale_factor(); |
| + gfx::Transform transform; |
| + switch (rotation_changed) { |
| + case 0: |
| + break; |
| + case 1: |
| + transform.Rotate(270); |
| + transform.Translate(-display.bounds().height() + one_pixel, 0); |
| + break; |
| + case 2: |
| + transform.Rotate(180); |
| + transform.Translate(-display.bounds().width() + one_pixel, |
| + -display.bounds().height() + one_pixel); |
| + break; |
| + case 3: |
| + transform.Rotate(90); |
| + transform.Translate(0, -display.bounds().width() + one_pixel); |
| + break; |
| } |
| - private: |
| - DISALLOW_COPY_AND_ASSIGN(ScreenRotationAnimationMetricsReporter); |
| -}; |
| + RoundNearZero(&transform); |
| + layer->SetTransform(transform); |
| +} |
| } // namespace |
| struct ScreenRotationAnimator::ScreenRotationRequest { |
| - ScreenRotationRequest(display::Display::Rotation to_rotation, |
| - display::Display::RotationSource from_source) |
| - : new_rotation(to_rotation), source(from_source) {} |
| + ScreenRotationRequest(const display::Display::Rotation& from_rotation, |
| + const display::Display::Rotation& to_rotation, |
| + const display::Display::RotationSource& from_source) |
| + : old_rotation(from_rotation), |
| + new_rotation(to_rotation), |
| + source(from_source) {} |
| + display::Display::Rotation old_rotation; |
| display::Display::Rotation new_rotation; |
| display::Display::RotationSource source; |
| }; |
| @@ -213,69 +214,156 @@ ScreenRotationAnimator::~ScreenRotationAnimator() { |
| metrics_reporter_.reset(); |
| } |
| -void ScreenRotationAnimator::AnimateRotation( |
| +void ScreenRotationAnimator::StartRotationAnimation( |
| std::unique_ptr<ScreenRotationRequest> rotation_request) { |
| - aura::Window* root_window = GetRootWindow(display_id_); |
| + if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kAshEnableSmoothScreenRotation)) { |
| + const cc::CopyOutputRequest::CopyOutputRequestCallback callback = |
| + base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation, |
| + weak_factory_.GetWeakPtr(), base::Passed(&rotation_request)); |
| + RequestCopyRootLayerByName(kDelegateRootLayerName, callback); |
| + } else { |
| + StartSlowAnimation(std::move(rotation_request)); |
| + } |
| +} |
| - const gfx::Rect original_screen_bounds = root_window->GetTargetBounds(); |
| +void ScreenRotationAnimator::SetRotation( |
| + const display::Display::Rotation& new_rotation, |
| + const display::Display::Rotation& old_rotation, |
| + const display::Display::RotationSource& source) { |
| + Shell::GetInstance()->display_manager()->SetDisplayRotation( |
| + display_id_, new_rotation, source); |
| + TransformLayerToOldRotation(old_layer_tree_owner_->root(), display_id_, |
| + new_rotation, old_rotation); |
| +} |
| - const int rotation_factor = GetRotationFactor( |
| - GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); |
| +void ScreenRotationAnimator::StartSlowAnimation( |
| + std::unique_ptr<ScreenRotationRequest> rotation_request) { |
| + CreateOldLayerTree(); |
| + SetRotation(rotation_request->new_rotation, rotation_request->old_rotation, |
| + rotation_request->source); |
| + AnimateRotation(std::move(rotation_request)); |
| +} |
| - const int old_layer_initial_rotation_degrees = GetInitialDegrees( |
| - GetCurrentScreenRotation(display_id_), rotation_request->new_rotation); |
| +void ScreenRotationAnimator::RequestCopyRootLayerByName( |
| + const std::string& layer_name, |
| + const cc::CopyOutputRequest::CopyOutputRequestCallback& callback) { |
| + std::unique_ptr<cc::CopyOutputRequest> copy_output_request = |
| + cc::CopyOutputRequest::CreateRequest(callback); |
| + ui::Layer* layer = |
| + GetChildLayerByName(GetRootWindow(display_id_)->layer(), layer_name); |
| + gfx::Rect rect(layer->size()); |
| + copy_output_request->set_area(rect); |
| + layer->RequestCopyOfOutput(std::move(copy_output_request)); |
| +} |
| - const base::TimeDelta duration = |
| - base::TimeDelta::FromMilliseconds(kRotationDurationInMs); |
| +void ScreenRotationAnimator::OnRootLayerCopiedBeforeRotation( |
| + std::unique_ptr<ScreenRotationRequest> rotation_request, |
| + std::unique_ptr<cc::CopyOutputResult> result) { |
| + // If copy request does not succeed or canceled, fall back to recreate layers |
| + // solution. |
| + if (result->IsEmpty() || result->size().IsEmpty() || !result->HasTexture()) { |
|
danakj
2017/03/31 19:32:30
I don't think you need to check size() or HasTextu
wutao
2017/04/07 06:59:11
Acknowledged.
|
| + StartSlowAnimation(std::move(rotation_request)); |
| + } else { |
| + old_layer_tree_owner_ = CopyLayerTree(kOldRootLayerName, std::move(result)); |
| - const gfx::Tween::Type tween_type = gfx::Tween::FAST_OUT_LINEAR_IN; |
| + SetRotation(rotation_request->new_rotation, rotation_request->old_rotation, |
| + rotation_request->source); |
| - std::unique_ptr<ui::LayerTreeOwner> old_layer_tree = |
| - ::wm::RecreateLayers(root_window); |
| - old_layer_tree->root()->set_name("ScreenRotationAnimator:old_layer_tree"); |
| + const cc::CopyOutputRequest::CopyOutputRequestCallback callback = |
| + base::Bind(&ScreenRotationAnimator::OnRootLayerCopiedAfterRotation, |
| + weak_factory_.GetWeakPtr(), base::Passed(&rotation_request)); |
| + RequestCopyRootLayerByName(kDelegateRootLayerName, callback); |
|
danakj
2017/03/31 19:32:30
Why not do both of these copies at the same time i
wutao
2017/04/07 06:59:11
Talked offline, The two requests are on the same l
|
| + } |
| +} |
| - // Add the cloned layer tree in to the root, so it will be rendered. |
| - root_window->layer()->Add(old_layer_tree->root()); |
| - root_window->layer()->StackAtTop(old_layer_tree->root()); |
| +void ScreenRotationAnimator::OnRootLayerCopiedAfterRotation( |
| + std::unique_ptr<ScreenRotationRequest> rotation_request, |
| + std::unique_ptr<cc::CopyOutputResult> result) { |
| + if (!result->IsEmpty() && !result->size().IsEmpty() && result->HasTexture()) |
|
danakj
2017/03/31 19:32:30
same about size and HasTexture
wutao
2017/04/07 06:59:11
Acknowledged.
|
| + new_layer_tree_owner_ = CopyLayerTree(kNewRootLayerName, std::move(result)); |
| + AnimateRotation(std::move(rotation_request)); |
| +} |
| - old_layer_tree_owner_ = std::move(old_layer_tree); |
| - std::unique_ptr<LayerCleanupObserver> old_layer_cleanup_observer( |
| - new LayerCleanupObserver(weak_factory_.GetWeakPtr())); |
| +void ScreenRotationAnimator::CreateOldLayerTree() { |
| + aura::Window* root_window = GetRootWindow(display_id_); |
| + old_layer_tree_owner_ = ::wm::RecreateLayers(root_window); |
| + old_layer_tree_owner_->root()->set_name(kOldRootLayerName); |
| + AddLayerAtTopOfWindowLayers(root_window, old_layer_tree_owner_->root()); |
| +} |
| - Shell::GetInstance()->display_manager()->SetDisplayRotation( |
| - display_id_, rotation_request->new_rotation, rotation_request->source); |
| +std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree( |
| + const std::string& layer_name, |
| + 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()); |
| + 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()); |
| + |
| + copy_layer->set_name(layer_name); |
| + AddLayerAtTopOfWindowLayers(root_window, copy_layer.get()); |
| + return base::MakeUnique<ui::LayerTreeOwner>(std::move(copy_layer)); |
| +} |
| +void ScreenRotationAnimator::AnimateRotation( |
| + std::unique_ptr<ScreenRotationRequest> rotation_request) { |
| + const int rotation_factor = GetRotationFactor(rotation_request->old_rotation, |
| + rotation_request->new_rotation); |
| + const int old_layer_initial_rotation_degrees = GetInitialDegrees( |
| + 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; |
| + aura::Window* root_window = GetRootWindow(display_id_); |
| 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* old_root_layer = old_layer_tree_owner_->root(); |
| - // We must animate each non-cloned child layer individually because the cloned |
| - // layer was added as a child to |root_window|'s layer so that it will be |
| - // rendered. |
| - // TODO(bruthig): Add a NOT_DRAWN layer in between the root_window's layer and |
| - // its current children so that we only need to initiate two |
| - // LayerAnimationSequences. One for the new layers and one for the old layer. |
| - for (ui::Layer* child_layer : root_window->layer()->children()) { |
| - // Skip the cloned layer because it has a different animation. |
| - if (child_layer == old_root_layer) |
| - continue; |
| - |
| - std::unique_ptr<ScreenRotationAnimation> screen_rotation = |
| - base::MakeUnique<ScreenRotationAnimation>( |
| - child_layer, kRotationDegrees * rotation_factor, |
| - 0 /* end_degrees */, child_layer->opacity(), |
| - 1.0f /* target_opacity */, pivot, duration, tween_type); |
| - |
| - ui::LayerAnimator* animator = child_layer->GetAnimator(); |
| - animator->set_preemption_strategy( |
| - ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
| - std::unique_ptr<ui::LayerAnimationSequence> animation_sequence = |
| - base::MakeUnique<ui::LayerAnimationSequence>( |
| - std::move(screen_rotation)); |
| - animator->StartAnimation(animation_sequence.release()); |
| + // Make the current layers invisible. |
| + if (new_layer_tree_owner_) { |
| + GetChildLayerByName(root_window->layer(), kDelegateRootLayerName) |
| + ->SetOpacity(0.0f); |
| } |
| + // Add an observer so that the copied layers can be cleaned up with the |
| + // animation completes/aborts. |
| + ui::CallbackLayerAnimationObserver* observer = |
| + new ui::CallbackLayerAnimationObserver( |
| + base::Bind(&AnimationEndedCallback, weak_factory_.GetWeakPtr())); |
| + |
| + ui::Layer* new_root_layer; |
| + if (new_layer_tree_owner_ && |
| + base::CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kAshEnableSmoothScreenRotation)) { |
| + new_root_layer = new_layer_tree_owner_->root(); |
| + } else { |
| + new_root_layer = |
| + GetChildLayerByName(root_window->layer(), kDelegateRootLayerName); |
| + } |
| + |
| + std::unique_ptr<ScreenRotationAnimation> current_layer_screen_rotation = |
| + base::MakeUnique<ScreenRotationAnimation>( |
| + new_root_layer, kRotationDegrees * rotation_factor, |
| + 0 /* end_degrees */, 0.0f, |
| + new_root_layer->opacity() /* target_opacity */, pivot, duration, |
| + tween_type); |
| + |
| + ui::LayerAnimator* current_layer_animator = new_root_layer->GetAnimator(); |
| + current_layer_animator->set_preemption_strategy( |
| + ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
| + std::unique_ptr<ui::LayerAnimationSequence> current_layer_animation_sequence = |
| + base::MakeUnique<ui::LayerAnimationSequence>( |
| + std::move(current_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 |
| @@ -286,7 +374,7 @@ void ScreenRotationAnimator::AnimateRotation( |
| (rotated_screen_bounds.height() - original_screen_bounds.height()) / 2); |
| old_root_layer->SetTransform(translate_transform); |
| - std::unique_ptr<ScreenRotationAnimation> screen_rotation = |
| + std::unique_ptr<ScreenRotationAnimation> old_layer_screen_rotation = |
| base::MakeUnique<ScreenRotationAnimation>( |
| old_root_layer, old_layer_initial_rotation_degrees * rotation_factor, |
| (old_layer_initial_rotation_degrees - kRotationDegrees) * |
| @@ -294,31 +382,37 @@ void ScreenRotationAnimator::AnimateRotation( |
| old_root_layer->opacity(), 0.0f /* target_opacity */, pivot, duration, |
| tween_type); |
| - ui::LayerAnimator* animator = old_root_layer->GetAnimator(); |
| - animator->set_preemption_strategy( |
| + ui::LayerAnimator* old_layer_animator = old_root_layer->GetAnimator(); |
| + old_layer_animator->set_preemption_strategy( |
| ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); |
| - std::unique_ptr<ui::LayerAnimationSequence> animation_sequence = |
| - base::MakeUnique<ui::LayerAnimationSequence>(std::move(screen_rotation)); |
| - // Add an observer so that the cloned layers can be cleaned up with the |
| - // animation completes/aborts. |
| - 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_) |
| - animator->set_disable_timer_for_test(true); |
| - animation_sequence->SetAnimationMetricsReporter(metrics_reporter_.get()); |
| - animator->StartAnimation(animation_sequence.release()); |
| + std::unique_ptr<ui::LayerAnimationSequence> old_layer_animation_sequence = |
| + base::MakeUnique<ui::LayerAnimationSequence>( |
| + std::move(old_layer_screen_rotation)); |
| + if (disable_animation_timers_for_test_) |
| + old_layer_animator->set_disable_timer_for_test(true); |
| + old_layer_animation_sequence->SetAnimationMetricsReporter( |
| + metrics_reporter_.get()); |
| + |
| + current_layer_animator->AddObserver(observer); |
| + old_layer_animator->AddObserver(observer); |
| + current_layer_animator->StartAnimation( |
| + current_layer_animation_sequence.release()); |
| + old_layer_animator->StartAnimation(old_layer_animation_sequence.release()); |
| + observer->SetActive(); |
| rotation_request.reset(); |
| } |
| 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; |
| std::unique_ptr<ScreenRotationRequest> rotation_request = |
| - base::MakeUnique<ScreenRotationRequest>(new_rotation, source); |
| + base::MakeUnique<ScreenRotationRequest>(current_rotation, new_rotation, |
| + source); |
| if (is_rotating_) { |
| last_pending_request_ = std::move(rotation_request); |
| @@ -328,7 +422,7 @@ void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, |
| StopAnimating(); |
| } else { |
| is_rotating_ = true; |
| - AnimateRotation(std::move(rotation_request)); |
| + StartRotationAnimation(std::move(rotation_request)); |
| } |
| } |
| @@ -344,7 +438,9 @@ void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver( |
| void ScreenRotationAnimator::ProcessAnimationQueue() { |
| is_rotating_ = false; |
| + StopAnimating(); |
| old_layer_tree_owner_.reset(); |
| + new_layer_tree_owner_.reset(); |
| if (last_pending_request_ && IsDisplayIdValid(display_id_)) { |
| std::unique_ptr<ScreenRotationRequest> rotation_request = |
| std::move(last_pending_request_); |
| @@ -363,15 +459,14 @@ void ScreenRotationAnimator::set_disable_animation_timers_for_test( |
| } |
| void ScreenRotationAnimator::StopAnimating() { |
| - aura::Window* root_window = GetRootWindow(display_id_); |
| - for (ui::Layer* child_layer : root_window->layer()->children()) { |
| - if (child_layer == old_layer_tree_owner_->root()) |
| - continue; |
| - |
| - child_layer->GetAnimator()->StopAnimating(); |
| - } |
| - |
| + GetChildLayerByName(GetRootWindow(display_id_)->layer(), |
| + kDelegateRootLayerName) |
| + ->SetOpacity(1.0f); |
| old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); |
| + // |new_layer_tree_owner_| could be nullptr if the second copy request failed |
| + // or canceled. |
| + if (new_layer_tree_owner_) |
| + new_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); |
| } |
| } // namespace ash |