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. 4 5 #include "ash/wm/dock/docked_window_resizer.h" 6 7 #include "ash/ash_switches.h" 8 #include "ash/launcher/launcher.h" 9 #include "ash/launcher/launcher_model.h" 10 #include "ash/root_window_controller.h" 11 #include "ash/screen_ash.h" 12 #include "ash/shelf/shelf_layout_manager.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_launcher_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_properties.h" 25 #include "ash/wm/window_util.h" 26 #include "base/command_line.h" 27 #include "ui/aura/client/aura_constants.h" 28 #include "ui/aura/root_window.h" 29 #include "ui/aura/test/test_window_delegate.h" 30 #include "ui/base/hit_test.h" 31 #include "ui/base/ui_base_types.h" 32 #include "ui/views/widget/widget.h" 33 34 namespace ash { 35 namespace internal { 36 37 class DockedWindowResizerTest 38 : public test::AshTestBase, 39 public testing::WithParamInterface<aura::client::WindowType> { 40 public: 41 DockedWindowResizerTest() : model_(NULL), window_type_(GetParam()) {} 42 virtual ~DockedWindowResizerTest() {} 43 44 virtual void SetUp() OVERRIDE { 45 CommandLine::ForCurrentProcess()->AppendSwitch( 46 ash::switches::kAshEnableStickyEdges); 47 CommandLine::ForCurrentProcess()->AppendSwitch( 48 ash::switches::kAshEnableDockedWindows); 49 AshTestBase::SetUp(); 50 UpdateDisplay("600x400"); 51 test::ShellTestApi test_api(Shell::GetInstance()); 52 model_ = test_api.launcher_model(); 53 } 54 55 virtual void TearDown() OVERRIDE { 56 AshTestBase::TearDown(); 57 } 58 59 protected: 60 enum DockedEdge { 61 DOCKED_EDGE_NONE, 62 DOCKED_EDGE_LEFT, 63 DOCKED_EDGE_RIGHT, 64 }; 65 66 enum DockedState { 67 UNDOCKED, 68 DOCKED, 69 }; 70 71 aura::Window* CreateTestWindow(const gfx::Rect& bounds) { 72 aura::Window* window = CreateTestWindowInShellWithDelegateAndType( 73 &delegate_, 74 window_type_, 75 0, 76 bounds); 77 if (window_type_ == aura::client::WINDOW_TYPE_PANEL) { 78 test::TestLauncherDelegate* launcher_delegate = 79 test::TestLauncherDelegate::instance(); 80 launcher_delegate->AddLauncherItem(window); 81 PanelLayoutManager* manager = 82 static_cast<PanelLayoutManager*>( 83 Shell::GetContainer(window->GetRootWindow(), 84 internal::kShellWindowId_PanelContainer)-> 85 layout_manager()); 86 manager->Relayout(); 87 } 88 return window; 89 } 90 91 static WindowResizer* CreateSomeWindowResizer( 92 aura::Window* window, 93 const gfx::Point& point_in_parent, 94 int window_component) { 95 return CreateWindowResizer( 96 window, 97 point_in_parent, 98 window_component, 99 aura::client::WINDOW_MOVE_SOURCE_MOUSE).release(); 100 } 101 102 void DragStart(aura::Window* window) { 103 initial_location_in_parent_ = window->bounds().origin(); 104 resizer_.reset(CreateSomeWindowResizer(window, 105 initial_location_in_parent_, 106 HTCAPTION)); 107 ASSERT_TRUE(resizer_.get()); 108 } 109 110 void DragStartAtOffsetFromwindowOrigin(aura::Window* window, 111 int dx, 112 int dy) { 113 initial_location_in_parent_ = 114 window->bounds().origin() + gfx::Vector2d(dx, dy); 115 resizer_.reset(CreateSomeWindowResizer(window, 116 initial_location_in_parent_, 117 HTCAPTION)); 118 ASSERT_TRUE(resizer_.get()); 119 } 120 121 void ResizeStartAtOffsetFromwindowOrigin(aura::Window* window, 122 int dx, 123 int dy, 124 int window_component) { 125 initial_location_in_parent_ = 126 window->bounds().origin() + gfx::Vector2d(dx, dy); 127 resizer_.reset(CreateSomeWindowResizer(window, 128 initial_location_in_parent_, 129 window_component)); 130 ASSERT_TRUE(resizer_.get()); 131 } 132 133 void DragMove(int dx, int dy) { 134 resizer_->Drag(initial_location_in_parent_ + gfx::Vector2d(dx, dy), 0); 135 } 136 137 void DragEnd() { 138 resizer_->CompleteDrag(0); 139 resizer_.reset(); 140 } 141 142 void DragRevert() { 143 resizer_->RevertDrag(); 144 resizer_.reset(); 145 } 146 147 // Panels are parented by panel container during drags. 148 // Docked windows are parented by dock container during drags. 149 // All other windows that we are testing here have default container as a 150 // parent. 151 int CorrectContainerIdDuringDrag(DockedState is_docked) { 152 if (window_type_ == aura::client::WINDOW_TYPE_PANEL) 153 return internal::kShellWindowId_PanelContainer; 154 if (is_docked == DOCKED) 155 return internal::kShellWindowId_DockedContainer; 156 return internal::kShellWindowId_DefaultContainer; 157 } 158 159 // Test dragging the window vertically (to detach if it is a panel) and then 160 // horizontally to the edge with an added offset from the edge of |dx|. 161 void DragRelativeToEdge(DockedEdge edge, 162 aura::Window* window, 163 int dx) { 164 DragVerticallyAndRelativeToEdge( 165 edge, 166 window, 167 dx, 168 window_type_ == aura::client::WINDOW_TYPE_PANEL ? -100 : 20); 169 } 170 171 void DragToVerticalPositionAndToEdge(DockedEdge edge, 172 aura::Window* window, 173 int y) { 174 DragToVerticalPositionRelativeToEdge(edge, window, 0, y); 175 } 176 177 void DragToVerticalPositionRelativeToEdge(DockedEdge edge, 178 aura::Window* window, 179 int dx, 180 int y) { 181 gfx::Rect initial_bounds = window->GetBoundsInScreen(); 182 DragVerticallyAndRelativeToEdge(edge, window, dx, y - initial_bounds.y()); 183 } 184 185 // Detach if our window is a panel, then drag it vertically by |dy| and 186 // horizontally to the edge with an added offset from the edge of |dx|. 187 void DragVerticallyAndRelativeToEdge(DockedEdge edge, 188 aura::Window* window, 189 int dx, 190 int dy) { 191 aura::RootWindow* root_window = window->GetRootWindow(); 192 gfx::Rect initial_bounds = window->GetBoundsInScreen(); 193 194 if (window_type_ == aura::client::WINDOW_TYPE_PANEL) { 195 ASSERT_NO_FATAL_FAILURE(DragStart(window)); 196 EXPECT_TRUE(window->GetProperty(kPanelAttachedKey)); 197 198 // Drag enough to detach since our tests assume panels to be initially 199 // detached. 200 DragMove(0, dy); 201 EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id()); 202 EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x()); 203 EXPECT_EQ(initial_bounds.y() + dy, window->GetBoundsInScreen().y()); 204 205 // The panel should be detached when the drag completes. 206 DragEnd(); 207 208 EXPECT_FALSE(window->GetProperty(kPanelAttachedKey)); 209 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 210 window->parent()->id()); 211 EXPECT_EQ(root_window, window->GetRootWindow()); 212 } 213 214 // avoid snap by clicking away from the border 215 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(window, 25, 5)); 216 217 // Drag the window left or right to the edge (or almost to it). 218 if (edge == DOCKED_EDGE_LEFT) 219 dx += window->GetRootWindow()->bounds().x() - initial_bounds.x(); 220 else if (edge == DOCKED_EDGE_RIGHT) 221 dx += window->GetRootWindow()->bounds().right() - initial_bounds.right(); 222 DragMove(dx, window_type_ == aura::client::WINDOW_TYPE_PANEL ? 0 : dy); 223 EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id()); 224 // Release the mouse and the panel should be attached to the dock. 225 DragEnd(); 226 227 // x-coordinate can get adjusted by snapping or sticking. 228 // y-coordinate could be changed by possible automatic layout if docked. 229 if (window->parent()->id() != internal::kShellWindowId_DockedContainer) 230 EXPECT_EQ(initial_bounds.y() + dy, window->GetBoundsInScreen().y()); 231 } 232 233 bool test_panels() const { 234 return window_type_ == aura::client::WINDOW_TYPE_PANEL; 235 } 236 237 private: 238 scoped_ptr<WindowResizer> resizer_; 239 LauncherModel* model_; 240 aura::client::WindowType window_type_; 241 aura::test::TestWindowDelegate delegate_; 242 243 // Location at start of the drag in |window->parent()|'s coordinates. 244 gfx::Point initial_location_in_parent_; 245 246 DISALLOW_COPY_AND_ASSIGN(DockedWindowResizerTest); 247 }; 248 249 // Verifies a window can be dragged and attached to the dock. 250 TEST_P(DockedWindowResizerTest, AttachRightPrecise) { 251 if (!SupportsHostWindowResize()) 252 return; 253 254 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 255 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); 256 257 // The window should be attached and snapped to the right edge. 258 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 259 window->GetBoundsInScreen().right()); 260 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 261 } 262 263 // Verifies a window can be dragged and attached to the dock 264 // even if we overshoot the screen edge by a few pixels (sticky edge) 265 TEST_P(DockedWindowResizerTest, AttachRightOvershoot) { 266 if (!SupportsHostWindowResize()) 267 return; 268 269 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 270 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), +4); 271 272 // The window should be attached and snapped to the right edge. 273 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 274 window->GetBoundsInScreen().right()); 275 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 276 } 277 278 // Verifies a window can be dragged and then if not quite reaching the screen 279 // edge it does not get docked to a screen edge and stays in the desktop. 280 TEST_P(DockedWindowResizerTest, AttachRightUndershoot) { 281 if (!SupportsHostWindowResize()) 282 return; 283 284 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 285 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), -1); 286 287 // The window should not be attached to the dock. 288 EXPECT_EQ(window->GetRootWindow()->bounds().right() - 1, 289 window->GetBoundsInScreen().right()); 290 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 291 window->parent()->id()); 292 } 293 294 // Verifies a window can be dragged and attached to the dock. 295 TEST_P(DockedWindowResizerTest, AttachLeftPrecise) { 296 if (!SupportsHostWindowResize()) 297 return; 298 299 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 300 DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 0); 301 302 // The window should be attached and snapped to the left dock. 303 EXPECT_EQ(window->GetRootWindow()->bounds().x(), 304 window->GetBoundsInScreen().x()); 305 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 306 } 307 308 // Verifies a window can be dragged and attached to the dock 309 // even if we overshoot the screen edge by a few pixels (sticky edge) 310 TEST_P(DockedWindowResizerTest, AttachLeftOvershoot) { 311 if (!SupportsHostWindowResize()) 312 return; 313 314 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 315 DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), -4); 316 317 // The window should be attached and snapped to the left dock. 318 EXPECT_EQ(window->GetRootWindow()->bounds().x(), 319 window->GetBoundsInScreen().x()); 320 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 321 } 322 323 // Verifies a window can be dragged and then if not quite reaching the screen 324 // edge it does not get docked to a screen edge and stays in the desktop. 325 TEST_P(DockedWindowResizerTest, AttachLeftUndershoot) { 326 if (!SupportsHostWindowResize()) 327 return; 328 329 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 330 DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 1); 331 332 // The window should not be attached to the dock. 333 EXPECT_EQ(window->GetRootWindow()->bounds().x() + 1, 334 window->GetBoundsInScreen().x()); 335 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 336 window->parent()->id()); 337 } 338 339 // Dock on the right side, change shelf alignment, check that windows move to 340 // the opposite side. 341 TEST_P(DockedWindowResizerTest, AttachRightChangeShelf) { 342 if (!SupportsHostWindowResize()) 343 return; 344 345 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 346 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); 347 348 // The window should be attached and snapped to the right edge. 349 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 350 window->GetBoundsInScreen().right()); 351 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 352 353 // set launcher shelf to be aligned on the right 354 ash::Shell* shell = ash::Shell::GetInstance(); 355 shell->SetShelfAlignment(SHELF_ALIGNMENT_RIGHT, 356 shell->GetPrimaryRootWindow()); 357 // The window should have moved and get attached to the left dock. 358 EXPECT_EQ(window->GetRootWindow()->bounds().x(), 359 window->GetBoundsInScreen().x()); 360 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 361 362 // set launcher shelf to be aligned on the left 363 shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, 364 shell->GetPrimaryRootWindow()); 365 // The window should have moved and get attached to the right edge. 366 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 367 window->GetBoundsInScreen().right()); 368 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 369 370 // set launcher shelf to be aligned at the bottom 371 shell->SetShelfAlignment(SHELF_ALIGNMENT_BOTTOM, 372 shell->GetPrimaryRootWindow()); 373 // The window should stay in the right edge. 374 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 375 window->GetBoundsInScreen().right()); 376 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 377 } 378 379 // Dock on the right side, try to undock, then drag more to really undock 380 TEST_P(DockedWindowResizerTest, AttachTryDetach) { 381 if (!SupportsHostWindowResize()) 382 return; 383 384 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 385 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); 386 387 // The window should be attached and snapped to the right edge. 388 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 389 window->GetBoundsInScreen().right()); 390 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 391 392 // Try to detach by dragging left a bit (should stay docked) 393 ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); 394 DragMove(-10, -10); 395 // Release the mouse and the window should be still attached to the dock. 396 DragEnd(); 397 398 // The window should be still attached to the right edge. 399 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 400 window->GetBoundsInScreen().right()); 401 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 402 403 // Try to detach by dragging left a bit more (should get undocked) 404 ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); 405 DragMove(-32, -10); 406 // Release the mouse and the window should be no longer attached to the dock. 407 DragEnd(); 408 409 // The window should be floating on the desktop again. 410 EXPECT_EQ(window->GetRootWindow()->bounds().right() - 32, 411 window->GetBoundsInScreen().right()); 412 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 413 window->parent()->id()); 414 } 415 416 // Minimize a docked window, then restore it and check that it is still docked. 417 TEST_P(DockedWindowResizerTest, AttachMinimizeRestore) { 418 if (!SupportsHostWindowResize()) 419 return; 420 421 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 422 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); 423 424 // The window should be attached and snapped to the right edge. 425 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 426 window->GetBoundsInScreen().right()); 427 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 428 429 // Minimize the window, it should be hidden. 430 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); 431 RunAllPendingInMessageLoop(); 432 EXPECT_FALSE(window->IsVisible()); 433 // Restore the window; window should be visible. 434 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); 435 RunAllPendingInMessageLoop(); 436 EXPECT_TRUE(window->IsVisible()); 437 } 438 439 // Dock two windows, undock one, check that the other one is still docked. 440 TEST_P(DockedWindowResizerTest, AttachTwoWindows) 441 { 442 if (!SupportsHostWindowResize()) 443 return; 444 445 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 446 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 447 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 448 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 50); 449 450 // Both windows should be attached and snapped to the right edge. 451 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 452 w1->GetBoundsInScreen().right()); 453 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 454 455 EXPECT_EQ(w2->GetRootWindow()->bounds().right(), 456 w2->GetBoundsInScreen().right()); 457 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 458 459 // Detach by dragging left (should get undocked). 460 ASSERT_NO_FATAL_FAILURE(DragStart(w2.get())); 461 // Drag up as well to avoid attaching panels to launcher shelf. 462 DragMove(-32, -100); 463 // Release the mouse and the window should be no longer attached to the edge. 464 DragEnd(); 465 466 // The first window should be still docked. 467 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 468 w1->GetBoundsInScreen().right()); 469 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 470 471 // The second window should be floating on the desktop again. 472 EXPECT_EQ(w2->GetRootWindow()->bounds().right() - 32, 473 w2->GetBoundsInScreen().right()); 474 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 475 w2->parent()->id()); 476 } 477 478 // Dock one window, try to dock another window on the opposite side (should not 479 // dock). 480 TEST_P(DockedWindowResizerTest, AttachOnTwoSides) 481 { 482 if (!SupportsHostWindowResize()) 483 return; 484 485 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 486 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 487 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 488 DragToVerticalPositionAndToEdge(DOCKED_EDGE_LEFT, w2.get(), 50); 489 490 // The first window should be attached and snapped to the right edge. 491 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 492 w1->GetBoundsInScreen().right()); 493 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 494 495 // The second window should be near the left edge but not snapped. 496 EXPECT_EQ(w2->GetRootWindow()->bounds().x(), w2->GetBoundsInScreen().x()); 497 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 498 } 499 500 // Reverting drag 501 TEST_P(DockedWindowResizerTest, RevertDragRestoresAttachment) { 502 if (!SupportsHostWindowResize()) 503 return; 504 505 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 506 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); 507 508 // The window should be attached and snapped to the right edge. 509 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 510 window->GetBoundsInScreen().right()); 511 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 512 513 // Drag the window out but revert the drag 514 ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); 515 DragMove(-50, 0); 516 DragRevert(); 517 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 518 519 // Detach window. 520 ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); 521 DragMove(-50, 0); 522 DragEnd(); 523 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 524 window->parent()->id()); 525 } 526 527 // Move a docked window to the second display 528 TEST_P(DockedWindowResizerTest, DragAcrossDisplays) { 529 if (!SupportsMultipleDisplays()) 530 return; 531 532 UpdateDisplay("800x800,800x800"); 533 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); 534 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 535 gfx::Rect initial_bounds = window->GetBoundsInScreen(); 536 EXPECT_EQ(root_windows[0], window->GetRootWindow()); 537 538 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); 539 // The window should be attached and snapped to the right edge. 540 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 541 window->GetBoundsInScreen().right()); 542 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 543 544 // Undock and move to the right - enough to get it peeking at the other screen 545 // but not enough to land in the other screen 546 ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); 547 DragMove(70, 0); 548 EXPECT_EQ(CorrectContainerIdDuringDrag(DOCKED), window->parent()->id()); 549 DragEnd(); 550 EXPECT_NE(window->GetRootWindow()->bounds().right(), 551 window->GetBoundsInScreen().right()); 552 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 553 window->parent()->id()); 554 EXPECT_EQ(root_windows[0], window->GetRootWindow()); 555 556 // Move back left - should dock again. 557 ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); 558 DragMove(-70, 0); 559 EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id()); 560 DragEnd(); 561 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 562 window->GetBoundsInScreen().right()); 563 EXPECT_EQ(internal::kShellWindowId_DockedContainer, 564 window->parent()->id()); 565 EXPECT_EQ(root_windows[0], window->GetRootWindow()); 566 567 // Undock and move to the right - enough to get the mouse pointer past the 568 // edge of the screen and into the second screen. The window should now be 569 // in the second screen and not docked. 570 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin( 571 window.get(), 572 window->bounds().width()/2 + 10, 573 0)); 574 DragMove(window->bounds().width()/2 - 5, 0); 575 EXPECT_EQ(CorrectContainerIdDuringDrag(DOCKED), window->parent()->id()); 576 DragEnd(); 577 EXPECT_NE(window->GetRootWindow()->bounds().right(), 578 window->GetBoundsInScreen().right()); 579 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 580 window->parent()->id()); 581 EXPECT_EQ(root_windows[1], window->GetRootWindow()); 582 583 // Keep dragging it to the right until it docks. The window should now be 584 // in the second screen. 585 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin( 586 window.get(), 587 window->bounds().width()/2 + 10, 588 0)); 589 DragMove(window->GetRootWindow()->GetBoundsInScreen().x() - 590 window->GetBoundsInScreen().x(), 591 0); 592 EXPECT_EQ(CorrectContainerIdDuringDrag(UNDOCKED), window->parent()->id()); 593 DragEnd(); 594 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().x(), 595 window->GetBoundsInScreen().x()); 596 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 597 EXPECT_EQ(root_windows[1], window->GetRootWindow()); 598 } 599 600 // Dock two windows, undock one. 601 // Test the docked windows area size and default container resizing. 602 TEST_P(DockedWindowResizerTest, AttachTwoWindowsDetachOne) 603 { 604 if (!SupportsHostWindowResize()) 605 return; 606 607 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 608 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201))); 609 // Work area should cover the whole screen. 610 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), 611 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 612 613 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 614 // A window should be attached and snapped to the right edge. 615 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 616 w1->GetBoundsInScreen().right()); 617 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 618 DockedWindowLayoutManager* manager = 619 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); 620 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 621 EXPECT_EQ(w1->bounds().width(), manager->docked_width_); 622 623 DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), 0, 50); 624 // Both windows should now be attached and snapped to the right edge. 625 EXPECT_EQ(w2->GetRootWindow()->bounds().right(), 626 w2->GetBoundsInScreen().right()); 627 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 628 // Dock width should be set to a wider window. 629 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 630 EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()), 631 manager->docked_width_); 632 633 // Try to detach by dragging left a bit (should not get undocked). 634 // This would normally detach a single docked window but since we have another 635 // window and the mouse pointer does not leave the dock area the window 636 // should stay docked. 637 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w2.get(), 60, 0)); 638 // Drag up as well as left to avoid attaching panels to launcher shelf. 639 DragMove(-40, -40); 640 // Release the mouse and the window should be still attached to the edge. 641 DragEnd(); 642 643 // The first window should be still docked. 644 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 645 w1->GetBoundsInScreen().right()); 646 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 647 648 // The second window should be still docked. 649 EXPECT_EQ(w2->GetRootWindow()->bounds().right(), 650 w2->GetBoundsInScreen().right()); 651 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 652 653 // Detach by dragging left more (should get undocked). 654 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin( 655 w2.get(), 656 w2->bounds().width()/2 + 10, 657 0)); 658 // Drag up as well to avoid attaching panels to launcher shelf. 659 DragMove(-(w2->bounds().width()/2 + 20), -100); 660 // Release the mouse and the window should be no longer attached to the edge. 661 DragEnd(); 662 663 // The second window should be floating on the desktop again. 664 EXPECT_EQ(w2->GetRootWindow()->bounds().right() - 665 (w2->bounds().width()/2 + 20), 666 w2->GetBoundsInScreen().right()); 667 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 668 // Dock width should be set to remaining single docked window. 669 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 670 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 671 EXPECT_EQ(w1->bounds().width(), manager->docked_width_); 672 } 673 674 // Dock one windows. Maximize other testing desktop resizing. 675 TEST_P(DockedWindowResizerTest, AttachWindowMaximizeOther) 676 { 677 if (!SupportsHostWindowResize()) 678 return; 679 680 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 681 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201))); 682 // Work area should cover the whole screen. 683 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), 684 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 685 686 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 687 // A window should be attached and snapped to the right edge. 688 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 689 w1->GetBoundsInScreen().right()); 690 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 691 DockedWindowLayoutManager* manager = 692 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); 693 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 694 EXPECT_EQ(w1->bounds().width(), manager->docked_width_); 695 696 DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, 697 w2.get(), 698 -(w2->bounds().width()/2 + 20), 699 50); 700 // The first window should be still docked. 701 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 702 w1->GetBoundsInScreen().right()); 703 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 704 705 // The second window should be floating on the desktop. 706 EXPECT_EQ(w2->GetRootWindow()->bounds().right() - 707 (w2->bounds().width()/2 + 20), 708 w2->GetBoundsInScreen().right()); 709 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 710 // Dock width should be set to remaining single docked window. 711 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 712 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 713 EXPECT_EQ(w1->bounds().width(), manager->docked_width_); 714 // Desktop work area should now shrink. 715 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 716 manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap, 717 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 718 719 // Maximize the second window - Maximized area should be shrunk. 720 const gfx::Rect restored_bounds = w2->bounds(); 721 wm::MaximizeWindow(w2.get()); 722 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 723 manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap, 724 w2->bounds().width()); 725 726 // Detach the first window (this should require very little drag). 727 ASSERT_NO_FATAL_FAILURE(DragStart(w1.get())); 728 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 729 DragMove(-35, 10); 730 // For NORMAL windows alignment is set to "RIGHT" until the drag is completed. 731 // For PANEL windows alignment is set to "NONE" when drag starts. 732 EXPECT_EQ(test_panels() ? DOCKED_ALIGNMENT_NONE : DOCKED_ALIGNMENT_RIGHT, 733 manager->alignment_); 734 // Release the mouse and the window should be no longer attached to the edge. 735 DragEnd(); 736 // Dock should get shrunk and desktop should get expanded. 737 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id()); 738 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 739 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, manager->alignment_); 740 EXPECT_EQ(0, manager->docked_width_); 741 // The second window should now get resized and take up the whole screen. 742 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), 743 w2->bounds().width()); 744 745 // Dock the first window to the left edge. 746 // Click at an offset from origin to prevent snapping. 747 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w1.get(), 10, 0)); 748 DragMove(-w1->bounds().x(), 0); 749 // Alignment set to "NONE" during the drag of the window when none are docked. 750 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, manager->alignment_); 751 // Release the mouse and the window should be now attached to the edge. 752 DragEnd(); 753 // Dock should get expanded and desktop should get shrunk. 754 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 755 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_); 756 EXPECT_EQ(w1->bounds().width(), manager->docked_width_); 757 // Second window should still be in the desktop. 758 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 759 // Maximized window should be shrunk. 760 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 761 manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap, 762 w2->bounds().width()); 763 764 // Unmaximize the second window. 765 wm::RestoreWindow(w2.get()); 766 // Its bounds should get restored. 767 EXPECT_EQ(restored_bounds, w2->bounds()); 768 } 769 770 // Dock one window. Test the sticky behavior near screen or desktop edge. 771 TEST_P(DockedWindowResizerTest, AttachOneTestSticky) 772 { 773 if (!SupportsHostWindowResize()) 774 return; 775 776 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 777 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201))); 778 // Work area should cover the whole screen. 779 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), 780 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 781 782 DragToVerticalPositionAndToEdge(DOCKED_EDGE_LEFT, w1.get(), 20); 783 // A window should be attached and snapped to the left edge. 784 EXPECT_EQ(w1->GetRootWindow()->bounds().x(), 785 w1->GetBoundsInScreen().x()); 786 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 787 DockedWindowLayoutManager* manager = 788 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); 789 // The first window should be docked. 790 EXPECT_EQ(w1->GetRootWindow()->bounds().x(), 791 w1->GetBoundsInScreen().x()); 792 // Dock width should be set to that of a single docked window. 793 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 794 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_); 795 EXPECT_EQ(w1->bounds().width(), manager->docked_width_); 796 797 // Position second window in the desktop just to the right of the docked w1. 798 DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_LEFT, 799 w2.get(), 800 w1->bounds().right() + 20, 801 50); 802 // The second window should be floating on the desktop. 803 EXPECT_EQ(w2->GetRootWindow()->bounds().x() + (w1->bounds().right() + 20), 804 w2->GetBoundsInScreen().x()); 805 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 806 // Dock width should be set to that of a single docked window. 807 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 808 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_); 809 EXPECT_EQ(w1->bounds().width(), manager->docked_width_); 810 811 // Drag w2 almost to the dock, the mouse pointer not quite reaching the dock. 812 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromwindowOrigin(w2.get(), 10, 0)); 813 DragMove(1 + manager->docked_width_ - w2->bounds().x(), 0); 814 // Alignment set to "LEFT" during the drag because dock has a window in it. 815 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_); 816 // Release the mouse and the window should not be attached to the edge. 817 DragEnd(); 818 // Dock should still have only one window in it. 819 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_); 820 EXPECT_EQ(w1->bounds().width(), manager->docked_width_); 821 // The second window should still be in the desktop. 822 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 823 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 824 825 // Drag w2 by a bit more - it should resist the drag (stuck edges) 826 int start_x = w2->bounds().x(); 827 ASSERT_NO_FATAL_FAILURE(DragStart(w2.get())); 828 DragMove(-2, 0); 829 // Window should not actually move. 830 EXPECT_EQ(start_x, w2->bounds().x()); 831 // Alignment set to "LEFT" during the drag because dock has a window in it. 832 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_); 833 // Release the mouse and the window should not be attached to the edge. 834 DragEnd(); 835 // Window should be still where it was before the last drag started. 836 EXPECT_EQ(start_x, w2->bounds().x()); 837 // Dock should still have only one window in it 838 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_); 839 EXPECT_EQ(w1->bounds().width(), manager->docked_width_); 840 // The second window should still be in the desktop 841 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 842 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 843 844 // Drag w2 by more than the stuck threshold and drop it into the dock. 845 ASSERT_NO_FATAL_FAILURE(DragStart(w2.get())); 846 DragMove(-100, 0); 847 // Window should actually move. 848 EXPECT_NE(start_x, w2->bounds().x()); 849 // Alignment set to "LEFT" during the drag because dock has a window in it. 850 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_); 851 // Release the mouse and the window should be attached to the edge. 852 DragEnd(); 853 // Both windows are docked now. 854 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 855 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 856 // Dock should get expanded and desktop should get shrunk. 857 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, manager->alignment_); 858 EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()), 859 manager->docked_width_); 860 // Desktop work area should now shrink by dock width. 861 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 862 manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap, 863 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 864 } 865 866 // Dock two windows, resize one or both. 867 // Test the docked windows area size and remaining desktop resizing. 868 TEST_P(DockedWindowResizerTest, ResizeTwoWindows) 869 { 870 if (!SupportsHostWindowResize()) 871 return; 872 873 // Wider display to start since panels are limited to half the display width. 874 UpdateDisplay("1000x400"); 875 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 876 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201))); 877 // Work area should cover the whole screen. 878 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), 879 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 880 881 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 882 // A window should be attached and snapped to the right edge. 883 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 884 w1->GetBoundsInScreen().right()); 885 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 886 DockedWindowLayoutManager* manager = 887 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); 888 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 889 EXPECT_EQ(w1->bounds().width(), manager->docked_width_); 890 891 DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), 0, 50); 892 // Both windows should now be attached and snapped to the right edge. 893 EXPECT_EQ(w2->GetRootWindow()->bounds().right(), 894 w2->GetBoundsInScreen().right()); 895 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 896 // Dock width should be set to a wider window. 897 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 898 EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()), 899 manager->docked_width_); 900 901 // Resize the first window left by a bit and test that the dock expands. 902 int previous_width = w1->bounds().width(); 903 const int kResizeSpan1 = 30; 904 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromwindowOrigin(w1.get(), 905 0, 906 20, 907 HTLEFT)); 908 DragMove(-kResizeSpan1, 0); 909 // Alignment set to "RIGHT" during the drag because dock has a window in it. 910 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 911 // Release the mouse and the window should be attached to the edge. 912 DragEnd(); 913 // Dock should still have both windows in it. 914 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 915 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 916 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 917 // w1 is now wider than w2 and the dock should expand and be as wide as w1. 918 EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width()); 919 EXPECT_GT(w1->bounds().width(), w2->bounds().width()); 920 EXPECT_EQ(w1->bounds().width(), manager->docked_width_); 921 // Desktop work area should shrink. 922 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 923 manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap, 924 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 925 926 // Resize the first window left by more than the dock maximum width. 927 // This should cause the window to overhang and the dock to shrink to w2. 928 previous_width = w1->bounds().width(); 929 const int kResizeSpan2 = 250; 930 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromwindowOrigin(w1.get(), 931 0, 932 20, 933 HTLEFT)); 934 DragMove(-kResizeSpan2, 0); 935 // Alignment set to "RIGHT" during the drag because dock has a window in it. 936 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 937 // Release the mouse and the window should be attached to the edge. 938 DragEnd(); 939 // Dock should still have both windows in it. 940 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 941 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 942 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 943 // w1 is now wider than the maximum dock width and the dock should shrink to 944 // the next widest window (w2). 945 EXPECT_EQ(previous_width + kResizeSpan2, w1->bounds().width()); 946 EXPECT_GT(w1->bounds().width(), w2->bounds().width()); 947 EXPECT_EQ(w2->bounds().width(), manager->docked_width_); 948 // Desktop work area should shrink. 949 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 950 manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap, 951 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 952 953 // Resize the first window right to get it completely inside the docked area. 954 previous_width = w1->bounds().width(); 955 const int kResizeSpan3 = 100; 956 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromwindowOrigin(w1.get(), 957 0, 958 20, 959 HTLEFT)); 960 DragMove(kResizeSpan3, 0); 961 // Alignment set to "RIGHT" during the drag because dock has a window in it. 962 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 963 // Release the mouse and the window should be attached to the edge. 964 DragEnd(); 965 // Dock should still have both windows in it. 966 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 967 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 968 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 969 // w1 is still wider than w2 so the dock should expand and be as wide as w1. 970 EXPECT_EQ(previous_width - kResizeSpan3, w1->bounds().width()); 971 EXPECT_GT(w1->bounds().width(), w2->bounds().width()); 972 EXPECT_EQ(w1->bounds().width(), manager->docked_width_); 973 // Desktop work area should shrink. 974 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 975 manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap, 976 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 977 978 // Resize the first window left to be overhang again. 979 previous_width = w1->bounds().width(); 980 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromwindowOrigin(w1.get(), 981 0, 982 20, 983 HTLEFT)); 984 DragMove(-kResizeSpan3, 0); 985 DragEnd(); 986 EXPECT_EQ(previous_width + kResizeSpan3, w1->bounds().width()); 987 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 988 // Docked area should be as wide as the second window - the first is too wide. 989 EXPECT_EQ(w2->bounds().width(), manager->docked_width_); 990 991 // Undock the second window. Docked area should shrink to its minimum size. 992 ASSERT_NO_FATAL_FAILURE(DragStart(w2.get())); 993 // Drag up as well to avoid attaching panels to launcher shelf. 994 DragMove(-40, -100); 995 // Alignment set to "RIGHT" since we have another window docked. 996 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 997 // Release the mouse and the window should be no longer attached to the edge. 998 DragEnd(); 999 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 1000 // Dock should get shrunk to minimum size. 1001 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 1002 EXPECT_EQ(manager->kMinDockWidth, manager->docked_width_); 1003 // The first window should be still docked. 1004 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 1005 // Desktop work area should be inset. 1006 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 1007 manager->docked_width_ - DockedWindowLayoutManager::kMinDockGap, 1008 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 1009 } 1010 1011 TEST_P(DockedWindowResizerTest, DragToShelf) 1012 { 1013 if (!SupportsHostWindowResize()) 1014 return; 1015 1016 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 1017 // Work area should cover the whole screen. 1018 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w1.get()).width(), 1019 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w1.get()).width()); 1020 1021 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 1022 // A window should be attached and snapped to the right edge. 1023 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 1024 w1->GetBoundsInScreen().right()); 1025 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 1026 DockedWindowLayoutManager* manager = 1027 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); 1028 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, manager->alignment_); 1029 EXPECT_EQ(w1->bounds().width(), manager->docked_width_); 1030 1031 // Detach and drag down to shelf. 1032 ASSERT_NO_FATAL_FAILURE(DragStart(w1.get())); 1033 DragMove(-40, 0); 1034 // For NORMAL windows alignment is set to "RIGHT" until the drag is completed. 1035 // For PANEL windows alignment is set to "NONE" when drag starts. 1036 EXPECT_EQ(test_panels() ? DOCKED_ALIGNMENT_NONE : DOCKED_ALIGNMENT_RIGHT, 1037 manager->alignment_); 1038 // Release the mouse and the window should be no longer attached to the edge. 1039 DragEnd(); 1040 1041 // Drag down almost to shelf. A panel will snap, a regular window won't. 1042 ShelfWidget* shelf = Launcher::ForPrimaryDisplay()->shelf_widget(); 1043 const int shelf_y = shelf->GetWindowBoundsInScreen().y(); 1044 const int kDistanceFromShelf = 10; 1045 ASSERT_NO_FATAL_FAILURE(DragStart(w1.get())); 1046 DragMove(0, -kDistanceFromShelf + shelf_y - w1->bounds().bottom()); 1047 DragEnd(); 1048 if (test_panels()) { 1049 // The panel should be touching the shelf and attached. 1050 EXPECT_EQ(shelf_y, w1->bounds().bottom()); 1051 EXPECT_TRUE(w1->GetProperty(kPanelAttachedKey)); 1052 } else { 1053 // The window should not be touching the shelf. 1054 EXPECT_EQ(shelf_y - kDistanceFromShelf, w1->bounds().bottom()); 1055 } 1056 } 1057 1058 // Tests run twice - on both panels and normal windows 1059 INSTANTIATE_TEST_CASE_P(NormalOrPanel, 1060 DockedWindowResizerTest, 1061 testing::Values(aura::client::WINDOW_TYPE_NORMAL, 1062 aura::client::WINDOW_TYPE_PANEL)); 1063 } // namespace internal 1064 } // namespace ash 1065