diff options
author | varkha@chromium.org <varkha@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-14 08:12:55 +0000 |
---|---|---|
committer | varkha@chromium.org <varkha@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-14 08:12:55 +0000 |
commit | f68204f7a6e61f278250fb62f3e1138d6b6167c3 (patch) | |
tree | 9bdfe19638e886439e0c4e2d44f131af996567b9 | |
parent | d9ba0d15ca7a1f572f6db627af54b4e2625fe7e5 (diff) | |
download | chromium_src-f68204f7a6e61f278250fb62f3e1138d6b6167c3.zip chromium_src-f68204f7a6e61f278250fb62f3e1138d6b6167c3.tar.gz chromium_src-f68204f7a6e61f278250fb62f3e1138d6b6167c3.tar.bz2 |
Moves transient parent together with its children when auto-positioning
BUG=362197
TEST=ash_unittests --gtest_filter=WorkspaceControllerTest.AutoPlacingMovesTransientChild
TEST=Repeat the repro steps in the bug
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=263507
Review URL: https://codereview.chromium.org/233853002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@263600 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ash/wm/window_positioner.cc | 53 | ||||
-rw-r--r-- | ash/wm/workspace_controller_unittest.cc | 48 |
2 files changed, 93 insertions, 8 deletions
diff --git a/ash/wm/window_positioner.cc b/ash/wm/window_positioner.cc index 56d3ac9..415211e 100644 --- a/ash/wm/window_positioner.cc +++ b/ash/wm/window_positioner.cc @@ -20,6 +20,7 @@ #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/screen.h" #include "ui/wm/core/window_animations.h" +#include "ui/wm/core/window_util.h" namespace ash { @@ -108,11 +109,33 @@ bool MoveRectToOneSide(const gfx::Rect& work_area, return false; } -// Move a |window| to a new |bound|. Animate if desired by user. -// Note: The function will do nothing if the bounds did not change. -void SetBoundsAnimated(aura::Window* window, const gfx::Rect& bounds) { - if (bounds == window->GetTargetBounds()) - return; +// Move a |window| to new |bounds|. Animate if desired by user. +// Moves the transient children of the |window| as well by the same |offset| as +// the parent |window|. +void SetBoundsAndOffsetTransientChildren(aura::Window* window, + const gfx::Rect& bounds, + const gfx::Rect& work_area, + const gfx::Vector2d& offset) { + aura::Window::Windows transient_children = + ::wm::GetTransientChildren(window); + for (aura::Window::Windows::iterator iter = transient_children.begin(); + iter != transient_children.end(); ++iter) { + aura::Window* transient_child = *iter; + gfx::Rect child_bounds = transient_child->bounds(); + gfx::Rect new_child_bounds = child_bounds + offset; + if ((child_bounds.x() <= work_area.x() && + new_child_bounds.x() <= work_area.x()) || + (child_bounds.right() >= work_area.right() && + new_child_bounds.right() >= work_area.right())) { + continue; + } + if (new_child_bounds.right() > work_area.right()) + new_child_bounds.set_x(work_area.right() - bounds.width()); + else if (new_child_bounds.x() < work_area.x()) + new_child_bounds.set_x(work_area.x()); + SetBoundsAndOffsetTransientChildren(transient_child, + new_child_bounds, work_area, offset); + } if (::wm::WindowAnimationsDisabled(window)) { window->SetBounds(bounds); @@ -125,6 +148,18 @@ void SetBoundsAnimated(aura::Window* window, const gfx::Rect& bounds) { window->SetBounds(bounds); } +// Move a |window| to new |bounds|. Animate if desired by user. +// Note: The function will do nothing if the bounds did not change. +void SetBoundsAnimated(aura::Window* window, + const gfx::Rect& bounds, + const gfx::Rect& work_area) { + gfx::Rect old_bounds = window->GetTargetBounds(); + if (bounds == old_bounds) + return; + gfx::Vector2d offset(bounds.origin() - old_bounds.origin()); + SetBoundsAndOffsetTransientChildren(window, bounds, work_area, offset); +} + // Move |window| into the center of the screen - or restore it to the previous // position. void AutoPlaceSingleWindow(aura::Window* window, bool animated) { @@ -141,7 +176,7 @@ void AutoPlaceSingleWindow(aura::Window* window, bool animated) { } if (animated) - SetBoundsAnimated(window, bounds); + SetBoundsAnimated(window, bounds, work_area); else window->SetBounds(bounds); } @@ -178,6 +213,8 @@ aura::Window* GetReferenceWindow(const aura::Window* root_window, aura::Window* found = NULL; for (int i = index + windows.size(); i >= 0; i--) { aura::Window* window = windows[i % windows.size()]; + while (::wm::GetTransientParent(window)) + window = ::wm::GetTransientParent(window); if (window != exclude && window->type() == ui::wm::WINDOW_TYPE_NORMAL && window->GetRootWindow() == root_window && window->TargetVisibility() && wm::GetWindowState(window)->window_position_managed()) { @@ -282,7 +319,7 @@ void WindowPositioner::RearrangeVisibleWindowOnShow( if (!UseAutoWindowManager(added_window) || added_window_state->bounds_changed_by_user()) { if (added_window_state->minimum_visibility()) { - // Guarante minimum visibility within the work area. + // Guarantee minimum visibility within the work area. gfx::Rect work_area = GetWorkAreaForWindowInParent(added_window); gfx::Rect bounds = added_window->bounds(); gfx::Rect new_bounds = bounds; @@ -330,7 +367,7 @@ void WindowPositioner::RearrangeVisibleWindowOnShow( // Push away the other window after remembering its current position. if (MoveRectToOneSide(work_area, move_other_right, &other_bounds)) - SetBoundsAnimated(other_shown_window, other_bounds); + SetBoundsAnimated(other_shown_window, other_bounds, work_area); } } diff --git a/ash/wm/workspace_controller_unittest.cc b/ash/wm/workspace_controller_unittest.cc index 09d1c94..6056a2f 100644 --- a/ash/wm/workspace_controller_unittest.cc +++ b/ash/wm/workspace_controller_unittest.cc @@ -772,6 +772,54 @@ TEST_F(WorkspaceControllerTest, BasicAutoPlacingOnCreate) { } } +// Test that adding a second window shifts both the first window and its +// transient child. +TEST_F(WorkspaceControllerTest, AutoPlacingMovesTransientChild) { + // Create an auto-positioned window. + scoped_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)); + gfx::Rect desktop_area = window1->parent()->bounds(); + wm::GetWindowState(window1.get())->set_window_position_managed(true); + // Hide and then show |window1| to trigger auto-positioning logic. + window1->Hide(); + window1->SetBounds(gfx::Rect(16, 32, 300, 300)); + window1->Show(); + + // |window1| should be horizontally centered. + int x_window1 = (desktop_area.width() - 300) / 2; + EXPECT_EQ(base::IntToString(x_window1) + ",32 300x300", + window1->bounds().ToString()); + + // Create a |child| window and make it a transient child of |window1|. + scoped_ptr<Window> child(CreateTestWindowUnparented()); + ::wm::AddTransientChild(window1.get(), child.get()); + const int x_child = x_window1 + 50; + child->SetBounds(gfx::Rect(x_child, 20, 200, 200)); + ParentWindowInPrimaryRootWindow(child.get()); + child->Show(); + wm::ActivateWindow(child.get()); + + // The |child| should be where it was created. + EXPECT_EQ(base::IntToString(x_child) + ",20 200x200", + child->bounds().ToString()); + + // Create and show a second window forcing the first window and its child to + // move. + scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1)); + wm::GetWindowState(window2.get())->set_window_position_managed(true); + // Hide and then show |window2| to trigger auto-positioning logic. + window2->Hide(); + window2->SetBounds(gfx::Rect(32, 48, 250, 250)); + window2->Show(); + + // Check that both |window1| and |child| have moved left. + EXPECT_EQ("0,32 300x300", window1->bounds().ToString()); + int x = x_child - x_window1; + EXPECT_EQ(base::IntToString(x) + ",20 200x200", child->bounds().ToString()); + // Check that |window2| has moved right. + x = desktop_area.width() - window2->bounds().width(); + EXPECT_EQ(base::IntToString(x) + ",48 250x250", window2->bounds().ToString()); +} + // Test the basic auto placement of one and or two windows in a "simulated // session" of sequential window operations. TEST_F(WorkspaceControllerTest, BasicAutoPlacingOnShowHide) { |