diff options
author | antrim@chromium.org <antrim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-03 15:40:26 +0000 |
---|---|---|
committer | antrim@chromium.org <antrim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-03 15:40:26 +0000 |
commit | 2e27010cb42190d75c2dcbd261d3eacda52a61cd (patch) | |
tree | 4399d185177a2c7ebc8c5df5e858a7e37db12ad2 /ash/wm | |
parent | 0a3ca08ab7bb1ec5fa88fd7eaf96f51321d8129e (diff) | |
download | chromium_src-2e27010cb42190d75c2dcbd261d3eacda52a61cd.zip chromium_src-2e27010cb42190d75c2dcbd261d3eacda52a61cd.tar.gz chromium_src-2e27010cb42190d75c2dcbd261d3eacda52a61cd.tar.bz2 |
Refactoring part 1 : extract animator
BUG=138171,139461
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=159690
Review URL: https://chromiumcodereview.appspot.com/10914016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@159896 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/wm')
-rw-r--r-- | ash/wm/power_button_controller.cc | 390 | ||||
-rw-r--r-- | ash/wm/power_button_controller.h | 90 | ||||
-rw-r--r-- | ash/wm/power_button_controller_unittest.cc | 148 | ||||
-rw-r--r-- | ash/wm/session_state_animator.cc | 312 | ||||
-rw-r--r-- | ash/wm/session_state_animator.h | 150 |
5 files changed, 627 insertions, 463 deletions
diff --git a/ash/wm/power_button_controller.cc b/ash/wm/power_button_controller.cc index 58c8181..bd9bb91 100644 --- a/ash/wm/power_button_controller.cc +++ b/ash/wm/power_button_controller.cc @@ -8,23 +8,10 @@ #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/shell_window_ids.h" -#include "ash/wm/cursor_manager.h" +#include "ash/wm/session_state_animator.h" #include "base/command_line.h" -#include "base/logging.h" -#include "base/time.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/aura/env.h" #include "ui/aura/root_window.h" #include "ui/aura/shared/compound_event_filter.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/layer_animation_element.h" -#include "ui/compositor/layer_animation_sequence.h" -#include "ui/compositor/layer_animator.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/size.h" -#include "ui/gfx/transform.h" namespace ash { @@ -59,256 +46,20 @@ const int kUndoSlowCloseAnimMs = 100; // system is shutting down. const int kFastCloseAnimMs = 150; -// Amount of time taken to make the lock window fade in when the screen is -// locked. -const int kLockFadeInAnimMs = 200; - // Additional time (beyond kFastCloseAnimMs) to wait after starting the // fast-close shutdown animation before actually requesting shutdown, to give // the animation time to finish. const int kShutdownRequestDelayMs = 50; -// Slightly-smaller size that we scale the screen down to for the pre-lock and -// pre-shutdown states. -const float kSlowCloseSizeRatio = 0.95f; - -// Returns the transform that should be applied to containers for the slow-close -// animation. -ui::Transform GetSlowCloseTransform() { - gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size(); - ui::Transform transform; - transform.SetScale(kSlowCloseSizeRatio, kSlowCloseSizeRatio); - transform.ConcatTranslate( - floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.width() + 0.5), - floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.height() + 0.5)); - return transform; -} - -// Returns the transform that should be applied to containers for the fast-close -// animation. -ui::Transform GetFastCloseTransform() { - gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size(); - ui::Transform transform; - transform.SetScale(0.0, 0.0); - transform.ConcatTranslate(floor(0.5 * root_size.width() + 0.5), - floor(0.5 * root_size.height() + 0.5)); - return transform; -} - -// Slowly shrinks |window| to a slightly-smaller size. -void StartSlowCloseAnimationForWindow(aura::Window* window) { - ui::LayerAnimator* animator = window->layer()->GetAnimator(); - animator->set_preemption_strategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - animator->StartAnimation( - new ui::LayerAnimationSequence( - ui::LayerAnimationElement::CreateTransformElement( - GetSlowCloseTransform(), - base::TimeDelta::FromMilliseconds(kSlowCloseAnimMs)))); -} - -// Quickly undoes the effects of the slow-close animation on |window|. -void StartUndoSlowCloseAnimationForWindow(aura::Window* window) { - ui::LayerAnimator* animator = window->layer()->GetAnimator(); - animator->set_preemption_strategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - animator->StartAnimation( - new ui::LayerAnimationSequence( - ui::LayerAnimationElement::CreateTransformElement( - ui::Transform(), - base::TimeDelta::FromMilliseconds(kUndoSlowCloseAnimMs)))); -} - -// Quickly shrinks |window| down to a point in the center of the screen and -// fades it out to 0 opacity. -void StartFastCloseAnimationForWindow(aura::Window* window) { - ui::LayerAnimator* animator = window->layer()->GetAnimator(); - animator->set_preemption_strategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - animator->StartAnimation( - new ui::LayerAnimationSequence( - ui::LayerAnimationElement::CreateTransformElement( - GetFastCloseTransform(), - base::TimeDelta::FromMilliseconds(kFastCloseAnimMs)))); - animator->StartAnimation( - new ui::LayerAnimationSequence( - ui::LayerAnimationElement::CreateOpacityElement( - 0.0, base::TimeDelta::FromMilliseconds(kFastCloseAnimMs)))); -} - -// Fades |window| in to full opacity. -void FadeInWindow(aura::Window* window) { - ui::LayerAnimator* animator = window->layer()->GetAnimator(); - animator->set_preemption_strategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - animator->StartAnimation( - new ui::LayerAnimationSequence( - ui::LayerAnimationElement::CreateOpacityElement( - 1.0, base::TimeDelta::FromMilliseconds(kLockFadeInAnimMs)))); -} - -// Makes |window| fully transparent instantaneously. -void HideWindow(aura::Window* window) { - window->layer()->SetOpacity(0.0); -} - -// Restores |window| to its original position and scale and full opacity -// instantaneously. -void RestoreWindow(aura::Window* window) { - window->layer()->SetTransform(ui::Transform()); - window->layer()->SetOpacity(1.0); -} - -// Fills |containers| with the containers described by |container_mask|. -void GetContainers(int container_mask, aura::Window::Windows* containers) { - aura::RootWindow* root_window = Shell::GetPrimaryRootWindow(); - containers->clear(); - - if (container_mask & PowerButtonController::DESKTOP_BACKGROUND) { - containers->push_back(Shell::GetContainer( - root_window, - internal::kShellWindowId_DesktopBackgroundContainer)); - } - if (container_mask & PowerButtonController::LAUNCHER) { - containers->push_back(Shell::GetContainer( - root_window, - internal::kShellWindowId_LauncherContainer)); - } - if (container_mask & PowerButtonController::NON_LOCK_SCREEN_CONTAINERS) { - // TODO(antrim): Figure out a way to eliminate a need to exclude launcher - // in such way. - aura::Window* non_lock_screen_containers = Shell::GetContainer( - root_window, - internal::kShellWindowId_NonLockScreenContainersContainer); - aura::Window::Windows children = non_lock_screen_containers->children(); - - for (aura::Window::Windows::const_iterator it = children.begin(); - it != children.end(); ++it) { - aura::Window* window = *it; - if (window->id() == internal::kShellWindowId_LauncherContainer) - continue; - containers->push_back(window); - } - } - if (container_mask & PowerButtonController::LOCK_SCREEN_BACKGROUND) { - containers->push_back(Shell::GetContainer( - root_window, - internal::kShellWindowId_LockScreenBackgroundContainer)); - } - if (container_mask & PowerButtonController::LOCK_SCREEN_CONTAINERS) { - containers->push_back(Shell::GetContainer( - root_window, - internal::kShellWindowId_LockScreenContainersContainer)); - } - if (container_mask & PowerButtonController::LOCK_SCREEN_RELATED_CONTAINERS) { - containers->push_back(Shell::GetContainer( - root_window, - internal::kShellWindowId_LockScreenRelatedContainersContainer)); - } -} - -// Apply animation |type| to all containers described by |container_mask|. -void StartAnimation(int container_mask, - PowerButtonController::AnimationType type) { - aura::Window::Windows containers; - GetContainers(container_mask, &containers); - - for (aura::Window::Windows::const_iterator it = containers.begin(); - it != containers.end(); ++it) { - aura::Window* window = *it; - switch (type) { - case PowerButtonController::ANIMATION_SLOW_CLOSE: - StartSlowCloseAnimationForWindow(window); - break; - case PowerButtonController::ANIMATION_UNDO_SLOW_CLOSE: - StartUndoSlowCloseAnimationForWindow(window); - break; - case PowerButtonController::ANIMATION_FAST_CLOSE: - StartFastCloseAnimationForWindow(window); - break; - case PowerButtonController::ANIMATION_FADE_IN: - FadeInWindow(window); - break; - case PowerButtonController::ANIMATION_HIDE: - HideWindow(window); - break; - case PowerButtonController::ANIMATION_RESTORE: - RestoreWindow(window); - break; - default: - NOTREACHED() << "Unhandled animation type " << type; - } - } -} - } // namespace -bool PowerButtonController::TestApi::ContainersAreAnimated( - int container_mask, AnimationType type) const { - aura::Window::Windows containers; - GetContainers(container_mask, &containers); - for (aura::Window::Windows::const_iterator it = containers.begin(); - it != containers.end(); ++it) { - aura::Window* window = *it; - ui::Layer* layer = window->layer(); - - switch (type) { - case PowerButtonController::ANIMATION_SLOW_CLOSE: - if (layer->GetTargetTransform() != GetSlowCloseTransform()) - return false; - break; - case PowerButtonController::ANIMATION_UNDO_SLOW_CLOSE: - if (layer->GetTargetTransform() != ui::Transform()) - return false; - break; - case PowerButtonController::ANIMATION_FAST_CLOSE: - if (layer->GetTargetTransform() != GetFastCloseTransform() || - layer->GetTargetOpacity() > 0.0001) - return false; - break; - case PowerButtonController::ANIMATION_FADE_IN: - if (layer->GetTargetOpacity() < 0.9999) - return false; - break; - case PowerButtonController::ANIMATION_HIDE: - if (layer->GetTargetOpacity() > 0.0001) - return false; - break; - case PowerButtonController::ANIMATION_RESTORE: - if (layer->opacity() < 0.9999 || layer->transform() != ui::Transform()) - return false; - break; - default: - NOTREACHED() << "Unhandled animation type " << type; - return false; - } - } - return true; -} - -bool PowerButtonController::TestApi::BlackLayerIsVisible() const { - return controller_->black_layer_.get() && - controller_->black_layer_->visible(); -} - -gfx::Rect PowerButtonController::TestApi::GetBlackLayerBounds() const { - ui::Layer* layer = controller_->black_layer_.get(); - return layer ? layer->bounds() : gfx::Rect(); +PowerButtonController::TestApi::TestApi(PowerButtonController* controller) + : controller_(controller), + animator_api_(new internal::SessionStateAnimator::TestApi( + controller->animator_.get())) { } -// static -int PowerButtonController::GetAllContainersMask() { - return PowerButtonController::DESKTOP_BACKGROUND | - PowerButtonController::LAUNCHER | - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS | - GetAllLockScreenContainersMask(); -} - -// static -int PowerButtonController::GetAllLockScreenContainersMask() { - return PowerButtonController::LOCK_SCREEN_BACKGROUND | - PowerButtonController::LOCK_SCREEN_CONTAINERS | - PowerButtonController::LOCK_SCREEN_RELATED_CONTAINERS; +PowerButtonController::TestApi::~TestApi() { } PowerButtonController::PowerButtonController() @@ -320,7 +71,8 @@ PowerButtonController::PowerButtonController() shutting_down_(false), has_legacy_power_button_( CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAuraLegacyPowerButton)) { + switches::kAuraLegacyPowerButton)), + animator_(new internal::SessionStateAnimator()) { Shell::GetPrimaryRootWindow()->AddRootWindowObserver(this); } @@ -341,8 +93,10 @@ void PowerButtonController::OnAppTerminating() { Shell* shell = ash::Shell::GetInstance(); shell->env_filter()->set_cursor_hidden_by_filter(false); shell->cursor_manager()->ShowCursor(false); - ShowBlackLayer(); - StartAnimation(GetAllContainersMask(), ANIMATION_HIDE); + animator_->ShowBlackLayer(); + animator_->StartAnimation( + internal::SessionStateAnimator::kAllContainersMask, + internal::SessionStateAnimator::ANIMATION_HIDE); } } @@ -359,7 +113,9 @@ void PowerButtonController::OnLockStateChanged(bool locked) { } if (locked) { - StartAnimation(LOCK_SCREEN_CONTAINERS, ANIMATION_FADE_IN); + animator_->StartAnimation( + internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_FADE_IN); lock_timer_.Stop(); lock_fail_timer_.Stop(); @@ -371,9 +127,12 @@ void PowerButtonController::OnLockStateChanged(bool locked) { this, &PowerButtonController::OnLockToShutdownTimeout); } } else { - StartAnimation(DESKTOP_BACKGROUND | LAUNCHER | NON_LOCK_SCREEN_CONTAINERS, - ANIMATION_RESTORE); - HideBlackLayer(); + animator_->StartAnimation( + internal::SessionStateAnimator::DESKTOP_BACKGROUND | + internal::SessionStateAnimator::LAUNCHER | + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_RESTORE); + animator_->DropBlackLayer(); } } @@ -388,14 +147,20 @@ void PowerButtonController::OnStartingLock() { // Ensure that the black layer is visible -- if the screen was locked via // the wrench menu, we won't have already shown the black background // as part of the slow-close animation. - ShowBlackLayer(); + animator_->ShowBlackLayer(); - StartAnimation(LAUNCHER, ANIMATION_HIDE); + animator_->StartAnimation( + internal::SessionStateAnimator::LAUNCHER, + internal::SessionStateAnimator::ANIMATION_HIDE); - StartAnimation(NON_LOCK_SCREEN_CONTAINERS, ANIMATION_FAST_CLOSE); + animator_->StartAnimation( + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_FAST_CLOSE); // Hide the screen locker containers so we can make them fade in later. - StartAnimation(LOCK_SCREEN_CONTAINERS, ANIMATION_HIDE); + animator_->StartAnimation( + internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_HIDE); } void PowerButtonController::OnPowerButtonEvent( @@ -415,9 +180,11 @@ void PowerButtonController::OnPowerButtonEvent( // running on official hardware, just lock the screen or shut down // immediately. if (down) { - ShowBlackLayer(); + animator_->ShowBlackLayer(); if (LoggedInAsNonGuest() && login_status_ != user::LOGGED_IN_LOCKED) { - StartAnimation(NON_LOCK_SCREEN_CONTAINERS, ANIMATION_SLOW_CLOSE); + animator_->StartAnimation( + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE); OnLockTimeout(); } else { OnShutdownTimeout(); @@ -438,22 +205,21 @@ void PowerButtonController::OnPowerButtonEvent( if (login_status_ == user::LOGGED_IN_LOCKED) { // If we've already started shutdown transition at lock screen // desktop background needs to be restored immediately. - StartAnimation(DESKTOP_BACKGROUND, ANIMATION_RESTORE); + animator_->StartAnimation( + internal::SessionStateAnimator::DESKTOP_BACKGROUND, + internal::SessionStateAnimator::ANIMATION_RESTORE); } - StartAnimation( + animator_->StartAnimation( (login_status_ == user::LOGGED_IN_LOCKED) ? - GetAllLockScreenContainersMask() : GetAllContainersMask(), - ANIMATION_UNDO_SLOW_CLOSE); + internal::SessionStateAnimator::kAllLockScreenContainersMask : + internal::SessionStateAnimator::kAllContainersMask, + internal::SessionStateAnimator::ANIMATION_UNDO_SLOW_CLOSE); } // Drop the black layer after the undo animation finishes. if (lock_timer_.IsRunning() || (shutdown_timer_.IsRunning() && !LoggedInAsNonGuest())) { - hide_black_layer_timer_.Stop(); - hide_black_layer_timer_.Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds(kUndoSlowCloseAnimMs), - this, &PowerButtonController::HideBlackLayer); + animator_->ScheduleDropBlackLayer(); } lock_timer_.Stop(); @@ -482,12 +248,10 @@ void PowerButtonController::OnLockButtonEvent( StartLockTimer(); } else { if (lock_timer_.IsRunning()) { - StartAnimation(NON_LOCK_SCREEN_CONTAINERS, ANIMATION_UNDO_SLOW_CLOSE); - hide_black_layer_timer_.Stop(); - hide_black_layer_timer_.Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds(kUndoSlowCloseAnimMs), - this, &PowerButtonController::HideBlackLayer); + animator_->StartAnimation( + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_UNDO_SLOW_CLOSE); + animator_->ScheduleDropBlackLayer(); lock_timer_.Stop(); } } @@ -498,12 +262,6 @@ void PowerButtonController::RequestShutdown() { StartShutdownAnimationAndRequestShutdown(); } -void PowerButtonController::OnRootWindowResized(const aura::RootWindow* root, - const gfx::Size& new_size) { - if (black_layer_.get()) - black_layer_->SetBounds(gfx::Rect(root->bounds().size())); -} - void PowerButtonController::OnRootWindowHostCloseRequested( const aura::RootWindow*) { if(Shell::GetInstance() && Shell::GetInstance()->delegate()) @@ -530,8 +288,11 @@ void PowerButtonController::OnLockTimeout() { void PowerButtonController::OnLockFailTimeout() { DCHECK_NE(login_status_, user::LOGGED_IN_LOCKED); LOG(ERROR) << "Screen lock request timed out"; - StartAnimation(LAUNCHER | NON_LOCK_SCREEN_CONTAINERS, ANIMATION_RESTORE); - HideBlackLayer(); + animator_->StartAnimation( + internal::SessionStateAnimator::LAUNCHER | + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_RESTORE); + animator_->DropBlackLayer(); } void PowerButtonController::OnLockToShutdownTimeout() { @@ -550,8 +311,10 @@ void PowerButtonController::OnRealShutdownTimeout() { } void PowerButtonController::StartLockTimer() { - ShowBlackLayer(); - StartAnimation(NON_LOCK_SCREEN_CONTAINERS, ANIMATION_SLOW_CLOSE); + animator_->ShowBlackLayer(); + animator_->StartAnimation( + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE); lock_timer_.Stop(); lock_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kSlowCloseAnimMs), @@ -559,8 +322,10 @@ void PowerButtonController::StartLockTimer() { } void PowerButtonController::StartShutdownTimer() { - ShowBlackLayer(); - StartAnimation(GetAllContainersMask(), ANIMATION_SLOW_CLOSE); + animator_->ShowBlackLayer(); + animator_->StartAnimation( + internal::SessionStateAnimator::kAllContainersMask, + internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE); shutdown_timer_.Stop(); shutdown_timer_.Start( FROM_HERE, @@ -576,15 +341,22 @@ void PowerButtonController::StartShutdownAnimationAndRequestShutdown() { shell->env_filter()->set_cursor_hidden_by_filter(false); shell->cursor_manager()->ShowCursor(false); - ShowBlackLayer(); + animator_->ShowBlackLayer(); if (login_status_ != user::LOGGED_IN_NONE) { // Hide the other containers before starting the animation. // ANIMATION_FAST_CLOSE will make the screen locker windows partially // transparent, and we don't want the other windows to show through. - StartAnimation(LAUNCHER | NON_LOCK_SCREEN_CONTAINERS, ANIMATION_HIDE); - StartAnimation(GetAllLockScreenContainersMask(), ANIMATION_FAST_CLOSE); + animator_->StartAnimation( + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS | + internal::SessionStateAnimator::LAUNCHER, + internal::SessionStateAnimator::ANIMATION_HIDE); + animator_->StartAnimation( + internal::SessionStateAnimator::kAllLockScreenContainersMask, + internal::SessionStateAnimator::ANIMATION_FAST_CLOSE); } else { - StartAnimation(GetAllContainersMask(), ANIMATION_FAST_CLOSE); + animator_->StartAnimation( + internal::SessionStateAnimator::kAllContainersMask, + internal::SessionStateAnimator::ANIMATION_FAST_CLOSE); } real_shutdown_timer_.Start( @@ -594,24 +366,4 @@ void PowerButtonController::StartShutdownAnimationAndRequestShutdown() { this, &PowerButtonController::OnRealShutdownTimeout); } -void PowerButtonController::ShowBlackLayer() { - if (hide_black_layer_timer_.IsRunning()) - hide_black_layer_timer_.Stop(); - - if (!black_layer_.get()) { - black_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); - black_layer_->SetColor(SK_ColorBLACK); - - ui::Layer* root_layer = Shell::GetPrimaryRootWindow()->layer(); - black_layer_->SetBounds(root_layer->bounds()); - root_layer->Add(black_layer_.get()); - root_layer->StackAtBottom(black_layer_.get()); - } - black_layer_->SetVisible(true); -} - -void PowerButtonController::HideBlackLayer() { - black_layer_.reset(); -} - } // namespace ash diff --git a/ash/wm/power_button_controller.h b/ash/wm/power_button_controller.h index 29b99a2..db8ec4f 100644 --- a/ash/wm/power_button_controller.h +++ b/ash/wm/power_button_controller.h @@ -7,6 +7,7 @@ #include "ash/ash_export.h" #include "ash/shell_observer.h" +#include "ash/wm/session_state_animator.h" #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "base/time.h" @@ -42,47 +43,13 @@ class ASH_EXPORT PowerButtonControllerDelegate { class ASH_EXPORT PowerButtonController : public aura::RootWindowObserver, public ShellObserver { public: - // Animations that can be applied to groups of containers. - // Exposed here for TestApi::ContainersAreAnimated(). - enum AnimationType { - ANIMATION_SLOW_CLOSE = 0, - ANIMATION_UNDO_SLOW_CLOSE, - ANIMATION_FAST_CLOSE, - ANIMATION_FADE_IN, - ANIMATION_HIDE, - ANIMATION_RESTORE, - }; - - // Specific containers or groups of containers that can be animated. - // Exposed here for TestApi::ContainersAreAnimated(). - enum Container { - DESKTOP_BACKGROUND = 1 << 0, - - LAUNCHER = 1 << 1, - - // All user session related containers including system background but - // not including desktop background (wallpaper) and launcher. - NON_LOCK_SCREEN_CONTAINERS = 1 << 2, - - // Desktop wallpaper is moved to this layer when screen is locked. - // This layer is excluded from lock animation so that wallpaper stays as is, - // user session windows are hidden and lock UI is shown on top of it. - // This layer is included in shutdown animation. - LOCK_SCREEN_BACKGROUND = 1 << 3, - - // Lock screen and lock screen modal containers. - LOCK_SCREEN_CONTAINERS = 1 << 4, - - // Multiple system layers belong here like status, menu, tooltip - // and overlay layers. - LOCK_SCREEN_RELATED_CONTAINERS = 1 << 5, - }; // Helper class used by tests to access internal state. class ASH_EXPORT TestApi { public: - explicit TestApi(PowerButtonController* controller) - : controller_(controller) {} + explicit TestApi(PowerButtonController* controller); + + virtual ~TestApi(); bool lock_timer_is_running() const { return controller_->lock_timer_.IsRunning(); @@ -100,7 +67,7 @@ class ASH_EXPORT PowerButtonController : public aura::RootWindowObserver, return controller_->real_shutdown_timer_.IsRunning(); } bool hide_black_layer_timer_is_running() const { - return controller_->hide_black_layer_timer_.IsRunning(); + return animator_api_->hide_black_layer_timer_is_running(); } void trigger_lock_timeout() { @@ -123,36 +90,37 @@ class ASH_EXPORT PowerButtonController : public aura::RootWindowObserver, controller_->OnRealShutdownTimeout(); controller_->real_shutdown_timer_.Stop(); } - void trigger_hide_black_layer_timeout() { - controller_->HideBlackLayer(); - controller_->hide_black_layer_timer_.Stop(); + void TriggerHideBlackLayerTimeout() { + animator_api_->TriggerHideBlackLayerTimeout(); } // Returns true if containers of a given |container_mask| // were last animated with |type| (probably; the analysis is fairly ad-hoc). // |container_mask| is a bitfield of a Container. - bool ContainersAreAnimated(int container_mask, AnimationType type) const; + bool ContainersAreAnimated(int container_mask, + internal::SessionStateAnimator::AnimationType type) const { + return animator_api_->ContainersAreAnimated(container_mask, type); + } // Returns true if |black_layer_| is non-NULL and visible. - bool BlackLayerIsVisible() const; + bool BlackLayerIsVisible() { + return animator_api_->BlackLayerIsVisible(); + } // Returns |black_layer_|'s bounds, or an empty rect if the layer is // NULL. - gfx::Rect GetBlackLayerBounds() const; + gfx::Rect GetBlackLayerBounds() const { + return animator_api_->GetBlackLayerBounds(); + } private: PowerButtonController* controller_; // not owned + scoped_ptr<internal::SessionStateAnimator::TestApi> animator_api_; + DISALLOW_COPY_AND_ASSIGN(TestApi); }; - // Helper method that returns a bitfield mask of all containers. - static int GetAllContainersMask(); - - // Helper method that returns a bitfield mask including LOCK_SCREEN_WALLPAPER, - // LOCK_SCREEN_CONTAINERS, and LOCK_SCREEN_RELATED_CONTAINERS. - static int GetAllLockScreenContainersMask(); - PowerButtonController(); virtual ~PowerButtonController(); @@ -177,9 +145,6 @@ class ASH_EXPORT PowerButtonController : public aura::RootWindowObserver, // Displays the shutdown animation and requests shutdown when it's done. void RequestShutdown(); - // aura::RootWindowObserver overrides: - virtual void OnRootWindowResized(const aura::RootWindow* root, - const gfx::Size& old_size) OVERRIDE; virtual void OnRootWindowHostCloseRequested( const aura::RootWindow* root) OVERRIDE; @@ -213,11 +178,6 @@ class ASH_EXPORT PowerButtonController : public aura::RootWindowObserver, // Displays the shutdown animation and starts |real_shutdown_timer_|. void StartShutdownAnimationAndRequestShutdown(); - // Shows or hides |black_layer_|. The show method creates and - // initializes the layer if it doesn't already exist. - void ShowBlackLayer(); - void HideBlackLayer(); - scoped_ptr<PowerButtonControllerDelegate> delegate_; // The current login status. @@ -240,13 +200,6 @@ class ASH_EXPORT PowerButtonController : public aura::RootWindowObserver, // that misreports power button releases? bool has_legacy_power_button_; - // Layer that's stacked under all of the root window's children to provide a - // black background when we're scaling all of the other windows down. - // TODO(derat): Remove this in favor of having the compositor only clear the - // viewport when there are regions not covered by a layer: - // http://crbug.com/113445 - scoped_ptr<ui::Layer> black_layer_; - // Started when the user first presses the power button while in a // logged-in-as-a-non-guest-user, unlocked state. When it fires, we lock the // screen. @@ -270,10 +223,7 @@ class ASH_EXPORT PowerButtonController : public aura::RootWindowObserver, // etc. are shut down. base::OneShotTimer<PowerButtonController> real_shutdown_timer_; - // Started when we abort the pre-lock state. When it fires, we hide - // |black_layer_|, as the desktop background is now covering the whole - // screen. - base::OneShotTimer<PowerButtonController> hide_black_layer_timer_; + scoped_ptr<internal::SessionStateAnimator> animator_; DISALLOW_COPY_AND_ASSIGN(PowerButtonController); }; diff --git a/ash/wm/power_button_controller_unittest.cc b/ash/wm/power_button_controller_unittest.cc index 148d4c8..8eb7d54 100644 --- a/ash/wm/power_button_controller_unittest.cc +++ b/ash/wm/power_button_controller_unittest.cc @@ -91,8 +91,8 @@ TEST_F(PowerButtonControllerTest, LegacyLockAndShutDown) { controller_->OnPowerButtonEvent(true, base::TimeTicks::Now()); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_SLOW_CLOSE)); + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); EXPECT_FALSE(test_api_->hide_black_layer_timer_is_running()); EXPECT_FALSE(test_api_->lock_timer_is_running()); @@ -102,23 +102,23 @@ TEST_F(PowerButtonControllerTest, LegacyLockAndShutDown) { controller_->OnStartingLock(); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::LAUNCHER, - PowerButtonController::ANIMATION_HIDE)); + internal::SessionStateAnimator::LAUNCHER, + internal::SessionStateAnimator::ANIMATION_HIDE)); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_FAST_CLOSE)); + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_FAST_CLOSE)); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_HIDE)); + internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_HIDE)); // Notify that the lock window is visible. We should make it fade in. controller_->OnLockStateChanged(true); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::GetAllLockScreenContainersMask(), - PowerButtonController::ANIMATION_FADE_IN)); + internal::SessionStateAnimator::kAllLockScreenContainersMask, + internal::SessionStateAnimator::ANIMATION_FADE_IN)); // We shouldn't progress towards the shutdown state, however. EXPECT_FALSE(test_api_->lock_to_shutdown_timer_is_running()); @@ -140,8 +140,8 @@ TEST_F(PowerButtonControllerTest, LegacyLockAndShutDown) { // containers are animated during shutdown. EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::GetAllLockScreenContainersMask(), - PowerButtonController::ANIMATION_FAST_CLOSE)); + internal::SessionStateAnimator::kAllLockScreenContainersMask, + internal::SessionStateAnimator::ANIMATION_FAST_CLOSE)); // Make sure a mouse move event won't show the cursor. GenerateMouseMoveEvent(); EXPECT_FALSE(cursor_visible()); @@ -184,8 +184,8 @@ TEST_F(PowerButtonControllerTest, ShutdownWhenNotLoggedIn) { EXPECT_TRUE(test_api_->shutdown_timer_is_running()); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::GetAllContainersMask(), - PowerButtonController::ANIMATION_SLOW_CLOSE)); + internal::SessionStateAnimator::kAllContainersMask, + internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); // Release the power button before the shutdown timer fires. @@ -193,14 +193,14 @@ TEST_F(PowerButtonControllerTest, ShutdownWhenNotLoggedIn) { EXPECT_FALSE(test_api_->shutdown_timer_is_running()); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::GetAllContainersMask(), - PowerButtonController::ANIMATION_UNDO_SLOW_CLOSE)); + internal::SessionStateAnimator::kAllContainersMask, + internal::SessionStateAnimator::ANIMATION_UNDO_SLOW_CLOSE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); // We should re-hide the black layer after waiting long enough for // the animation to finish. EXPECT_TRUE(test_api_->hide_black_layer_timer_is_running()); - test_api_->trigger_hide_black_layer_timeout(); + test_api_->TriggerHideBlackLayerTimeout(); EXPECT_FALSE(test_api_->BlackLayerIsVisible()); // Press the button again and make the shutdown timeout fire this time. @@ -212,13 +212,13 @@ TEST_F(PowerButtonControllerTest, ShutdownWhenNotLoggedIn) { EXPECT_EQ(0, delegate_->num_shutdown_requests()); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::LAUNCHER | - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_HIDE)); + internal::SessionStateAnimator::LAUNCHER | + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_HIDE)); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::GetAllLockScreenContainersMask(), - PowerButtonController::ANIMATION_FAST_CLOSE)); + internal::SessionStateAnimator::kAllLockScreenContainersMask, + internal::SessionStateAnimator::ANIMATION_FAST_CLOSE)); // When the timout fires, we should request a shutdown. test_api_->trigger_real_shutdown_timeout(); @@ -237,8 +237,8 @@ TEST_F(PowerButtonControllerTest, LockAndUnlock) { // logging-in animation. EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_RESTORE)); + internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_RESTORE)); // Press the power button and check that the lock timer is started and that we // start scaling the non-screen-locker containers. @@ -247,8 +247,8 @@ TEST_F(PowerButtonControllerTest, LockAndUnlock) { EXPECT_FALSE(test_api_->shutdown_timer_is_running()); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_SLOW_CLOSE)); + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); // Release the button before the lock timer fires. @@ -256,11 +256,11 @@ TEST_F(PowerButtonControllerTest, LockAndUnlock) { EXPECT_FALSE(test_api_->lock_timer_is_running()); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_UNDO_SLOW_CLOSE)); + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_UNDO_SLOW_CLOSE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); EXPECT_TRUE(test_api_->hide_black_layer_timer_is_running()); - test_api_->trigger_hide_black_layer_timeout(); + test_api_->TriggerHideBlackLayerTimeout(); EXPECT_FALSE(test_api_->BlackLayerIsVisible()); // Press the button and fire the lock timer. We should request that the @@ -272,31 +272,31 @@ TEST_F(PowerButtonControllerTest, LockAndUnlock) { EXPECT_EQ(1, delegate_->num_lock_requests()); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_SLOW_CLOSE)); + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); // Notify that we locked successfully. controller_->OnStartingLock(); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::LAUNCHER, - PowerButtonController::ANIMATION_HIDE)); + internal::SessionStateAnimator::LAUNCHER, + internal::SessionStateAnimator::ANIMATION_HIDE)); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_FAST_CLOSE)); + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_FAST_CLOSE)); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_HIDE)); + internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_HIDE)); // Notify that the lock window is visible. We should make it fade in. controller_->OnLockStateChanged(true); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::GetAllLockScreenContainersMask(), - PowerButtonController::ANIMATION_FADE_IN)); + internal::SessionStateAnimator::kAllLockScreenContainersMask, + internal::SessionStateAnimator::ANIMATION_FADE_IN)); // When we release the power button, the lock-to-shutdown timer should be // stopped. @@ -309,10 +309,10 @@ TEST_F(PowerButtonControllerTest, LockAndUnlock) { controller_->OnLockStateChanged(false); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::DESKTOP_BACKGROUND | - PowerButtonController::LAUNCHER | - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_RESTORE)); + internal::SessionStateAnimator::DESKTOP_BACKGROUND | + internal::SessionStateAnimator::LAUNCHER | + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_RESTORE)); EXPECT_FALSE(test_api_->BlackLayerIsVisible()); } @@ -337,8 +337,8 @@ TEST_F(PowerButtonControllerTest, LockToShutdown) { EXPECT_TRUE(test_api_->shutdown_timer_is_running()); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::GetAllContainersMask(), - PowerButtonController::ANIMATION_SLOW_CLOSE)); + internal::SessionStateAnimator::kAllContainersMask, + internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE)); // Fire the shutdown timeout and check that we request shutdown. test_api_->trigger_shutdown_timeout(); @@ -363,10 +363,10 @@ TEST_F(PowerButtonControllerTest, LockFail) { EXPECT_TRUE(test_api_->lock_timer_is_running()); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::DESKTOP_BACKGROUND | - PowerButtonController::LAUNCHER | - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_RESTORE)); + internal::SessionStateAnimator::DESKTOP_BACKGROUND | + internal::SessionStateAnimator::LAUNCHER | + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_RESTORE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); test_api_->trigger_lock_timeout(); EXPECT_EQ(1, delegate_->num_lock_requests()); @@ -380,8 +380,8 @@ TEST_F(PowerButtonControllerTest, LockFail) { test_api_->trigger_lock_fail_timeout(); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_RESTORE)); + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_RESTORE)); EXPECT_FALSE(test_api_->BlackLayerIsVisible()); } @@ -427,8 +427,8 @@ TEST_F(PowerButtonControllerTest, LockButtonBasic) { EXPECT_TRUE(test_api_->lock_timer_is_running()); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_SLOW_CLOSE)); + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); // If the button is released immediately, we shouldn't lock the screen. @@ -436,11 +436,11 @@ TEST_F(PowerButtonControllerTest, LockButtonBasic) { EXPECT_FALSE(test_api_->lock_timer_is_running()); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_UNDO_SLOW_CLOSE)); + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_UNDO_SLOW_CLOSE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); EXPECT_TRUE(test_api_->hide_black_layer_timer_is_running()); - test_api_->trigger_hide_black_layer_timeout(); + test_api_->TriggerHideBlackLayerTimeout(); EXPECT_FALSE(test_api_->BlackLayerIsVisible()); EXPECT_EQ(0, delegate_->num_lock_requests()); @@ -505,8 +505,8 @@ TEST_F(PowerButtonControllerTest, LockWithoutButton) { controller_->OnStartingLock(); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_FAST_CLOSE)); + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_FAST_CLOSE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); } @@ -517,8 +517,8 @@ TEST_F(PowerButtonControllerTest, ShutdownWithoutButton) { controller_->OnAppTerminating(); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::GetAllContainersMask(), - PowerButtonController::ANIMATION_HIDE)); + internal::SessionStateAnimator::kAllContainersMask, + internal::SessionStateAnimator::ANIMATION_HIDE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); GenerateMouseMoveEvent(); EXPECT_FALSE(cursor_visible()); @@ -531,12 +531,12 @@ TEST_F(PowerButtonControllerTest, RequestShutdownFromLoginScreen) { controller_->RequestShutdown(); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_HIDE)); + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_HIDE)); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::GetAllLockScreenContainersMask(), - PowerButtonController::ANIMATION_FAST_CLOSE)); + internal::SessionStateAnimator::kAllLockScreenContainersMask, + internal::SessionStateAnimator::ANIMATION_FAST_CLOSE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); GenerateMouseMoveEvent(); EXPECT_FALSE(cursor_visible()); @@ -553,12 +553,12 @@ TEST_F(PowerButtonControllerTest, RequestShutdownFromLockScreen) { controller_->RequestShutdown(); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::NON_LOCK_SCREEN_CONTAINERS, - PowerButtonController::ANIMATION_HIDE)); + internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, + internal::SessionStateAnimator::ANIMATION_HIDE)); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::GetAllLockScreenContainersMask(), - PowerButtonController::ANIMATION_FAST_CLOSE)); + internal::SessionStateAnimator::kAllLockScreenContainersMask, + internal::SessionStateAnimator::ANIMATION_FAST_CLOSE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); GenerateMouseMoveEvent(); EXPECT_FALSE(cursor_visible()); @@ -579,8 +579,8 @@ TEST_F(PowerButtonControllerTest, RequestAndCancelShutdownFromLockScreen) { EXPECT_TRUE(test_api_->shutdown_timer_is_running()); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::GetAllContainersMask(), - PowerButtonController::ANIMATION_SLOW_CLOSE)); + internal::SessionStateAnimator::kAllContainersMask, + internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); // Release the power button before the shutdown timer fires. @@ -588,12 +588,12 @@ TEST_F(PowerButtonControllerTest, RequestAndCancelShutdownFromLockScreen) { EXPECT_FALSE(test_api_->shutdown_timer_is_running()); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::GetAllLockScreenContainersMask(), - PowerButtonController::ANIMATION_UNDO_SLOW_CLOSE)); + internal::SessionStateAnimator::kAllLockScreenContainersMask, + internal::SessionStateAnimator::ANIMATION_UNDO_SLOW_CLOSE)); EXPECT_TRUE( test_api_->ContainersAreAnimated( - PowerButtonController::DESKTOP_BACKGROUND, - PowerButtonController::ANIMATION_RESTORE)); + internal::SessionStateAnimator::DESKTOP_BACKGROUND, + internal::SessionStateAnimator::ANIMATION_RESTORE)); EXPECT_TRUE(test_api_->BlackLayerIsVisible()); } diff --git a/ash/wm/session_state_animator.cc b/ash/wm/session_state_animator.cc new file mode 100644 index 0000000..bc9c067c --- /dev/null +++ b/ash/wm/session_state_animator.cc @@ -0,0 +1,312 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/session_state_animator.h" + +#include "ash/shell.h" +#include "ash/shell_window_ids.h" +#include "ui/aura/root_window.h" +#include "ui/compositor/layer_animation_sequence.h" + +namespace ash { +namespace internal { + +namespace { + +// Amount of time taken to scale the snapshot of the screen down to a +// slightly-smaller size once the user starts holding the power button. Used +// for both the pre-lock and pre-shutdown animations. +const int kSlowCloseAnimMs = 400; + +// Amount of time taken to scale the snapshot of the screen back to its original +// size when the button is released. +const int kUndoSlowCloseAnimMs = 100; + +// Amount of time taken to scale the snapshot down to a point in the center of +// the screen once the screen has been locked or we've been notified that the +// system is shutting down. +const int kFastCloseAnimMs = 150; + +// Amount of time taken to make the lock window fade in when the screen is +// locked. +const int kLockFadeInAnimMs = 200; + +// Slightly-smaller size that we scale the screen down to for the pre-lock and +// pre-shutdown states. +const float kSlowCloseSizeRatio = 0.95f; + +// Returns the transform that should be applied to containers for the slow-close +// animation. +ui::Transform GetSlowCloseTransform() { + gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size(); + ui::Transform transform; + transform.SetScale(kSlowCloseSizeRatio, kSlowCloseSizeRatio); + transform.ConcatTranslate( + floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.width() + 0.5), + floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.height() + 0.5)); + return transform; +} + +// Returns the transform that should be applied to containers for the fast-close +// animation. +ui::Transform GetFastCloseTransform() { + gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size(); + ui::Transform transform; + transform.SetScale(0.0, 0.0); + transform.ConcatTranslate(floor(0.5 * root_size.width() + 0.5), + floor(0.5 * root_size.height() + 0.5)); + return transform; +} + +// Slowly shrinks |window| to a slightly-smaller size. +void StartSlowCloseAnimationForWindow(aura::Window* window) { + ui::LayerAnimator* animator = window->layer()->GetAnimator(); + animator->set_preemption_strategy( + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + animator->StartAnimation( + new ui::LayerAnimationSequence( + ui::LayerAnimationElement::CreateTransformElement( + GetSlowCloseTransform(), + base::TimeDelta::FromMilliseconds(kSlowCloseAnimMs)))); +} + +// Quickly undoes the effects of the slow-close animation on |window|. +void StartUndoSlowCloseAnimationForWindow(aura::Window* window) { + ui::LayerAnimator* animator = window->layer()->GetAnimator(); + animator->set_preemption_strategy( + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + animator->StartAnimation( + new ui::LayerAnimationSequence( + ui::LayerAnimationElement::CreateTransformElement( + ui::Transform(), + base::TimeDelta::FromMilliseconds(kUndoSlowCloseAnimMs)))); +} + +// Quickly shrinks |window| down to a point in the center of the screen and +// fades it out to 0 opacity. +void StartFastCloseAnimationForWindow(aura::Window* window) { + ui::LayerAnimator* animator = window->layer()->GetAnimator(); + animator->set_preemption_strategy( + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + animator->StartAnimation( + new ui::LayerAnimationSequence( + ui::LayerAnimationElement::CreateTransformElement( + GetFastCloseTransform(), + base::TimeDelta::FromMilliseconds(kFastCloseAnimMs)))); + animator->StartAnimation( + new ui::LayerAnimationSequence( + ui::LayerAnimationElement::CreateOpacityElement( + 0.0, base::TimeDelta::FromMilliseconds(kFastCloseAnimMs)))); +} + +// Fades |window| in to full opacity. +void FadeInWindow(aura::Window* window) { + ui::LayerAnimator* animator = window->layer()->GetAnimator(); + animator->set_preemption_strategy( + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + animator->StartAnimation( + new ui::LayerAnimationSequence( + ui::LayerAnimationElement::CreateOpacityElement( + 1.0, base::TimeDelta::FromMilliseconds(kLockFadeInAnimMs)))); +} + +// Makes |window| fully transparent instantaneously. +void HideWindow(aura::Window* window) { + window->layer()->SetOpacity(0.0); +} + +// Restores |window| to its original position and scale and full opacity +// instantaneously. +void RestoreWindow(aura::Window* window) { + window->layer()->SetTransform(ui::Transform()); + window->layer()->SetOpacity(1.0); +} + +} // namespace + +void SessionStateAnimator::TestApi::TriggerHideBlackLayerTimeout() { + animator_->DropBlackLayer(); + animator_->hide_black_layer_timer_.Stop(); +} + +bool SessionStateAnimator::TestApi::ContainersAreAnimated( + int container_mask, AnimationType type) const { + aura::Window::Windows containers; + animator_->GetContainers(container_mask, &containers); + for (aura::Window::Windows::const_iterator it = containers.begin(); + it != containers.end(); ++it) { + aura::Window* window = *it; + ui::Layer* layer = window->layer(); + + switch (type) { + case ANIMATION_SLOW_CLOSE: + if (layer->GetTargetTransform() != GetSlowCloseTransform()) + return false; + break; + case ANIMATION_UNDO_SLOW_CLOSE: + if (layer->GetTargetTransform() != ui::Transform()) + return false; + break; + case ANIMATION_FAST_CLOSE: + if (layer->GetTargetTransform() != GetFastCloseTransform() || + layer->GetTargetOpacity() > 0.0001) + return false; + break; + case ANIMATION_FADE_IN: + if (layer->GetTargetOpacity() < 0.9999) + return false; + break; + case ANIMATION_HIDE: + if (layer->GetTargetOpacity() > 0.0001) + return false; + break; + case ANIMATION_RESTORE: + if (layer->opacity() < 0.9999 || layer->transform() != ui::Transform()) + return false; + break; + default: + NOTREACHED() << "Unhandled animation type " << type; + return false; + } + } + return true; +} + +bool SessionStateAnimator::TestApi::BlackLayerIsVisible() const { + return animator_->black_layer_.get() && + animator_->black_layer_->visible(); +} + +gfx::Rect SessionStateAnimator::TestApi::GetBlackLayerBounds() const { + ui::Layer* layer = animator_->black_layer_.get(); + return layer ? layer->bounds() : gfx::Rect(); +} + +SessionStateAnimator::SessionStateAnimator() { + Shell::GetPrimaryRootWindow()->AddRootWindowObserver(this); +} + +SessionStateAnimator::~SessionStateAnimator() { + Shell::GetPrimaryRootWindow()->RemoveRootWindowObserver(this); +} + +// Fills |containers| with the containers described by |container_mask|. +void SessionStateAnimator::GetContainers(int container_mask, + aura::Window::Windows* containers) { + aura::RootWindow* root_window = Shell::GetPrimaryRootWindow(); + containers->clear(); + + if (container_mask & DESKTOP_BACKGROUND) { + containers->push_back(Shell::GetContainer( + root_window, + internal::kShellWindowId_DesktopBackgroundContainer)); + } + if (container_mask & LAUNCHER) { + containers->push_back(Shell::GetContainer( + root_window, + internal::kShellWindowId_LauncherContainer)); + } + if (container_mask & NON_LOCK_SCREEN_CONTAINERS) { + // TODO(antrim): Figure out a way to eliminate a need to exclude launcher + // in such way. + aura::Window* non_lock_screen_containers = Shell::GetContainer( + root_window, + internal::kShellWindowId_NonLockScreenContainersContainer); + aura::Window::Windows children = non_lock_screen_containers->children(); + + for (aura::Window::Windows::const_iterator it = children.begin(); + it != children.end(); ++it) { + aura::Window* window = *it; + if (window->id() == internal::kShellWindowId_LauncherContainer) + continue; + containers->push_back(window); + } + } + if (container_mask & LOCK_SCREEN_BACKGROUND) { + containers->push_back(Shell::GetContainer( + root_window, + internal::kShellWindowId_LockScreenBackgroundContainer)); + } + if (container_mask & LOCK_SCREEN_CONTAINERS) { + containers->push_back(Shell::GetContainer( + root_window, + internal::kShellWindowId_LockScreenContainersContainer)); + } + if (container_mask & LOCK_SCREEN_RELATED_CONTAINERS) { + containers->push_back(Shell::GetContainer( + root_window, + internal::kShellWindowId_LockScreenRelatedContainersContainer)); + } +} + +// Apply animation |type| to all containers described by |container_mask|. +void SessionStateAnimator::StartAnimation(int container_mask, + AnimationType type) { + aura::Window::Windows containers; + GetContainers(container_mask, &containers); + + for (aura::Window::Windows::const_iterator it = containers.begin(); + it != containers.end(); ++it) { + aura::Window* window = *it; + switch (type) { + case ANIMATION_SLOW_CLOSE: + StartSlowCloseAnimationForWindow(window); + break; + case ANIMATION_UNDO_SLOW_CLOSE: + StartUndoSlowCloseAnimationForWindow(window); + break; + case ANIMATION_FAST_CLOSE: + StartFastCloseAnimationForWindow(window); + break; + case ANIMATION_FADE_IN: + FadeInWindow(window); + break; + case ANIMATION_HIDE: + HideWindow(window); + break; + case ANIMATION_RESTORE: + RestoreWindow(window); + break; + default: + NOTREACHED() << "Unhandled animation type " << type; + } + } +} + +void SessionStateAnimator::OnRootWindowResized(const aura::RootWindow* root, + const gfx::Size& new_size) { + if (black_layer_.get()) + black_layer_->SetBounds(gfx::Rect(root->bounds().size())); +} + +void SessionStateAnimator::ShowBlackLayer() { + if (hide_black_layer_timer_.IsRunning()) + hide_black_layer_timer_.Stop(); + + if (!black_layer_.get()) { + black_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); + black_layer_->SetColor(SK_ColorBLACK); + + ui::Layer* root_layer = Shell::GetPrimaryRootWindow()->layer(); + black_layer_->SetBounds(root_layer->bounds()); + root_layer->Add(black_layer_.get()); + root_layer->StackAtBottom(black_layer_.get()); + } + black_layer_->SetVisible(true); +} + +void SessionStateAnimator::DropBlackLayer() { + black_layer_.reset(); +} + +void SessionStateAnimator::ScheduleDropBlackLayer() { + hide_black_layer_timer_.Stop(); + hide_black_layer_timer_.Start( + FROM_HERE, + base::TimeDelta::FromMilliseconds(kUndoSlowCloseAnimMs), + this, &SessionStateAnimator::DropBlackLayer); +} + +} // namespace internal +} // namespace ash diff --git a/ash/wm/session_state_animator.h b/ash/wm/session_state_animator.h new file mode 100644 index 0000000..841a4dc --- /dev/null +++ b/ash/wm/session_state_animator.h @@ -0,0 +1,150 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WM_SESSION_STATE_ANIMATOR_H_ +#define ASH_WM_SESSION_STATE_ANIMATOR_H_ + +#include "ash/ash_export.h" +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/time.h" +#include "base/timer.h" +#include "ui/aura/root_window_observer.h" +#include "ui/aura/window.h" + +namespace gfx { +class Rect; +class Size; +} + +namespace ui { +class Layer; +} + +namespace ash { +namespace internal { + +// Displays onscreen animations for session state changes (lock/unlock, sign +// out, shut down). +class SessionStateAnimator : public aura::RootWindowObserver { + public: + // Animations that can be applied to groups of containers. + enum AnimationType { + ANIMATION_SLOW_CLOSE = 0, + ANIMATION_UNDO_SLOW_CLOSE, + ANIMATION_FAST_CLOSE, + ANIMATION_FADE_IN, + ANIMATION_HIDE, + ANIMATION_RESTORE, + }; + + // Specific containers or groups of containers that can be animated. + enum Container { + DESKTOP_BACKGROUND = 1 << 0, + LAUNCHER = 1 << 1, + + // All user session related containers including system background but + // not including desktop background (wallpaper). + NON_LOCK_SCREEN_CONTAINERS = 1 << 2, + + // Desktop wallpaper is moved to this layer when screen is locked. + // This layer is excluded from lock animation so that wallpaper stays as is, + // user session windows are hidden and lock UI is shown on top of it. + // This layer is included in shutdown animation. + LOCK_SCREEN_BACKGROUND = 1 << 3, + + // Lock screen and lock screen modal containers. + LOCK_SCREEN_CONTAINERS = 1 << 4, + + // Multiple system layers belong here like status, menu, tooltip + // and overlay layers. + LOCK_SCREEN_RELATED_CONTAINERS = 1 << 5, + }; + + // Helper class used by tests to access internal state. + class ASH_EXPORT TestApi { + public: + explicit TestApi(SessionStateAnimator* animator) + : animator_(animator) {} + + bool hide_black_layer_timer_is_running() const { + return animator_->hide_black_layer_timer_.IsRunning(); + } + + void TriggerHideBlackLayerTimeout(); + + // Returns true if containers of a given |container_mask| + // were last animated with |type| (probably; the analysis is fairly ad-hoc). + // |container_mask| is a bitfield of a Container. + bool ContainersAreAnimated(int container_mask, AnimationType type) const; + + // Returns true if |black_layer_| is non-NULL and visible. + bool BlackLayerIsVisible() const; + + // Returns |black_layer_|'s bounds, or an empty rect if the layer is + // NULL. + gfx::Rect GetBlackLayerBounds() const; + + private: + SessionStateAnimator* animator_; // not owned + + DISALLOW_COPY_AND_ASSIGN(TestApi); + }; + + // A bitfield mask including LOCK_SCREEN_WALLPAPER, + // LOCK_SCREEN_CONTAINERS, and LOCK_SCREEN_RELATED_CONTAINERS. + const static int kAllLockScreenContainersMask = + LOCK_SCREEN_BACKGROUND | + LOCK_SCREEN_CONTAINERS | + LOCK_SCREEN_RELATED_CONTAINERS; + + // A bitfield mask of all containers. + const static int kAllContainersMask = kAllLockScreenContainersMask | + DESKTOP_BACKGROUND | + LAUNCHER | + NON_LOCK_SCREEN_CONTAINERS; + + SessionStateAnimator(); + virtual ~SessionStateAnimator(); + + // Shows or hides |black_layer_|. The show method creates and + // initializes the layer if it doesn't already exist. + void ShowBlackLayer(); + void DropBlackLayer(); + + // Drops back layer after |UNDO_SLOW_CLOSE| animation delay. + void ScheduleDropBlackLayer(); + + // Apply animation |type| to all containers included in |container_mask|. + void StartAnimation(int container_mask, + AnimationType type); + + // Fills |containers| with the containers included in |container_mask|. + void GetContainers(int container_mask, + aura::Window::Windows* containers); + + // aura::RootWindowObserver overrides: + virtual void OnRootWindowResized(const aura::RootWindow* root, + const gfx::Size& old_size) OVERRIDE; + + private: + // Layer that's stacked under all of the root window's children to provide a + // black background when we're scaling all of the other windows down. + // TODO(derat): Remove this in favor of having the compositor only clear the + // viewport when there are regions not covered by a layer: + // http://crbug.com/113445 + scoped_ptr<ui::Layer> black_layer_; + + // Started when we abort the pre-lock state. When it fires, we hide + // |black_layer_|, as the desktop background is now covering the whole + // screen. + base::OneShotTimer<SessionStateAnimator> hide_black_layer_timer_; + + DISALLOW_COPY_AND_ASSIGN(SessionStateAnimator); +}; + +} // namespace internal +} // namespace ash + +#endif // ASH_WM_SESSION_STATE_ANIMATOR_H_ |