Index: ash/wm/workspace/workspace_manager2.cc |
diff --git a/ash/wm/workspace/workspace_manager2.cc b/ash/wm/workspace/workspace_manager2.cc |
index 805dd183584e96b98757554ab279df8c7c968a0a..148ca71485c3f19caf020f2681b22bc3c4e8a4e7 100644 |
--- a/ash/wm/workspace/workspace_manager2.cc |
+++ b/ash/wm/workspace/workspace_manager2.cc |
@@ -7,6 +7,7 @@ |
#include <algorithm> |
#include <functional> |
+#include "ash/ash_switches.h" |
#include "ash/root_window_controller.h" |
#include "ash/shell.h" |
#include "ash/shell_window_ids.h" |
@@ -16,13 +17,14 @@ |
#include "ash/wm/window_animations.h" |
#include "ash/wm/window_properties.h" |
#include "ash/wm/window_util.h" |
+#include "ash/wm/workspace/desktop_background_fade_controller.h" |
+#include "ash/wm/workspace/workspace_animations.h" |
#include "ash/wm/workspace/workspace_layout_manager2.h" |
#include "ash/wm/workspace/workspace2.h" |
#include "base/auto_reset.h" |
#include "base/command_line.h" |
#include "base/logging.h" |
#include "base/stl_util.h" |
-#include "base/stringprintf.h" |
#include "ui/aura/client/aura_constants.h" |
#include "ui/aura/root_window.h" |
#include "ui/aura/window.h" |
@@ -30,6 +32,8 @@ |
#include "ui/base/ui_base_types.h" |
#include "ui/compositor/layer.h" |
#include "ui/compositor/layer_animator.h" |
+#include "ui/compositor/scoped_layer_animation_settings.h" |
+#include "ui/views/widget/widget.h" |
DECLARE_WINDOW_PROPERTY_TYPE(ash::internal::Workspace2*); |
@@ -42,6 +46,13 @@ DEFINE_WINDOW_PROPERTY_KEY(Workspace2*, kWorkspaceKey, NULL); |
namespace { |
+// Duration for fading out the desktop background when maximizing. |
+const int kCrossFadeSwitchTimeMS = 700; |
+ |
+// Amount of time to pause before animating anything. Only used during initial |
+// animation (when logging in). |
+const int kInitialPauseTimeMS = 750; |
+ |
// Changes the parent of |window| and all its transient children to |
// |new_parent|. If |stack_beneach| is non-NULL all the windows are stacked |
// beneath it. |
@@ -55,40 +66,39 @@ void ReparentWindow(Window* window, |
ReparentWindow(window->transient_children()[i], new_parent, stack_beneath); |
} |
-WorkspaceType WorkspaceType(Workspace2* workspace) { |
- return workspace->is_maximized() ? WORKSPACE_MAXIMIZED : WORKSPACE_DESKTOP; |
-} |
+} // namespace |
// Workspace ------------------------------------------------------------------- |
-// LayoutManager installed on the parent window of all the Workspace windows (eg |
+// LayoutManager installed on the parent window of all the Workspace window (eg |
// |WorkspaceManager2::contents_view_|). |
-class WorkspaceManagerLayoutManager2 : public BaseLayoutManager { |
+class WorkspaceManager2::LayoutManagerImpl : public BaseLayoutManager { |
public: |
- WorkspaceManagerLayoutManager2(Window* window) |
- : BaseLayoutManager(window->GetRootWindow()), |
- window_(window) { |
+ explicit LayoutManagerImpl(WorkspaceManager2* workspace_manager) |
+ : BaseLayoutManager(workspace_manager->contents_view_->GetRootWindow()), |
+ workspace_manager_(workspace_manager) { |
} |
- virtual ~WorkspaceManagerLayoutManager2() {} |
+ virtual ~LayoutManagerImpl() {} |
// Overridden from BaseWorkspaceLayoutManager: |
virtual void OnWindowResized() OVERRIDE { |
- for (size_t i = 0; i < window_->children().size(); ++i) |
- window_->children()[i]->SetBounds(gfx::Rect(window_->bounds().size())); |
+ for (size_t i = 0; i < window()->children().size(); ++i) |
+ window()->children()[i]->SetBounds(gfx::Rect(window()->bounds().size())); |
} |
virtual void OnWindowAddedToLayout(Window* child) OVERRIDE { |
// Only workspaces should be added as children. |
- DCHECK_EQ(kShellWindowId_WorkspaceContainer, child->id()); |
- child->SetBounds(gfx::Rect(window_->bounds().size())); |
+ DCHECK((child->id() == kShellWindowId_WorkspaceContainer) || |
+ workspace_manager_->creating_fade_); |
+ child->SetBounds(gfx::Rect(window()->bounds().size())); |
} |
private: |
- Window* window_; |
+ aura::Window* window() { return workspace_manager_->contents_view_; } |
- DISALLOW_COPY_AND_ASSIGN(WorkspaceManagerLayoutManager2); |
-}; |
+ WorkspaceManager2* workspace_manager_; |
-} // namespace |
+ DISALLOW_COPY_AND_ASSIGN(LayoutManagerImpl); |
+}; |
// WorkspaceManager2 ----------------------------------------------------------- |
@@ -100,12 +110,12 @@ WorkspaceManager2::WorkspaceManager2(Window* contents_view) |
ALLOW_THIS_IN_INITIALIZER_LIST( |
clear_unminimizing_workspace_factory_(this)), |
unminimizing_workspace_(NULL), |
- app_terminating_(false) { |
+ app_terminating_(false), |
+ creating_fade_(false) { |
// Clobber any existing event filter. |
contents_view->SetEventFilter(NULL); |
- // |contents_view| takes ownership of WorkspaceManagerLayoutManager2. |
- contents_view->SetLayoutManager( |
- new WorkspaceManagerLayoutManager2(contents_view)); |
+ // |contents_view| takes ownership of LayoutManagerImpl. |
+ contents_view->SetLayoutManager(new LayoutManagerImpl(this)); |
active_workspace_ = CreateWorkspace(false); |
workspaces_.push_back(active_workspace_); |
active_workspace_->window()->Show(); |
@@ -218,7 +228,8 @@ void WorkspaceManager2::SetActiveWorkspaceByWindow(Window* window) { |
!(wm::IsWindowMinimized(window) && WillRestoreMaximized(window)))) { |
ReparentWindow(window, active_workspace_->window(), NULL); |
} else { |
- SetActiveWorkspace(workspace, ANIMATE_OLD_AND_NEW); |
+ SetActiveWorkspace(workspace, SWITCH_WINDOW_MADE_ACTIVE, |
+ base::TimeDelta()); |
} |
} |
if (workspace->is_maximized() && IsMaximized(window)) { |
@@ -262,12 +273,11 @@ void WorkspaceManager2::DoInitialAnimation() { |
aura::Window* background = root_controller->GetContainer( |
kShellWindowId_DesktopBackgroundContainer); |
background->Show(); |
- AnimateWorkspaceOut(background, WORKSPACE_ANIMATE_DOWN, |
- WORKSPACE_DESKTOP, true, base::TimeDelta()); |
+ ShowOrHideDesktopBackground(background, SWITCH_INITIAL, |
+ base::TimeDelta(), false); |
} |
} |
- AnimateWorkspaceIn(active_workspace_->window(), WORKSPACE_ANIMATE_DOWN, |
- true, base::TimeDelta()); |
+ ShowWorkspace(active_workspace_, active_workspace_, SWITCH_INITIAL); |
} |
void WorkspaceManager2::OnAppTerminating() { |
@@ -290,7 +300,8 @@ Workspace2* WorkspaceManager2::FindBy(Window* window) const { |
} |
void WorkspaceManager2::SetActiveWorkspace(Workspace2* workspace, |
- AnimateType animate_type) { |
+ SwitchReason reason, |
+ base::TimeDelta duration) { |
DCHECK(workspace); |
if (active_workspace_ == workspace) |
return; |
@@ -299,12 +310,11 @@ void WorkspaceManager2::SetActiveWorkspace(Workspace2* workspace, |
// Adjust the z-order. No need to adjust the z-order for the desktop since |
// it always stays at the bottom. |
- if (workspace != desktop_workspace()) { |
- if (FindWorkspace(workspace) == workspaces_.end()) { |
- contents_view_->StackChildAbove(workspace->window(), |
- workspaces_.back()->window()); |
- workspaces_.push_back(workspace); |
- } |
+ if (workspace != desktop_workspace() && |
+ FindWorkspace(workspace) == workspaces_.end()) { |
+ contents_view_->StackChildAbove(workspace->window(), |
+ workspaces_.back()->window()); |
+ workspaces_.push_back(workspace); |
} |
Workspace2* last_active = active_workspace_; |
@@ -332,15 +342,9 @@ void WorkspaceManager2::SetActiveWorkspace(Workspace2* workspace, |
UpdateShelfVisibility(); |
- if (animate_type != ANIMATE_NONE) { |
- AnimateBetweenWorkspaces( |
- last_active->window(), |
- WorkspaceType(last_active), |
- (animate_type == ANIMATE_OLD_AND_NEW), |
- workspace->window(), |
- WorkspaceType(workspace), |
- is_unminimizing_maximized_window); |
- } |
+ // NOTE: duration supplied to this method is only used for desktop background. |
+ HideWorkspace(last_active, reason, is_unminimizing_maximized_window); |
+ ShowWorkspace(workspace, last_active, reason); |
RootWindowController* root_controller = GetRootWindowController( |
contents_view_->GetRootWindow()); |
@@ -348,11 +352,9 @@ void WorkspaceManager2::SetActiveWorkspace(Workspace2* workspace, |
aura::Window* background = root_controller->GetContainer( |
kShellWindowId_DesktopBackgroundContainer); |
if (last_active == desktop_workspace()) { |
- AnimateWorkspaceOut(background, WORKSPACE_ANIMATE_DOWN, |
- WORKSPACE_DESKTOP, false, switch_duration_); |
+ ShowOrHideDesktopBackground(background, reason, duration, false); |
} else if (active_workspace_ == desktop_workspace() && !app_terminating_) { |
- AnimateWorkspaceIn(background, WORKSPACE_ANIMATE_UP, false, |
- switch_duration_); |
+ ShowOrHideDesktopBackground(background, reason, duration, true); |
} |
} |
} |
@@ -369,7 +371,7 @@ Workspace2* WorkspaceManager2::CreateWorkspace(bool maximized) { |
void WorkspaceManager2::MoveWorkspaceToPendingOrDelete( |
Workspace2* workspace, |
Window* stack_beneath, |
- AnimateType animate_type) { |
+ SwitchReason reason) { |
// We're all ready moving windows. |
if (in_move_) |
return; |
@@ -377,7 +379,7 @@ void WorkspaceManager2::MoveWorkspaceToPendingOrDelete( |
DCHECK_NE(desktop_workspace(), workspace); |
if (workspace == active_workspace_) |
- SelectNextWorkspace(animate_type); |
+ SelectNextWorkspace(reason); |
AutoReset<bool> setter(&in_move_, true); |
@@ -422,15 +424,15 @@ void WorkspaceManager2::MoveChildrenToDesktop(aura::Window* window, |
} |
} |
-void WorkspaceManager2::SelectNextWorkspace(AnimateType animate_type) { |
+void WorkspaceManager2::SelectNextWorkspace(SwitchReason reason) { |
DCHECK_NE(active_workspace_, desktop_workspace()); |
Workspaces::const_iterator workspace_i(FindWorkspace(active_workspace_)); |
Workspaces::const_iterator next_workspace_i(workspace_i + 1); |
if (next_workspace_i != workspaces_.end()) |
- SetActiveWorkspace(*next_workspace_i, animate_type); |
+ SetActiveWorkspace(*next_workspace_i, reason, base::TimeDelta()); |
else |
- SetActiveWorkspace(*(workspace_i - 1), animate_type); |
+ SetActiveWorkspace(*(workspace_i - 1), reason, base::TimeDelta()); |
} |
void WorkspaceManager2::ScheduleDelete(Workspace2* workspace) { |
@@ -458,6 +460,116 @@ void WorkspaceManager2::SetUnminimizingWorkspace(Workspace2* workspace) { |
} |
} |
+void WorkspaceManager2::FadeDesktop(aura::Window* window, |
+ base::TimeDelta duration) { |
+ if (CommandLine::ForCurrentProcess()->HasSwitch( |
+ ash::switches::kAshWindowAnimationsDisabled) || |
+ ui::LayerAnimator::disable_animations_for_test()) |
+ return; |
+ |
+ AutoReset<bool> reseter(&creating_fade_, true); |
+ DesktopBackgroundFadeController::Direction direction; |
+ aura::Window* parent = NULL; |
+ aura::Window* stack_above = NULL; |
+ if (active_workspace_ == desktop_workspace()) { |
+ direction = DesktopBackgroundFadeController::FADE_IN; |
+ parent = desktop_workspace()->window(); |
+ stack_above = window; |
+ } else { |
+ direction = DesktopBackgroundFadeController::FADE_OUT; |
+ parent = contents_view_; |
+ stack_above = desktop_workspace()->window(); |
+ DCHECK_EQ(kCrossFadeSwitchTimeMS, (int)duration.InMilliseconds()); |
+ duration = base::TimeDelta::FromMilliseconds(kCrossFadeSwitchTimeMS); |
+ } |
+ desktop_fade_controller_.reset( |
+ new DesktopBackgroundFadeController( |
+ parent, stack_above, duration, direction)); |
+} |
+ |
+void WorkspaceManager2::ShowOrHideDesktopBackground( |
+ aura::Window* window, |
+ SwitchReason reason, |
+ base::TimeDelta duration, |
+ bool show) const { |
+ WorkspaceAnimationDetails details; |
+ details.animate = true; |
+ details.direction = show ? WORKSPACE_ANIMATE_UP : WORKSPACE_ANIMATE_DOWN; |
+ details.animate_scale = reason != SWITCH_MAXIMIZED_OR_RESTORED; |
+ details.duration = duration; |
+ if (reason == SWITCH_INITIAL) |
+ details.pause_time_ms = kInitialPauseTimeMS; |
+ if (show) |
+ ash::internal::ShowWorkspace(window, details); |
+ else |
+ ash::internal::HideWorkspace(window, details); |
+} |
+ |
+void WorkspaceManager2::ShowWorkspace( |
+ Workspace2* workspace, |
+ Workspace2* last_active, |
+ SwitchReason reason) const { |
+ WorkspaceAnimationDetails details; |
+ details.direction = |
+ (last_active == desktop_workspace() || reason == SWITCH_INITIAL) ? |
+ WORKSPACE_ANIMATE_DOWN : WORKSPACE_ANIMATE_UP; |
+ |
+ switch (reason) { |
+ case SWITCH_WINDOW_MADE_ACTIVE: |
+ case SWITCH_TRACKED_BY_WORKSPACE_CHANGED: |
+ case SWITCH_WINDOW_REMOVED: |
+ case SWITCH_VISIBILITY_CHANGED: |
+ case SWITCH_MINIMIZED: |
+ details.animate = details.animate_scale = true; |
+ details.animate_opacity = last_active == desktop_workspace(); |
+ break; |
+ |
+ case SWITCH_INITIAL: |
+ details.animate = details.animate_opacity = details.animate_scale = true; |
+ details.pause_time_ms = kInitialPauseTimeMS; |
+ break; |
+ |
+ // Remaining cases require no animation. |
+ default: |
+ break; |
+ } |
+ ash::internal::ShowWorkspace(workspace->window(), details); |
+} |
+ |
+void WorkspaceManager2::HideWorkspace( |
+ Workspace2* workspace, |
+ SwitchReason reason, |
+ bool is_unminimizing_maximized_window) const { |
+ WorkspaceAnimationDetails details; |
+ details.direction = active_workspace_ == desktop_workspace() ? |
+ WORKSPACE_ANIMATE_UP : WORKSPACE_ANIMATE_DOWN; |
+ switch (reason) { |
+ case SWITCH_WINDOW_MADE_ACTIVE: |
+ case SWITCH_TRACKED_BY_WORKSPACE_CHANGED: |
+ details.animate_opacity = |
+ ((active_workspace_ == desktop_workspace() || |
+ workspace != desktop_workspace()) && |
+ !is_unminimizing_maximized_window); |
+ details.animate_scale = true; |
+ details.animate = true; |
+ break; |
+ |
+ case SWITCH_MAXIMIZED_OR_RESTORED: |
+ if (active_workspace_->is_maximized()) { |
+ // Delay the hide until the animation is done. |
+ details.duration = |
+ base::TimeDelta::FromMilliseconds(kCrossFadeSwitchTimeMS); |
+ details.animate = true; |
+ } |
+ break; |
+ |
+ // Remaining cases require no animation. |
+ default: |
+ break; |
+ } |
+ ash::internal::HideWorkspace(workspace->window(), details); |
+} |
+ |
void WorkspaceManager2::ProcessDeletion() { |
std::set<Workspace2*> to_delete; |
to_delete.swap(to_delete_); |
@@ -495,14 +607,14 @@ void WorkspaceManager2::OnWillRemoveWindowFromWorkspace(Workspace2* workspace, |
void WorkspaceManager2::OnWindowRemovedFromWorkspace(Workspace2* workspace, |
Window* child) { |
if (workspace->ShouldMoveToPending()) |
- MoveWorkspaceToPendingOrDelete(workspace, NULL, ANIMATE_NEW); |
+ MoveWorkspaceToPendingOrDelete(workspace, NULL, SWITCH_WINDOW_REMOVED); |
} |
void WorkspaceManager2::OnWorkspaceChildWindowVisibilityChanged( |
Workspace2* workspace, |
Window* child) { |
if (workspace->ShouldMoveToPending()) |
- MoveWorkspaceToPendingOrDelete(workspace, NULL, ANIMATE_NEW); |
+ MoveWorkspaceToPendingOrDelete(workspace, NULL, SWITCH_VISIBILITY_CHANGED); |
else if (workspace == active_workspace_) |
UpdateShelfVisibility(); |
} |
@@ -523,7 +635,7 @@ void WorkspaceManager2::OnWorkspaceWindowShowStateChanged( |
DCHECK_EQ(workspace, child->GetProperty(kWorkspaceKey)); |
if (wm::IsWindowMinimized(child)) { |
if (workspace->ShouldMoveToPending()) |
- MoveWorkspaceToPendingOrDelete(workspace, NULL, ANIMATE_NEW); |
+ MoveWorkspaceToPendingOrDelete(workspace, NULL, SWITCH_MINIMIZED); |
DCHECK(!old_layer); |
} else { |
// Set of cases to deal with: |
@@ -536,6 +648,9 @@ void WorkspaceManager2::OnWorkspaceWindowShowStateChanged( |
const bool is_active = wm::IsActiveWindow(child); |
Workspace2* new_workspace = NULL; |
const int max_count = workspace->GetNumMaximizedWindows(); |
+ base::TimeDelta duration = old_layer && !IsMaximized(child) ? |
+ GetCrossFadeDuration(old_layer->bounds(), child->bounds()) : |
+ base::TimeDelta::FromMilliseconds(kCrossFadeSwitchTimeMS); |
if (max_count == 0) { |
if (workspace != desktop_workspace()) { |
{ |
@@ -543,10 +658,13 @@ void WorkspaceManager2::OnWorkspaceWindowShowStateChanged( |
ReparentWindow(child, desktop_workspace()->window(), NULL); |
} |
DCHECK(!is_active || old_layer); |
- MoveWorkspaceToPendingOrDelete(workspace, child, ANIMATE_NONE); |
+ new_workspace = desktop_workspace(); |
+ SetActiveWorkspace(new_workspace, SWITCH_MAXIMIZED_OR_RESTORED, |
+ duration); |
+ MoveWorkspaceToPendingOrDelete(workspace, child, |
+ SWITCH_MAXIMIZED_OR_RESTORED); |
if (FindWorkspace(workspace) == workspaces_.end()) |
workspace = NULL; |
- new_workspace = desktop_workspace(); |
} |
} else if ((max_count == 1 && workspace == desktop_workspace()) || |
max_count > 1) { |
@@ -559,15 +677,16 @@ void WorkspaceManager2::OnWorkspaceWindowShowStateChanged( |
// WorkspaceLayoutManager2::OnWindowPropertyChanged() the window is made |
// active. |
if (old_layer) { |
- switch_duration_ = |
- GetCrossFadeDuration(old_layer->bounds(), child->bounds()); |
- SetActiveWorkspace(new_workspace, ANIMATE_NONE); |
- switch_duration_ = base::TimeDelta(); |
- CrossFadeWindowBetweenWorkspaces( |
- workspace ? workspace->window() : NULL, new_workspace->window(), |
- child, old_layer); |
+ SetActiveWorkspace(new_workspace, SWITCH_MAXIMIZED_OR_RESTORED, |
+ duration); |
+ CrossFadeWindowBetweenWorkspaces(new_workspace->window(), child, |
+ old_layer); |
+ if (workspace == desktop_workspace() || |
+ new_workspace == desktop_workspace()) { |
+ FadeDesktop(child, duration); |
+ } |
} else { |
- SetActiveWorkspace(new_workspace, ANIMATE_NONE); |
+ SetActiveWorkspace(new_workspace, SWITCH_OTHER, base::TimeDelta()); |
} |
} else { |
if (last_show_state == ui::SHOW_STATE_MINIMIZED) |
@@ -596,8 +715,10 @@ void WorkspaceManager2::OnTrackedByWorkspaceChanged(Workspace2* workspace, |
if (is_active) |
new_workspace->window()->Show(); |
ReparentWindow(window, new_workspace->window(), NULL); |
- if (is_active) |
- SetActiveWorkspace(new_workspace, ANIMATE_OLD_AND_NEW); |
+ if (is_active) { |
+ SetActiveWorkspace(new_workspace, SWITCH_TRACKED_BY_WORKSPACE_CHANGED, |
+ base::TimeDelta()); |
+ } |
} |
} // namespace internal |