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 5bf704e705dc7712b0bc07b3b1c096b2465d94c3..42721eefeba42d47d755eb6f1a9fd95c47fb9874 100644 |
| --- a/ash/rotator/screen_rotation_animator.cc |
| +++ b/ash/rotator/screen_rotation_animator.cc |
| @@ -34,6 +34,22 @@ |
| namespace ash { |
| +// struct ScreenRotationAnimator::RotationRequest { |
|
bruthig
2017/03/02 18:25:45
Did you mean to remove this?
wutao
2017/03/03 02:45:52
Done.
|
| +// base::WeakPtr<ScreenRotationAnimator> animator; |
| +// int64_t display_id; |
| +// display::Display::Rotation initial_rotation; |
| +// display::Display::Rotation new_rotation; |
| +// display::Display::RotationSource source; |
| +//}; |
| + |
| +ScreenRotationAnimator::ScreenRotationAnimatorObserver:: |
| + ScreenRotationAnimatorObserver() {} |
| +ScreenRotationAnimator::ScreenRotationAnimatorObserver:: |
| + ~ScreenRotationAnimatorObserver() {} |
| + |
| +void ScreenRotationAnimator::ScreenRotationAnimatorObserver:: |
| + OnEndedOrAbortedAnimation(base::WeakPtr<ScreenRotationAnimator> animator) {} |
| + |
| namespace { |
| // The number of degrees that the rotation animations animate through. |
| @@ -42,13 +58,14 @@ const int kRotationDegrees = 20; |
| // The time it takes for the rotation animations to run. |
| const int kRotationDurationInMs = 250; |
| -// Gets the current display rotation for the display with the specified |
| -// |display_id|. |
| -display::Display::Rotation GetCurrentRotation(int64_t display_id) { |
| - return Shell::GetInstance() |
| - ->display_manager() |
| - ->GetDisplayInfo(display_id) |
| - .GetActiveRotation(); |
| +// The rotation directions |
| +const int kCountClockWiseRotation = 1; |
| +const int kClockWiseRotation = -1; |
| + |
| +int GetRotationFactor(display::Display::Rotation initial_rotation, |
| + display::Display::Rotation new_rotation) { |
| + return (initial_rotation + 3) % 4 == new_rotation ? kCountClockWiseRotation |
| + : kClockWiseRotation; |
| } |
| // Returns true if the rotation between |initial_rotation| and |new_rotation| is |
| @@ -58,12 +75,25 @@ bool Is180DegreeFlip(display::Display::Rotation initial_rotation, |
| return (initial_rotation + 2) % 4 == new_rotation; |
| } |
| +// Returns the initial degrees the old layer animation to begin with. |
| +int GetInitialDegrees(display::Display::Rotation initial_rotation, |
| + display::Display::Rotation new_rotation) { |
| + return (Is180DegreeFlip(initial_rotation, new_rotation) ? 180 : 90); |
| +} |
| + |
| +aura::Window* GetRootWindow(int64_t display_id) { |
| + return Shell::GetInstance() |
| + ->window_tree_host_manager() |
| + ->GetRootWindowForDisplayId(display_id); |
| +} |
| + |
| // 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: |
| explicit LayerCleanupObserver( |
| - std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner); |
| + std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner, |
| + base::WeakPtr<ScreenRotationAnimator> animator); |
| ~LayerCleanupObserver() override; |
| // Get the root layer of the owned layer tree. |
| @@ -88,8 +118,7 @@ class LayerCleanupObserver : public ui::LayerAnimationObserver { |
| // layers. |
| void AbortAnimations(ui::Layer* layer); |
| - // The owned layer tree. |
| - std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner_; |
| + base::WeakPtr<ScreenRotationAnimator> animator_; |
| // The LayerAnimationSequence that |this| has been attached to. Defaults to |
| // nullptr. |
| @@ -99,28 +128,46 @@ class LayerCleanupObserver : public ui::LayerAnimationObserver { |
| }; |
| LayerCleanupObserver::LayerCleanupObserver( |
| - std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner) |
| - : layer_tree_owner_(std::move(layer_tree_owner)), sequence_(nullptr) {} |
| + std::unique_ptr<ui::LayerTreeOwner> layer_tree_owner, |
| + base::WeakPtr<ScreenRotationAnimator> animator) |
| + : animator_(animator), sequence_(nullptr) { |
| + animator_->set_old_layer_tree_owner(layer_tree_owner.release()); |
| +} |
| LayerCleanupObserver::~LayerCleanupObserver() { |
| // We must eplicitly detach from |sequence_| because we return true from |
| // RequiresNotificationWhenAnimatorDestroyed. |
| if (sequence_) |
| sequence_->RemoveObserver(this); |
| - AbortAnimations(layer_tree_owner_->root()); |
| } |
| ui::Layer* LayerCleanupObserver::GetRootLayer() { |
| - return layer_tree_owner_->root(); |
| + if (animator_ && animator_->old_layer_tree_owner()) |
| + return animator_->old_layer_tree_owner()->root(); |
| + else { |
| + NOTREACHED(); |
| + return nullptr; |
| + } |
| } |
| void LayerCleanupObserver::OnLayerAnimationEnded( |
| ui::LayerAnimationSequence* sequence) { |
| + if (animator_ && animator_->observer()) { |
| + animator_->reset_old_layer_tree_owner(); |
| + animator_->observer()->OnEndedOrAbortedAnimation(animator_); |
| + } |
| + |
| delete this; |
| } |
| void LayerCleanupObserver::OnLayerAnimationAborted( |
| ui::LayerAnimationSequence* sequence) { |
| + if (animator_ && animator_->observer()) { |
| + AbortAnimations(animator_->old_layer_tree_owner()->root()); |
| + animator_->reset_old_layer_tree_owner(); |
| + animator_->observer()->OnEndedOrAbortedAnimation(animator_); |
| + } |
| + |
| delete this; |
| } |
| @@ -146,23 +193,20 @@ void LayerCleanupObserver::AbortAnimations(ui::Layer* layer) { |
| // layer towards the new orientation through |rotation_degrees| while fading |
| // out, and the new orientation's layer will be rotated in to the |
| // |new_orientation| through |rotation_degrees| arc. |
| -void RotateScreen(int64_t display_id, |
| - display::Display::Rotation new_rotation, |
| - display::Display::RotationSource source) { |
| - aura::Window* root_window = Shell::GetInstance() |
| - ->window_tree_host_manager() |
| - ->GetRootWindowForDisplayId(display_id); |
| +void RotateScreen( |
| + const ScreenRotationAnimator::ScreenRotationRequest rotation_request) { |
| + rotation_request.animator->set_is_animating(true); |
| - const display::Display::Rotation initial_orientation = |
| - GetCurrentRotation(display_id); |
| + aura::Window* root_window = |
| + GetRootWindow(rotation_request.animator->display_id()); |
| const gfx::Rect original_screen_bounds = root_window->GetTargetBounds(); |
| // 180 degree rotations should animate clock-wise. |
| - const int rotation_factor = |
| - (initial_orientation + 3) % 4 == new_rotation ? 1 : -1; |
| + const int rotation_factor = GetRotationFactor( |
| + rotation_request.initial_rotation, rotation_request.new_rotation); |
| - const int old_layer_initial_rotation_degrees = |
| - (Is180DegreeFlip(initial_orientation, new_rotation) ? 180 : 90); |
| + const int old_layer_initial_rotation_degrees = GetInitialDegrees( |
| + rotation_request.initial_rotation, rotation_request.new_rotation); |
| const base::TimeDelta duration = |
| base::TimeDelta::FromMilliseconds(kRotationDurationInMs); |
| @@ -171,16 +215,19 @@ void RotateScreen(int64_t display_id, |
| std::unique_ptr<ui::LayerTreeOwner> old_layer_tree = |
| ::wm::RecreateLayers(root_window); |
| + old_layer_tree->root()->set_name("old_layer_tree"); |
| // 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()); |
| std::unique_ptr<LayerCleanupObserver> layer_cleanup_observer( |
| - new LayerCleanupObserver(std::move(old_layer_tree))); |
| + new LayerCleanupObserver(std::move(old_layer_tree), |
| + rotation_request.animator->WeakPtr())); |
| Shell::GetInstance()->display_manager()->SetDisplayRotation( |
| - display_id, new_rotation, source); |
| + rotation_request.animator->display_id(), rotation_request.new_rotation, |
| + rotation_request.source); |
| const gfx::Rect rotated_screen_bounds = root_window->GetTargetBounds(); |
| const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, |
| @@ -246,26 +293,102 @@ void RotateScreen(int64_t display_id, |
| } // namespace |
| ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id) |
| - : display_id_(display_id) {} |
| + : display_id_(display_id), |
| + is_animating_(false), |
| + observer_(nullptr), |
| + weak_factory_(this) {} |
| ScreenRotationAnimator::~ScreenRotationAnimator() {} |
| -bool ScreenRotationAnimator::CanAnimate() const { |
| +// Gets the current display rotation. |
| +display::Display::Rotation ScreenRotationAnimator::GetCurrentRotation() const { |
| return Shell::GetInstance() |
| ->display_manager() |
| - ->GetDisplayForId(display_id_) |
| - .is_valid(); |
| + ->GetDisplayInfo(display_id_) |
| + .GetActiveRotation(); |
| } |
| -void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, |
| - display::Display::RotationSource source) { |
| - const display::Display::Rotation current_rotation = |
| - GetCurrentRotation(display_id_); |
| +int64_t ScreenRotationAnimator::display_id() const { |
| + return display_id_; |
| +} |
| + |
| +bool ScreenRotationAnimator::is_animating() const { |
| + return is_animating_; |
| +} |
| - if (current_rotation == new_rotation) |
| - return; |
| +void ScreenRotationAnimator::set_is_animating(bool rotating) { |
| + is_animating_ = rotating; |
| +} |
| + |
| +ScreenRotationAnimator::ScreenRotationAnimatorObserver* |
| +ScreenRotationAnimator::observer() const { |
| + return observer_; |
| +} |
| + |
| +void ScreenRotationAnimator::SetObserver( |
| + ScreenRotationAnimatorObserver* observer) { |
| + observer_ = observer; |
| +} |
| + |
| +void ScreenRotationAnimator::RemoveObserver() { |
| + if (observer_) |
| + observer_ = nullptr; |
| +} |
| + |
| +ui::LayerTreeOwner* ScreenRotationAnimator::old_layer_tree_owner() const { |
| + return old_layer_tree_owner_.get(); |
| +} |
| + |
| +void ScreenRotationAnimator::reset_old_layer_tree_owner() { |
| + old_layer_tree_owner_.reset(); |
| +} |
| - RotateScreen(display_id_, new_rotation, source); |
| +void ScreenRotationAnimator::set_old_layer_tree_owner( |
| + ui::LayerTreeOwner* layer_tree_owner) { |
| + old_layer_tree_owner_.reset(layer_tree_owner); |
| +} |
| + |
| +ScreenRotationAnimator::ScreenRotationRequest* |
| +ScreenRotationAnimator::last_pending_request() const { |
| + return last_pending_request_.get(); |
| +} |
| + |
| +void ScreenRotationAnimator::reset_last_pending_request() { |
| + last_pending_request_.reset(); |
| +} |
| + |
| +base::WeakPtr<ScreenRotationAnimator> ScreenRotationAnimator::WeakPtr() { |
| + return weak_factory_.GetWeakPtr(); |
| +} |
| + |
| +void ScreenRotationAnimator::Rotate(display::Display::Rotation new_rotation, |
| + display::Display::RotationSource source) { |
| + std::unique_ptr<ScreenRotationRequest> rotation_request = |
| + base::MakeUnique<ScreenRotationRequest>(); |
| + rotation_request->animator = this; |
| + rotation_request->display_id = display_id_; |
| + rotation_request->initial_rotation = GetCurrentRotation(); |
| + rotation_request->new_rotation = new_rotation; |
| + rotation_request->source = source; |
| + |
| + if (is_animating()) { |
| + last_pending_request_.reset(rotation_request.release()); |
| + |
| + aura::Window* root_window = GetRootWindow(display_id_); |
| + for (ui::Layer* child_layer : root_window->layer()->children()) { |
| + if (old_layer_tree_owner_ && child_layer == old_layer_tree_owner_->root()) |
| + continue; |
| + |
| + child_layer->GetAnimator()->StopAnimating(); |
| + } |
| + |
| + if (old_layer_tree_owner_) { |
| + old_layer_tree_owner_->root()->GetAnimator()->StopAnimating(); |
| + } |
| + } else { |
| + RotateScreen(*rotation_request); |
| + rotation_request.reset(); |
| + } |
| } |
| } // namespace ash |