| Index: ash/rotator/screen_rotation_animator.cc
|
| diff --git a/ash/rotator/screen_rotation_animator.cc b/ash/rotator/screen_rotation_animator.cc
|
| index 31a54537dd859ca1f3d8535baabb1442e81af0d6..f52bdb723306525b2ebae1c88afc5025a93e4783 100644
|
| --- a/ash/rotator/screen_rotation_animator.cc
|
| +++ b/ash/rotator/screen_rotation_animator.cc
|
| @@ -8,12 +8,15 @@
|
| #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_lock.h"
|
| #include "ash/rotator/screen_rotation_animator_observer.h"
|
| #include "ash/shell.h"
|
| #include "ash/utility/transformer_util.h"
|
| +#include "ash/wallpaper/wallpaper_controller.h"
|
| #include "base/command_line.h"
|
| #include "base/memory/ptr_util.h"
|
| #include "base/metrics/histogram_macros.h"
|
| +#include "base/threading/thread_task_runner_handle.h"
|
| #include "base/time/time.h"
|
| #include "cc/output/copy_output_request.h"
|
| #include "cc/output/copy_output_result.h"
|
| @@ -41,14 +44,17 @@ namespace ash {
|
| namespace {
|
|
|
| // The number of degrees that the rotation animations animate through.
|
| -const int kRotationDegrees = 20;
|
| +constexpr int kRotationDegrees = 20;
|
|
|
| // The time it takes for the rotation animations to run.
|
| -const int kRotationDurationInMs = 250;
|
| +constexpr int kRotationDurationInMs = 250;
|
| +
|
| +// The timeout for waiting |ScreenRotationAnimatorLock|.
|
| +constexpr int kAnimatorLockTimeoutMs = 500;
|
|
|
| // The rotation factors.
|
| -const int kCounterClockWiseRotationFactor = 1;
|
| -const int kClockWiseRotationFactor = -1;
|
| +constexpr int kCounterClockWiseRotationFactor = 1;
|
| +constexpr int kClockWiseRotationFactor = -1;
|
|
|
| display::Display::Rotation GetCurrentScreenRotation(int64_t display_id) {
|
| return Shell::Get()
|
| @@ -176,9 +182,11 @@ ScreenRotationAnimator::ScreenRotationAnimator(int64_t display_id)
|
| root_window_(GetRootWindow(display_id_)),
|
| screen_rotation_container_layer_(
|
| GetScreenRotationContainer(root_window_)->layer()),
|
| - weak_factory_(this) {}
|
| + weak_factory_(this),
|
| + lock_weak_ptr_factory_(this) {}
|
|
|
| ScreenRotationAnimator::~ScreenRotationAnimator() {
|
| + lock_weak_ptr_factory_.InvalidateWeakPtrs();
|
| // To prevent a call to |AnimationEndedCallback()| from calling a method on
|
| // the |animator_|.
|
| weak_factory_.InvalidateWeakPtrs();
|
| @@ -201,6 +209,14 @@ void ScreenRotationAnimator::StartRotationAnimation(
|
| return;
|
| }
|
|
|
| + // The |ScreenRotationAnimatorLock| will be reset in |ProcessAnimationQueue|
|
| + // when animation is finished.
|
| + // |ScreenRotationAnimatorLock| will only work in the smooth animation. But
|
| + // for simplicity, set/reset the lock for both slow/smooth animation.
|
| + // If we need to wait for multiple event, e.g. ARC app resize, we can add more
|
| + // locks here.
|
| + Shell::Get()->wallpaper_controller()->SetScreenRotationAnimatorLock(
|
| + CreateAnimatorLock());
|
| rotation_request->old_rotation = current_rotation;
|
| if (has_switch_ash_disable_smooth_screen_rotation_) {
|
| StartSlowAnimation(std::move(rotation_request));
|
| @@ -285,10 +301,17 @@ void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation(
|
| 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));
|
| +
|
| + // If the rotation angle is 180 degree, there is no resize.
|
| + if (Is180DegreeFlip(rotation_request->old_rotation,
|
| + rotation_request->new_rotation)) {
|
| + std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
|
| + cc::CopyOutputRequest::CreateRequest(
|
| + CreateAfterCopyCallbackAfterRotation(std::move(rotation_request)));
|
| + RequestCopyScreenRotationContainerLayer(std::move(copy_output_request));
|
| + } else {
|
| + rotation_request_after_unlock_ = std::move(rotation_request);
|
| + }
|
| }
|
|
|
| void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation(
|
| @@ -469,6 +492,7 @@ void ScreenRotationAnimator::ProcessAnimationQueue() {
|
| old_layer_tree_owner_.reset();
|
| new_layer_tree_owner_.reset();
|
| black_mask_layer_owner_.reset();
|
| + ResetCreatedAnimatorLocks();
|
| if (last_pending_request_ && IsDisplayIdValid(display_id_)) {
|
| StartRotationAnimation(std::move(last_pending_request_));
|
| return;
|
| @@ -490,4 +514,55 @@ void ScreenRotationAnimator::StopAnimating() {
|
| root_window_->layer()->Remove(black_mask_layer_owner_->layer());
|
| }
|
|
|
| +ScreenRotationAnimatorLock* ScreenRotationAnimator::CreateAnimatorLock() {
|
| + auto lock_unique_ptr = base::MakeUnique<ScreenRotationAnimatorLock>(
|
| + lock_weak_ptr_factory_.GetWeakPtr());
|
| + auto* lock = lock_unique_ptr.get();
|
| + created_locks_.push_back(std::move(lock_unique_ptr));
|
| + return lock;
|
| +}
|
| +
|
| +void ScreenRotationAnimator::AddAnimatorLock(ScreenRotationAnimatorLock* lock) {
|
| + bool was_empty = active_locks_.empty();
|
| + active_locks_.push_back(lock);
|
| + if (was_empty) {
|
| + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
| + FROM_HERE,
|
| + base::Bind(&ScreenRotationAnimator::TimeoutAnimatorLocks,
|
| + lock_weak_ptr_factory_.GetWeakPtr()),
|
| + base::TimeDelta::FromMilliseconds(kAnimatorLockTimeoutMs));
|
| + }
|
| +}
|
| +
|
| +void ScreenRotationAnimator::RemoveAnimatorLock(
|
| + ScreenRotationAnimatorLock* lock) {
|
| + base::Erase(active_locks_, lock);
|
| + if (active_locks_.empty()) {
|
| + lock_weak_ptr_factory_.InvalidateWeakPtrs();
|
| + // If we are waiting for the lock, we should send the second copy request
|
| + // after screen rotation.
|
| + if (rotation_request_after_unlock_) {
|
| + std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
|
| + cc::CopyOutputRequest::CreateRequest(
|
| + CreateAfterCopyCallbackAfterRotation(
|
| + std::move(rotation_request_after_unlock_)));
|
| + RequestCopyScreenRotationContainerLayer(std::move(copy_output_request));
|
| + }
|
| + }
|
| +}
|
| +
|
| +void ScreenRotationAnimator::TimeoutAnimatorLocks() {
|
| + // Make a copy, we're going to cause |active_locks_| to become
|
| + // empty
|
| + std::vector<ScreenRotationAnimatorLock*> locks = active_locks_;
|
| + for (auto* lock : locks)
|
| + lock->TimeoutLock();
|
| + DCHECK(active_locks_.empty());
|
| +}
|
| +
|
| +void ScreenRotationAnimator::ResetCreatedAnimatorLocks() {
|
| + created_locks_.clear();
|
| + active_locks_.clear();
|
| +}
|
| +
|
| } // namespace ash
|
|
|