summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ash/ash.gyp2
-rw-r--r--ash/wm/power_button_controller.cc390
-rw-r--r--ash/wm/power_button_controller.h90
-rw-r--r--ash/wm/power_button_controller_unittest.cc148
-rw-r--r--ash/wm/session_state_animator.cc323
-rw-r--r--ash/wm/session_state_animator.h144
6 files changed, 634 insertions, 463 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp
index 0c6246f..08cf90b 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -323,6 +323,8 @@
'wm/root_window_layout_manager.h',
'wm/screen_dimmer.cc',
'wm/screen_dimmer.h',
+ 'wm/session_state_animator.cc',
+ 'wm/session_state_animator.h',
'wm/shadow.cc',
'wm/shadow.h',
'wm/shadow_controller.cc',
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..41a1996
--- /dev/null
+++ b/ash/wm/session_state_animator.cc
@@ -0,0 +1,323 @@
+// 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();
+}
+
+const int SessionStateAnimator::kAllLockScreenContainersMask =
+ SessionStateAnimator::LOCK_SCREEN_BACKGROUND |
+ SessionStateAnimator::LOCK_SCREEN_CONTAINERS |
+ SessionStateAnimator::LOCK_SCREEN_RELATED_CONTAINERS;
+
+const int SessionStateAnimator::kAllContainersMask =
+ SessionStateAnimator::kAllLockScreenContainersMask |
+ SessionStateAnimator::DESKTOP_BACKGROUND |
+ SessionStateAnimator::LAUNCHER |
+ SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS;
+
+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..58bf7ed
--- /dev/null
+++ b/ash/wm/session_state_animator.h
@@ -0,0 +1,144 @@
+// 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 ASH_EXPORT 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;
+
+ // A bitfield mask of all containers.
+ const static int kAllContainersMask;
+
+ 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_