summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ash/wm/dock/docked_window_layout_manager.cc96
-rw-r--r--ash/wm/dock/docked_window_layout_manager.h13
-rw-r--r--ash/wm/dock/docked_window_layout_manager_unittest.cc129
-rw-r--r--ash/wm/dock/docked_window_resizer.cc19
-rw-r--r--ash/wm/dock/docked_window_resizer_unittest.cc31
-rw-r--r--ash/wm/workspace/workspace_window_resizer.cc30
-rw-r--r--ash/wm/workspace/workspace_window_resizer.h6
7 files changed, 268 insertions, 56 deletions
diff --git a/ash/wm/dock/docked_window_layout_manager.cc b/ash/wm/dock/docked_window_layout_manager.cc
index 1601af2..dee78ac 100644
--- a/ash/wm/dock/docked_window_layout_manager.cc
+++ b/ash/wm/dock/docked_window_layout_manager.cc
@@ -25,6 +25,7 @@
#include "ui/aura/focus_manager.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_delegate.h"
#include "ui/gfx/rect.h"
namespace ash {
@@ -37,6 +38,8 @@ const int DockedWindowLayoutManager::kMaxDockWidth = 360;
const int DockedWindowLayoutManager::kMinDockWidth = 200;
// static
const int DockedWindowLayoutManager::kMinDockGap = 2;
+//static
+const int DockedWindowLayoutManager::kIdealWidth = 250;
namespace {
@@ -291,13 +294,21 @@ bool DockedWindowLayoutManager::CanDockWindow(aura::Window* window,
switches::kAshEnableDockedWindows)) {
return false;
}
+ // If a window is wide and cannot be resized down to maximum width allowed
+ // then it cannot be docked.
+ if (window->bounds().width() > kMaxDockWidth &&
+ (!wm::GetWindowState(window)->CanResize() ||
+ (window->delegate() &&
+ window->delegate()->GetMinimumSize().width() != 0 &&
+ window->delegate()->GetMinimumSize().width() > kMaxDockWidth))) {
+ return false;
+ }
// Cannot dock on the other size from an existing dock.
const DockedAlignment alignment = CalculateAlignment();
if ((edge == SNAP_LEFT && alignment == DOCKED_ALIGNMENT_RIGHT) ||
(edge == SNAP_RIGHT && alignment == DOCKED_ALIGNMENT_LEFT)) {
return false;
}
-
// Do not allow docking on the same side as launcher shelf.
ShelfAlignment shelf_alignment = SHELF_ALIGNMENT_BOTTOM;
if (launcher_)
@@ -531,6 +542,24 @@ bool DockedWindowLayoutManager::IsAnyWindowDocked() {
return CalculateAlignment() != DOCKED_ALIGNMENT_NONE;
}
+// static
+int DockedWindowLayoutManager::GetWindowWidthCloseTo(aura::Window* window,
+ int target_width) {
+ if (!wm::GetWindowState(window)->CanResize()) {
+ DCHECK_LE(window->bounds().width(), kMaxDockWidth);
+ return window->bounds().width();
+ }
+ int width = std::max(kMinDockWidth, std::min(target_width, kMaxDockWidth));
+ if (window->delegate()) {
+ if (window->delegate()->GetMinimumSize().width() != 0)
+ width = std::max(width, window->delegate()->GetMinimumSize().width());
+ if (window->delegate()->GetMaximumSize().width() != 0)
+ width = std::min(width, window->delegate()->GetMaximumSize().width());
+ }
+ DCHECK_LE(width, kMaxDockWidth);
+ return width;
+}
+
void DockedWindowLayoutManager::Relayout() {
if (in_layout_)
return;
@@ -541,7 +570,6 @@ void DockedWindowLayoutManager::Relayout() {
gfx::Rect dock_bounds = dock_container_->GetBoundsInScreen();
aura::Window* active_window = NULL;
aura::Window::Windows visible_windows;
- docked_width_ = 0;
for (size_t i = 0; i < dock_container_->children().size(); ++i) {
aura::Window* window(dock_container_->children()[i]);
@@ -577,9 +605,34 @@ void DockedWindowLayoutManager::Relayout() {
dock_container_);
const gfx::Rect work_area = display.work_area();
int available_room = work_area.height();
+ int ideal_docked_width = 0;
for (aura::Window::Windows::const_iterator iter = visible_windows.begin();
iter != visible_windows.end(); ++iter) {
- available_room -= (*iter)->bounds().height();
+ aura::Window* window = *iter;
+ available_room -= window->bounds().height();
+
+ // Adjust the dragged window to the dock. If that is not possible then
+ // other docked windows area adjusted to the one that is being dragged.
+ int adjusted_docked_width = window->bounds().width();
+ if (window == dragged_window_) {
+ // Adjust the dragged window width to the current dock size or ideal when
+ // there are no other docked windows.
+ adjusted_docked_width = GetWindowWidthCloseTo(
+ window, (docked_width_ > 0) ? docked_width_ : kIdealWidth);
+ } else if (!is_dragged_from_dock_ && is_dragged_window_docked_) {
+ // When a docked window is dragged-in other docked windows' widths are
+ // adjusted to the new width if necessary.
+ // When there is no dragged docked window the docked windows retain their
+ // widths.
+ // When a dragged window is simply being reordered in the docked area the
+ // other windows are not resized (but the dragged window can be).
+ adjusted_docked_width = GetWindowWidthCloseTo(window, 0);
+ }
+ ideal_docked_width = std::max(ideal_docked_width, adjusted_docked_width);
+
+ // Restrict docked area width regardless of window restrictions.
+ ideal_docked_width = std::max(std::min(ideal_docked_width, kMaxDockWidth),
+ kMinDockWidth);
}
const int num_windows = visible_windows.size();
const float delta = (float)available_room /
@@ -587,18 +640,35 @@ void DockedWindowLayoutManager::Relayout() {
num_windows + 1 : num_windows - 1);
float y_pos = work_area.y() + ((available_room > 0) ? delta : 0);
+ // Docked area is shown only if there is at least one non-dragged visible
+ // docked window.
+ docked_width_ = ideal_docked_width;
+ if (visible_windows.empty() ||
+ (visible_windows.size() == 1 && visible_windows[0] == dragged_window_)) {
+ docked_width_ = 0;
+ }
+
// Sort windows by their center positions and fan out overlapping
// windows.
std::sort(visible_windows.begin(),
visible_windows.end(),
CompareWindowPos(is_dragged_from_dock_ ? dragged_window_ : NULL,
delta));
- is_dragged_from_dock_ = true;
for (aura::Window::Windows::const_iterator iter = visible_windows.begin();
iter != visible_windows.end(); ++iter) {
aura::Window* window = *iter;
gfx::Rect bounds = window->GetBoundsInScreen();
+ // 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.
+ // This also enforces the min / max restrictions on the docked area width.
+ bounds.set_width(GetWindowWidthCloseTo(
+ window,
+ (!is_dragged_from_dock_ || window == dragged_window_) ?
+ ideal_docked_width : bounds.width()));
+ DCHECK_LE(bounds.width(), ideal_docked_width);
+
DockedAlignment alignment = alignment_;
if (alignment == DOCKED_ALIGNMENT_NONE && window == dragged_window_) {
alignment = GetAlignmentOfWindow(window);
@@ -606,10 +676,6 @@ void DockedWindowLayoutManager::Relayout() {
bounds.set_size(gfx::Size());
}
- // Restrict width.
- if (bounds.width() > kMaxDockWidth)
- bounds.set_width(kMaxDockWidth);
-
// Fan out windows evenly distributing the overlap or remaining free space.
bounds.set_y(std::max(work_area.y(),
std::min(work_area.bottom() - bounds.height(),
@@ -617,13 +683,15 @@ void DockedWindowLayoutManager::Relayout() {
y_pos += bounds.height() + delta;
// All docked windows other than the one currently dragged remain stuck
- // to the screen edge.
+ // to the screen edge (flush with the edge or centered in the dock area).
switch (alignment) {
case DOCKED_ALIGNMENT_LEFT:
- bounds.set_x(dock_bounds.x());
+ bounds.set_x(dock_bounds.x() +
+ (ideal_docked_width - bounds.width()) / 2);
break;
case DOCKED_ALIGNMENT_RIGHT:
- bounds.set_x(dock_bounds.right() - bounds.width());
+ bounds.set_x(dock_bounds.right() -
+ (ideal_docked_width + bounds.width()) / 2);
break;
case DOCKED_ALIGNMENT_NONE:
break;
@@ -635,14 +703,10 @@ void DockedWindowLayoutManager::Relayout() {
// If the following asserts it is probably because not all the children
// have been removed when dock was closed.
DCHECK_NE(alignment_, DOCKED_ALIGNMENT_NONE);
- // Keep the dock at least kMinDockWidth when all windows in it overhang.
- docked_width_ = std::min(kMaxDockWidth,
- std::max(docked_width_,
- bounds.width() > kMaxDockWidth ?
- kMinDockWidth : bounds.width()));
bounds = ScreenAsh::ConvertRectFromScreen(dock_container_, bounds);
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 8bea763..2afbd59 100644
--- a/ash/wm/dock/docked_window_layout_manager.h
+++ b/ash/wm/dock/docked_window_layout_manager.h
@@ -143,15 +143,20 @@ class ASH_EXPORT DockedWindowLayoutManager
ShelfVisibilityState new_state) OVERRIDE;
private:
+ FRIEND_TEST_ALL_PREFIXES(DockedWindowResizerTest, AttachTryDetach);
FRIEND_TEST_ALL_PREFIXES(DockedWindowResizerTest, AttachTwoWindowsDetachOne);
FRIEND_TEST_ALL_PREFIXES(DockedWindowResizerTest, AttachWindowMaximizeOther);
FRIEND_TEST_ALL_PREFIXES(DockedWindowResizerTest, AttachOneTestSticky);
FRIEND_TEST_ALL_PREFIXES(DockedWindowResizerTest, ResizeTwoWindows);
FRIEND_TEST_ALL_PREFIXES(DockedWindowResizerTest, DragToShelf);
+ FRIEND_TEST_ALL_PREFIXES(DockedWindowLayoutManagerTest, AddOneWindow);
FRIEND_TEST_ALL_PREFIXES(DockedWindowLayoutManagerTest, AutoPlacingLeft);
FRIEND_TEST_ALL_PREFIXES(DockedWindowLayoutManagerTest, AutoPlacingRight);
FRIEND_TEST_ALL_PREFIXES(DockedWindowLayoutManagerTest,
AutoPlacingRightSecondScreen);
+ FRIEND_TEST_ALL_PREFIXES(DockedWindowLayoutManagerTest, TwoWindowsWidthNew);
+ FRIEND_TEST_ALL_PREFIXES(DockedWindowLayoutManagerTest,
+ TwoWindowsWidthNonResizableSecond);
friend class DockedWindowLayoutManagerTest;
friend class DockedWindowResizerTest;
@@ -161,6 +166,9 @@ class ASH_EXPORT DockedWindowLayoutManager
// Width of the gap between the docked windows and a workspace.
static const int kMinDockGap;
+ // Ideal (starting) width of the dock.
+ static const int kIdealWidth;
+
// Minimize / restore window and relayout.
void MinimizeDockedWindow(aura::Window* window);
void RestoreDockedWindow(aura::Window* window);
@@ -174,6 +182,11 @@ class ASH_EXPORT DockedWindowLayoutManager
// Returns true if there are any windows currently docked.
bool IsAnyWindowDocked();
+ // Returns width that is as close as possible to |target_width| while being
+ // consistent with docked min and max restrictions and respects the |window|'s
+ // minimum and maximum size.
+ static int GetWindowWidthCloseTo(aura::Window* window, int target_width);
+
// Called whenever the window layout might change.
void Relayout();
diff --git a/ash/wm/dock/docked_window_layout_manager_unittest.cc b/ash/wm/dock/docked_window_layout_manager_unittest.cc
index 68601ad..87bca92 100644
--- a/ash/wm/dock/docked_window_layout_manager_unittest.cc
+++ b/ash/wm/dock/docked_window_layout_manager_unittest.cc
@@ -30,6 +30,7 @@
#include "base/strings/string_number_conversions.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/root_window.h"
+#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
#include "ui/base/hit_test.h"
#include "ui/gfx/screen.h"
@@ -68,10 +69,24 @@ class DockedWindowLayoutManagerTest
aura::Window* CreateTestWindow(const gfx::Rect& bounds) {
aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
- NULL,
- window_type_,
- 0,
- bounds);
+ NULL, window_type_, 0, bounds);
+ if (window_type_ == aura::client::WINDOW_TYPE_PANEL) {
+ test::TestLauncherDelegate* launcher_delegate =
+ test::TestLauncherDelegate::instance();
+ launcher_delegate->AddLauncherItem(window);
+ PanelLayoutManager* manager =
+ static_cast<PanelLayoutManager*>(GetPanelContainer(window)->
+ layout_manager());
+ manager->Relayout();
+ }
+ return window;
+ }
+
+ aura::Window* CreateTestWindowWithDelegate(
+ const gfx::Rect& bounds,
+ aura::test::TestWindowDelegate* delegate) {
+ aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
+ delegate, window_type_, 0, bounds);
if (window_type_ == aura::client::WINDOW_TYPE_PANEL) {
test::TestLauncherDelegate* launcher_delegate =
test::TestLauncherDelegate::instance();
@@ -216,9 +231,11 @@ TEST_P(DockedWindowLayoutManagerTest, AddOneWindow) {
scoped_ptr<aura::Window> window(CreateTestWindow(bounds));
DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
- // The window should be attached and snapped to the right side of the screen.
+ // The window should be attached and docked at the right edge.
+ // Its width should shrink or grow to ideal width.
EXPECT_EQ(window->GetRootWindow()->bounds().right(),
window->GetBoundsInScreen().right());
+ EXPECT_EQ(DockedWindowLayoutManager::kIdealWidth, window->bounds().width());
EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
}
@@ -563,6 +580,108 @@ TEST_P(DockedWindowLayoutManagerTest, ThreeWindowsDraggingSecondScreen) {
EXPECT_EQ(0, overlap4);
}
+// Tests that a second window added to the dock is resized to match.
+TEST_P(DockedWindowLayoutManagerTest, TwoWindowsWidthNew) {
+ if (!SupportsHostWindowResize())
+ return;
+
+ scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
+ scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 280, 202)));
+ DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
+ // The first window should get resized to ideal width.
+ EXPECT_EQ(DockedWindowLayoutManager::kIdealWidth, w1->bounds().width());
+
+ DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 300);
+ // The second window should get resized to the existing dock.
+ EXPECT_EQ(DockedWindowLayoutManager::kIdealWidth, w2->bounds().width());
+}
+
+// Tests that a first non-resizable window added to the dock is not resized.
+TEST_P(DockedWindowLayoutManagerTest, TwoWindowsWidthNonResizableFirst) {
+ if (!SupportsHostWindowResize())
+ return;
+
+ scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
+ w1->SetProperty(aura::client::kCanResizeKey, false);
+ scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 280, 202)));
+ DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
+ // The first window should not get resized.
+ EXPECT_EQ(201, w1->bounds().width());
+
+ DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 300);
+ // The second window should get resized to the first window's width.
+ EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
+}
+
+// Tests that a second non-resizable window added to the dock is not resized.
+TEST_P(DockedWindowLayoutManagerTest, TwoWindowsWidthNonResizableSecond) {
+ if (!SupportsHostWindowResize())
+ return;
+
+ scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
+ scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 280, 202)));
+ w2->SetProperty(aura::client::kCanResizeKey, false);
+ DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
+ // The first window should get resized to ideal width.
+ EXPECT_EQ(DockedWindowLayoutManager::kIdealWidth, w1->bounds().width());
+
+ DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 300);
+ // The second window should not get resized.
+ EXPECT_EQ(280, w2->bounds().width());
+
+ // The first window should get resized again - to match the second window.
+ EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
+}
+
+// Test that restrictions on minimum and maximum width of windows are honored.
+TEST_P(DockedWindowLayoutManagerTest, TwoWindowsWidthRestrictions) {
+ if (!SupportsHostWindowResize())
+ return;
+
+ aura::test::TestWindowDelegate delegate1;
+ delegate1.set_maximum_size(gfx::Size(240, 0));
+ scoped_ptr<aura::Window> w1(CreateTestWindowWithDelegate(
+ gfx::Rect(0, 0, 201, 201), &delegate1));
+ aura::test::TestWindowDelegate delegate2;
+ delegate2.set_minimum_size(gfx::Size(260, 0));
+ scoped_ptr<aura::Window> w2(CreateTestWindowWithDelegate(
+ gfx::Rect(0, 0, 280, 202), &delegate2));
+ DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
+ // The first window should get resized to its maximum width.
+ EXPECT_EQ(240, w1->bounds().width());
+
+ DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 300);
+ // The second window should get resized to its minimum width.
+ EXPECT_EQ(260, w2->bounds().width());
+
+ // The first window should be centered relative to the second.
+ EXPECT_EQ(w1->bounds().CenterPoint().x(), w2->bounds().CenterPoint().x());
+}
+
+// Test that restrictions on minimum and maximum width of windows are honored.
+TEST_P(DockedWindowLayoutManagerTest, WidthMoreThanMax) {
+ if (!SupportsHostWindowResize())
+ return;
+
+ aura::test::TestWindowDelegate delegate;
+ delegate.set_minimum_size(gfx::Size(400, 0));
+ scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
+ gfx::Rect(0, 0, 400, 201), &delegate));
+ DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, window.get(), 20);
+
+ // Secondary drag ensures that we are testing the minimum size restriction
+ // and not just failure to get past the tiling step in SnapSizer.
+ ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(window.get(),
+ 25, 5));
+ DragMove(150,0);
+ DragEnd();
+
+ // The window should not get docked even though it is dragged past the edge.
+ EXPECT_NE(window->GetRootWindow()->bounds().right(),
+ window->GetBoundsInScreen().right());
+ EXPECT_NE(internal::kShellWindowId_DockedContainer, window->parent()->id());
+}
+
// Tests run twice - on both panels and normal windows
INSTANTIATE_TEST_CASE_P(NormalOrPanel,
DockedWindowLayoutManagerTest,
diff --git a/ash/wm/dock/docked_window_resizer.cc b/ash/wm/dock/docked_window_resizer.cc
index 2882f3b..c0ca976 100644
--- a/ash/wm/dock/docked_window_resizer.cc
+++ b/ash/wm/dock/docked_window_resizer.cc
@@ -187,11 +187,6 @@ bool DockedWindowResizer::MaybeSnapToEdge(const gfx::Rect& bounds,
GetTarget()->parent(),
dock_layout_->dock_container()->GetBoundsInScreen());
- // Distance in pixels that the cursor must move past an edge for a window
- // to move beyond that edge. Same constant as in WorkspaceWindowResizer
- // is used for consistency.
- const int kStickyDistance = WorkspaceWindowResizer::kStickyDistancePixels;
-
// Short-range magnetism when retaining docked state. Same constant as in
// MagnetismMatcher is used for consistency.
const int kSnapToDockDistance = MagnetismMatcher::kMagneticDistance;
@@ -199,7 +194,7 @@ bool DockedWindowResizer::MaybeSnapToEdge(const gfx::Rect& bounds,
if (dock_alignment == DOCKED_ALIGNMENT_LEFT ||
dock_alignment == DOCKED_ALIGNMENT_NONE) {
const int distance = bounds.x() - dock_bounds.x();
- if (distance < kSnapToDockDistance && distance > -kStickyDistance) {
+ if (distance < kSnapToDockDistance && distance > 0) {
offset->set_x(-distance);
return true;
}
@@ -207,7 +202,7 @@ bool DockedWindowResizer::MaybeSnapToEdge(const gfx::Rect& bounds,
if (dock_alignment == DOCKED_ALIGNMENT_RIGHT ||
dock_alignment == DOCKED_ALIGNMENT_NONE) {
const int distance = dock_bounds.right() - bounds.right();
- if (distance < kSnapToDockDistance && distance > -kStickyDistance) {
+ if (distance < kSnapToDockDistance && distance > 0) {
offset->set_x(distance);
return true;
}
@@ -249,6 +244,16 @@ void DockedWindowResizer::FinishedDragging() {
window_state->panel_attached();
const bool is_resized =
(details_.bounds_change & WindowResizer::kBoundsChange_Resizes) != 0;
+
+ // When drag is completed the dragged docked window is resized to the bounds
+ // calculated by the layout manager that conform to other docked windows.
+ if (!attached_panel && is_docked_ && !is_resized) {
+ gfx::Rect bounds = ScreenAsh::ConvertRectFromScreen(
+ window->parent(), dock_layout_->dragged_bounds());
+ if (!bounds.IsEmpty() && bounds.width() != window->bounds().width()) {
+ window->SetBounds(bounds);
+ }
+ }
// No longer restore to pre-docked bounds if a window has been resized.
if (is_resized && is_docked_)
window_state->ClearRestoreBounds();
diff --git a/ash/wm/dock/docked_window_resizer_unittest.cc b/ash/wm/dock/docked_window_resizer_unittest.cc
index 024187c..1808be1 100644
--- a/ash/wm/dock/docked_window_resizer_unittest.cc
+++ b/ash/wm/dock/docked_window_resizer_unittest.cc
@@ -367,17 +367,22 @@ TEST_P(DockedWindowResizerTest, AttachTryDetach) {
if (!SupportsHostWindowResize())
return;
- scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
+ scoped_ptr<aura::Window> window(CreateTestWindow(
+ gfx::Rect(0, 0, DockedWindowLayoutManager::kIdealWidth + 10, 201)));
DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
- // The window should be attached and snapped to the right edge.
+ // The window should be attached and docked at the right edge.
+ // Its width should shrink to ideal width.
EXPECT_EQ(window->GetRootWindow()->bounds().right(),
window->GetBoundsInScreen().right());
+ EXPECT_EQ(DockedWindowLayoutManager::kIdealWidth,
+ window->GetBoundsInScreen().width());
EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id());
// Try to detach by dragging left less than kSnapToDockDistance.
// The window should stay docked.
- ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
+ ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(
+ window.get(), 10, 0));
DragMove(-4, -10);
// Release the mouse and the window should be still attached to the dock.
DragEnd();
@@ -389,14 +394,14 @@ TEST_P(DockedWindowResizerTest, AttachTryDetach) {
// Try to detach by dragging left by kSnapToDockDistance or more.
// The window should get undocked.
+ const int left_edge = window->bounds().x();
ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
DragMove(-32, -10);
// Release the mouse and the window should be no longer attached to the dock.
DragEnd();
- // The window should be floating on the desktop again.
- EXPECT_EQ(window->GetRootWindow()->bounds().right() - 32,
- window->GetBoundsInScreen().right());
+ // The window should be floating on the desktop again and moved to the left.
+ EXPECT_EQ(left_edge - 32, window->GetBoundsInScreen().x());
EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
window->parent()->id());
}
@@ -445,6 +450,7 @@ TEST_P(DockedWindowResizerTest, AttachTwoWindows)
EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
// Detach by dragging left (should get undocked).
+ const int left_edge = w2->bounds().x();
ASSERT_NO_FATAL_FAILURE(DragStart(w2.get()));
// Drag up as well to avoid attaching panels to launcher shelf.
DragMove(-32, -100);
@@ -456,9 +462,8 @@ TEST_P(DockedWindowResizerTest, AttachTwoWindows)
w1->GetBoundsInScreen().right());
EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
- // The second window should be floating on the desktop again.
- EXPECT_EQ(w2->GetRootWindow()->bounds().right() - 32,
- w2->GetBoundsInScreen().right());
+ // The window should be floating on the desktop again and moved to the left.
+ EXPECT_EQ(left_edge - 32, w2->GetBoundsInScreen().x());
EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
w2->parent()->id());
}
@@ -631,19 +636,19 @@ TEST_P(DockedWindowResizerTest, AttachTwoWindowsDetachOne)
EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id());
// Detach by dragging left more (should get undocked).
+ const int left_edge = w2->bounds().x();
ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(
w2.get(),
w2->bounds().width()/2 + 10,
0));
// Drag up as well to avoid attaching panels to launcher shelf.
- DragMove(-(w2->bounds().width()/2 + 20), -100);
+ const int drag_x = -(w2->bounds().width()/2 + 20);
+ DragMove(drag_x, -100);
// Release the mouse and the window should be no longer attached to the edge.
DragEnd();
// The second window should be floating on the desktop again.
- EXPECT_EQ(w2->GetRootWindow()->bounds().right() -
- (w2->bounds().width()/2 + 20),
- w2->GetBoundsInScreen().right());
+ EXPECT_EQ(left_edge + drag_x, w2->bounds().x());
EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id());
// Dock width should be set to remaining single docked window.
EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id());
diff --git a/ash/wm/workspace/workspace_window_resizer.cc b/ash/wm/workspace/workspace_window_resizer.cc
index 29be68b..81c34e6 100644
--- a/ash/wm/workspace/workspace_window_resizer.cc
+++ b/ash/wm/workspace/workspace_window_resizer.cc
@@ -418,7 +418,7 @@ void WorkspaceWindowResizer::Drag(const gfx::Point& location_in_parent,
snap_type_ = SNAP_NONE;
snap_phantom_window_controller_.reset();
snap_sizer_.reset();
- UpdateDockedState(false);
+ SetDraggedWindowDocked(false);
}
}
@@ -894,9 +894,10 @@ void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location,
if (snap_type_ == SNAP_NONE || snap_type_ != last_type) {
snap_phantom_window_controller_.reset();
snap_sizer_.reset();
- UpdateDockedState(false);
- if (snap_type_ == SNAP_NONE)
+ if (snap_type_ == SNAP_NONE) {
+ SetDraggedWindowDocked(false);
return;
+ }
}
SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT) ?
SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE;
@@ -911,20 +912,25 @@ void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location,
}
const bool can_dock = dock_layout_->CanDockWindow(window(), snap_type_);
- if (!window_state()->CanSnap() && !can_dock)
+ const bool can_snap = window_state()->CanSnap();
+ if (!can_snap && !can_dock)
return;
// Update phantom window with snapped or docked guide bounds.
// Windows that cannot be snapped or are less wide than kMaxDockWidth can get
// docked without going through a snapping sequence.
gfx::Rect phantom_bounds;
- if (!can_dock ||
- window()->bounds().width() > DockedWindowLayoutManager::kMaxDockWidth)
+ if (can_snap &&
+ (!can_dock ||
+ window()->bounds().width() > DockedWindowLayoutManager::kMaxDockWidth))
phantom_bounds = snap_sizer_->target_bounds();
- const bool is_docked = can_dock &&
- (phantom_bounds.IsEmpty() || snap_sizer_->end_of_sequence());
- UpdateDockedState(is_docked);
- if (is_docked) {
+ const bool should_dock = can_dock &&
+ (phantom_bounds.IsEmpty() ||
+ snap_sizer_->end_of_sequence() ||
+ dock_layout_->is_dragged_window_docked());
+ SetDraggedWindowDocked(should_dock);
+ snap_type_ = GetSnapType(location);
+ if (dock_layout_->is_dragged_window_docked()) {
phantom_bounds = ScreenAsh::ConvertRectFromScreen(
window()->parent(), dock_layout_->dragged_bounds());
}
@@ -985,8 +991,8 @@ SnapType WorkspaceWindowResizer::GetSnapType(
return SNAP_NONE;
}
-void WorkspaceWindowResizer::UpdateDockedState(bool is_docked) {
- if (is_docked &&
+void WorkspaceWindowResizer::SetDraggedWindowDocked(bool should_dock) {
+ if (should_dock &&
dock_layout_->GetAlignmentOfWindow(window()) != DOCKED_ALIGNMENT_NONE) {
if (!dock_layout_->is_dragged_window_docked())
dock_layout_->DockDraggedWindow(window());
diff --git a/ash/wm/workspace/workspace_window_resizer.h b/ash/wm/workspace/workspace_window_resizer.h
index 1cd0942..5acaf8e 100644
--- a/ash/wm/workspace/workspace_window_resizer.h
+++ b/ash/wm/workspace/workspace_window_resizer.h
@@ -161,9 +161,9 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
// snapping should be used.
SnapType GetSnapType(const gfx::Point& location) const;
- // Dock when a window is at its last step in snapping sequence, undock
- // otherwise.
- void UpdateDockedState(bool is_docked);
+ // Docks the dragged window if |should_dock| and the window can be docked.
+ // Undocks the window if |should_dock| is false.
+ void SetDraggedWindowDocked(bool should_dock);
aura::Window* window() const { return details_.window; }