summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvarkha@chromium.org <varkha@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-14 08:12:55 +0000
committervarkha@chromium.org <varkha@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-14 08:12:55 +0000
commitf68204f7a6e61f278250fb62f3e1138d6b6167c3 (patch)
tree9bdfe19638e886439e0c4e2d44f131af996567b9
parentd9ba0d15ca7a1f572f6db627af54b4e2625fe7e5 (diff)
downloadchromium_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.cc53
-rw-r--r--ash/wm/workspace_controller_unittest.cc48
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) {