diff options
author | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-06 02:21:19 +0000 |
---|---|---|
committer | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-06 02:21:19 +0000 |
commit | 91f4c79176102cab860d4a0ad14280d8bec50f15 (patch) | |
tree | 4fda682ef36115ed6ce029e49ff4495ddc19ec46 /ash | |
parent | 88e241257ce551af29d26c087d5093e48eac294d (diff) | |
download | chromium_src-91f4c79176102cab860d4a0ad14280d8bec50f15.zip chromium_src-91f4c79176102cab860d4a0ad14280d8bec50f15.tar.gz chromium_src-91f4c79176102cab860d4a0ad14280d8bec50f15.tar.bz2 |
Reland: ash: Improved window maximize/restore animations
This implements a cross-fade while scaling the window between the new and old size.
When a maximize animation is triggered we grab the window's current layer (and those of child windows) and start an animation on those layers to scale them up to full size. Simultaneously, we install a fresh layer for the window, set the bounds to fill the workspace, and tell the window to paint. We scale down that layer to match the window size at the start of the animation, then fade it in while scaling it up to full size.
The restore animation essentially does the above in reverse. However, we always keep the higher resolution layer on top (it looks better), and we always keep the lower layer fully opaque (so the desktop doesn't bleed through).
The animation is aborted if the window is closed mid-animation or the GPU process crashes mid-animation.
The animation does not yet work for app windows, see crbug.com/131293
BUG=116618
TEST=aura_shell_unittests WorkspaceManagerTest and WindowAnimationsTest, trigger slow window animation with shift-click on maximize widget and close window during animation, kill -9 the GPU process during the animation and observe that Chrome recovers
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=139494
Review URL: https://chromiumcodereview.appspot.com/10444014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@140698 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r-- | ash/accelerators/accelerator_controller.cc | 6 | ||||
-rw-r--r-- | ash/wm/base_layout_manager.cc | 36 | ||||
-rw-r--r-- | ash/wm/base_layout_manager.h | 7 | ||||
-rw-r--r-- | ash/wm/window_animations.cc | 181 | ||||
-rw-r--r-- | ash/wm/window_animations.h | 12 | ||||
-rw-r--r-- | ash/wm/window_animations_unittest.cc | 60 | ||||
-rw-r--r-- | ash/wm/workspace/workspace.cc | 4 | ||||
-rw-r--r-- | ash/wm/workspace/workspace.h | 4 | ||||
-rw-r--r-- | ash/wm/workspace/workspace_manager.cc | 16 | ||||
-rw-r--r-- | ash/wm/workspace/workspace_manager.h | 14 | ||||
-rw-r--r-- | ash/wm/workspace/workspace_manager_unittest.cc | 4 |
11 files changed, 300 insertions, 44 deletions
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index c4f21ba..f1fb427 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc @@ -178,21 +178,21 @@ bool HandlePrintLayerHierarchy() { void PrintWindowHierarchy(aura::Window* window, int indent) { std::string indent_str(indent, ' '); - VLOG(1) << indent_str << window->name() << " type " << window->type() + DLOG(INFO) << indent_str << window->name() << " type " << window->type() << (ash::wm::IsActiveWindow(window) ? "active" : ""); for (size_t i = 0; i < window->children().size(); ++i) PrintWindowHierarchy(window->children()[i], indent + 3); } bool HandlePrintWindowHierarchy() { - VLOG(1) << "Window hierarchy:"; + DLOG(INFO) << "Window hierarchy:"; aura::Window* container = ash::Shell::GetInstance()->GetContainer( ash::internal::kShellWindowId_DefaultContainer); PrintWindowHierarchy(container, 0); return true; } -#endif +#endif // !defined(NDEBUG) } // namespace diff --git a/ash/wm/base_layout_manager.cc b/ash/wm/base_layout_manager.cc index 4f27115..f2de193 100644 --- a/ash/wm/base_layout_manager.cc +++ b/ash/wm/base_layout_manager.cc @@ -4,12 +4,14 @@ #include "ash/wm/base_layout_manager.h" +#include "ash/ash_switches.h" #include "ash/screen_ash.h" #include "ash/shell.h" #include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_animations.h" #include "ash/wm/window_properties.h" #include "ash/wm/window_util.h" +#include "base/command_line.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/root_window.h" #include "ui/aura/window.h" @@ -75,7 +77,7 @@ void BaseLayoutManager::OnWindowAddedToLayout(aura::Window* child) { // Only update the bounds if the window has a show state that depends on the // workspace area. if (wm::IsWindowMaximized(child) || wm::IsWindowFullscreen(child)) - UpdateBoundsFromShowState(child); + UpdateBoundsFromShowState(child, false); } void BaseLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { @@ -99,8 +101,7 @@ void BaseLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, void BaseLayoutManager::SetChildBounds(aura::Window* child, const gfx::Rect& requested_bounds) { gfx::Rect child_bounds(requested_bounds); - // Avoid a janky resize on startup by ensuring the initial bounds fill the - // screen. + // Some windows rely on this to set their initial bounds. if (wm::IsWindowMaximized(child)) child_bounds = ScreenAsh::GetMaximizedWindowBounds(child); else if (wm::IsWindowFullscreen(child)) @@ -130,7 +131,7 @@ void BaseLayoutManager::OnWindowPropertyChanged(aura::Window* window, const void* key, intptr_t old) { if (key == aura::client::kShowStateKey) { - UpdateBoundsFromShowState(window); + UpdateBoundsFromShowState(window, true); ShowStateChanged(window, static_cast<ui::WindowShowState>(old)); } } @@ -167,13 +168,15 @@ void BaseLayoutManager::ShowStateChanged(aura::Window* window, } } -void BaseLayoutManager::UpdateBoundsFromShowState(aura::Window* window) { +void BaseLayoutManager::UpdateBoundsFromShowState(aura::Window* window, + bool animate) { switch (window->GetProperty(aura::client::kShowStateKey)) { case ui::SHOW_STATE_DEFAULT: case ui::SHOW_STATE_NORMAL: { const gfx::Rect* restore = GetRestoreBounds(window); if (restore) { - SetChildBoundsDirect(window, + MaybeAnimateToBounds(window, + animate, BoundsWithScreenEdgeVisible(window, *restore)); } window->ClearProperty(aura::client::kRestoreBoundsKey); @@ -182,11 +185,15 @@ void BaseLayoutManager::UpdateBoundsFromShowState(aura::Window* window) { case ui::SHOW_STATE_MAXIMIZED: SetRestoreBoundsIfNotSet(window); - SetChildBoundsDirect(window, ScreenAsh::GetMaximizedWindowBounds(window)); + MaybeAnimateToBounds(window, + animate, + ScreenAsh::GetMaximizedWindowBounds(window)); break; case ui::SHOW_STATE_FULLSCREEN: SetRestoreBoundsIfNotSet(window); + // Don't animate the full-screen window transition. + // TODO(jamescook): Use animation here. Be sure the lock screen works. SetChildBoundsDirect( window, gfx::Screen::GetMonitorNearestWindow(window).bounds()); break; @@ -196,6 +203,21 @@ void BaseLayoutManager::UpdateBoundsFromShowState(aura::Window* window) { } } +void BaseLayoutManager::MaybeAnimateToBounds(aura::Window* window, + bool animate, + const gfx::Rect& new_bounds) { + // Only animate visible windows. + if (animate && + window->TargetVisibility() && + !window->GetProperty(aura::client::kAnimationsDisabledKey) && + !CommandLine::ForCurrentProcess()->HasSwitch( + ash::switches::kAshWindowAnimationsDisabled)) { + CrossFadeToBounds(window, new_bounds); + return; + } + SetChildBoundsDirect(window, new_bounds); +} + void BaseLayoutManager::AdjustWindowSizesForScreenChange() { // If a user plugs an external monitor into a laptop running Aura the // monitor size will change. Maximized windows need to resize to match. diff --git a/ash/wm/base_layout_manager.h b/ash/wm/base_layout_manager.h index 4965777..becf24a 100644 --- a/ash/wm/base_layout_manager.h +++ b/ash/wm/base_layout_manager.h @@ -72,7 +72,12 @@ class ASH_EXPORT BaseLayoutManager : public aura::LayoutManager, private: // Update window bounds based on a change in show state. - void UpdateBoundsFromShowState(aura::Window* window); + void UpdateBoundsFromShowState(aura::Window* window, bool animate); + + // Updates window bounds and animates when requested and possible. + void MaybeAnimateToBounds(aura::Window* window, + bool animate, + const gfx::Rect& new_bounds); // Adjusts the window sizes when the screen changes its size or its // work area insets. diff --git a/ash/wm/window_animations.cc b/ash/wm/window_animations.cc index 0d7e8c8..70e7d07 100644 --- a/ash/wm/window_animations.cc +++ b/ash/wm/window_animations.cc @@ -17,6 +17,7 @@ #include "ui/aura/window.h" #include "ui/aura/window_observer.h" #include "ui/aura/window_property.h" +#include "ui/compositor/compositor_observer.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/layer_animation_sequence.h" @@ -32,7 +33,9 @@ DECLARE_WINDOW_PROPERTY_TYPE(ash::WindowVisibilityAnimationType) DECLARE_WINDOW_PROPERTY_TYPE(ash::WindowVisibilityAnimationTransition) DECLARE_WINDOW_PROPERTY_TYPE(float) +using aura::Window; using base::TimeDelta; +using ui::Layer; namespace ash { namespace internal { @@ -55,6 +58,9 @@ namespace { const int kDefaultAnimationDurationForMenuMS = 150; +// TODO(jamescook): Shorten the duration if the window doesn't move much. +const int kCrossFadeAnimationDurationMs = 400; + const float kWindowAnimation_HideOpacity = 0.f; const float kWindowAnimation_ShowOpacity = 1.f; const float kWindowAnimation_TranslateFactor = -0.025f; @@ -497,6 +503,102 @@ bool AnimateHideWindow(aura::Window* window) { } } +// Recreates a fresh layer for |window| and all its child windows. Does not +// recreate shadows or other non-window layers. Returns the old layer and its +// children, maintaining the hierarchy. +Layer* RecreateWindowLayers(Window* window) { + Layer* old_layer = window->RecreateLayer(); + for (Window::Windows::const_iterator it = window->children().begin(); + it != window->children().end(); + ++it) { + aura::Window* child = *it; + Layer* old_child_layer = RecreateWindowLayers(child); + // Maintain the hierarchy of the detached layers. + old_layer->Add(old_child_layer); + } + return old_layer; +} + +// Deletes |layer| and all its child layers. +void DeepDelete(Layer* layer) { + std::vector<Layer*> children = layer->children(); + for (std::vector<Layer*>::const_iterator it = children.begin(); + it != children.end(); + ++it) { + Layer* child = *it; + DeepDelete(child); + } + delete layer; +} + +// Observer for a window cross-fade animation. If either the window closes or +// the layer's animation completes or compositing is aborted due to GPU crash, +// it deletes the layer and removes itself as an observer. +class CrossFadeObserver : public ui::CompositorObserver, + public aura::WindowObserver, + public ui::ImplicitAnimationObserver { + public: + // Observes |window| for destruction, but does not take ownership. + // Takes ownership of |layer| and its child layers. + CrossFadeObserver(Window* window, Layer* layer) + : window_(window), + layer_(layer) { + window_->AddObserver(this); + layer_->GetCompositor()->AddObserver(this); + } + virtual ~CrossFadeObserver() { + Cleanup(); + } + + // ui::CompositorObserver overrides: + virtual void OnCompositingStarted(ui::Compositor* compositor) OVERRIDE { + } + virtual void OnCompositingEnded(ui::Compositor* compositor) OVERRIDE { + } + virtual void OnCompositingAborted(ui::Compositor* compositor) OVERRIDE { + // Something went wrong with compositing and our layers are now invalid. + if (layer_) + layer_->GetAnimator()->StopAnimating(); + // Delete is scheduled in OnImplicitAnimationsCompleted(). + Cleanup(); + } + + // aura::WindowObserver overrides: + virtual void OnWindowDestroying(Window* window) OVERRIDE { + if (layer_) + layer_->GetAnimator()->StopAnimating(); + // Delete is scheduled in OnImplicitAnimationsCompleted(). + Cleanup(); + } + + // ui::ImplicitAnimationObserver overrides: + virtual void OnImplicitAnimationsCompleted() OVERRIDE { + // ImplicitAnimationObserver's base class uses the object after calling + // this function, so we cannot delete |this|. + MessageLoop::current()->DeleteSoon(FROM_HERE, this); + } + + private: + // Can be called multiple times if the window is closed or the compositor + // fails in the middle of the animation. + void Cleanup() { + if (window_) { + window_->RemoveObserver(this); + window_ = NULL; + } + if (layer_) { + layer_->GetCompositor()->RemoveObserver(this); + DeepDelete(layer_); + layer_ = NULL; + } + } + + Window* window_; // not owned + Layer* layer_; // owned + + DISALLOW_COPY_AND_ASSIGN(CrossFadeObserver); +}; + } // namespace } // namespace internal @@ -539,6 +641,85 @@ ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver( namespace internal { +void CrossFadeToBounds(aura::Window* window, const gfx::Rect& new_bounds) { + DCHECK(window->TargetVisibility()); + gfx::Rect old_bounds = window->bounds(); + + // Create fresh layers for the window and all its children to paint into. + // Takes ownership of the old layer and all its children, which will be + // cleaned up after the animation completes. + ui::Layer* old_layer = RecreateWindowLayers(window); + ui::Layer* new_layer = window->layer(); + + // Ensure the higher-resolution layer is on top. + bool old_on_top = (old_bounds.width() > new_bounds.width()); + if (old_on_top) + old_layer->parent()->StackBelow(new_layer, old_layer); + else + old_layer->parent()->StackAbove(new_layer, old_layer); + + // Tween types for transform animations must match to keep the window edges + // aligned during the animation. + const ui::Tween::Type kTransformTween = ui::Tween::EASE_OUT; + { + // Scale up the old layer while translating to new position. + ui::ScopedLayerAnimationSettings settings(old_layer->GetAnimator()); + // Animation observer owns the old layer and deletes itself. + settings.AddObserver(new CrossFadeObserver(window, old_layer)); + settings.SetTransitionDuration( + TimeDelta::FromMilliseconds(kCrossFadeAnimationDurationMs)); + settings.SetTweenType(kTransformTween); + ui::Transform out_transform; + float scale_x = static_cast<float>(new_bounds.width()) / + static_cast<float>(old_bounds.width()); + float scale_y = static_cast<float>(new_bounds.height()) / + static_cast<float>(old_bounds.height()); + out_transform.ConcatScale(scale_x, scale_y); + out_transform.ConcatTranslate(new_bounds.x() - old_bounds.x(), + new_bounds.y() - old_bounds.y()); + old_layer->SetTransform(out_transform); + if (old_on_top) { + // The old layer is on top, and should fade out. The new layer below will + // stay opaque to block the desktop. + old_layer->SetOpacity(0.f); + } + // In tests |old_layer| is deleted here, as animations have zero duration. + } + + // Resize the window to the new size, which will force a layout and paint. + window->SetBounds(new_bounds); + + // Set the new layer's current transform, such that the user sees a scaled + // version of the window with the original bounds at the original position. + ui::Transform in_transform; + float scale_x = static_cast<float>(old_bounds.width()) / + static_cast<float>(new_bounds.width()); + float scale_y = static_cast<float>(old_bounds.height()) / + static_cast<float>(new_bounds.height()); + in_transform.ConcatScale(scale_x, scale_y); + in_transform.ConcatTranslate(old_bounds.x() - new_bounds.x(), + old_bounds.y() - new_bounds.y()); + new_layer->SetTransform(in_transform); + if (!old_on_top) { + // The new layer is on top and should fade in. The old layer below will + // stay opaque and block the desktop. + new_layer->SetOpacity(0.f); + } + { + // Animate the new layer to the identity transform, so the window goes to + // its newly set bounds. + ui::ScopedLayerAnimationSettings settings(new_layer->GetAnimator()); + settings.SetTransitionDuration( + TimeDelta::FromMilliseconds(kCrossFadeAnimationDurationMs)); + settings.SetTweenType(kTransformTween); + new_layer->SetTransform(ui::Transform()); + if (!old_on_top) { + // New layer is on top, fade it in. + new_layer->SetOpacity(1.f); + } + } +} + bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) { if (window->GetProperty(aura::client::kAnimationsDisabledKey) || CommandLine::ForCurrentProcess()->HasSwitch( diff --git a/ash/wm/window_animations.h b/ash/wm/window_animations.h index 3bba85c..29083d3 100644 --- a/ash/wm/window_animations.h +++ b/ash/wm/window_animations.h @@ -7,12 +7,16 @@ #pragma once #include "ash/ash_export.h" -#include "base/time.h" namespace aura { class Window; } - +namespace base { +class TimeDelta; +} +namespace gfx { +class Rect; +} namespace ui { class ImplicitAnimationObserver; } @@ -72,6 +76,10 @@ ASH_EXPORT ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver( namespace internal { +// Animate a cross-fade of |window| from its current bounds to |new_bounds|. +ASH_EXPORT void CrossFadeToBounds(aura::Window* window, + const gfx::Rect& new_bounds); + // Returns false if the |window| didn't animate. ASH_EXPORT bool AnimateOnChildWindowVisibilityChanged( aura::Window* window, bool visible); diff --git a/ash/wm/window_animations_unittest.cc b/ash/wm/window_animations_unittest.cc index 3e4a623..0b1b377 100644 --- a/ash/wm/window_animations_unittest.cc +++ b/ash/wm/window_animations_unittest.cc @@ -12,12 +12,15 @@ #include "ui/compositor/layer.h" #include "ui/compositor/layer_animator.h" +using aura::Window; +using ui::Layer; + namespace ash { namespace internal { -typedef ash::test::AshTestBase WindowAnimationsWorkspaceTest; +typedef ash::test::AshTestBase WindowAnimationsTest; -TEST_F(WindowAnimationsWorkspaceTest, HideShow) { +TEST_F(WindowAnimationsTest, HideShow) { aura::Window* default_container = ash::Shell::GetInstance()->GetContainer( internal::kShellWindowId_DefaultContainer); @@ -54,7 +57,7 @@ TEST_F(WindowAnimationsWorkspaceTest, HideShow) { EXPECT_TRUE(window->layer()->visible()); } -TEST_F(WindowAnimationsWorkspaceTest, ShowHide) { +TEST_F(WindowAnimationsTest, ShowHide) { aura::Window* default_container = ash::Shell::GetInstance()->GetContainer( internal::kShellWindowId_DefaultContainer); @@ -91,7 +94,7 @@ TEST_F(WindowAnimationsWorkspaceTest, ShowHide) { EXPECT_FALSE(window->layer()->visible()); } -TEST_F(WindowAnimationsWorkspaceTest, LayerTargetVisibility) { +TEST_F(WindowAnimationsTest, LayerTargetVisibility) { aura::Window* default_container = ash::Shell::GetInstance()->GetContainer( internal::kShellWindowId_DefaultContainer); @@ -107,5 +110,54 @@ TEST_F(WindowAnimationsWorkspaceTest, LayerTargetVisibility) { EXPECT_TRUE(window->layer()->GetTargetVisibility()); } +TEST_F(WindowAnimationsTest, CrossFadeToBounds) { + Window* default_container = + ash::Shell::GetInstance()->GetContainer( + internal::kShellWindowId_DefaultContainer); + scoped_ptr<Window> window( + aura::test::CreateTestWindowWithId(0, default_container)); + window->SetBounds(gfx::Rect(5, 10, 320, 240)); + window->Show(); + + Layer* old_layer = window->layer(); + EXPECT_EQ(1.0f, old_layer->GetTargetOpacity()); + + // Cross fade to a larger size, as in a maximize animation. + CrossFadeToBounds(window.get(), gfx::Rect(0, 0, 640, 480)); + // Window's layer has been replaced. + EXPECT_NE(old_layer, window->layer()); + // Original layer stays opaque and stretches to new size. + EXPECT_EQ(1.0f, old_layer->GetTargetOpacity()); + EXPECT_EQ("5,10 320x240", old_layer->bounds().ToString()); + ui::Transform grow_transform; + grow_transform.ConcatScale(640.f / 320.f, 480.f / 240.f); + grow_transform.ConcatTranslate(-5.f, -10.f); + EXPECT_EQ(grow_transform, old_layer->GetTargetTransform()); + // New layer animates in to the identity transform. + EXPECT_EQ(1.0f, window->layer()->GetTargetOpacity()); + EXPECT_EQ(ui::Transform(), window->layer()->GetTargetTransform()); + + // Allow the animation observer to delete itself. + RunAllPendingInMessageLoop(); + + // Cross fade to a smaller size, as in a restore animation. + old_layer = window->layer(); + CrossFadeToBounds(window.get(), gfx::Rect(5, 10, 320, 240)); + // Again, window layer has been replaced. + EXPECT_NE(old_layer, window->layer()); + // Original layer fades out and stretches down to new size. + EXPECT_EQ(0.0f, old_layer->GetTargetOpacity()); + EXPECT_EQ("0,0 640x480", old_layer->bounds().ToString()); + ui::Transform shrink_transform; + shrink_transform.ConcatScale(320.f / 640.f, 240.f / 480.f); + shrink_transform.ConcatTranslate(5.f, 10.f); + EXPECT_EQ(shrink_transform, old_layer->GetTargetTransform()); + // New layer animates in to the identity transform. + EXPECT_EQ(1.0f, window->layer()->GetTargetOpacity()); + EXPECT_EQ(ui::Transform(), window->layer()->GetTargetTransform()); + + RunAllPendingInMessageLoop(); +} + } // namespace internal } // namespace ash diff --git a/ash/wm/workspace/workspace.cc b/ash/wm/workspace/workspace.cc index 207333d..e153de4 100644 --- a/ash/wm/workspace/workspace.cc +++ b/ash/wm/workspace/workspace.cc @@ -67,9 +67,5 @@ void Workspace::SetWindowBounds(aura::Window* window, const gfx::Rect& bounds) { workspace_manager_->SetWindowBounds(window, bounds); } -void Workspace::SetIgnoredWindow(aura::Window* window) { - workspace_manager_->set_ignored_window(window); -} - } // namespace internal } // namespace ash diff --git a/ash/wm/workspace/workspace.h b/ash/wm/workspace/workspace.h index 149a5cc..e212e55 100644 --- a/ash/wm/workspace/workspace.h +++ b/ash/wm/workspace/workspace.h @@ -67,10 +67,6 @@ class ASH_EXPORT Workspace { // Sets the bounds of the specified window. void SetWindowBounds(aura::Window* window, const gfx::Rect& bounds); - // Sets the ignore window. See WorkspaceManager::set_ignored_window() for - // details. - void SetIgnoredWindow(aura::Window* window); - // Returns true if the given |window| can be added to this workspace. virtual bool CanAdd(aura::Window* window) const = 0; diff --git a/ash/wm/workspace/workspace_manager.cc b/ash/wm/workspace/workspace_manager.cc index d4eda81d..c50fc84 100644 --- a/ash/wm/workspace/workspace_manager.cc +++ b/ash/wm/workspace/workspace_manager.cc @@ -30,13 +30,17 @@ namespace { -// Returns a list of all the windows with layers in |result|. +// Returns a list of all the windows with layers in |result|. Optionally +// ignores the window |ignore_window|. void BuildWindowList(const std::vector<aura::Window*>& windows, + aura::Window* ignore_window, std::vector<aura::Window*>* result) { for (size_t i = 0; i < windows.size(); ++i) { + if (windows[i] == ignore_window) + continue; if (windows[i]->layer()) result->push_back(windows[i]); - BuildWindowList(windows[i]->transient_children(), result); + BuildWindowList(windows[i]->transient_children(), ignore_window, result); } } @@ -51,7 +55,7 @@ namespace internal { WorkspaceManager::WorkspaceManager(aura::Window* contents_view) : contents_view_(contents_view), active_workspace_(NULL), - ignored_window_(NULL), + maximize_restore_window_(NULL), grid_size_(0), shelf_(NULL) { DCHECK(contents_view); @@ -212,7 +216,7 @@ void WorkspaceManager::SetVisibilityOfWorkspaceWindows( AnimateChangeType change_type, bool value) { std::vector<aura::Window*> children; - BuildWindowList(workspace->windows(), &children); + BuildWindowList(workspace->windows(), maximize_restore_window_, &children); SetWindowLayerVisibility(children, change_type, value); } @@ -289,9 +293,7 @@ int WorkspaceManager::GetWorkspaceIndexContaining(aura::Window* window) const { void WorkspaceManager::SetWindowBounds(aura::Window* window, const gfx::Rect& bounds) { - ignored_window_ = window; window->SetBounds(bounds); - ignored_window_ = NULL; } void WorkspaceManager::OnTypeOfWorkspacedNeededChanged(aura::Window* window) { @@ -312,7 +314,9 @@ void WorkspaceManager::OnTypeOfWorkspacedNeededChanged(aura::Window* window) { new_workspace = CreateWorkspace(Workspace::TYPE_MANAGED); new_workspace->AddWindowAfter(window, NULL); } + maximize_restore_window_ = window; SetActiveWorkspace(new_workspace); + maximize_restore_window_ = NULL; // Delete at the end so that we don't attempt to switch to another // workspace in RemoveWorkspace(). CleanupWorkspace(current_workspace); diff --git a/ash/wm/workspace/workspace_manager.h b/ash/wm/workspace/workspace_manager.h index 4f80f36..2f9985d 100644 --- a/ash/wm/workspace/workspace_manager.h +++ b/ash/wm/workspace/workspace_manager.h @@ -76,10 +76,6 @@ class ASH_EXPORT WorkspaceManager { // Returns the bounds in which a window can be moved/resized. gfx::Rect GetDragAreaBounds(); - // Returns the window the layout manager should allow the size to be set for. - // TODO: maybe this should be set on WorkspaceLayoutManager. - aura::Window* ignored_window() { return ignored_window_; } - // Sets the size of the grid. Newly added windows are forced to align to the // size of the grid. void set_grid_size(int size) { grid_size_ = size; } @@ -106,11 +102,6 @@ class ASH_EXPORT WorkspaceManager { friend class Workspace; friend class WorkspaceManagerTest; - // See description above getter. - void set_ignored_window(aura::Window* ignored_window) { - ignored_window_ = ignored_window; - } - void AddWorkspace(Workspace* workspace); void RemoveWorkspace(Workspace* workspace); @@ -162,8 +153,9 @@ class ASH_EXPORT WorkspaceManager { std::vector<Workspace*> workspaces_; - // The window that WorkspaceManager does not set the bounds on. - aura::Window* ignored_window_; + // Window being maximized or restored during a workspace type change. + // It has its own animation and is ignored by workspace show/hide animations. + aura::Window* maximize_restore_window_; // See description above setter. int grid_size_; diff --git a/ash/wm/workspace/workspace_manager_unittest.cc b/ash/wm/workspace/workspace_manager_unittest.cc index 0409a76..b311825 100644 --- a/ash/wm/workspace/workspace_manager_unittest.cc +++ b/ash/wm/workspace/workspace_manager_unittest.cc @@ -30,7 +30,7 @@ namespace internal { class WorkspaceManagerTest : public test::AshTestBase { public: - WorkspaceManagerTest() {} + WorkspaceManagerTest() : manager_(NULL) {} virtual ~WorkspaceManagerTest() {} aura::Window* CreateTestWindowUnparented() { @@ -571,7 +571,7 @@ TEST_F(WorkspaceManagerTest, PersistAcrossAllWorkspaces) { } // Verifies Show()ing a minimized window that persists across all workspaces -// unminimizes thew indow. +// unminimizes the window. TEST_F(WorkspaceManagerTest, ShowMinimizedPersistWindow) { // Create a window that persists across all workspaces. scoped_ptr<Window> w1(CreateTestWindow()); |