diff options
author | varkha@chromium.org <varkha@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-24 21:46:30 +0000 |
---|---|---|
committer | varkha@chromium.org <varkha@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-24 21:46:30 +0000 |
commit | 5cf5569f4b4d4d653a222b714e1592f84a96eaec (patch) | |
tree | bfcbce172694097486522d97388624c9a8226db6 /ash | |
parent | 75af0a4b616526abff3447c6eb02f58d46da78ae (diff) | |
download | chromium_src-5cf5569f4b4d4d653a222b714e1592f84a96eaec.zip chromium_src-5cf5569f4b4d4d653a222b714e1592f84a96eaec.tar.gz chromium_src-5cf5569f4b4d4d653a222b714e1592f84a96eaec.tar.bz2 |
Animating docking transitions and limiting opportunities for vertical overlap. This introduces a limit of how many windows can be docked at the same time (2 by default). If additional windows are docked the last active one gets minimized. Restored window is always docked near the top of the docked area.
Animations are changed a bit so that a window that is being restored into docked state is fading in with 720ms animation, a docked window being minimized is using standard minimize animation and windows moving in the dock are sliding with 120ms time constant. This is done in order to create a visually connected animation that ends with the afterglow of the last window being restored.
BUG=275812
TEST=ash_unittests --gtest_filter=*Dock*ThreeWindowsMinimize*
Review URL: https://chromiumcodereview.appspot.com/23769012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@225069 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r-- | ash/wm/dock/docked_window_layout_manager.cc | 75 | ||||
-rw-r--r-- | ash/wm/dock/docked_window_layout_manager.h | 13 | ||||
-rw-r--r-- | ash/wm/dock/docked_window_layout_manager_unittest.cc | 31 |
3 files changed, 111 insertions, 8 deletions
diff --git a/ash/wm/dock/docked_window_layout_manager.cc b/ash/wm/dock/docked_window_layout_manager.cc index dee78ac..89445e8 100644 --- a/ash/wm/dock/docked_window_layout_manager.cc +++ b/ash/wm/dock/docked_window_layout_manager.cc @@ -26,6 +26,7 @@ #include "ui/aura/root_window.h" #include "ui/aura/window.h" #include "ui/aura/window_delegate.h" +#include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/rect.h" namespace ash { @@ -40,6 +41,10 @@ const int DockedWindowLayoutManager::kMinDockWidth = 200; const int DockedWindowLayoutManager::kMinDockGap = 2; //static const int DockedWindowLayoutManager::kIdealWidth = 250; +//static +const int kMaxVisibleWindows = 2; +const int kSlideDurationMs = 120; +const int kFadeDurationMs = 720; namespace { @@ -102,9 +107,13 @@ struct CompareWindowPos { : dragged_window_(dragged_window), delta_(delta / 2) {} - bool operator()(const aura::Window* win1, const aura::Window* win2) { - const gfx::Rect win1_bounds = win1->GetBoundsInScreen(); - const gfx::Rect win2_bounds = win2->GetBoundsInScreen(); + bool operator()(aura::Window* win1, aura::Window* win2) { + // Use target coordinates since animations may be active when windows are + // reordered. + const gfx::Rect win1_bounds = ScreenAsh::ConvertRectToScreen( + win1->parent(), win1->GetTargetBounds()); + const gfx::Rect win2_bounds = ScreenAsh::ConvertRectToScreen( + win2->parent(), win2->GetTargetBounds()); // If one of the windows is the |dragged_window_| attempt to make an // earlier swap between the windows than just based on their centers. // This is possible if the dragged window is at least as tall as the other @@ -160,6 +169,7 @@ DockedWindowLayoutManager::DockedWindowLayoutManager( shelf_layout_manager_(NULL), shelf_hidden_(false), docked_width_(0), + max_visible_windows_(kMaxVisibleWindows), alignment_(DOCKED_ALIGNMENT_NONE), last_active_window_(NULL), background_widget_(new DockedBackgroundWidget(dock_container_)) { @@ -230,6 +240,12 @@ void DockedWindowLayoutManager::FinishDragging() { dragged_window_->RemoveObserver(this); if (last_active_window_ == dragged_window_) last_active_window_ = NULL; + } else { + // A window is no longer dragged and is a child. + // When a window becomes a child at drag start this is + // the only opportunity we will have to enforce a window + // count limit so do it here. + MaybeMinimizeChildrenExcept(dragged_window_); } dragged_window_ = NULL; dragged_bounds_ = gfx::Rect(); @@ -341,6 +357,7 @@ void DockedWindowLayoutManager::OnWindowAddedToLayout(aura::Window* child) { alignment_ = GetAlignmentOfWindow(child); DCHECK(alignment_ != DOCKED_ALIGNMENT_NONE); } + MaybeMinimizeChildrenExcept(child); child->AddObserver(this); Relayout(); UpdateDockBounds(); @@ -438,6 +455,17 @@ void DockedWindowLayoutManager::OnWindowBoundsChanged( Relayout(); } +void DockedWindowLayoutManager::OnWindowVisibilityChanging( + aura::Window* window, bool visible) { + int animation_type = WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE; + if (visible) { + animation_type = views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT; + views::corewm::SetWindowVisibilityAnimationDuration( + window, base::TimeDelta::FromMilliseconds(kFadeDurationMs)); + } + views::corewm::SetWindowVisibilityAnimationType(window, animation_type); +} + void DockedWindowLayoutManager::OnWindowDestroying(aura::Window* window) { if (dragged_window_ == window) { FinishDragging(); @@ -505,10 +533,23 @@ void DockedWindowLayoutManager::WillChangeVisibilityState( //////////////////////////////////////////////////////////////////////////////// // DockLayoutManager private implementation: +void DockedWindowLayoutManager::MaybeMinimizeChildrenExcept( + aura::Window* child) { + // Account for the |child| by initializing to 1. + int child_index = 1; + aura::Window::Windows children(dock_container_->children()); + aura::Window::Windows::const_reverse_iterator iter = children.rbegin(); + while (iter != children.rend()) { + aura::Window* window(*iter++); + if (window == child || !IsUsedByLayout(window)) + continue; + if (++child_index > max_visible_windows_) + wm::GetWindowState(window)->Minimize(); + } +} + void DockedWindowLayoutManager::MinimizeDockedWindow(aura::Window* window) { DCHECK_NE(window->type(), aura::client::WINDOW_TYPE_POPUP); - views::corewm::SetWindowVisibilityAnimationType( - window, WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE); window->Hide(); wm::WindowState* window_state = wm::GetWindowState(window); if (window_state->IsActive()) @@ -517,7 +558,17 @@ void DockedWindowLayoutManager::MinimizeDockedWindow(aura::Window* window) { void DockedWindowLayoutManager::RestoreDockedWindow(aura::Window* window) { DCHECK_NE(window->type(), aura::client::WINDOW_TYPE_POPUP); + // Always place restored window at the top shuffling the other windows down. + // TODO(varkha): add a separate container for docked windows to keep track + // of ordering. + gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow( + dock_container_); + const gfx::Rect work_area = display.work_area(); + gfx::Rect bounds(window->bounds()); + bounds.set_y(work_area.y() - bounds.height()); + window->SetBounds(bounds); window->Show(); + MaybeMinimizeChildrenExcept(window); } void DockedWindowLayoutManager::OnWindowDocked(aura::Window* window) { @@ -657,8 +708,8 @@ void DockedWindowLayoutManager::Relayout() { for (aura::Window::Windows::const_iterator iter = visible_windows.begin(); iter != visible_windows.end(); ++iter) { aura::Window* window = *iter; - gfx::Rect bounds = window->GetBoundsInScreen(); - + gfx::Rect bounds = ScreenAsh::ConvertRectToScreen( + window->parent(), window->GetTargetBounds()); // A window is extended or shrunk to be as close as possible to the docked // area width. Windows other than the dragged window are kept at their // existing size when the dragged window is just being reordered. @@ -704,7 +755,15 @@ void DockedWindowLayoutManager::Relayout() { // have been removed when dock was closed. DCHECK_NE(alignment_, DOCKED_ALIGNMENT_NONE); bounds = ScreenAsh::ConvertRectFromScreen(dock_container_, bounds); - SetChildBoundsDirect(window, bounds); + if (bounds != window->GetTargetBounds()) { + ui::Layer* layer = window->layer(); + ui::ScopedLayerAnimationSettings slide_settings(layer->GetAnimator()); + slide_settings.SetPreemptionStrategy( + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + slide_settings.SetTransitionDuration( + base::TimeDelta::FromMilliseconds(kSlideDurationMs)); + SetChildBoundsDirect(window, bounds); + } } is_dragged_from_dock_ = true; UpdateStacking(active_window); diff --git a/ash/wm/dock/docked_window_layout_manager.h b/ash/wm/dock/docked_window_layout_manager.h index 2afbd59..124ffc1 100644 --- a/ash/wm/dock/docked_window_layout_manager.h +++ b/ash/wm/dock/docked_window_layout_manager.h @@ -132,6 +132,8 @@ class ASH_EXPORT DockedWindowLayoutManager virtual void OnWindowBoundsChanged(aura::Window* window, const gfx::Rect& old_bounds, const gfx::Rect& new_bounds) OVERRIDE; + virtual void OnWindowVisibilityChanging(aura::Window* window, + bool visible) OVERRIDE; virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; // aura::client::ActivationChangeObserver: @@ -157,6 +159,9 @@ class ASH_EXPORT DockedWindowLayoutManager FRIEND_TEST_ALL_PREFIXES(DockedWindowLayoutManagerTest, TwoWindowsWidthNew); FRIEND_TEST_ALL_PREFIXES(DockedWindowLayoutManagerTest, TwoWindowsWidthNonResizableSecond); + FRIEND_TEST_ALL_PREFIXES(DockedWindowLayoutManagerTest, ThreeWindowsDragging); + FRIEND_TEST_ALL_PREFIXES(DockedWindowLayoutManagerTest, + ThreeWindowsDraggingSecondScreen); friend class DockedWindowLayoutManagerTest; friend class DockedWindowResizerTest; @@ -169,6 +174,10 @@ class ASH_EXPORT DockedWindowLayoutManager // Ideal (starting) width of the dock. static const int kIdealWidth; + // Keep at most kMaxVisibleWindows visible in the dock and minimize the rest + // (except for |child|). + void MaybeMinimizeChildrenExcept(aura::Window* child); + // Minimize / restore window and relayout. void MinimizeDockedWindow(aura::Window* window); void RestoreDockedWindow(aura::Window* window); @@ -231,6 +240,10 @@ class ASH_EXPORT DockedWindowLayoutManager // Current width of the dock. int docked_width_; + // How many docked windows are allowed to be shown. + // TODO(varkha): Make this dynamic based on windows heights. + int max_visible_windows_; + // Last bounds that were sent to observers. gfx::Rect docked_bounds_; diff --git a/ash/wm/dock/docked_window_layout_manager_unittest.cc b/ash/wm/dock/docked_window_layout_manager_unittest.cc index 87bca92..df93031 100644 --- a/ash/wm/dock/docked_window_layout_manager_unittest.cc +++ b/ash/wm/dock/docked_window_layout_manager_unittest.cc @@ -463,6 +463,9 @@ TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsDragging) { scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); + DockedWindowLayoutManager* manager = static_cast<DockedWindowLayoutManager*>( + w1->parent()->layout_manager()); + manager->max_visible_windows_ = 3; scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 202))); DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 200); scoped_ptr<aura::Window> w3(CreateTestWindow(gfx::Rect(0, 0, 220, 204))); @@ -530,6 +533,9 @@ TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsDraggingSecondScreen) { scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 600, 201, 201))); DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 600 + 20); + DockedWindowLayoutManager* manager = static_cast<DockedWindowLayoutManager*>( + w1->parent()->layout_manager()); + manager->max_visible_windows_ = 3; scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 600, 210, 202))); DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 600 + 200); scoped_ptr<aura::Window> w3(CreateTestWindow(gfx::Rect(0, 600, 220, 204))); @@ -682,6 +688,31 @@ TEST_P(DockedWindowLayoutManagerTest, WidthMoreThanMax) { EXPECT_NE(internal::kShellWindowId_DockedContainer, window->parent()->id()); } +// Docks three windows and tests that the very first window gets minimized. +TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsMinimize) { + if (!SupportsHostWindowResize()) + return; + + scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); + DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); + scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 202))); + DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 200); + scoped_ptr<aura::Window> w3(CreateTestWindow(gfx::Rect(0, 0, 220, 204))); + DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w3.get(), 300); + + // The last two windows should be attached and snapped to the right edge. + EXPECT_EQ(w2->GetRootWindow()->bounds().right(), + w2->GetBoundsInScreen().right()); + EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); + EXPECT_EQ(w3->GetRootWindow()->bounds().right(), + w3->GetBoundsInScreen().right()); + EXPECT_EQ(internal::kShellWindowId_DockedContainer, w3->parent()->id()); + + // The first window should get minimized but parented by the dock container. + EXPECT_TRUE(wm::GetWindowState(w1.get())->IsMinimized()); + EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); +} + // Tests run twice - on both panels and normal windows INSTANTIATE_TEST_CASE_P(NormalOrPanel, DockedWindowLayoutManagerTest, |