platformKeys: Add per-extension sign permissions.
[chromium-blink-merge.git] / ash / wm / dock / docked_window_resizer_unittest.cc
blobc8128261b087d457e43e6ba12c02ec22eacc3e4e
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/wm/dock/docked_window_resizer.h"
7 #include "ash/ash_switches.h"
8 #include "ash/root_window_controller.h"
9 #include "ash/screen_util.h"
10 #include "ash/shelf/shelf.h"
11 #include "ash/shelf/shelf_layout_manager.h"
12 #include "ash/shelf/shelf_model.h"
13 #include "ash/shelf/shelf_types.h"
14 #include "ash/shelf/shelf_widget.h"
15 #include "ash/shell.h"
16 #include "ash/shell_window_ids.h"
17 #include "ash/test/ash_test_base.h"
18 #include "ash/test/cursor_manager_test_api.h"
19 #include "ash/test/shell_test_api.h"
20 #include "ash/test/test_shelf_delegate.h"
21 #include "ash/wm/dock/docked_window_layout_manager.h"
22 #include "ash/wm/drag_window_resizer.h"
23 #include "ash/wm/panels/panel_layout_manager.h"
24 #include "ash/wm/window_state.h"
25 #include "ash/wm/window_util.h"
26 #include "ash/wm/wm_event.h"
27 #include "base/command_line.h"
28 #include "ui/aura/client/aura_constants.h"
29 #include "ui/aura/client/window_tree_client.h"
30 #include "ui/aura/test/test_window_delegate.h"
31 #include "ui/aura/window_event_dispatcher.h"
32 #include "ui/base/hit_test.h"
33 #include "ui/base/ui_base_types.h"
34 #include "ui/events/test/event_generator.h"
35 #include "ui/views/widget/widget.h"
36 #include "ui/wm/core/coordinate_conversion.h"
37 #include "ui/wm/core/window_util.h"
39 namespace ash {
41 class DockedWindowResizerTest
42 : public test::AshTestBase,
43 public testing::WithParamInterface<ui::wm::WindowType> {
44 public:
45 DockedWindowResizerTest() : model_(NULL), window_type_(GetParam()) {}
46 virtual ~DockedWindowResizerTest() {}
48 void SetUp() override {
49 AshTestBase::SetUp();
50 UpdateDisplay("600x400");
51 test::ShellTestApi test_api(Shell::GetInstance());
52 model_ = test_api.shelf_model();
55 void TearDown() override { AshTestBase::TearDown(); }
57 protected:
58 enum DockedEdge {
59 DOCKED_EDGE_NONE,
60 DOCKED_EDGE_LEFT,
61 DOCKED_EDGE_RIGHT,
64 int ideal_width() const { return DockedWindowLayoutManager::kIdealWidth; }
65 int min_dock_gap() const { return DockedWindowLayoutManager::kMinDockGap; }
66 int max_width() const { return DockedWindowLayoutManager::kMaxDockWidth; }
67 int docked_width(const DockedWindowLayoutManager* layout_manager) const {
68 return layout_manager->docked_width_;
70 int docked_alignment(const DockedWindowLayoutManager* layout_manager) const {
71 return layout_manager->alignment_;
73 aura::Window* CreateTestWindow(const gfx::Rect& bounds) {
74 aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
75 &delegate_,
76 window_type_,
78 bounds);
79 if (window_type_ == ui::wm::WINDOW_TYPE_PANEL) {
80 test::TestShelfDelegate* shelf_delegate =
81 test::TestShelfDelegate::instance();
82 shelf_delegate->AddShelfItem(window);
83 PanelLayoutManager* manager = static_cast<PanelLayoutManager*>(
84 Shell::GetContainer(window->GetRootWindow(),
85 kShellWindowId_PanelContainer)->layout_manager());
86 manager->Relayout();
88 return window;
91 aura::Window* CreateModalWindow(const gfx::Rect& bounds) {
92 aura::Window* window = new aura::Window(&delegate_);
93 window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM);
94 window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
95 window->Init(aura::WINDOW_LAYER_TEXTURED);
96 window->Show();
98 if (bounds.IsEmpty()) {
99 ParentWindowInPrimaryRootWindow(window);
100 } else {
101 gfx::Display display =
102 Shell::GetScreen()->GetDisplayMatching(bounds);
103 aura::Window* root = ash::Shell::GetInstance()->display_controller()->
104 GetRootWindowForDisplayId(display.id());
105 gfx::Point origin = bounds.origin();
106 ::wm::ConvertPointFromScreen(root, &origin);
107 window->SetBounds(gfx::Rect(origin, bounds.size()));
108 aura::client::ParentWindowWithContext(window, root, bounds);
110 return window;
113 static WindowResizer* CreateSomeWindowResizer(
114 aura::Window* window,
115 const gfx::Point& point_in_parent,
116 int window_component) {
117 return CreateWindowResizer(
118 window,
119 point_in_parent,
120 window_component,
121 aura::client::WINDOW_MOVE_SOURCE_MOUSE).release();
124 void DragStart(aura::Window* window) {
125 DragStartAtOffsetFromWindowOrigin(window, 0, 0);
128 void DragStartAtOffsetFromWindowOrigin(aura::Window* window,
129 int dx, int dy) {
130 initial_location_in_parent_ =
131 window->bounds().origin() + gfx::Vector2d(dx, dy);
132 resizer_.reset(CreateSomeWindowResizer(window,
133 initial_location_in_parent_,
134 HTCAPTION));
135 ASSERT_TRUE(resizer_.get());
138 void ResizeStartAtOffsetFromWindowOrigin(aura::Window* window,
139 int dx, int dy,
140 int window_component) {
141 initial_location_in_parent_ =
142 window->bounds().origin() + gfx::Vector2d(dx, dy);
143 resizer_.reset(CreateSomeWindowResizer(window,
144 initial_location_in_parent_,
145 window_component));
146 ASSERT_TRUE(resizer_.get());
149 void DragMove(int dx, int dy) {
150 resizer_->Drag(initial_location_in_parent_ + gfx::Vector2d(dx, dy), 0);
153 void DragEnd() {
154 resizer_->CompleteDrag();
155 resizer_.reset();
158 void DragRevert() {
159 resizer_->RevertDrag();
160 resizer_.reset();
163 // Panels are parented by panel container during drags.
164 // All other windows that are tested here are parented by dock container
165 // during drags.
166 int CorrectContainerIdDuringDrag() {
167 if (window_type_ == ui::wm::WINDOW_TYPE_PANEL)
168 return kShellWindowId_PanelContainer;
169 return kShellWindowId_DockedContainer;
172 // Test dragging the window vertically (to detach if it is a panel) and then
173 // horizontally to the edge with an added offset from the edge of |dx|.
174 void DragRelativeToEdge(DockedEdge edge,
175 aura::Window* window,
176 int dx) {
177 DragVerticallyAndRelativeToEdge(
178 edge,
179 window,
181 window_type_ == ui::wm::WINDOW_TYPE_PANEL ? -100 : 20,
186 void DragToVerticalPositionAndToEdge(DockedEdge edge,
187 aura::Window* window,
188 int y) {
189 DragToVerticalPositionRelativeToEdge(edge, window, 0, y);
192 void DragToVerticalPositionRelativeToEdge(DockedEdge edge,
193 aura::Window* window,
194 int dx,
195 int y) {
196 gfx::Rect initial_bounds = window->GetBoundsInScreen();
197 DragVerticallyAndRelativeToEdge(edge,
198 window,
199 dx, y - initial_bounds.y(),
200 25, 5);
203 // Detach if our window is a panel, then drag it vertically by |dy| and
204 // horizontally to the edge with an added offset from the edge of |dx|.
205 void DragVerticallyAndRelativeToEdge(DockedEdge edge,
206 aura::Window* window,
207 int dx, int dy,
208 int grab_x, int grab_y) {
209 gfx::Rect initial_bounds = window->GetBoundsInScreen();
210 // avoid snap by clicking away from the border
211 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(window,
212 grab_x, grab_y));
214 gfx::Rect work_area =
215 Shell::GetScreen()->GetDisplayNearestWindow(window).work_area();
216 gfx::Point initial_location_in_screen = initial_location_in_parent_;
217 ::wm::ConvertPointToScreen(window->parent(), &initial_location_in_screen);
218 // Drag the window left or right to the edge (or almost to it).
219 if (edge == DOCKED_EDGE_LEFT)
220 dx += work_area.x() - initial_location_in_screen.x();
221 else if (edge == DOCKED_EDGE_RIGHT)
222 dx += work_area.right() - 1 - initial_location_in_screen.x();
223 DragMove(dx, dy);
224 EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
225 // Release the mouse and the panel should be attached to the dock.
226 DragEnd();
228 // x-coordinate can get adjusted by snapping or sticking.
229 // y-coordinate could be changed by possible automatic layout if docked.
230 if (window->parent()->id() != kShellWindowId_DockedContainer &&
231 !wm::GetWindowState(window)->HasRestoreBounds()) {
232 EXPECT_EQ(initial_bounds.y() + dy, window->GetBoundsInScreen().y());
236 bool test_panels() const { return window_type_ == ui::wm::WINDOW_TYPE_PANEL; }
238 aura::test::TestWindowDelegate* delegate() {
239 return &delegate_;
242 const gfx::Point& initial_location_in_parent() const {
243 return initial_location_in_parent_;
246 private:
247 scoped_ptr<WindowResizer> resizer_;
248 ShelfModel* model_;
249 ui::wm::WindowType window_type_;
250 aura::test::TestWindowDelegate delegate_;
252 // Location at start of the drag in |window->parent()|'s coordinates.
253 gfx::Point initial_location_in_parent_;
255 DISALLOW_COPY_AND_ASSIGN(DockedWindowResizerTest);
258 // Verifies a window can be dragged and attached to the dock.
259 TEST_P(DockedWindowResizerTest, AttachRightPrecise) {
260 if (!SupportsHostWindowResize())
261 return;
263 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
264 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
266 // The window should be docked at the right edge.
267 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
268 window->GetBoundsInScreen().right());
269 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
272 // Verifies a window can be dragged and attached to the dock
273 // even if pointer overshoots the screen edge by a few pixels (sticky edge)
274 TEST_P(DockedWindowResizerTest, AttachRightOvershoot) {
275 if (!SupportsHostWindowResize())
276 return;
278 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
279 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), +4);
281 // The window should be docked at the right edge.
282 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
283 window->GetBoundsInScreen().right());
284 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
287 // Verifies a window can be dragged and then if a pointer is not quite reaching
288 // the screen edge the window does not get docked and stays in the desktop.
289 TEST_P(DockedWindowResizerTest, AttachRightUndershoot) {
290 if (!SupportsHostWindowResize())
291 return;
293 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
294 // Grabbing at 70px ensures that at least 30% of the window is in screen,
295 // otherwise the window would be adjusted in
296 // WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded.
297 const int kGrabOffsetX = 70;
298 const int kUndershootBy = 1;
299 DragVerticallyAndRelativeToEdge(DOCKED_EDGE_RIGHT,
300 window.get(),
301 -kUndershootBy, test_panels() ? -100 : 20,
302 kGrabOffsetX, 5);
304 // The window right should be past the screen edge but not docked.
305 // Initial touch point is 70px to the right which helps to find where the edge
306 // should be.
307 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right() +
308 window->bounds().width() - kGrabOffsetX - kUndershootBy - 1,
309 window->GetBoundsInScreen().right());
310 EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
313 // Verifies a window can be dragged and attached to the dock.
314 TEST_P(DockedWindowResizerTest, AttachLeftPrecise) {
315 if (!SupportsHostWindowResize())
316 return;
318 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
319 DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 0);
321 // The window should be docked at the left edge.
322 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().x(),
323 window->GetBoundsInScreen().x());
324 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
327 // Verifies a window can be dragged and attached to the dock
328 // even if pointer overshoots the screen edge by a few pixels (sticky edge)
329 TEST_P(DockedWindowResizerTest, AttachLeftOvershoot) {
330 if (!SupportsHostWindowResize())
331 return;
333 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
334 DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), -4);
336 // The window should be docked at the left edge.
337 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().x(),
338 window->GetBoundsInScreen().x());
339 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
342 // Verifies a window can be dragged and then if a pointer is not quite reaching
343 // the screen edge the window does not get docked and stays in the desktop.
344 TEST_P(DockedWindowResizerTest, AttachLeftUndershoot) {
345 if (!SupportsHostWindowResize())
346 return;
348 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
349 gfx::Rect initial_bounds(window->bounds());
350 DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 1);
352 // The window should be crossing the screen edge but not docked.
353 int expected_x = initial_bounds.x() - initial_location_in_parent().x() + 1;
354 EXPECT_EQ(expected_x, window->GetBoundsInScreen().x());
355 EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
358 // Dock on the right side, change shelf alignment, check that windows move to
359 // the opposite side.
360 TEST_P(DockedWindowResizerTest, AttachRightChangeShelf) {
361 if (!SupportsHostWindowResize())
362 return;
364 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
365 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
367 // The window should be docked at the right edge.
368 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
369 window->GetBoundsInScreen().right());
370 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
372 // set launcher shelf to be aligned on the right
373 ash::Shell* shell = ash::Shell::GetInstance();
374 shell->SetShelfAlignment(SHELF_ALIGNMENT_RIGHT,
375 shell->GetPrimaryRootWindow());
376 // The window should have moved and get attached to the left dock.
377 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().x(),
378 window->GetBoundsInScreen().x());
379 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
381 // set launcher shelf to be aligned on the left
382 shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT,
383 shell->GetPrimaryRootWindow());
384 // The window should have moved and get attached to the right edge.
385 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
386 window->GetBoundsInScreen().right());
387 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
389 // set launcher shelf to be aligned at the bottom
390 shell->SetShelfAlignment(SHELF_ALIGNMENT_BOTTOM,
391 shell->GetPrimaryRootWindow());
392 // The window should stay in the right edge.
393 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
394 window->GetBoundsInScreen().right());
395 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
398 // Dock on the right side, try to undock, then drag more to really undock
399 TEST_P(DockedWindowResizerTest, AttachTryDetach) {
400 if (!SupportsHostWindowResize())
401 return;
403 scoped_ptr<aura::Window> window(CreateTestWindow(
404 gfx::Rect(0, 0, ideal_width() + 10, 201)));
405 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
407 // The window should be docked at the right edge.
408 // Its width should shrink to ideal width.
409 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
410 window->GetBoundsInScreen().right());
411 EXPECT_EQ(ideal_width(), window->GetBoundsInScreen().width());
412 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
414 // Try to detach by dragging left less than kSnapToDockDistance.
415 // The window should stay docked.
416 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(
417 window.get(), 10, 0));
418 DragMove(-4, -10);
419 // Release the mouse and the window should be still attached to the dock.
420 DragEnd();
422 // The window should be still attached to the right edge.
423 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
424 window->GetBoundsInScreen().right());
425 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
427 // Try to detach by dragging left by kSnapToDockDistance or more.
428 // The window should get undocked.
429 const int left_edge = window->bounds().x();
430 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(
431 window.get(), 10, 0));
432 DragMove(-32, -10);
433 // Release the mouse and the window should be no longer attached to the dock.
434 DragEnd();
436 // The window should be floating on the desktop again and moved to the left.
437 EXPECT_EQ(left_edge - 32, window->GetBoundsInScreen().x());
438 EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
441 // Dock on the right side, and undock by dragging the right edge of the window
442 // header. This test is useful because both the position of the dragged window
443 // and the position of the mouse are used in determining whether a window should
444 // be undocked.
445 TEST_P(DockedWindowResizerTest, AttachTryDetachDragRightEdgeOfHeader) {
446 if (!SupportsHostWindowResize())
447 return;
449 scoped_ptr<aura::Window> window(CreateTestWindow(
450 gfx::Rect(0, 0, ideal_width() + 10, 201)));
451 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
453 // The window should be docked at the right edge.
454 // Its width should shrink to ideal width.
455 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
456 window->GetBoundsInScreen().right());
457 EXPECT_EQ(ideal_width(), window->GetBoundsInScreen().width());
458 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
460 // Try to detach by dragging left less than kSnapToDockDistance.
461 // The window should stay docked.
462 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(
463 window.get(), ideal_width() - 10, 0));
464 DragMove(-4, -10);
465 // Release the mouse and the window should be still attached to the dock.
466 DragEnd();
468 // The window should be still attached to the right edge.
469 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
470 window->GetBoundsInScreen().right());
471 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
473 // Try to detach by dragging left by kSnapToDockDistance or more.
474 // The window should get undocked.
475 const int left_edge = window->bounds().x();
476 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(
477 window.get(), ideal_width() - 10, 0));
478 DragMove(-32, -10);
479 // Release the mouse and the window should be no longer attached to the dock.
480 DragEnd();
482 // The window should be floating on the desktop again and moved to the left.
483 EXPECT_EQ(left_edge - 32, window->GetBoundsInScreen().x());
484 EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
487 // Minimize a docked window, then restore it and check that it is still docked.
488 TEST_P(DockedWindowResizerTest, AttachMinimizeRestore) {
489 if (!SupportsHostWindowResize())
490 return;
492 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
493 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
495 // The window should be docked at the right edge.
496 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
497 window->GetBoundsInScreen().right());
498 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
500 wm::WindowState* window_state = wm::GetWindowState(window.get());
501 // Minimize the window, it should be hidden.
502 window_state->Minimize();
503 RunAllPendingInMessageLoop();
504 EXPECT_FALSE(window->IsVisible());
505 EXPECT_TRUE(window_state->IsMinimized());
506 // Restore the window; window should be visible.
507 window_state->Restore();
508 RunAllPendingInMessageLoop();
509 EXPECT_TRUE(window->IsVisible());
510 EXPECT_TRUE(window_state->IsDocked());
513 // Maximize a docked window and check that it is maximized and no longer docked.
514 TEST_P(DockedWindowResizerTest, AttachMaximize) {
515 if (!SupportsHostWindowResize())
516 return;
518 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
519 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
521 // The window should be docked at the right edge.
522 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
523 window->GetBoundsInScreen().right());
524 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
526 wm::WindowState* window_state = wm::GetWindowState(window.get());
527 // Maximize the window, it should get undocked and maximized in a desktop.
528 window_state->Maximize();
529 RunAllPendingInMessageLoop();
530 EXPECT_TRUE(window->IsVisible());
531 EXPECT_TRUE(window_state->IsMaximized());
532 EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
535 // Dock two windows, undock one, check that the other one is still docked.
536 TEST_P(DockedWindowResizerTest, AttachTwoWindows) {
537 if (!SupportsHostWindowResize())
538 return;
539 UpdateDisplay("600x600");
541 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
542 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
543 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
544 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 50);
546 // Docking second window should not minimize the first.
547 wm::WindowState* window_state1 = wm::GetWindowState(w1.get());
548 EXPECT_FALSE(window_state1->IsMinimized());
550 // Both windows should be docked at the right edge.
551 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
552 w1->GetBoundsInScreen().right());
553 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
555 EXPECT_EQ(w2->GetRootWindow()->GetBoundsInScreen().right(),
556 w2->GetBoundsInScreen().right());
557 EXPECT_EQ(kShellWindowId_DockedContainer, w2->parent()->id());
559 // Detach by dragging left (should get undocked).
560 const int left_edge = w2->bounds().x();
561 ASSERT_NO_FATAL_FAILURE(DragStart(w2.get()));
562 // Drag up as well to avoid attaching panels to launcher shelf.
563 DragMove(-32, -100);
564 // Release the mouse and the window should be no longer attached to the edge.
565 DragEnd();
567 // The first window should be still docked.
568 EXPECT_FALSE(window_state1->IsMinimized());
569 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
570 w1->GetBoundsInScreen().right());
571 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
573 // The window should be floating on the desktop again and moved to the left.
574 EXPECT_EQ(left_edge - 32, w2->GetBoundsInScreen().x());
575 EXPECT_EQ(kShellWindowId_DefaultContainer, w2->parent()->id());
578 // Create two windows, dock one and change shelf to auto-hide.
579 TEST_P(DockedWindowResizerTest, AttachOneAutoHideShelf) {
580 if (!SupportsHostWindowResize())
581 return;
583 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
584 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
586 // w1 should be docked at the right edge.
587 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
588 w1->GetBoundsInScreen().right());
589 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
591 scoped_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegateAndType(
592 NULL, ui::wm::WINDOW_TYPE_NORMAL, 0, gfx::Rect(20, 20, 150, 20)));
593 wm::GetWindowState(w2.get())->Maximize();
594 EXPECT_EQ(kShellWindowId_DefaultContainer, w2->parent()->id());
595 EXPECT_TRUE(wm::GetWindowState(w2.get())->IsMaximized());
597 gfx::Rect work_area =
598 Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area();
599 DockedWindowLayoutManager* manager =
600 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
602 // Docked window should be centered vertically in the work area.
603 EXPECT_EQ(work_area.CenterPoint().y(), w1->bounds().CenterPoint().y());
604 // Docked background should extend to the bottom of work area.
605 EXPECT_EQ(work_area.bottom(), manager->docked_bounds().bottom());
607 // set launcher shelf to be aligned on the right
608 ash::Shell* shell = ash::Shell::GetInstance();
609 shell->SetShelfAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS,
610 shell->GetPrimaryRootWindow());
611 work_area =
612 Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area();
613 // Docked window should be centered vertically in the work area.
614 EXPECT_EQ(work_area.CenterPoint().y(), w1->bounds().CenterPoint().y());
615 // Docked background should extend to the bottom of work area.
616 EXPECT_EQ(work_area.bottom(), manager->docked_bounds().bottom());
619 // Dock one window, try to dock another window on the opposite side (should not
620 // dock).
621 TEST_P(DockedWindowResizerTest, AttachOnTwoSides) {
622 if (!SupportsHostWindowResize())
623 return;
625 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
626 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
627 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
628 gfx::Rect initial_bounds(w2->bounds());
629 DragToVerticalPositionAndToEdge(DOCKED_EDGE_LEFT, w2.get(), 50);
631 // The first window should be docked at the right edge.
632 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
633 w1->GetBoundsInScreen().right());
634 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
636 // The second window should be near the left edge but not snapped.
637 // Normal window will get side-maximized while panels will not.
638 int expected_x = test_panels() ?
639 (initial_bounds.x() - initial_location_in_parent().x()) : 0;
640 EXPECT_EQ(expected_x, w2->GetBoundsInScreen().x());
641 EXPECT_EQ(kShellWindowId_DefaultContainer, w2->parent()->id());
644 // Tests that reverting a drag restores docked state if a window was docked.
645 TEST_P(DockedWindowResizerTest, RevertDragRestoresAttachment) {
646 if (!SupportsHostWindowResize())
647 return;
649 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
650 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
652 // The window should be docked at the right edge.
653 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
654 window->GetBoundsInScreen().right());
655 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
657 // Drag the window out but revert the drag
658 ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
659 DragMove(-50, 0);
660 DragRevert();
661 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
663 // Detach window.
664 ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
665 DragMove(-50, 0);
666 DragEnd();
667 EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
670 // Tests that reverting drag restores undocked state if a window was not docked.
671 TEST_P(DockedWindowResizerTest, RevertDockedDragRevertsAttachment) {
672 if (!SupportsHostWindowResize())
673 return;
674 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
675 aura::Window* dock_container = Shell::GetContainer(
676 window->GetRootWindow(),
677 kShellWindowId_DockedContainer);
678 DockedWindowLayoutManager* manager =
679 static_cast<DockedWindowLayoutManager*>(dock_container->layout_manager());
680 int previous_container_id = window->parent()->id();
681 // Drag the window out but revert the drag
682 ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
683 DragMove(-50 - window->bounds().x(), 50 - window->bounds().y());
684 EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
685 DragRevert();
686 EXPECT_EQ(previous_container_id, window->parent()->id());
687 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
689 // Drag a window to the left so that it overlaps the screen edge.
690 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(
691 window.get(),
692 window->bounds().width()/2 + 10,
693 0));
694 DragMove(-50 - window->bounds().x(), 50 - window->bounds().y());
695 DragEnd();
696 // The window now overlaps the left screen edge but is not docked.
697 EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
698 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
699 EXPECT_LT(window->bounds().x(), 0);
700 EXPECT_GT(window->bounds().right(), 0);
702 // Drag the window further left and revert the drag.
703 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(
704 window.get(),
705 window->bounds().width()/2 + 10,
706 0));
707 DragMove(-10, 10);
708 DragRevert();
709 // The window should be in default container and not docked.
710 EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
711 // Docked area alignment should be cleared.
712 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
715 // Move a docked window to the second display
716 TEST_P(DockedWindowResizerTest, DragAcrossDisplays) {
717 if (!SupportsMultipleDisplays())
718 return;
720 UpdateDisplay("800x800,800x800");
721 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
722 EXPECT_EQ(2, static_cast<int>(root_windows.size()));
723 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
724 gfx::Rect initial_bounds = window->GetBoundsInScreen();
725 EXPECT_EQ(root_windows[0], window->GetRootWindow());
727 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0);
728 // The window should be docked at the right edge.
729 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
730 window->GetBoundsInScreen().right());
731 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
733 // Try dragging to the right - enough to get it peeking at the other screen
734 // but not enough to land in the other screen.
735 // The window should stay on the left screen.
736 ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
737 DragMove(100, 0);
738 EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
739 DragEnd();
740 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
741 window->GetBoundsInScreen().right());
742 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
743 EXPECT_EQ(root_windows[0], window->GetRootWindow());
745 // Undock and move to the right - enough to get the mouse pointer past the
746 // edge of the screen and into the second screen. The window should now be
747 // in the second screen and not docked.
748 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(
749 window.get(),
750 window->bounds().width()/2 + 10,
751 0));
752 DragMove(window->bounds().width()/2 - 5, 0);
753 EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
754 DragEnd();
755 EXPECT_NE(window->GetRootWindow()->GetBoundsInScreen().right(),
756 window->GetBoundsInScreen().right());
757 EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
758 EXPECT_EQ(root_windows[1], window->GetRootWindow());
760 // Keep dragging it to the right until its left edge touches the screen edge.
761 // The window should now be in the second screen and not docked.
762 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(
763 window.get(),
764 window->bounds().width()/2 + 10,
765 0));
766 DragMove(window->GetRootWindow()->GetBoundsInScreen().x() -
767 window->GetBoundsInScreen().x(),
769 EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
770 DragEnd();
771 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().x(),
772 window->GetBoundsInScreen().x());
773 EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
774 EXPECT_EQ(root_windows[1], window->GetRootWindow());
777 // Dock two windows, undock one.
778 // Test the docked windows area size and default container resizing.
779 TEST_P(DockedWindowResizerTest, AttachTwoWindowsDetachOne) {
780 if (!SupportsHostWindowResize())
781 return;
782 UpdateDisplay("600x600");
784 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
785 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201)));
786 // Work area should cover the whole screen.
787 EXPECT_EQ(ScreenUtil::GetDisplayBoundsInParent(w2.get()).width(),
788 ScreenUtil::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
790 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
791 // A window should be docked at the right edge.
792 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
793 w1->GetBoundsInScreen().right());
794 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
795 DockedWindowLayoutManager* manager =
796 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
797 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
798 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
800 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100);
801 // Both windows should now be docked at the right edge.
802 EXPECT_EQ(w2->GetRootWindow()->GetBoundsInScreen().right(),
803 w2->GetBoundsInScreen().right());
804 EXPECT_EQ(kShellWindowId_DockedContainer, w2->parent()->id());
805 // Dock width should be set to a wider window.
806 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
807 EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()),
808 docked_width(manager));
810 // Try to detach by dragging left a bit (should not get undocked).
811 // This would normally detach a single docked window but since we have another
812 // window and the mouse pointer does not leave the dock area the window
813 // should stay docked.
814 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 60, 0));
815 // Drag up as well as left to avoid attaching panels to launcher shelf.
816 DragMove(-40, -40);
817 // Release the mouse and the window should be still attached to the edge.
818 DragEnd();
820 // The first window should be still docked.
821 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
822 w1->GetBoundsInScreen().right());
823 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
825 // The second window should be still docked.
826 EXPECT_EQ(w2->GetRootWindow()->GetBoundsInScreen().right(),
827 w2->GetBoundsInScreen().right());
828 EXPECT_EQ(kShellWindowId_DockedContainer, w2->parent()->id());
830 // Detach by dragging left more (should get undocked).
831 const int left_edge = w2->bounds().x();
832 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(
833 w2.get(),
834 w2->bounds().width()/2 + 10,
835 0));
836 // Drag up as well to avoid attaching panels to launcher shelf.
837 const int drag_x = -(w2->bounds().width()/2 + 20);
838 DragMove(drag_x, -100);
839 // Release the mouse and the window should be no longer attached to the edge.
840 DragEnd();
842 // The second window should be floating on the desktop again.
843 EXPECT_EQ(left_edge + drag_x, w2->bounds().x());
844 EXPECT_EQ(kShellWindowId_DefaultContainer, w2->parent()->id());
845 // Dock width should be set to remaining single docked window.
846 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
847 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
848 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
851 // Dock one of the windows. Maximize other testing desktop resizing.
852 TEST_P(DockedWindowResizerTest, AttachWindowMaximizeOther) {
853 if (!SupportsHostWindowResize())
854 return;
856 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
857 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201)));
858 // Work area should cover the whole screen.
859 EXPECT_EQ(ScreenUtil::GetDisplayBoundsInParent(w2.get()).width(),
860 ScreenUtil::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
862 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
863 // A window should be docked at the right edge.
864 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
865 w1->GetBoundsInScreen().right());
866 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
867 DockedWindowLayoutManager* manager =
868 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
869 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
870 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
872 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 25, 5));
873 DragMove(w2->GetRootWindow()->bounds().width()
874 -w2->bounds().width()
875 -(w2->bounds().width()/2 + 20)
876 -w2->bounds().x(),
877 50 - w2->bounds().y());
878 DragEnd();
879 // The first window should be still docked.
880 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
881 w1->GetBoundsInScreen().right());
882 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
884 // The second window should be floating on the desktop.
885 EXPECT_EQ(w2->GetRootWindow()->GetBoundsInScreen().right() -
886 (w2->bounds().width()/2 + 20),
887 w2->GetBoundsInScreen().right());
888 EXPECT_EQ(kShellWindowId_DefaultContainer, w2->parent()->id());
889 // Dock width should be set to remaining single docked window.
890 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
891 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
892 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
893 // Desktop work area should now shrink.
894 EXPECT_EQ(ScreenUtil::GetDisplayBoundsInParent(w2.get()).width() -
895 docked_width(manager) - min_dock_gap(),
896 ScreenUtil::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
898 // Maximize the second window - Maximized area should be shrunk.
899 const gfx::Rect restored_bounds = w2->bounds();
900 wm::WindowState* w2_state = wm::GetWindowState(w2.get());
901 w2_state->Maximize();
902 EXPECT_EQ(ScreenUtil::GetDisplayBoundsInParent(w2.get()).width() -
903 docked_width(manager) - min_dock_gap(),
904 w2->bounds().width());
906 // Detach the first window (this should require very little drag).
907 ASSERT_NO_FATAL_FAILURE(DragStart(w1.get()));
908 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
909 DragMove(-35, 10);
910 // Alignment is set to "NONE" when drag starts.
911 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
912 // Release the mouse and the window should be no longer attached to the edge.
913 DragEnd();
914 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
915 // Dock should get shrunk and desktop should get expanded.
916 EXPECT_EQ(kShellWindowId_DefaultContainer, w1->parent()->id());
917 EXPECT_EQ(kShellWindowId_DefaultContainer, w2->parent()->id());
918 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
919 EXPECT_EQ(0, docked_width(manager));
920 // The second window should now get resized and take up the whole screen.
921 EXPECT_EQ(ScreenUtil::GetDisplayBoundsInParent(w2.get()).width(),
922 w2->bounds().width());
924 // Dock the first window to the left edge.
925 // Click at an offset from origin to prevent snapping.
926 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w1.get(), 10, 0));
927 // Drag left to get pointer touching the screen edge.
928 DragMove(-w1->bounds().x() - 10, 0);
929 // Alignment set to "NONE" during the drag of the window when none are docked.
930 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
931 // Release the mouse and the window should be now attached to the edge.
932 DragEnd();
933 // Dock should get expanded and desktop should get shrunk.
934 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
935 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
936 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
937 // Second window should still be in the desktop.
938 EXPECT_EQ(kShellWindowId_DefaultContainer, w2->parent()->id());
939 // Maximized window should be shrunk.
940 EXPECT_EQ(ScreenUtil::GetDisplayBoundsInParent(w2.get()).width() -
941 docked_width(manager) - min_dock_gap(),
942 w2->bounds().width());
944 // Unmaximize the second window.
945 w2_state->Restore();
946 // Its bounds should get restored.
947 EXPECT_EQ(restored_bounds, w2->bounds());
950 // Dock one window. Test the sticky behavior near screen or desktop edge.
951 TEST_P(DockedWindowResizerTest, AttachOneTestSticky) {
952 if (!SupportsHostWindowResize())
953 return;
955 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
956 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201)));
957 // Work area should cover the whole screen.
958 EXPECT_EQ(ScreenUtil::GetDisplayBoundsInParent(w2.get()).width(),
959 ScreenUtil::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
961 DragToVerticalPositionAndToEdge(DOCKED_EDGE_LEFT, w1.get(), 20);
962 // A window should be docked at the left edge.
963 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().x(),
964 w1->GetBoundsInScreen().x());
965 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
966 DockedWindowLayoutManager* manager =
967 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
968 // The first window should be docked.
969 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().x(),
970 w1->GetBoundsInScreen().x());
971 // Dock width should be set to that of a single docked window.
972 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
973 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
974 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
976 // Position second window in the desktop 20px to the right of the docked w1.
977 DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_LEFT,
978 w2.get(),
979 20 + 25 -
980 min_dock_gap(),
981 50);
982 // The second window should be floating on the desktop.
983 EXPECT_EQ(w2->GetRootWindow()->GetBoundsInScreen().x() +
984 (w1->bounds().right() + 20),
985 w2->GetBoundsInScreen().x());
986 EXPECT_EQ(kShellWindowId_DefaultContainer, w2->parent()->id());
987 // Dock width should be set to that of a single docked window.
988 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
989 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
990 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
992 // Drag w2 almost to the dock, the mouse pointer not quite reaching the dock.
993 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 10, 0));
994 DragMove(1 + docked_width(manager) - w2->bounds().x(), 0);
995 // Alignment set to "LEFT" during the drag because dock has a window in it.
996 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
997 // Release the mouse and the window should not be attached to the edge.
998 DragEnd();
999 // Dock should still have only one window in it.
1000 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
1001 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1002 // The second window should still be in the desktop.
1003 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1004 EXPECT_EQ(kShellWindowId_DefaultContainer, w2->parent()->id());
1006 // Drag w2 by a bit more - it should resist the drag (stuck edges)
1007 int start_x = w2->bounds().x();
1008 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 100, 5));
1009 DragMove(-2, 0);
1010 // Window should not actually move.
1011 EXPECT_EQ(start_x, w2->bounds().x());
1012 // Alignment set to "LEFT" during the drag because dock has a window in it.
1013 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
1014 // Release the mouse and the window should not be attached to the edge.
1015 DragEnd();
1016 // Window should be still where it was before the last drag started.
1017 EXPECT_EQ(start_x, w2->bounds().x());
1018 // Dock should still have only one window in it
1019 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
1020 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1021 // The second window should still be in the desktop
1022 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1023 EXPECT_EQ(kShellWindowId_DefaultContainer, w2->parent()->id());
1025 // Drag w2 by more than the stuck threshold and drop it into the dock.
1026 ASSERT_NO_FATAL_FAILURE(DragStart(w2.get()));
1027 DragMove(-100, 0);
1028 // Window should actually move.
1029 EXPECT_NE(start_x, w2->bounds().x());
1030 // Alignment set to "LEFT" during the drag because dock has a window in it.
1031 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
1032 // Release the mouse and the window should be attached to the edge.
1033 DragEnd();
1034 // Both windows are docked now.
1035 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1036 EXPECT_EQ(kShellWindowId_DockedContainer, w2->parent()->id());
1037 // Dock should get expanded and desktop should get shrunk.
1038 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager));
1039 EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()),
1040 docked_width(manager));
1041 // Desktop work area should now shrink by dock width.
1042 EXPECT_EQ(ScreenUtil::GetDisplayBoundsInParent(w2.get()).width() -
1043 docked_width(manager) - min_dock_gap(),
1044 ScreenUtil::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
1047 // Dock two windows, resize one.
1048 // Test the docked windows area size and remaining desktop resizing.
1049 TEST_P(DockedWindowResizerTest, ResizeOneOfTwoWindows) {
1050 if (!SupportsHostWindowResize())
1051 return;
1053 // Wider display to start since panels are limited to half the display width.
1054 UpdateDisplay("1000x600");
1055 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
1056 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201)));
1057 // Work area should cover the whole screen.
1058 EXPECT_EQ(ScreenUtil::GetDisplayBoundsInParent(w2.get()).width(),
1059 ScreenUtil::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
1061 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
1062 // A window should be docked at the right edge.
1063 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
1064 w1->GetBoundsInScreen().right());
1065 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1066 DockedWindowLayoutManager* manager =
1067 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
1068 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1069 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1071 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100);
1072 // Both windows should now be docked at the right edge.
1073 EXPECT_EQ(w2->GetRootWindow()->GetBoundsInScreen().right(),
1074 w2->GetBoundsInScreen().right());
1075 EXPECT_EQ(kShellWindowId_DockedContainer, w2->parent()->id());
1076 // Dock width should be set to a wider window.
1077 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1078 EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()),
1079 docked_width(manager));
1081 // Resize the first window left by a bit and test that the dock expands.
1082 int previous_width = w1->bounds().width();
1083 const int kResizeSpan1 = 30;
1084 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(),
1085 0, 20,
1086 HTLEFT));
1087 DragMove(-kResizeSpan1, 0);
1088 // Alignment set to "RIGHT" during the drag because dock has a window in it.
1089 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1090 // Release the mouse and the window should be attached to the edge.
1091 DragEnd();
1092 // Dock should still have both windows in it.
1093 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1094 EXPECT_EQ(kShellWindowId_DockedContainer, w2->parent()->id());
1095 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1096 // w1 is now wider than before. The dock should expand and be as wide as w1.
1097 EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width());
1098 // Both windows should get resized since they both don't have min/max size.
1099 EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
1100 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1101 // Desktop work area should shrink.
1102 EXPECT_EQ(ScreenUtil::GetDisplayBoundsInParent(w2.get()).width() -
1103 docked_width(manager) - min_dock_gap(),
1104 ScreenUtil::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
1106 // Resize the first window left by more than the dock maximum width.
1107 // This should cause the window width to be restricted by maximum dock width.
1108 previous_width = w1->bounds().width();
1109 const int kResizeSpan2 = 250;
1110 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(),
1111 0, 20,
1112 HTLEFT));
1113 DragMove(-kResizeSpan2, 0);
1114 // Alignment set to "RIGHT" during the drag because dock has a window in it.
1115 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1116 // Release the mouse and the window should be attached to the edge.
1117 DragEnd();
1118 // Dock should still have both windows in it.
1119 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1120 EXPECT_EQ(kShellWindowId_DockedContainer, w2->parent()->id());
1121 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1122 // w1 is now as wide as the maximum dock width and the dock should get
1123 // resized to the maximum width.
1124 EXPECT_EQ(max_width(), w1->bounds().width());
1125 // Both windows should get resized since they both don't have min/max size.
1126 EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
1127 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1128 // Desktop work area should shrink.
1129 EXPECT_EQ(ScreenUtil::GetDisplayBoundsInParent(w2.get()).width() -
1130 docked_width(manager) - min_dock_gap(),
1131 ScreenUtil::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
1133 // Resize the first window right to get it completely inside the docked area.
1134 previous_width = w1->bounds().width();
1135 const int kResizeSpan3 = 100;
1136 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(),
1137 0, 20,
1138 HTLEFT));
1139 DragMove(kResizeSpan3, 0);
1140 // Alignment set to "RIGHT" during the drag because dock has a window in it.
1141 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1142 // Release the mouse and the window should be docked.
1143 DragEnd();
1144 // Dock should still have both windows in it.
1145 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1146 EXPECT_EQ(kShellWindowId_DockedContainer, w2->parent()->id());
1147 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1148 // w1 should be narrower than before by the length of the drag.
1149 EXPECT_EQ(previous_width - kResizeSpan3, w1->bounds().width());
1150 // Both windows should get resized since they both don't have min/max size.
1151 EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
1152 // The dock should be as wide as w1 or w2.
1153 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1154 // Desktop work area should shrink.
1155 EXPECT_EQ(ScreenUtil::GetDisplayBoundsInParent(w2.get()).width() -
1156 docked_width(manager) - min_dock_gap(),
1157 ScreenUtil::GetDisplayWorkAreaBoundsInParent(w2.get()).width());
1159 // Resize the first window left to be overhang again.
1160 previous_width = w1->bounds().width();
1161 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(),
1162 0, 20,
1163 HTLEFT));
1164 DragMove(-kResizeSpan3, 0);
1165 DragEnd();
1166 EXPECT_EQ(previous_width + kResizeSpan3, w1->bounds().width());
1167 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1168 // Docked area should be as wide as possible (maximum) and same as w1.
1169 EXPECT_EQ(max_width(), docked_width(manager));
1170 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1172 // Undock the first window. Docked area should shrink to its ideal size.
1173 ASSERT_NO_FATAL_FAILURE(DragStart(w1.get()));
1174 // Drag up as well to avoid attaching panels to launcher shelf.
1175 DragMove(-(400 - 210), -100);
1176 // Alignment set to "RIGHT" since we have another window docked.
1177 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1178 // Release the mouse and the window should be no longer attached to the edge.
1179 DragEnd();
1180 EXPECT_EQ(kShellWindowId_DefaultContainer, w1->parent()->id());
1181 // Dock should be as wide as w2 (and same as ideal width).
1182 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1183 EXPECT_EQ(ideal_width(), docked_width(manager));
1184 EXPECT_EQ(w2->bounds().width(), docked_width(manager));
1185 // The second window should be still docked.
1186 EXPECT_EQ(kShellWindowId_DockedContainer, w2->parent()->id());
1187 // Desktop work area should be inset.
1188 EXPECT_EQ(ScreenUtil::GetDisplayBoundsInParent(w1.get()).width() -
1189 docked_width(manager) - min_dock_gap(),
1190 ScreenUtil::GetDisplayWorkAreaBoundsInParent(w1.get()).width());
1193 // Dock a window, resize it and test that undocking it preserves the width.
1194 TEST_P(DockedWindowResizerTest, ResizingKeepsWidth) {
1195 if (!SupportsHostWindowResize())
1196 return;
1198 // Wider display to start since panels are limited to half the display width.
1199 UpdateDisplay("1000x600");
1200 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
1202 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
1203 // Window should be docked at the right edge.
1204 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
1205 w1->GetBoundsInScreen().right());
1206 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1207 DockedWindowLayoutManager* manager =
1208 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
1209 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1210 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1212 // Resize the window left by a bit and test that the dock expands.
1213 int previous_width = w1->bounds().width();
1214 const int kResizeSpan1 = 30;
1215 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(),
1216 0, 20,
1217 HTLEFT));
1218 DragMove(-kResizeSpan1, 0);
1219 // Alignment stays "RIGHT" during the drag because the only docked window
1220 // is being resized.
1221 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1222 // Release the mouse and the window should be attached to the edge.
1223 DragEnd();
1224 // The window should get docked.
1225 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1226 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1227 // w1 is now wider and the dock should expand to be as wide as w1.
1228 EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width());
1229 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1231 // Undock by dragging almost to the left edge.
1232 DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_LEFT, w1.get(), 100, 20);
1233 // Width should be preserved.
1234 EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width());
1235 // Height should be restored to what it was originally.
1236 EXPECT_EQ(201, w1->bounds().height());
1238 // Dock again.
1239 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
1240 // Width should be reset to initial ideal width (25px).
1241 EXPECT_EQ(ideal_width(), w1->bounds().width());
1243 // Undock again by dragging left.
1244 DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_LEFT, w1.get(), 100, 20);
1245 // Width should be reset to what it was last time the window was not docked.
1246 EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width());
1247 // Height should be restored to what it was originally.
1248 EXPECT_EQ(201, w1->bounds().height());
1251 // Dock a window, resize it and test that it stays docked.
1252 TEST_P(DockedWindowResizerTest, ResizingKeepsDockedState) {
1253 if (!SupportsHostWindowResize())
1254 return;
1256 // Wider display to start since panels are limited to half the display width.
1257 UpdateDisplay("1000x600");
1258 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
1260 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
1261 // Window should be docked at the right edge.
1262 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
1263 w1->GetBoundsInScreen().right());
1264 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1265 DockedWindowLayoutManager* manager =
1266 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
1267 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1268 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1270 // Resize the window left by a bit and test that the dock expands.
1271 int previous_width = w1->bounds().width();
1272 const int kResizeSpan1 = 30;
1273 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(
1274 w1.get(), 0, 20, HTLEFT));
1275 DragMove(-kResizeSpan1, 0);
1276 // Normally alignment would be reset to "NONE" during the drag when there is
1277 // only a single window docked and it is being dragged. However because that
1278 // window is being resized rather than moved the alignment is not changed.
1279 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1280 // Release the mouse and the window should be attached to the edge.
1281 DragEnd();
1282 // The window should stay docked.
1283 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1284 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1285 // w1 is now wider and the dock should expand to be as wide as w1.
1286 EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width());
1287 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1289 // Resize the window by dragging its right edge left a bit and test that the
1290 // window stays docked.
1291 previous_width = w1->bounds().width();
1292 const int kResizeSpan2 = 15;
1293 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(
1294 w1.get(), w1->bounds().width(), 20, HTRIGHT));
1295 DragMove(-kResizeSpan2, 0);
1296 // Alignment stays "RIGHT" during the drag because the window is being
1297 // resized rather than dragged.
1298 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1299 // Release the mouse and the window should be attached to the edge.
1300 DragEnd();
1301 // The window should stay docked.
1302 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1303 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1304 // The dock should stay as wide as w1 is now (a bit less than before).
1305 EXPECT_EQ(previous_width - kResizeSpan2, w1->bounds().width());
1306 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1309 // Dock two windows, resize one. Test the docked windows area size.
1310 TEST_P(DockedWindowResizerTest, ResizeTwoWindows) {
1311 if (!SupportsHostWindowResize())
1312 return;
1314 // Wider display to start since panels are limited to half the display width.
1315 UpdateDisplay("1000x600");
1316 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
1317 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201)));
1319 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
1320 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100);
1321 // Both windows should now be docked at the right edge.
1322 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1323 EXPECT_EQ(kShellWindowId_DockedContainer, w2->parent()->id());
1324 // Dock width should be set to ideal width.
1325 DockedWindowLayoutManager* manager =
1326 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
1327 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1328 EXPECT_EQ(ideal_width(), docked_width(manager));
1330 // Resize the first window left by a bit and test that the dock expands.
1331 int previous_width = w1->bounds().width();
1332 const int kResizeSpan1 = 30;
1333 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(),
1334 0, 20,
1335 HTLEFT));
1336 DragMove(-kResizeSpan1, 0);
1337 DragEnd();
1338 // w1 is now wider than before.
1339 EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width());
1340 // Both windows should get resized since they both don't have min/max size.
1341 EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
1342 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1344 // Resize the second window left by a bit more and test that the dock expands.
1345 previous_width = w2->bounds().width();
1346 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w2.get(),
1347 0, 20,
1348 HTLEFT));
1349 DragMove(-kResizeSpan1, 0);
1350 DragEnd();
1351 // w2 should get wider since it was resized by a user.
1352 EXPECT_EQ(previous_width + kResizeSpan1, w2->bounds().width());
1353 // w1 should stay as wide as w2 since both were flush with the dock edge.
1354 EXPECT_EQ(w2->bounds().width(), w1->bounds().width());
1355 EXPECT_EQ(w2->bounds().width(), docked_width(manager));
1357 // Undock w2 and then dock it back.
1358 DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), -400, 100);
1359 EXPECT_EQ(kShellWindowId_DefaultContainer, w2->parent()->id());
1360 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100);
1361 EXPECT_EQ(kShellWindowId_DockedContainer, w2->parent()->id());
1362 // w2 should become same width as w1.
1363 EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
1364 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1366 // Make w1 even wider.
1367 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(),
1368 0, 20,
1369 HTLEFT));
1370 DragMove(-kResizeSpan1, 0);
1371 DragEnd();
1372 // Making w1 wider should make both windows wider since w2 no longer remembers
1373 // user width.
1374 EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
1375 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1378 // Tests that dragging a window down to shelf attaches a panel but does not
1379 // attach a regular window.
1380 TEST_P(DockedWindowResizerTest, DragToShelf) {
1381 if (!SupportsHostWindowResize())
1382 return;
1384 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
1385 // Work area should cover the whole screen.
1386 EXPECT_EQ(ScreenUtil::GetDisplayBoundsInParent(w1.get()).width(),
1387 ScreenUtil::GetDisplayWorkAreaBoundsInParent(w1.get()).width());
1389 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
1390 // A window should be docked at the right edge.
1391 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
1392 w1->GetBoundsInScreen().right());
1393 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1394 DockedWindowLayoutManager* manager =
1395 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
1396 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1397 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1399 // Detach and drag down to shelf.
1400 ASSERT_NO_FATAL_FAILURE(DragStart(w1.get()));
1401 DragMove(-40, 0);
1402 // Alignment is set to "NONE" when drag starts.
1403 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
1404 // Release the mouse and the window should be no longer attached to the edge.
1405 DragEnd();
1406 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager));
1408 // Drag down almost to shelf. A panel will snap, a regular window won't.
1409 ShelfWidget* shelf = Shelf::ForPrimaryDisplay()->shelf_widget();
1410 const int shelf_y = shelf->GetWindowBoundsInScreen().y();
1411 const int kDistanceFromShelf = 10;
1412 ASSERT_NO_FATAL_FAILURE(DragStart(w1.get()));
1413 DragMove(0, -kDistanceFromShelf + shelf_y - w1->bounds().bottom());
1414 DragEnd();
1415 if (test_panels()) {
1416 // The panel should be touching the shelf and attached.
1417 EXPECT_EQ(shelf_y, w1->bounds().bottom());
1418 EXPECT_TRUE(wm::GetWindowState(w1.get())->panel_attached());
1419 } else {
1420 // The window should not be touching the shelf.
1421 EXPECT_EQ(shelf_y - kDistanceFromShelf, w1->bounds().bottom());
1425 // Tests that docking and undocking a |window| with a transient child properly
1426 // maintains the parent of that transient child to be the same as the |window|.
1427 TEST_P(DockedWindowResizerTest, DragWindowWithTransientChild) {
1428 if (!SupportsHostWindowResize())
1429 return;
1431 // Create a window with a transient child.
1432 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
1433 scoped_ptr<aura::Window> child(CreateTestWindowInShellWithDelegateAndType(
1434 NULL, ui::wm::WINDOW_TYPE_NORMAL, 0, gfx::Rect(20, 20, 150, 20)));
1435 ::wm::AddTransientChild(window.get(), child.get());
1436 if (window->parent() != child->parent())
1437 window->parent()->AddChild(child.get());
1438 EXPECT_EQ(window.get(), ::wm::GetTransientParent(child.get()));
1440 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, window.get(), 20);
1442 // A window should be docked at the right edge.
1443 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
1444 EXPECT_EQ(kShellWindowId_DockedContainer, child->parent()->id());
1446 // Drag the child - it should move freely and stay where it is dragged.
1447 ASSERT_NO_FATAL_FAILURE(DragStart(child.get()));
1448 DragMove(500, 20);
1449 DragEnd();
1450 EXPECT_EQ(gfx::Point(20 + 500, 20 + 20).ToString(),
1451 child->GetBoundsInScreen().origin().ToString());
1453 // Undock the window by dragging left.
1454 ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
1455 DragMove(-32, -10);
1456 DragEnd();
1458 // The window should be undocked and the transient child should be reparented.
1459 EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
1460 EXPECT_EQ(kShellWindowId_DefaultContainer, child->parent()->id());
1461 // The child should not have moved.
1462 EXPECT_EQ(gfx::Point(20 + 500, 20 + 20).ToString(),
1463 child->GetBoundsInScreen().origin().ToString());
1466 // Tests that reparenting windows during the drag does not affect system modal
1467 // windows that are transient children of the dragged windows.
1468 TEST_P(DockedWindowResizerTest, DragWindowWithModalTransientChild) {
1469 if (!SupportsHostWindowResize())
1470 return;
1472 // Create a window.
1473 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
1474 gfx::Rect bounds(window->bounds());
1476 // Start dragging the window.
1477 ASSERT_NO_FATAL_FAILURE(DragStart(window.get()));
1478 gfx::Vector2d move_vector(40, test_panels() ? -60 : 60);
1479 DragMove(move_vector.x(), move_vector.y());
1480 EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id());
1482 // While still dragging create a modal window and make it a transient child of
1483 // the |window|.
1484 scoped_ptr<aura::Window> child(CreateModalWindow(gfx::Rect(20, 20, 150, 20)));
1485 ::wm::AddTransientChild(window.get(), child.get());
1486 EXPECT_EQ(window.get(), ::wm::GetTransientParent(child.get()));
1487 EXPECT_EQ(kShellWindowId_SystemModalContainer, child->parent()->id());
1489 // End the drag, the |window| should have moved (if it is a panel it will
1490 // no longer be attached to the shelf since we dragged it above).
1491 DragEnd();
1492 bounds.Offset(move_vector);
1493 EXPECT_EQ(bounds.ToString(), window->GetBoundsInScreen().ToString());
1495 // The original |window| should be in the default container (not docked or
1496 // attached).
1497 EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
1498 // The transient |child| should still be in system modal container.
1499 EXPECT_EQ(kShellWindowId_SystemModalContainer, child->parent()->id());
1500 // The |child| should not have moved.
1501 EXPECT_EQ(gfx::Point(20, 20).ToString(),
1502 child->GetBoundsInScreen().origin().ToString());
1503 // The |child| should still be a transient child of |window|.
1504 EXPECT_EQ(window.get(), ::wm::GetTransientParent(child.get()));
1507 // Tests that side snapping a window undocks it, closes the dock and then snaps.
1508 TEST_P(DockedWindowResizerTest, SideSnapDocked) {
1509 if (!SupportsHostWindowResize() || test_panels())
1510 return;
1512 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201)));
1513 wm::WindowState* window_state = wm::GetWindowState(w1.get());
1514 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
1515 // A window should be docked at the right edge.
1516 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
1517 w1->GetBoundsInScreen().right());
1518 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1519 DockedWindowLayoutManager* manager =
1520 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager());
1521 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1522 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1523 EXPECT_TRUE(window_state->IsDocked());
1524 EXPECT_FALSE(window_state->IsSnapped());
1526 // Side snap at right edge.
1527 const wm::WMEvent snap_right(wm::WM_EVENT_SNAP_RIGHT);
1528 window_state->OnWMEvent(&snap_right);
1529 // The window should be snapped at the right edge and the dock should close.
1530 gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(w1.get()));
1531 EXPECT_EQ(0, docked_width(manager));
1532 EXPECT_EQ(work_area.height(), w1->bounds().height());
1533 EXPECT_EQ(work_area.right(), w1->bounds().right());
1534 EXPECT_EQ(kShellWindowId_DefaultContainer, w1->parent()->id());
1535 EXPECT_FALSE(window_state->IsDocked());
1536 EXPECT_TRUE(window_state->IsSnapped());
1538 // Dock again.
1539 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20);
1540 // A window should be docked at the right edge.
1541 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(),
1542 w1->GetBoundsInScreen().right());
1543 EXPECT_EQ(kShellWindowId_DockedContainer, w1->parent()->id());
1544 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1545 EXPECT_EQ(w1->bounds().width(), docked_width(manager));
1546 EXPECT_TRUE(window_state->IsDocked());
1547 EXPECT_FALSE(window_state->IsSnapped());
1549 // Side snap at left edge.
1550 const wm::WMEvent snap_left(wm::WM_EVENT_SNAP_LEFT);
1551 window_state->OnWMEvent(&snap_left);
1552 // The window should be snapped at the right edge and the dock should close.
1553 EXPECT_EQ(work_area.ToString(),
1554 ScreenUtil::GetDisplayWorkAreaBoundsInParent(w1.get()).ToString());
1555 EXPECT_EQ(0, docked_width(manager));
1556 EXPECT_EQ(work_area.height(), w1->bounds().height());
1557 EXPECT_EQ(work_area.x(), w1->bounds().x());
1558 EXPECT_EQ(kShellWindowId_DefaultContainer, w1->parent()->id());
1559 EXPECT_FALSE(window_state->IsDocked());
1560 EXPECT_TRUE(window_state->IsSnapped());
1563 // Tests that a window is undocked if the window is maximized via a keyboard
1564 // accelerator during a drag.
1565 TEST_P(DockedWindowResizerTest, MaximizedDuringDrag) {
1566 if (!SupportsHostWindowResize() || test_panels())
1567 return;
1569 scoped_ptr<aura::Window> window(CreateTestWindow(
1570 gfx::Rect(0, 0, ideal_width(), 201)));
1571 wm::WindowState* window_state = wm::GetWindowState(window.get());
1573 // Dock the window to the right edge.
1574 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, window.get(), 20);
1575 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().right(),
1576 window->GetBoundsInScreen().right());
1577 EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
1578 DockedWindowLayoutManager* manager =
1579 static_cast<DockedWindowLayoutManager*>(
1580 window->parent()->layout_manager());
1581 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager));
1582 EXPECT_EQ(window->bounds().width(), docked_width(manager));
1583 EXPECT_TRUE(window_state->IsDocked());
1585 // Maximize the window while in a real drag. In particular,
1586 // ToplevelWindowEventHandler::ScopedWindowResizer::OnWindowStateTypeChanged()
1587 // must be called in order for the maximized window's size to be correct.
1588 delegate()->set_window_component(HTCAPTION);
1589 ui::test::EventGenerator& generator = GetEventGenerator();
1590 generator.MoveMouseTo(window->GetBoundsInScreen().origin());
1591 generator.PressLeftButton();
1592 generator.MoveMouseBy(10, 10);
1593 window_state->Maximize();
1594 generator.ReleaseLeftButton();
1596 // |window| should get undocked.
1597 EXPECT_EQ(kShellWindowId_DefaultContainer, window->parent()->id());
1598 EXPECT_EQ(0, docked_width(manager));
1599 EXPECT_EQ(
1600 ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString(),
1601 window->bounds().ToString());
1602 EXPECT_TRUE(window_state->IsMaximized());
1605 // Tests run twice - on both panels and normal windows
1606 INSTANTIATE_TEST_CASE_P(NormalOrPanel,
1607 DockedWindowResizerTest,
1608 testing::Values(ui::wm::WINDOW_TYPE_NORMAL,
1609 ui::wm::WINDOW_TYPE_PANEL));
1611 } // namespace ash