summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-28 17:54:01 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-28 17:54:01 +0000
commitcb776d3949174aa836b10a6011067ed990da3c65 (patch)
tree4da3836d333f1eb472d9dad55b5f17b1362977e0
parent22ccf8319f6384f73495aff20175f372c8f47817 (diff)
downloadchromium_src-cb776d3949174aa836b10a6011067ed990da3c65.zip
chromium_src-cb776d3949174aa836b10a6011067ed990da3c65.tar.gz
chromium_src-cb776d3949174aa836b10a6011067ed990da3c65.tar.bz2
Adds an animation for switching workspaces.
BUG=none TEST=none R=ben@chromium.org Review URL: https://chromiumcodereview.appspot.com/9476022 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@123994 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ash/wm/window_animations.cc119
-rw-r--r--ash/wm/window_animations.h14
-rw-r--r--ash/wm/workspace/workspace_manager.cc72
-rw-r--r--ash/wm/workspace/workspace_manager.h16
-rw-r--r--ui/gfx/compositor/layer.cc4
-rw-r--r--ui/gfx/compositor/scoped_layer_animation_settings.cc4
-rw-r--r--ui/gfx/compositor/scoped_layer_animation_settings.h1
7 files changed, 202 insertions, 28 deletions
diff --git a/ash/wm/window_animations.cc b/ash/wm/window_animations.cc
index adc2cda..e4e513e 100644
--- a/ash/wm/window_animations.cc
+++ b/ash/wm/window_animations.cc
@@ -16,12 +16,15 @@
#include "ui/aura/window_observer.h"
#include "ui/aura/window_property.h"
#include "ui/gfx/compositor/layer_animation_observer.h"
+#include "ui/gfx/compositor/layer_animator.h"
#include "ui/gfx/compositor/scoped_layer_animation_settings.h"
DECLARE_WINDOW_PROPERTY_TYPE(int)
DECLARE_WINDOW_PROPERTY_TYPE(ash::WindowVisibilityAnimationType)
DECLARE_WINDOW_PROPERTY_TYPE(ash::WindowVisibilityAnimationTransition)
+using base::TimeDelta;
+
namespace ash {
namespace internal {
namespace {
@@ -58,7 +61,7 @@ void SetWindowVisibilityAnimationTransition(
}
void SetWindowVisibilityAnimationDuration(aura::Window* window,
- const base::TimeDelta& duration) {
+ const TimeDelta& duration) {
window->SetProperty(internal::kWindowVisibilityAnimationDurationKey,
static_cast<int>(duration.ToInternalValue()));
}
@@ -81,6 +84,9 @@ const float kWindowAnimation_ScaleFactor = 1.05f;
const float kWindowAnimation_Vertical_TranslateY = 15.f;
+// Amount windows are scaled during workspace animations.
+const float kWorkspaceScale = .95f;
+
// Gets/sets the WindowVisibilityAnimationType associated with a window.
WindowVisibilityAnimationType GetWindowVisibilityAnimationType(
aura::Window* window) {
@@ -157,6 +163,32 @@ class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver,
DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserver);
};
+// ImplicitAnimationObserver used when switching workspaces. Resets the layer
+// visibility to 'false' when done. This doesn't need the complexity of
+// HidingWindowAnimationObserver as the window isn't closing, and if it does a
+// HidingWindowAnimationObserver will be created.
+class WorkspaceHidingWindowAnimationObserver :
+ public ui::ImplicitAnimationObserver {
+ public:
+ explicit WorkspaceHidingWindowAnimationObserver(aura::Window* window)
+ : layer_(window->layer()) {
+ }
+ virtual ~WorkspaceHidingWindowAnimationObserver() {
+ }
+
+ private:
+ // Overridden from ui::ImplicitAnimationObserver:
+ virtual void OnImplicitAnimationsCompleted() OVERRIDE {
+ // Restore the correct visibility value (overridden for the duration of the
+ // animation in AnimateHideWindow()).
+ layer_->SetVisible(false);
+ }
+
+ ui::Layer* layer_;
+
+ DISALLOW_COPY_AND_ASSIGN(WorkspaceHidingWindowAnimationObserver);
+};
+
// Shows a window using an animation, animating its opacity from 0.f to 1.f, and
// its transform from |start_transform| to |end_transform|.
void AnimateShowWindowCommon(aura::Window* window,
@@ -171,10 +203,8 @@ void AnimateShowWindowCommon(aura::Window* window,
ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
int duration =
window->GetProperty(internal::kWindowVisibilityAnimationDurationKey);
- if (duration > 0) {
- settings.SetTransitionDuration(
- base::TimeDelta::FromInternalValue(duration));
- }
+ if (duration > 0)
+ settings.SetTransitionDuration(TimeDelta::FromInternalValue(duration));
window->layer()->SetTransform(end_transform);
window->layer()->SetOpacity(kWindowAnimation_ShowOpacity);
@@ -193,10 +223,8 @@ void AnimateHideWindowCommon(aura::Window* window,
int duration =
window->GetProperty(internal::kWindowVisibilityAnimationDurationKey);
- if (duration > 0) {
- settings.SetTransitionDuration(
- base::TimeDelta::FromInternalValue(duration));
- }
+ if (duration > 0)
+ settings.SetTransitionDuration(TimeDelta::FromInternalValue(duration));
window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
window->layer()->SetTransform(end_transform);
@@ -245,6 +273,73 @@ void AnimateHideWindow_Fade(aura::Window* window) {
AnimateHideWindowCommon(window, ui::Transform());
}
+// Builds the transform used when switching workspaces for the specified
+// window.
+ui::Transform BuildWorkspaceSwitchTransform(aura::Window* window) {
+ // Animations for transitioning workspaces scale all windows. To give the
+ // effect of scaling from the center of the screen the windows are translated.
+ gfx::Rect parent_bounds(window->parent()->bounds());
+ float mid_x = static_cast<float>(parent_bounds.width()) / 2.0f;
+ float initial_x =
+ (static_cast<float>(window->bounds().x()) - mid_x) * kWorkspaceScale +
+ mid_x;
+ float mid_y = static_cast<float>(parent_bounds.height()) / 2.0f;
+ float initial_y =
+ (static_cast<float>(window->bounds().y()) - mid_y) * kWorkspaceScale +
+ mid_y;
+
+ ui::Transform transform;
+ transform.ConcatTranslate(
+ initial_x - static_cast<float>(window->bounds().x()),
+ initial_y - static_cast<float>(window->bounds().y()));
+ transform.ConcatScale(kWorkspaceScale, kWorkspaceScale);
+ return transform;
+}
+
+void AnimateShowWindow_Workspace(aura::Window* window) {
+ ui::Transform transform(BuildWorkspaceSwitchTransform(window));
+ window->layer()->SetVisible(true);
+ window->layer()->SetOpacity(0.0f);
+ window->layer()->SetTransform(transform);
+
+ {
+ // Property sets within this scope will be implicitly animated.
+ ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
+
+ window->layer()->SetTransform(ui::Transform());
+ // Opacity animates only during the first half of the animation.
+ settings.SetTransitionDuration(settings.GetTransitionDuration() / 2);
+ window->layer()->SetOpacity(1.0f);
+ }
+}
+
+void AnimateHideWindow_Workspace(aura::Window* window) {
+ ui::Transform transform(BuildWorkspaceSwitchTransform(window));
+ window->layer()->SetOpacity(1.0f);
+ window->layer()->SetTransform(ui::Transform());
+
+ // Opacity animates from 1 to 0 only over the second half of the animation. To
+ // get this functionality two animations are schedule for opacity, the first
+ // from 1 to 1 (which effectively does nothing) the second from 1 to 0.
+ // Because we're scheduling two animations of the same property we need to
+ // change the preemption strategy.
+ ui::LayerAnimator* animator = window->layer()->GetAnimator();
+ animator->set_preemption_strategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
+ {
+ // Property sets within this scope will be implicitly animated.
+ ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
+ // Add an observer that sets visibility of the layer to false once animation
+ // completes.
+ settings.AddObserver(new WorkspaceHidingWindowAnimationObserver(window));
+ window->layer()->SetTransform(transform);
+ settings.SetTransitionDuration(settings.GetTransitionDuration() / 2);
+ window->layer()->SetOpacity(1.0f);
+ window->layer()->SetOpacity(0.0f);
+ }
+ animator->set_preemption_strategy(
+ ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET);
+}
+
bool AnimateShowWindow(aura::Window* window) {
if (!HasWindowVisibilityAnimationTransition(window, ANIMATE_SHOW))
return false;
@@ -259,6 +354,9 @@ bool AnimateShowWindow(aura::Window* window) {
case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE:
AnimateShowWindow_Fade(window);
return true;
+ case WINDOW_VISIBILITY_ANIMATION_TYPE_WORKSPACE_SHOW:
+ AnimateShowWindow_Workspace(window);
+ return true;
default:
NOTREACHED();
return false;
@@ -279,6 +377,9 @@ bool AnimateHideWindow(aura::Window* window) {
case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE:
AnimateHideWindow_Fade(window);
return true;
+ case WINDOW_VISIBILITY_ANIMATION_TYPE_WORKSPACE_HIDE:
+ AnimateHideWindow_Workspace(window);
+ return true;
default:
NOTREACHED();
return false;
diff --git a/ash/wm/window_animations.h b/ash/wm/window_animations.h
index f15e484..70ea4ff 100644
--- a/ash/wm/window_animations.h
+++ b/ash/wm/window_animations.h
@@ -17,11 +17,15 @@ namespace ash {
// A variety of canned animations for window transitions.
enum WindowVisibilityAnimationType {
- WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT = 0, // Default. Lets the system
- // decide based on window type.
- WINDOW_VISIBILITY_ANIMATION_TYPE_DROP, // Window shrinks in.
- WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL, // Vertical Glenimation.
- WINDOW_VISIBILITY_ANIMATION_TYPE_FADE // Fades in/out.
+ WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT = 0, // Default. Lets the system
+ // decide based on window
+ // type.
+ WINDOW_VISIBILITY_ANIMATION_TYPE_DROP, // Window shrinks in.
+ WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL, // Vertical Glenimation.
+ WINDOW_VISIBILITY_ANIMATION_TYPE_FADE, // Fades in/out.
+ WINDOW_VISIBILITY_ANIMATION_TYPE_WORKSPACE_SHOW, // Windows are scaled and
+ // fade in.
+ WINDOW_VISIBILITY_ANIMATION_TYPE_WORKSPACE_HIDE, // Inverse of SHOW.
};
// Type of visibility change transition that a window should animate.
diff --git a/ash/wm/workspace/workspace_manager.cc b/ash/wm/workspace/workspace_manager.cc
index 59befcf..67862b0 100644
--- a/ash/wm/workspace/workspace_manager.cc
+++ b/ash/wm/workspace/workspace_manager.cc
@@ -9,6 +9,7 @@
#include "ash/shell.h"
#include "ash/wm/property_util.h"
#include "ash/wm/shelf_layout_manager.h"
+#include "ash/wm/window_animations.h"
#include "ash/wm/window_resizer.h"
#include "ash/wm/window_util.h"
#include "ash/wm/workspace/managed_workspace.h"
@@ -36,17 +37,13 @@ const int kWorkspaceHorizontalMargin = 50;
const float kMaxOverviewScale = 0.9f;
const float kMinOverviewScale = 0.3f;
-// Sets the visibility of the layer of each window in |windows| to |value|. We
-// set the visibility of the layer rather than the Window so that views doesn't
-// see the visibility change.
-// TODO: revisit this. Ideally the Window would think it's still visibile after
-// this. May be possible after Ben lands his changes.
-void SetWindowLayerVisibility(const std::vector<aura::Window*>& windows,
- bool value) {
- for (size_t i = 0; i < windows.size(); ++i){
+// Returns a list of all the windows with layers in |result|.
+void BuildWindowList(const std::vector<aura::Window*>& windows,
+ std::vector<aura::Window*>* result) {
+ for (size_t i = 0; i < windows.size(); ++i) {
if (windows[i]->layer())
- windows[i]->layer()->SetVisible(value);
- SetWindowLayerVisibility(windows[i]->transient_children(), value);
+ result->push_back(windows[i]);
+ BuildWindowList(windows[i]->transient_children(), result);
}
}
@@ -107,8 +104,16 @@ bool WorkspaceManager::ShouldMaximize(aura::Window* window) const {
void WorkspaceManager::AddWindow(aura::Window* window) {
DCHECK(IsManagedWindow(window));
- if (FindBy(window))
- return; // Already know about this window.
+ Workspace* current_workspace = FindBy(window);
+ if (current_workspace) {
+ // Already know about this window. Make sure the workspace is active.
+ if (active_workspace_ != current_workspace) {
+ if (active_workspace_)
+ window->layer()->GetAnimator()->StopAnimating();
+ current_workspace->Activate();
+ }
+ return;
+ }
if (!window_util::IsWindowMaximized(window) &&
!window_util::IsWindowFullscreen(window)) {
@@ -262,6 +267,43 @@ void WorkspaceManager::UpdateShelfVisibility() {
shelf_->SetVisible(!window_util::HasFullscreenWindow(windows));
}
+void WorkspaceManager::SetVisibilityOfWorkspaceWindows(
+ ash::internal::Workspace* workspace,
+ AnimateChangeType change_type,
+ bool value) {
+ std::vector<aura::Window*> children;
+ BuildWindowList(workspace->windows(), &children);
+ SetWindowLayerVisibility(children, change_type, value);
+}
+
+void WorkspaceManager::SetWindowLayerVisibility(
+ const std::vector<aura::Window*>& windows,
+ AnimateChangeType change_type,
+ bool value) {
+ for (size_t i = 0; i < windows.size(); ++i) {
+ ui::Layer* layer = windows[i]->layer();
+ if (layer) {
+ windows[i]->SetProperty(aura::client::kAnimationsDisabledKey,
+ change_type == DONT_ANIMATE);
+ bool update_layer = true;
+ if (change_type == ANIMATE) {
+ ash::SetWindowVisibilityAnimationType(
+ windows[i],
+ value ? ash::WINDOW_VISIBILITY_ANIMATION_TYPE_WORKSPACE_SHOW :
+ ash::WINDOW_VISIBILITY_ANIMATION_TYPE_WORKSPACE_HIDE);
+ if (ash::internal::AnimateOnChildWindowVisibilityChanged(
+ windows[i], value))
+ update_layer = false;
+ }
+ if (update_layer)
+ layer->SetVisible(value);
+ // Reset the animation type so it isn't used in a future hide/show.
+ ash::SetWindowVisibilityAnimationType(
+ windows[i], ash::WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT);
+ }
+ }
+}
+
Workspace* WorkspaceManager::GetActiveWorkspace() const {
return active_workspace_;
}
@@ -277,10 +319,12 @@ void WorkspaceManager::SetActiveWorkspace(Workspace* workspace) {
DCHECK(std::find(workspaces_.begin(), workspaces_.end(),
workspace) != workspaces_.end());
if (active_workspace_)
- SetWindowLayerVisibility(active_workspace_->windows(), false);
+ SetVisibilityOfWorkspaceWindows(active_workspace_, ANIMATE, false);
+ Workspace* last_active = active_workspace_;
active_workspace_ = workspace;
if (active_workspace_) {
- SetWindowLayerVisibility(active_workspace_->windows(), true);
+ SetVisibilityOfWorkspaceWindows(active_workspace_,
+ last_active ? ANIMATE : DONT_ANIMATE, true);
UpdateShelfVisibility();
}
diff --git a/ash/wm/workspace/workspace_manager.h b/ash/wm/workspace/workspace_manager.h
index 2960287..8adf5b96 100644
--- a/ash/wm/workspace/workspace_manager.h
+++ b/ash/wm/workspace/workspace_manager.h
@@ -101,6 +101,12 @@ class ASH_EXPORT WorkspaceManager : public aura::WindowObserver{
intptr_t old) OVERRIDE;
private:
+ // Enumeration of whether windows should animate or not.
+ enum AnimateChangeType {
+ ANIMATE,
+ DONT_ANIMATE
+ };
+
friend class Workspace;
friend class WorkspaceManagerTest;
@@ -114,6 +120,16 @@ class ASH_EXPORT WorkspaceManager : public aura::WindowObserver{
void UpdateShelfVisibility();
+ // Sets the visibility of the windows in |workspace|.
+ void SetVisibilityOfWorkspaceWindows(Workspace* workspace,
+ AnimateChangeType change_type,
+ bool value);
+
+ // Implementation of SetVisibilityOfWorkspaceWindows().
+ void SetWindowLayerVisibility(const std::vector<aura::Window*>& windows,
+ AnimateChangeType change_type,
+ bool value);
+
// Returns the active workspace.
Workspace* GetActiveWorkspace() const;
diff --git a/ui/gfx/compositor/layer.cc b/ui/gfx/compositor/layer.cc
index e80b5d8..b49e642 100644
--- a/ui/gfx/compositor/layer.cc
+++ b/ui/gfx/compositor/layer.cc
@@ -65,6 +65,10 @@ Layer::Layer(LayerType type)
}
Layer::~Layer() {
+ // Destroying the animator may cause observers to use the layer (and
+ // indirectly the WebLayer). Destroy the animator first so that the WebLayer
+ // is still around.
+ animator_.reset();
if (compositor_)
compositor_->SetRootLayer(NULL);
if (parent_)
diff --git a/ui/gfx/compositor/scoped_layer_animation_settings.cc b/ui/gfx/compositor/scoped_layer_animation_settings.cc
index 7a7dbc1..78fb067 100644
--- a/ui/gfx/compositor/scoped_layer_animation_settings.cc
+++ b/ui/gfx/compositor/scoped_layer_animation_settings.cc
@@ -44,5 +44,9 @@ void ScopedLayerAnimationSettings::SetTransitionDuration(
animator_->transition_duration_ = duration;
}
+base::TimeDelta ScopedLayerAnimationSettings::GetTransitionDuration() const {
+ return animator_->transition_duration_;
+}
+
} // namespace ui
diff --git a/ui/gfx/compositor/scoped_layer_animation_settings.h b/ui/gfx/compositor/scoped_layer_animation_settings.h
index dce64ef..94e5a4e 100644
--- a/ui/gfx/compositor/scoped_layer_animation_settings.h
+++ b/ui/gfx/compositor/scoped_layer_animation_settings.h
@@ -29,6 +29,7 @@ class COMPOSITOR_EXPORT ScopedLayerAnimationSettings {
void AddObserver(ImplicitAnimationObserver* observer);
void SetTransitionDuration(base::TimeDelta duration);
+ base::TimeDelta GetTransitionDuration() const;
private:
LayerAnimator* animator_;