| Index: ash/rotator/screen_rotation_animator.cc
|
| diff --git a/ash/rotator/screen_rotation_animator.cc b/ash/rotator/screen_rotation_animator.cc
|
| index f1c51a4c70edb8a1783d996859033570c3e60f9e..9c6bf5f6a265e267233df974a15b4f00b9571f2f 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,10 @@ aura::Window* GetRootWindow(int64_t display_id) {
|
| display_id);
|
| }
|
|
|
| +aura::Window* GetScreenRotationContainer(aura::Window* root_window) {
|
| + return root_window->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 +91,70 @@ 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();
|
| +void AddLayerBelowWindowLayer(aura::Window* root_window,
|
| + ui::Layer* top_layer,
|
| + 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()->StackBelow(layer, top_layer);
|
| +}
|
|
|
| - 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();
|
| +// Creates a Transform for the old layer in screen rotation animation.
|
| +gfx::Transform CreateScreenRotationOldLayerTransformForDisplay(
|
| + display::Display::Rotation old_rotation,
|
| + display::Display::Rotation new_rotation,
|
| + const display::Display& display) {
|
| + gfx::Transform inverse;
|
| + CHECK(CreateRotationTransform(old_rotation, new_rotation, display)
|
| + .GetInverse(&inverse));
|
| + return inverse;
|
| +}
|
|
|
| - delete this;
|
| +// 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::OnAttachedToSequence(
|
| - ui::LayerAnimationSequence* sequence) {
|
| - sequence_ = sequence;
|
| +// 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();
|
| }
|
|
|
| -void LayerCleanupObserver::OnDetachedFromSequence(
|
| - ui::LayerAnimationSequence* sequence) {
|
| - DCHECK_EQ(sequence, sequence_);
|
| - sequence_ = nullptr;
|
| +// Creates a black mask layer and returns the |layer_owner|.
|
| +std::unique_ptr<ui::LayerOwner> CreateBlackMaskLayerOwner(
|
| + const gfx::Rect& rect) {
|
| + std::unique_ptr<ui::Layer> black_mask_layer =
|
| + base::MakeUnique<ui::Layer>(ui::LAYER_SOLID_COLOR);
|
| + black_mask_layer->SetBounds(rect);
|
| + black_mask_layer->SetColor(SK_ColorBLACK);
|
| + std::unique_ptr<ui::LayerOwner> black_mask_layer_owner =
|
| + base::MakeUnique<ui::LayerOwner>();
|
| + black_mask_layer_owner->SetLayer(std::move(black_mask_layer));
|
| + return black_mask_layer_owner;
|
| }
|
|
|
| class ScreenRotationAnimationMetricsReporter
|
| @@ -187,11 +180,17 @@ ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id)
|
| metrics_reporter_(
|
| base::MakeUnique<ScreenRotationAnimationMetricsReporter>()),
|
| disable_animation_timers_for_test_(false),
|
| + has_switch_ash_enable_smooth_screen_rotation_(
|
| + base::CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kAshEnableSmoothScreenRotation)),
|
| + root_window_(GetRootWindow(display_id_)),
|
| + screen_rotation_container_layer_(
|
| + GetScreenRotationContainer(root_window_)->layer()),
|
| weak_factory_(this) {}
|
|
|
| ScreenRotationAnimator::~ScreenRotationAnimator() {
|
| - // To prevent a call to |LayerCleanupObserver::OnLayerAnimationAborted()| from
|
| - // calling a method on the |animator_|.
|
| + // To prevent a call to |AnimationEndedCallback()| from calling a method on
|
| + // the |animator_|.
|
| weak_factory_.InvalidateWeakPtrs();
|
|
|
| // Explicitly reset the |old_layer_tree_owner_| and |metrics_reporter_| in
|
| @@ -203,133 +202,175 @@ ScreenRotationAnimator::~ScreenRotationAnimator() {
|
|
|
| void ScreenRotationAnimator::StartRotationAnimation(
|
| std::unique_ptr<ScreenRotationRequest> rotation_request) {
|
| - if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
| - switches::kAshEnableSmoothScreenRotation)) {
|
| - RequestCopyRootLayerAndAnimateRotation(std::move(rotation_request));
|
| + const display::Display::Rotation current_rotation =
|
| + GetCurrentScreenRotation(display_id_);
|
| + if (current_rotation == rotation_request->new_rotation) {
|
| + // We need to call |ProcessAnimationQueue()| to prepare for next rotation
|
| + // request.
|
| + ProcessAnimationQueue();
|
| + return;
|
| + }
|
| +
|
| + rotation_request->old_rotation = current_rotation;
|
| + 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));
|
| + CreateOldLayerTreeForSlowAnimation();
|
| + SetRotation(rotation_request->old_rotation, rotation_request->new_rotation,
|
| + rotation_request->source);
|
| + AnimateRotation(std::move(rotation_request));
|
| +}
|
| +
|
| +void ScreenRotationAnimator::SetRotation(
|
| + display::Display::Rotation old_rotation,
|
| + display::Display::Rotation new_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(old_rotation,
|
| + new_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));
|
| + AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());
|
| + SetRotation(rotation_request->old_rotation, rotation_request->new_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));
|
| + AddLayerBelowWindowLayer(root_window_, old_layer_tree_owner_->root(),
|
| + new_layer_tree_owner_->root());
|
| AnimateRotation(std::move(rotation_request));
|
| }
|
|
|
| -void ScreenRotationAnimator::CreateOldLayerTree() {
|
| - old_layer_tree_owner_ = ::wm::RecreateLayers(GetRootWindow(display_id_));
|
| +void ScreenRotationAnimator::CreateOldLayerTreeForSlowAnimation() {
|
| + old_layer_tree_owner_ = ::wm::RecreateLayers(root_window_);
|
| + // |screen_rotation_container_layer_| needs update after |RecreateLayers()|.
|
| + screen_rotation_container_layer_ =
|
| + GetScreenRotationContainer(root_window_)->layer();
|
| + 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());
|
| + const gfx::Rect rect(screen_rotation_container_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));
|
| + 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_) {
|
| + new_root_layer = new_layer_tree_owner_->root();
|
| + // Add a black mask layer on top of |screen_rotation_container_layer_|.
|
| + black_mask_layer_owner_ = CreateBlackMaskLayerOwner(
|
| + gfx::Rect(screen_rotation_container_layer_->size()));
|
| + AddLayerBelowWindowLayer(root_window_, new_root_layer,
|
| + black_mask_layer_owner_->layer());
|
| + } 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,
|
| - 0 /* end_degrees */, screen_rotation_container_layer->opacity(),
|
| - screen_rotation_container_layer->opacity() /* target_opacity */,
|
| - pivot, duration, tween_type);
|
| -
|
| - ui::LayerAnimator* current_layer_animator =
|
| - screen_rotation_container_layer->GetAnimator();
|
| - current_layer_animator->set_preemption_strategy(
|
| + new_root_layer, kRotationDegrees * rotation_factor,
|
| + 0 /* end_degrees */, new_root_layer->opacity(),
|
| + new_root_layer->opacity() /* target_opacity */, pivot, duration,
|
| + tween_type);
|
| +
|
| + 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,31 +395,41 @@ 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());
|
| - old_layer_animator->StartAnimation(old_layer_animation_sequence.release());
|
|
|
| - rotation_request.reset();
|
| + // 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)
|
| - return;
|
| -
|
| + // |rotation_request_id_| is used to skip stale requests. Before the layer
|
| + // CopyOutputResult callback called, there could have new rotation request.
|
| + // Increases |rotation_request_id_| for each new request and in the callback,
|
| + // we compare the |rotation_request.id| and |rotation_request_id_| to
|
| + // determine the stale status.
|
| rotation_request_id_++;
|
| std::unique_ptr<ScreenRotationRequest> rotation_request =
|
| base::MakeUnique<ScreenRotationRequest>(rotation_request_id_,
|
| new_rotation, source);
|
| -
|
| switch (screen_rotation_state_) {
|
| case IDLE:
|
| case COPY_REQUESTED:
|
| @@ -387,8 +438,7 @@ void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation,
|
| case ROTATING:
|
| last_pending_request_ = std::move(rotation_request);
|
| // The pending request will be processed when the
|
| - // OnLayerAnimation(Ended|Aborted) methods should be called after
|
| - // |StopAnimating()|.
|
| + // |AnimationEndedCallback()| should be called after |StopAnimating()|.
|
| StopAnimating();
|
| break;
|
| }
|
| @@ -406,33 +456,30 @@ void ScreenRotationAnimator::RemoveScreenRotationAnimatorObserver(
|
|
|
| void ScreenRotationAnimator::ProcessAnimationQueue() {
|
| screen_rotation_state_ = IDLE;
|
| + if (IsDisplayIdValid(display_id_) && black_mask_layer_owner_)
|
| + root_window_->layer()->Remove(black_mask_layer_owner_->layer());
|
| old_layer_tree_owner_.reset();
|
| + new_layer_tree_owner_.reset();
|
| + black_mask_layer_owner_.reset();
|
| if (last_pending_request_ && IsDisplayIdValid(display_id_)) {
|
| - display::Display::Rotation new_rotation =
|
| - last_pending_request_->new_rotation;
|
| - display::Display::RotationSource source = last_pending_request_->source;
|
| - last_pending_request_.reset();
|
| - Rotate(new_rotation, source);
|
| + StartRotationAnimation(std::move(last_pending_request_));
|
| return;
|
| }
|
|
|
| + // This is only used in test to notify animator observer.
|
| for (auto& observer : screen_rotation_animator_observers_)
|
| observer.OnScreenRotationAnimationFinished(this);
|
| }
|
|
|
| -void ScreenRotationAnimator::set_disable_animation_timers_for_test(
|
| - bool disable_timers) {
|
| - disable_animation_timers_for_test_ = disable_timers;
|
| -}
|
| -
|
| 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_) && black_mask_layer_owner_)
|
| + root_window_->layer()->Remove(black_mask_layer_owner_->layer());
|
| }
|
|
|
| } // namespace ash
|
|
|