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/root_window_controller.h" 10 #include "ash/screen_ash.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/coordinate_conversion.h" 22 #include "ash/wm/dock/docked_window_layout_manager.h" 23 #include "ash/wm/drag_window_resizer.h" 24 #include "ash/wm/panels/panel_layout_manager.h" 25 #include "ash/wm/window_state.h" 26 #include "ash/wm/window_util.h" 27 #include "ash/wm/workspace/snap_sizer.h" 28 #include "base/command_line.h" 29 #include "ui/aura/client/aura_constants.h" 30 #include "ui/aura/client/window_tree_client.h" 31 #include "ui/aura/root_window.h" 32 #include "ui/aura/test/test_window_delegate.h" 33 #include "ui/base/hit_test.h" 34 #include "ui/base/ui_base_types.h" 35 #include "ui/views/widget/widget.h" 36 37 namespace ash { 38 namespace internal { 39 40 class DockedWindowResizerTest 41 : public test::AshTestBase, 42 public testing::WithParamInterface<aura::client::WindowType> { 43 public: 44 DockedWindowResizerTest() : model_(NULL), window_type_(GetParam()) {} 45 virtual ~DockedWindowResizerTest() {} 46 47 virtual void SetUp() OVERRIDE { 48 CommandLine::ForCurrentProcess()->AppendSwitch( 49 ash::switches::kAshEnableDockedWindows); 50 AshTestBase::SetUp(); 51 UpdateDisplay("600x400"); 52 test::ShellTestApi test_api(Shell::GetInstance()); 53 model_ = test_api.shelf_model(); 54 } 55 56 virtual void TearDown() OVERRIDE { 57 AshTestBase::TearDown(); 58 } 59 60 protected: 61 enum DockedEdge { 62 DOCKED_EDGE_NONE, 63 DOCKED_EDGE_LEFT, 64 DOCKED_EDGE_RIGHT, 65 }; 66 67 int ideal_width() const { return DockedWindowLayoutManager::kIdealWidth; } 68 int min_dock_gap() const { return DockedWindowLayoutManager::kMinDockGap; } 69 int max_width() const { return DockedWindowLayoutManager::kMaxDockWidth; } 70 int docked_width(const DockedWindowLayoutManager* layout_manager) const { 71 return layout_manager->docked_width_; 72 } 73 int docked_alignment(const DockedWindowLayoutManager* layout_manager) const { 74 return layout_manager->alignment_; 75 } 76 aura::Window* CreateTestWindow(const gfx::Rect& bounds) { 77 aura::Window* window = CreateTestWindowInShellWithDelegateAndType( 78 &delegate_, 79 window_type_, 80 0, 81 bounds); 82 if (window_type_ == aura::client::WINDOW_TYPE_PANEL) { 83 test::TestShelfDelegate* shelf_delegate = 84 test::TestShelfDelegate::instance(); 85 shelf_delegate->AddLauncherItem(window); 86 PanelLayoutManager* manager = 87 static_cast<PanelLayoutManager*>( 88 Shell::GetContainer(window->GetRootWindow(), 89 internal::kShellWindowId_PanelContainer)-> 90 layout_manager()); 91 manager->Relayout(); 92 } 93 return window; 94 } 95 96 aura::Window* CreateModalWindow(const gfx::Rect& bounds) { 97 aura::Window* window = new aura::Window(&delegate_); 98 window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM); 99 window->SetType(aura::client::WINDOW_TYPE_NORMAL); 100 window->Init(ui::LAYER_TEXTURED); 101 window->Show(); 102 103 if (bounds.IsEmpty()) { 104 ParentWindowInPrimaryRootWindow(window); 105 } else { 106 gfx::Display display = 107 Shell::GetScreen()->GetDisplayMatching(bounds); 108 aura::Window* root = ash::Shell::GetInstance()->display_controller()-> 109 GetRootWindowForDisplayId(display.id()); 110 gfx::Point origin = bounds.origin(); 111 wm::ConvertPointFromScreen(root, &origin); 112 window->SetBounds(gfx::Rect(origin, bounds.size())); 113 aura::client::ParentWindowWithContext(window, root, bounds); 114 } 115 return window; 116 } 117 118 static WindowResizer* CreateSomeWindowResizer( 119 aura::Window* window, 120 const gfx::Point& point_in_parent, 121 int window_component) { 122 return CreateWindowResizer( 123 window, 124 point_in_parent, 125 window_component, 126 aura::client::WINDOW_MOVE_SOURCE_MOUSE).release(); 127 } 128 129 void DragStart(aura::Window* window) { 130 DragStartAtOffsetFromWindowOrigin(window, 0, 0); 131 } 132 133 void DragStartAtOffsetFromWindowOrigin(aura::Window* window, 134 int dx, int dy) { 135 initial_location_in_parent_ = 136 window->bounds().origin() + gfx::Vector2d(dx, dy); 137 resizer_.reset(CreateSomeWindowResizer(window, 138 initial_location_in_parent_, 139 HTCAPTION)); 140 ASSERT_TRUE(resizer_.get()); 141 } 142 143 void ResizeStartAtOffsetFromWindowOrigin(aura::Window* window, 144 int dx, int dy, 145 int window_component) { 146 initial_location_in_parent_ = 147 window->bounds().origin() + gfx::Vector2d(dx, dy); 148 resizer_.reset(CreateSomeWindowResizer(window, 149 initial_location_in_parent_, 150 window_component)); 151 ASSERT_TRUE(resizer_.get()); 152 } 153 154 void DragMove(int dx, int dy) { 155 resizer_->Drag(initial_location_in_parent_ + gfx::Vector2d(dx, dy), 0); 156 } 157 158 void DragEnd() { 159 resizer_->CompleteDrag(0); 160 resizer_.reset(); 161 } 162 163 void DragRevert() { 164 resizer_->RevertDrag(); 165 resizer_.reset(); 166 } 167 168 // Panels are parented by panel container during drags. 169 // All other windows that are tested here are parented by dock container 170 // during drags. 171 int CorrectContainerIdDuringDrag() { 172 if (window_type_ == aura::client::WINDOW_TYPE_PANEL) 173 return internal::kShellWindowId_PanelContainer; 174 return internal::kShellWindowId_DockedContainer; 175 } 176 177 // Test dragging the window vertically (to detach if it is a panel) and then 178 // horizontally to the edge with an added offset from the edge of |dx|. 179 void DragRelativeToEdge(DockedEdge edge, 180 aura::Window* window, 181 int dx) { 182 DragVerticallyAndRelativeToEdge( 183 edge, 184 window, 185 dx, window_type_ == aura::client::WINDOW_TYPE_PANEL ? -100 : 20, 186 25, 5); 187 } 188 189 void DragToVerticalPositionAndToEdge(DockedEdge edge, 190 aura::Window* window, 191 int y) { 192 DragToVerticalPositionRelativeToEdge(edge, window, 0, y); 193 } 194 195 void DragToVerticalPositionRelativeToEdge(DockedEdge edge, 196 aura::Window* window, 197 int dx, 198 int y) { 199 gfx::Rect initial_bounds = window->GetBoundsInScreen(); 200 DragVerticallyAndRelativeToEdge(edge, 201 window, 202 dx, y - initial_bounds.y(), 203 25, 5); 204 } 205 206 // Detach if our window is a panel, then drag it vertically by |dy| and 207 // horizontally to the edge with an added offset from the edge of |dx|. 208 void DragVerticallyAndRelativeToEdge(DockedEdge edge, 209 aura::Window* window, 210 int dx, int dy, 211 int grab_x, int grab_y) { 212 gfx::Rect initial_bounds = window->GetBoundsInScreen(); 213 // avoid snap by clicking away from the border 214 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(window, 215 grab_x, grab_y)); 216 217 gfx::Rect work_area = 218 Shell::GetScreen()->GetDisplayNearestWindow(window).work_area(); 219 gfx::Point initial_location_in_screen = initial_location_in_parent_; 220 wm::ConvertPointToScreen(window->parent(), &initial_location_in_screen); 221 // Drag the window left or right to the edge (or almost to it). 222 if (edge == DOCKED_EDGE_LEFT) 223 dx += work_area.x() - initial_location_in_screen.x(); 224 else if (edge == DOCKED_EDGE_RIGHT) 225 dx += work_area.right() - 1 - initial_location_in_screen.x(); 226 DragMove(dx, dy); 227 EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); 228 // Release the mouse and the panel should be attached to the dock. 229 DragEnd(); 230 231 // x-coordinate can get adjusted by snapping or sticking. 232 // y-coordinate could be changed by possible automatic layout if docked. 233 if (window->parent()->id() != internal::kShellWindowId_DockedContainer && 234 !wm::GetWindowState(window)->HasRestoreBounds()) { 235 EXPECT_EQ(initial_bounds.y() + dy, window->GetBoundsInScreen().y()); 236 } 237 } 238 239 bool test_panels() const { 240 return window_type_ == aura::client::WINDOW_TYPE_PANEL; 241 } 242 243 const gfx::Point& initial_location_in_parent() const { 244 return initial_location_in_parent_; 245 } 246 247 private: 248 scoped_ptr<WindowResizer> resizer_; 249 ShelfModel* model_; 250 aura::client::WindowType window_type_; 251 aura::test::TestWindowDelegate delegate_; 252 253 // Location at start of the drag in |window->parent()|'s coordinates. 254 gfx::Point initial_location_in_parent_; 255 256 DISALLOW_COPY_AND_ASSIGN(DockedWindowResizerTest); 257 }; 258 259 // Verifies a window can be dragged and attached to the dock. 260 TEST_P(DockedWindowResizerTest, AttachRightPrecise) { 261 if (!SupportsHostWindowResize()) 262 return; 263 264 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 265 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); 266 267 // The window should be docked at the right edge. 268 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 269 window->GetBoundsInScreen().right()); 270 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 271 } 272 273 // Verifies a window can be dragged and attached to the dock 274 // even if pointer overshoots the screen edge by a few pixels (sticky edge) 275 TEST_P(DockedWindowResizerTest, AttachRightOvershoot) { 276 if (!SupportsHostWindowResize()) 277 return; 278 279 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 280 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), +4); 281 282 // The window should be docked at the right edge. 283 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 284 window->GetBoundsInScreen().right()); 285 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 286 } 287 288 // Verifies a window can be dragged and then if a pointer is not quite reaching 289 // the screen edge the window does not get docked and stays in the desktop. 290 TEST_P(DockedWindowResizerTest, AttachRightUndershoot) { 291 if (!SupportsHostWindowResize()) 292 return; 293 294 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 295 // Grabbing at 70px ensures that at least 30% of the window is in screen, 296 // otherwise the window would be adjusted in 297 // WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded. 298 const int kGrabOffsetX = 70; 299 const int kUndershootBy = 1; 300 DragVerticallyAndRelativeToEdge(DOCKED_EDGE_RIGHT, 301 window.get(), 302 -kUndershootBy, test_panels() ? -100 : 20, 303 kGrabOffsetX, 5); 304 305 // The window right should be past the screen edge but not docked. 306 // Initial touch point is 70px to the right which helps to find where the edge 307 // should be. 308 EXPECT_EQ(window->GetRootWindow()->bounds().right() + 309 window->bounds().width() - kGrabOffsetX - kUndershootBy - 1, 310 window->GetBoundsInScreen().right()); 311 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 312 window->parent()->id()); 313 } 314 315 // Verifies a window can be dragged and attached to the dock. 316 TEST_P(DockedWindowResizerTest, AttachLeftPrecise) { 317 if (!SupportsHostWindowResize()) 318 return; 319 320 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 321 DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 0); 322 323 // The window should be docked at the left edge. 324 EXPECT_EQ(window->GetRootWindow()->bounds().x(), 325 window->GetBoundsInScreen().x()); 326 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 327 } 328 329 // Verifies a window can be dragged and attached to the dock 330 // even if pointer overshoots the screen edge by a few pixels (sticky edge) 331 TEST_P(DockedWindowResizerTest, AttachLeftOvershoot) { 332 if (!SupportsHostWindowResize()) 333 return; 334 335 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 336 DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), -4); 337 338 // The window should be docked at the left edge. 339 EXPECT_EQ(window->GetRootWindow()->bounds().x(), 340 window->GetBoundsInScreen().x()); 341 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 342 } 343 344 // Verifies a window can be dragged and then if a pointer is not quite reaching 345 // the screen edge the window does not get docked and stays in the desktop. 346 TEST_P(DockedWindowResizerTest, AttachLeftUndershoot) { 347 if (!SupportsHostWindowResize()) 348 return; 349 350 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 351 gfx::Rect initial_bounds(window->bounds()); 352 DragRelativeToEdge(DOCKED_EDGE_LEFT, window.get(), 1); 353 354 // The window should be crossing the screen edge but not docked. 355 int expected_x = initial_bounds.x() - initial_location_in_parent().x() + 1; 356 EXPECT_EQ(expected_x, window->GetBoundsInScreen().x()); 357 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 358 window->parent()->id()); 359 } 360 361 // Dock on the right side, change shelf alignment, check that windows move to 362 // the opposite side. 363 TEST_P(DockedWindowResizerTest, AttachRightChangeShelf) { 364 if (!SupportsHostWindowResize()) 365 return; 366 367 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 368 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); 369 370 // The window should be docked at the right edge. 371 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 372 window->GetBoundsInScreen().right()); 373 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 374 375 // set launcher shelf to be aligned on the right 376 ash::Shell* shell = ash::Shell::GetInstance(); 377 shell->SetShelfAlignment(SHELF_ALIGNMENT_RIGHT, 378 shell->GetPrimaryRootWindow()); 379 // The window should have moved and get attached to the left dock. 380 EXPECT_EQ(window->GetRootWindow()->bounds().x(), 381 window->GetBoundsInScreen().x()); 382 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 383 384 // set launcher shelf to be aligned on the left 385 shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, 386 shell->GetPrimaryRootWindow()); 387 // The window should have moved and get attached 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 // set launcher shelf to be aligned at the bottom 393 shell->SetShelfAlignment(SHELF_ALIGNMENT_BOTTOM, 394 shell->GetPrimaryRootWindow()); 395 // The window should stay in the right edge. 396 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 397 window->GetBoundsInScreen().right()); 398 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 399 } 400 401 // Dock on the right side, try to undock, then drag more to really undock 402 TEST_P(DockedWindowResizerTest, AttachTryDetach) { 403 if (!SupportsHostWindowResize()) 404 return; 405 406 scoped_ptr<aura::Window> window(CreateTestWindow( 407 gfx::Rect(0, 0, ideal_width() + 10, 201))); 408 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); 409 410 // The window should be docked at the right edge. 411 // Its width should shrink to ideal width. 412 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 413 window->GetBoundsInScreen().right()); 414 EXPECT_EQ(ideal_width(), window->GetBoundsInScreen().width()); 415 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 416 417 // Try to detach by dragging left less than kSnapToDockDistance. 418 // The window should stay docked. 419 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin( 420 window.get(), 10, 0)); 421 DragMove(-4, -10); 422 // Release the mouse and the window should be still attached to the dock. 423 DragEnd(); 424 425 // The window should be still attached to the right edge. 426 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 427 window->GetBoundsInScreen().right()); 428 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 429 430 // Try to detach by dragging left by kSnapToDockDistance or more. 431 // The window should get undocked. 432 const int left_edge = window->bounds().x(); 433 ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); 434 DragMove(-32, -10); 435 // Release the mouse and the window should be no longer attached to the dock. 436 DragEnd(); 437 438 // The window should be floating on the desktop again and moved to the left. 439 EXPECT_EQ(left_edge - 32, window->GetBoundsInScreen().x()); 440 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 441 window->parent()->id()); 442 } 443 444 // Minimize a docked window, then restore it and check that it is still docked. 445 TEST_P(DockedWindowResizerTest, AttachMinimizeRestore) { 446 if (!SupportsHostWindowResize()) 447 return; 448 449 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 450 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); 451 452 // The window should be docked at the right edge. 453 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 454 window->GetBoundsInScreen().right()); 455 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 456 457 wm::WindowState* window_state = wm::GetWindowState(window.get()); 458 // Minimize the window, it should be hidden. 459 window_state->Minimize(); 460 RunAllPendingInMessageLoop(); 461 EXPECT_FALSE(window->IsVisible()); 462 EXPECT_TRUE(window_state->IsMinimized()); 463 // Restore the window; window should be visible. 464 window_state->Restore(); 465 RunAllPendingInMessageLoop(); 466 EXPECT_TRUE(window->IsVisible()); 467 EXPECT_TRUE(window_state->IsNormalShowState()); 468 } 469 470 // Maximize a docked window and check that it is maximized and no longer docked. 471 TEST_P(DockedWindowResizerTest, AttachMaximize) { 472 if (!SupportsHostWindowResize()) 473 return; 474 475 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 476 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); 477 478 // The window should be docked at the right edge. 479 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 480 window->GetBoundsInScreen().right()); 481 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 482 483 wm::WindowState* window_state = wm::GetWindowState(window.get()); 484 // Maximize the window, it should get undocked and maximized in a desktop. 485 window_state->Maximize(); 486 RunAllPendingInMessageLoop(); 487 EXPECT_TRUE(window->IsVisible()); 488 EXPECT_TRUE(window_state->IsMaximized()); 489 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); 490 } 491 492 // Dock two windows, undock one, check that the other one is still docked. 493 TEST_P(DockedWindowResizerTest, AttachTwoWindows) { 494 if (!SupportsHostWindowResize()) 495 return; 496 497 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 498 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 499 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 500 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 50); 501 502 // Both windows should be docked at the right edge. 503 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 504 w1->GetBoundsInScreen().right()); 505 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 506 507 EXPECT_EQ(w2->GetRootWindow()->bounds().right(), 508 w2->GetBoundsInScreen().right()); 509 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 510 511 // Detach by dragging left (should get undocked). 512 const int left_edge = w2->bounds().x(); 513 ASSERT_NO_FATAL_FAILURE(DragStart(w2.get())); 514 // Drag up as well to avoid attaching panels to launcher shelf. 515 DragMove(-32, -100); 516 // Release the mouse and the window should be no longer attached to the edge. 517 DragEnd(); 518 519 // The first window should be still docked. 520 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 521 w1->GetBoundsInScreen().right()); 522 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 523 524 // The window should be floating on the desktop again and moved to the left. 525 EXPECT_EQ(left_edge - 32, w2->GetBoundsInScreen().x()); 526 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 527 w2->parent()->id()); 528 } 529 530 // Create two windows, dock one and change shelf to auto-hide. 531 TEST_P(DockedWindowResizerTest, AttachOneAutoHideShelf) { 532 if (!SupportsHostWindowResize()) 533 return; 534 535 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 536 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 537 538 // w1 should be docked at the right edge. 539 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 540 w1->GetBoundsInScreen().right()); 541 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 542 543 scoped_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegateAndType( 544 NULL, aura::client::WINDOW_TYPE_NORMAL, 0, gfx::Rect(20, 20, 150, 20))); 545 wm::GetWindowState(w2.get())->Maximize(); 546 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 547 EXPECT_TRUE(wm::GetWindowState(w2.get())->IsMaximized()); 548 549 gfx::Rect work_area = 550 Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area(); 551 DockedWindowLayoutManager* manager = 552 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); 553 554 // Docked window should be centered vertically in the work area. 555 EXPECT_EQ(work_area.CenterPoint().y(), w1->bounds().CenterPoint().y()); 556 // Docked background should extend to the bottom of work area. 557 EXPECT_EQ(work_area.bottom(), manager->docked_bounds().bottom()); 558 559 // set launcher shelf to be aligned on the right 560 ash::Shell* shell = ash::Shell::GetInstance(); 561 shell->SetShelfAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, 562 shell->GetPrimaryRootWindow()); 563 work_area = 564 Shell::GetScreen()->GetDisplayNearestWindow(w1.get()).work_area(); 565 // Docked window should be centered vertically in the work area. 566 EXPECT_EQ(work_area.CenterPoint().y(), w1->bounds().CenterPoint().y()); 567 // Docked background should extend to the bottom of work area. 568 EXPECT_EQ(work_area.bottom(), manager->docked_bounds().bottom()); 569 } 570 571 // Dock one window, try to dock another window on the opposite side (should not 572 // dock). 573 TEST_P(DockedWindowResizerTest, AttachOnTwoSides) { 574 if (!SupportsHostWindowResize()) 575 return; 576 577 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 578 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 579 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 580 gfx::Rect initial_bounds(w2->bounds()); 581 DragToVerticalPositionAndToEdge(DOCKED_EDGE_LEFT, w2.get(), 50); 582 583 // The first window should be docked at the right edge. 584 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 585 w1->GetBoundsInScreen().right()); 586 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 587 588 // The second window should be near the left edge but not snapped. 589 // Normal window will get side-maximized while panels will not. 590 int expected_x = test_panels() ? 591 (initial_bounds.x() - initial_location_in_parent().x()) : 0; 592 EXPECT_EQ(expected_x, w2->GetBoundsInScreen().x()); 593 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 594 } 595 596 // Tests that reverting a drag restores docked state if a window was docked. 597 TEST_P(DockedWindowResizerTest, RevertDragRestoresAttachment) { 598 if (!SupportsHostWindowResize()) 599 return; 600 601 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 602 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); 603 604 // The window should be docked at the right edge. 605 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 606 window->GetBoundsInScreen().right()); 607 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 608 609 // Drag the window out but revert the drag 610 ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); 611 DragMove(-50, 0); 612 DragRevert(); 613 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 614 615 // Detach window. 616 ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); 617 DragMove(-50, 0); 618 DragEnd(); 619 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 620 window->parent()->id()); 621 } 622 623 // Tests that reverting drag restores undocked state if a window was not docked. 624 TEST_P(DockedWindowResizerTest, RevertDockedDragRevertsAttachment) { 625 if (!SupportsHostWindowResize()) 626 return; 627 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 628 int previous_container_id = window->parent()->id(); 629 // Drag the window out but revert the drag 630 ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); 631 DragMove(-50 - window->bounds().x(), 50 - window->bounds().y()); 632 EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); 633 DragRevert(); 634 EXPECT_EQ(previous_container_id, window->parent()->id()); 635 } 636 637 // Move a docked window to the second display 638 TEST_P(DockedWindowResizerTest, DragAcrossDisplays) { 639 if (!SupportsMultipleDisplays()) 640 return; 641 642 UpdateDisplay("800x800,800x800"); 643 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 644 EXPECT_EQ(2, static_cast<int>(root_windows.size())); 645 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 646 gfx::Rect initial_bounds = window->GetBoundsInScreen(); 647 EXPECT_EQ(root_windows[0], window->GetRootWindow()); 648 649 DragRelativeToEdge(DOCKED_EDGE_RIGHT, window.get(), 0); 650 // The window should be docked at the right edge. 651 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 652 window->GetBoundsInScreen().right()); 653 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 654 655 // Try dragging to the right - enough to get it peeking at the other screen 656 // but not enough to land in the other screen. 657 // The window should stay on the left screen. 658 ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); 659 DragMove(100, 0); 660 EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); 661 DragEnd(); 662 EXPECT_EQ(window->GetRootWindow()->bounds().right(), 663 window->GetBoundsInScreen().right()); 664 EXPECT_EQ(internal::kShellWindowId_DockedContainer, 665 window->parent()->id()); 666 EXPECT_EQ(root_windows[0], window->GetRootWindow()); 667 668 // Undock and move to the right - enough to get the mouse pointer past the 669 // edge of the screen and into the second screen. The window should now be 670 // in the second screen and not docked. 671 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin( 672 window.get(), 673 window->bounds().width()/2 + 10, 674 0)); 675 DragMove(window->bounds().width()/2 - 5, 0); 676 EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); 677 DragEnd(); 678 EXPECT_NE(window->GetRootWindow()->bounds().right(), 679 window->GetBoundsInScreen().right()); 680 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 681 window->parent()->id()); 682 EXPECT_EQ(root_windows[1], window->GetRootWindow()); 683 684 // Keep dragging it to the right until its left edge touches the screen edge. 685 // The window should now be in the second screen and not docked. 686 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin( 687 window.get(), 688 window->bounds().width()/2 + 10, 689 0)); 690 DragMove(window->GetRootWindow()->GetBoundsInScreen().x() - 691 window->GetBoundsInScreen().x(), 692 0); 693 EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); 694 DragEnd(); 695 EXPECT_EQ(window->GetRootWindow()->GetBoundsInScreen().x(), 696 window->GetBoundsInScreen().x()); 697 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); 698 EXPECT_EQ(root_windows[1], window->GetRootWindow()); 699 } 700 701 // Dock two windows, undock one. 702 // Test the docked windows area size and default container resizing. 703 TEST_P(DockedWindowResizerTest, AttachTwoWindowsDetachOne) { 704 if (!SupportsHostWindowResize()) 705 return; 706 UpdateDisplay("600x600"); 707 708 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 709 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201))); 710 // Work area should cover the whole screen. 711 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), 712 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 713 714 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 715 // A window should be docked at the right edge. 716 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 717 w1->GetBoundsInScreen().right()); 718 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 719 DockedWindowLayoutManager* manager = 720 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); 721 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 722 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 723 724 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100); 725 // Both windows should now be docked at the right edge. 726 EXPECT_EQ(w2->GetRootWindow()->bounds().right(), 727 w2->GetBoundsInScreen().right()); 728 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 729 // Dock width should be set to a wider window. 730 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 731 EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()), 732 docked_width(manager)); 733 734 // Try to detach by dragging left a bit (should not get undocked). 735 // This would normally detach a single docked window but since we have another 736 // window and the mouse pointer does not leave the dock area the window 737 // should stay docked. 738 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 60, 0)); 739 // Drag up as well as left to avoid attaching panels to launcher shelf. 740 DragMove(-40, -40); 741 // Release the mouse and the window should be still attached to the edge. 742 DragEnd(); 743 744 // The first window should be still docked. 745 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 746 w1->GetBoundsInScreen().right()); 747 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 748 749 // The second window should be still docked. 750 EXPECT_EQ(w2->GetRootWindow()->bounds().right(), 751 w2->GetBoundsInScreen().right()); 752 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 753 754 // Detach by dragging left more (should get undocked). 755 const int left_edge = w2->bounds().x(); 756 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin( 757 w2.get(), 758 w2->bounds().width()/2 + 10, 759 0)); 760 // Drag up as well to avoid attaching panels to launcher shelf. 761 const int drag_x = -(w2->bounds().width()/2 + 20); 762 DragMove(drag_x, -100); 763 // Release the mouse and the window should be no longer attached to the edge. 764 DragEnd(); 765 766 // The second window should be floating on the desktop again. 767 EXPECT_EQ(left_edge + drag_x, w2->bounds().x()); 768 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 769 // Dock width should be set to remaining single docked window. 770 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 771 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 772 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 773 } 774 775 // Dock one of the windows. Maximize other testing desktop resizing. 776 TEST_P(DockedWindowResizerTest, AttachWindowMaximizeOther) { 777 if (!SupportsHostWindowResize()) 778 return; 779 780 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 781 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201))); 782 // Work area should cover the whole screen. 783 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), 784 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 785 786 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 787 // A window should be docked at the right edge. 788 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 789 w1->GetBoundsInScreen().right()); 790 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 791 DockedWindowLayoutManager* manager = 792 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); 793 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 794 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 795 796 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 25, 5)); 797 DragMove(w2->GetRootWindow()->bounds().right() 798 -w2->bounds().width() 799 -(w2->bounds().width()/2 + 20) 800 -w2->bounds().x(), 801 50 - w2->bounds().y()); 802 DragEnd(); 803 // The first window should be still docked. 804 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 805 w1->GetBoundsInScreen().right()); 806 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 807 808 // The second window should be floating on the desktop. 809 EXPECT_EQ(w2->GetRootWindow()->bounds().right() - 810 (w2->bounds().width()/2 + 20), 811 w2->GetBoundsInScreen().right()); 812 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 813 // Dock width should be set to remaining single docked window. 814 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 815 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 816 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 817 // Desktop work area should now shrink. 818 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 819 docked_width(manager) - min_dock_gap(), 820 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 821 822 // Maximize the second window - Maximized area should be shrunk. 823 const gfx::Rect restored_bounds = w2->bounds(); 824 wm::WindowState* w2_state = wm::GetWindowState(w2.get()); 825 w2_state->Maximize(); 826 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 827 docked_width(manager) - min_dock_gap(), 828 w2->bounds().width()); 829 830 // Detach the first window (this should require very little drag). 831 ASSERT_NO_FATAL_FAILURE(DragStart(w1.get())); 832 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 833 DragMove(-35, 10); 834 // Alignment is set to "NONE" when drag starts. 835 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager)); 836 // Release the mouse and the window should be no longer attached to the edge. 837 DragEnd(); 838 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager)); 839 // Dock should get shrunk and desktop should get expanded. 840 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id()); 841 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 842 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager)); 843 EXPECT_EQ(0, docked_width(manager)); 844 // The second window should now get resized and take up the whole screen. 845 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), 846 w2->bounds().width()); 847 848 // Dock the first window to the left edge. 849 // Click at an offset from origin to prevent snapping. 850 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w1.get(), 10, 0)); 851 // Drag left to get pointer touching the screen edge. 852 DragMove(-w1->bounds().x() - 10, 0); 853 // Alignment set to "NONE" during the drag of the window when none are docked. 854 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager)); 855 // Release the mouse and the window should be now attached to the edge. 856 DragEnd(); 857 // Dock should get expanded and desktop should get shrunk. 858 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 859 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); 860 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 861 // Second window should still be in the desktop. 862 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 863 // Maximized window should be shrunk. 864 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 865 docked_width(manager) - min_dock_gap(), 866 w2->bounds().width()); 867 868 // Unmaximize the second window. 869 w2_state->Restore(); 870 // Its bounds should get restored. 871 EXPECT_EQ(restored_bounds, w2->bounds()); 872 } 873 874 // Dock one window. Test the sticky behavior near screen or desktop edge. 875 TEST_P(DockedWindowResizerTest, AttachOneTestSticky) { 876 if (!SupportsHostWindowResize()) 877 return; 878 879 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 880 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201))); 881 // Work area should cover the whole screen. 882 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), 883 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 884 885 DragToVerticalPositionAndToEdge(DOCKED_EDGE_LEFT, w1.get(), 20); 886 // A window should be docked at the left edge. 887 EXPECT_EQ(w1->GetRootWindow()->bounds().x(), 888 w1->GetBoundsInScreen().x()); 889 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 890 DockedWindowLayoutManager* manager = 891 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); 892 // The first window should be docked. 893 EXPECT_EQ(w1->GetRootWindow()->bounds().x(), 894 w1->GetBoundsInScreen().x()); 895 // Dock width should be set to that of a single docked window. 896 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 897 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); 898 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 899 900 // Position second window in the desktop 20px to the right of the docked w1. 901 DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_LEFT, 902 w2.get(), 903 20 + 25 - 904 min_dock_gap(), 905 50); 906 // The second window should be floating on the desktop. 907 EXPECT_EQ(w2->GetRootWindow()->bounds().x() + (w1->bounds().right() + 20), 908 w2->GetBoundsInScreen().x()); 909 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 910 // Dock width should be set to that of a single docked window. 911 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 912 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); 913 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 914 915 // Drag w2 almost to the dock, the mouse pointer not quite reaching the dock. 916 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 10, 0)); 917 DragMove(1 + docked_width(manager) - w2->bounds().x(), 0); 918 // Alignment set to "LEFT" during the drag because dock has a window in it. 919 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); 920 // Release the mouse and the window should not be attached to the edge. 921 DragEnd(); 922 // Dock should still have only one window in it. 923 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); 924 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 925 // The second window should still be in the desktop. 926 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 927 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 928 929 // Drag w2 by a bit more - it should resist the drag (stuck edges) 930 int start_x = w2->bounds().x(); 931 ASSERT_NO_FATAL_FAILURE(DragStartAtOffsetFromWindowOrigin(w2.get(), 100, 5)); 932 DragMove(-2, 0); 933 // Window should not actually move. 934 EXPECT_EQ(start_x, w2->bounds().x()); 935 // Alignment set to "LEFT" during the drag because dock has a window in it. 936 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); 937 // Release the mouse and the window should not be attached to the edge. 938 DragEnd(); 939 // Window should be still where it was before the last drag started. 940 EXPECT_EQ(start_x, w2->bounds().x()); 941 // Dock should still have only one window in it 942 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); 943 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 944 // The second window should still be in the desktop 945 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 946 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 947 948 // Drag w2 by more than the stuck threshold and drop it into the dock. 949 ASSERT_NO_FATAL_FAILURE(DragStart(w2.get())); 950 DragMove(-100, 0); 951 // Window should actually move. 952 EXPECT_NE(start_x, w2->bounds().x()); 953 // Alignment set to "LEFT" during the drag because dock has a window in it. 954 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); 955 // Release the mouse and the window should be attached to the edge. 956 DragEnd(); 957 // Both windows are docked now. 958 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 959 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 960 // Dock should get expanded and desktop should get shrunk. 961 EXPECT_EQ(DOCKED_ALIGNMENT_LEFT, docked_alignment(manager)); 962 EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()), 963 docked_width(manager)); 964 // Desktop work area should now shrink by dock width. 965 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 966 docked_width(manager) - min_dock_gap(), 967 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 968 } 969 970 // Dock two windows, resize one. 971 // Test the docked windows area size and remaining desktop resizing. 972 TEST_P(DockedWindowResizerTest, ResizeOneOfTwoWindows) { 973 if (!SupportsHostWindowResize()) 974 return; 975 976 // Wider display to start since panels are limited to half the display width. 977 UpdateDisplay("1000x600"); 978 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 979 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201))); 980 // Work area should cover the whole screen. 981 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width(), 982 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 983 984 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 985 // A window should be docked at the right edge. 986 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 987 w1->GetBoundsInScreen().right()); 988 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 989 DockedWindowLayoutManager* manager = 990 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); 991 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 992 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 993 994 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100); 995 // Both windows should now be docked at the right edge. 996 EXPECT_EQ(w2->GetRootWindow()->bounds().right(), 997 w2->GetBoundsInScreen().right()); 998 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 999 // Dock width should be set to a wider window. 1000 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1001 EXPECT_EQ(std::max(w1->bounds().width(), w2->bounds().width()), 1002 docked_width(manager)); 1003 1004 // Resize the first window left by a bit and test that the dock expands. 1005 int previous_width = w1->bounds().width(); 1006 const int kResizeSpan1 = 30; 1007 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(), 1008 0, 20, 1009 HTLEFT)); 1010 DragMove(-kResizeSpan1, 0); 1011 // Alignment set to "RIGHT" during the drag because dock has a window in it. 1012 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1013 // Release the mouse and the window should be attached to the edge. 1014 DragEnd(); 1015 // Dock should still have both windows in it. 1016 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 1017 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 1018 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1019 // w1 is now wider than before. The dock should expand and be as wide as w1. 1020 EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width()); 1021 // Both windows should get resized since they both don't have min/max size. 1022 EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); 1023 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 1024 // Desktop work area should shrink. 1025 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 1026 docked_width(manager) - min_dock_gap(), 1027 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 1028 1029 // Resize the first window left by more than the dock maximum width. 1030 // This should cause the window width to be restricted by maximum dock width. 1031 previous_width = w1->bounds().width(); 1032 const int kResizeSpan2 = 250; 1033 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(), 1034 0, 20, 1035 HTLEFT)); 1036 DragMove(-kResizeSpan2, 0); 1037 // Alignment set to "RIGHT" during the drag because dock has a window in it. 1038 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1039 // Release the mouse and the window should be attached to the edge. 1040 DragEnd(); 1041 // Dock should still have both windows in it. 1042 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 1043 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 1044 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1045 // w1 is now as wide as the maximum dock width and the dock should get 1046 // resized to the maximum width. 1047 EXPECT_EQ(max_width(), w1->bounds().width()); 1048 // Both windows should get resized since they both don't have min/max size. 1049 EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); 1050 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 1051 // Desktop work area should shrink. 1052 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 1053 docked_width(manager) - min_dock_gap(), 1054 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 1055 1056 // Resize the first window right to get it completely inside the docked area. 1057 previous_width = w1->bounds().width(); 1058 const int kResizeSpan3 = 100; 1059 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(), 1060 0, 20, 1061 HTLEFT)); 1062 DragMove(kResizeSpan3, 0); 1063 // Alignment set to "RIGHT" during the drag because dock has a window in it. 1064 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1065 // Release the mouse and the window should be docked. 1066 DragEnd(); 1067 // Dock should still have both windows in it. 1068 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 1069 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 1070 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1071 // w1 should be narrower than before by the length of the drag. 1072 EXPECT_EQ(previous_width - kResizeSpan3, w1->bounds().width()); 1073 // Both windows should get resized since they both don't have min/max size. 1074 EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); 1075 // The dock should be as wide as w1 or w2. 1076 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 1077 // Desktop work area should shrink. 1078 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w2.get()).width() - 1079 docked_width(manager) - min_dock_gap(), 1080 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w2.get()).width()); 1081 1082 // Resize the first window left to be overhang again. 1083 previous_width = w1->bounds().width(); 1084 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(), 1085 0, 20, 1086 HTLEFT)); 1087 DragMove(-kResizeSpan3, 0); 1088 DragEnd(); 1089 EXPECT_EQ(previous_width + kResizeSpan3, w1->bounds().width()); 1090 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 1091 // Docked area should be as wide as possible (maximum) and same as w1. 1092 EXPECT_EQ(max_width(), docked_width(manager)); 1093 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 1094 1095 // Undock the first window. Docked area should shrink to its ideal size. 1096 ASSERT_NO_FATAL_FAILURE(DragStart(w1.get())); 1097 // Drag up as well to avoid attaching panels to launcher shelf. 1098 DragMove(-(400 - 210), -100); 1099 // Alignment set to "RIGHT" since we have another window docked. 1100 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1101 // Release the mouse and the window should be no longer attached to the edge. 1102 DragEnd(); 1103 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id()); 1104 // Dock should be as wide as w2 (and same as ideal width). 1105 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1106 EXPECT_EQ(ideal_width(), docked_width(manager)); 1107 EXPECT_EQ(w2->bounds().width(), docked_width(manager)); 1108 // The second window should be still docked. 1109 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 1110 // Desktop work area should be inset. 1111 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w1.get()).width() - 1112 docked_width(manager) - min_dock_gap(), 1113 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w1.get()).width()); 1114 } 1115 1116 // Dock a window, resize it and test that undocking it preserves the width. 1117 TEST_P(DockedWindowResizerTest, ResizingKeepsWidth) { 1118 if (!SupportsHostWindowResize()) 1119 return; 1120 1121 // Wider display to start since panels are limited to half the display width. 1122 UpdateDisplay("1000x600"); 1123 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 1124 1125 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 1126 // A window should be docked at the right edge. 1127 EXPECT_EQ(w1->GetRootWindow()->GetBoundsInScreen().right(), 1128 w1->GetBoundsInScreen().right()); 1129 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 1130 DockedWindowLayoutManager* manager = 1131 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); 1132 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1133 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 1134 1135 // Resize the window left by a bit and test that the dock expands. 1136 int previous_width = w1->bounds().width(); 1137 const int kResizeSpan1 = 30; 1138 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(), 1139 0, 20, 1140 HTLEFT)); 1141 DragMove(-kResizeSpan1, 0); 1142 // Alignment set to "RIGHT" during the drag because the only docked window 1143 // is being dragged. 1144 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager)); 1145 // Release the mouse and the window should be attached to the edge. 1146 DragEnd(); 1147 // A window should get docked. 1148 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 1149 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1150 // w1 is now wider and the dock should expand to be as wide as w1. 1151 EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width()); 1152 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 1153 1154 // Undock by dragging almost to the left edge. 1155 DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_LEFT, w1.get(), 100, 20); 1156 // Width should be preserved. 1157 EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width()); 1158 // Height should be restored to what it was originally. 1159 EXPECT_EQ(201, w1->bounds().height()); 1160 1161 // Dock again. 1162 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 1163 // Width should be reset to initial ideal width (25px). 1164 EXPECT_EQ(ideal_width(), w1->bounds().width()); 1165 1166 // Undock again by dragging left. 1167 DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_LEFT, w1.get(), 100, 20); 1168 // Width should be reset to what it was last time the window was not docked. 1169 EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width()); 1170 // Height should be restored to what it was originally. 1171 EXPECT_EQ(201, w1->bounds().height()); 1172 } 1173 1174 // Dock two windows, resize one. Test the docked windows area size. 1175 TEST_P(DockedWindowResizerTest, ResizeTwoWindows) { 1176 if (!SupportsHostWindowResize()) 1177 return; 1178 1179 // Wider display to start since panels are limited to half the display width. 1180 UpdateDisplay("1000x600"); 1181 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 1182 scoped_ptr<aura::Window> w2(CreateTestWindow(gfx::Rect(0, 0, 210, 201))); 1183 1184 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 1185 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100); 1186 // Both windows should now be docked at the right edge. 1187 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 1188 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 1189 // Dock width should be set to ideal width. 1190 DockedWindowLayoutManager* manager = 1191 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); 1192 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1193 EXPECT_EQ(ideal_width(), docked_width(manager)); 1194 1195 // Resize the first window left by a bit and test that the dock expands. 1196 int previous_width = w1->bounds().width(); 1197 const int kResizeSpan1 = 30; 1198 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(), 1199 0, 20, 1200 HTLEFT)); 1201 DragMove(-kResizeSpan1, 0); 1202 DragEnd(); 1203 // w1 is now wider than before. 1204 EXPECT_EQ(previous_width + kResizeSpan1, w1->bounds().width()); 1205 // Both windows should get resized since they both don't have min/max size. 1206 EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); 1207 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 1208 1209 // Resize the second window left by a bit more and test that the dock expands. 1210 previous_width = w2->bounds().width(); 1211 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w2.get(), 1212 0, 20, 1213 HTLEFT)); 1214 DragMove(-kResizeSpan1, 0); 1215 DragEnd(); 1216 // Only w2 should get wider since w1 was resized by a user. 1217 EXPECT_EQ(previous_width + kResizeSpan1, w2->bounds().width()); 1218 // w1 should stays same size as before since it was resized by a user. 1219 EXPECT_EQ(previous_width, w1->bounds().width()); 1220 EXPECT_EQ(w2->bounds().width(), docked_width(manager)); 1221 1222 // Undock w2 and then dock it back. 1223 DragToVerticalPositionRelativeToEdge(DOCKED_EDGE_RIGHT, w2.get(), -400, 100); 1224 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w2->parent()->id()); 1225 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w2.get(), 100); 1226 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w2->parent()->id()); 1227 // w2 should become same width as w1. 1228 EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); 1229 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 1230 1231 // Make w1 even wider. 1232 ASSERT_NO_FATAL_FAILURE(ResizeStartAtOffsetFromWindowOrigin(w1.get(), 1233 0, 20, 1234 HTLEFT)); 1235 DragMove(-kResizeSpan1, 0); 1236 DragEnd(); 1237 // Making w1 wider should make both windows wider since w2 no longer remembers 1238 // user width. 1239 EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); 1240 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 1241 } 1242 1243 // Tests that dragging a window down to shelf attaches a panel but does not 1244 // attach a regular window. 1245 TEST_P(DockedWindowResizerTest, DragToShelf) { 1246 if (!SupportsHostWindowResize()) 1247 return; 1248 1249 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 1250 // Work area should cover the whole screen. 1251 EXPECT_EQ(ScreenAsh::GetDisplayBoundsInParent(w1.get()).width(), 1252 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w1.get()).width()); 1253 1254 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 1255 // A window should be docked at the right edge. 1256 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 1257 w1->GetBoundsInScreen().right()); 1258 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 1259 DockedWindowLayoutManager* manager = 1260 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); 1261 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1262 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 1263 1264 // Detach and drag down to shelf. 1265 ASSERT_NO_FATAL_FAILURE(DragStart(w1.get())); 1266 DragMove(-40, 0); 1267 // Alignment is set to "NONE" when drag starts. 1268 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager)); 1269 // Release the mouse and the window should be no longer attached to the edge. 1270 DragEnd(); 1271 EXPECT_EQ(DOCKED_ALIGNMENT_NONE, docked_alignment(manager)); 1272 1273 // Drag down almost to shelf. A panel will snap, a regular window won't. 1274 ShelfWidget* shelf = Launcher::ForPrimaryDisplay()->shelf_widget(); 1275 const int shelf_y = shelf->GetWindowBoundsInScreen().y(); 1276 const int kDistanceFromShelf = 10; 1277 ASSERT_NO_FATAL_FAILURE(DragStart(w1.get())); 1278 DragMove(0, -kDistanceFromShelf + shelf_y - w1->bounds().bottom()); 1279 DragEnd(); 1280 if (test_panels()) { 1281 // The panel should be touching the shelf and attached. 1282 EXPECT_EQ(shelf_y, w1->bounds().bottom()); 1283 EXPECT_TRUE(wm::GetWindowState(w1.get())->panel_attached()); 1284 } else { 1285 // The window should not be touching the shelf. 1286 EXPECT_EQ(shelf_y - kDistanceFromShelf, w1->bounds().bottom()); 1287 } 1288 } 1289 1290 // Tests that docking and undocking a |window| with a transient child properly 1291 // maintains the parent of that transient child to be the same as the |window|. 1292 TEST_P(DockedWindowResizerTest, DragWindowWithTransientChild) { 1293 if (!SupportsHostWindowResize()) 1294 return; 1295 1296 // Create a window with a transient child. 1297 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 1298 scoped_ptr<aura::Window> child(CreateTestWindowInShellWithDelegateAndType( 1299 NULL, aura::client::WINDOW_TYPE_NORMAL, 0, gfx::Rect(20, 20, 150, 20))); 1300 window->AddTransientChild(child.get()); 1301 if (window->parent() != child->parent()) 1302 window->parent()->AddChild(child.get()); 1303 EXPECT_EQ(window.get(), child->transient_parent()); 1304 1305 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, window.get(), 20); 1306 1307 // A window should be docked at the right edge. 1308 EXPECT_EQ(internal::kShellWindowId_DockedContainer, window->parent()->id()); 1309 EXPECT_EQ(internal::kShellWindowId_DockedContainer, child->parent()->id()); 1310 1311 // Drag the child - it should move freely and stay where it is dragged. 1312 ASSERT_NO_FATAL_FAILURE(DragStart(child.get())); 1313 DragMove(500, 20); 1314 DragEnd(); 1315 EXPECT_EQ(gfx::Point(20 + 500, 20 + 20).ToString(), 1316 child->GetBoundsInScreen().origin().ToString()); 1317 1318 // Undock the window by dragging left. 1319 ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); 1320 DragMove(-32, -10); 1321 DragEnd(); 1322 1323 // The window should be undocked and the transient child should be reparented. 1324 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); 1325 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, child->parent()->id()); 1326 // The child should not have moved. 1327 EXPECT_EQ(gfx::Point(20 + 500, 20 + 20).ToString(), 1328 child->GetBoundsInScreen().origin().ToString()); 1329 } 1330 1331 // Tests that reparenting windows during the drag does not affect system modal 1332 // windows that are transient children of the dragged windows. 1333 TEST_P(DockedWindowResizerTest, DragWindowWithModalTransientChild) { 1334 if (!SupportsHostWindowResize()) 1335 return; 1336 1337 // Create a window. 1338 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 1339 gfx::Rect bounds(window->bounds()); 1340 1341 // Start dragging the window. 1342 ASSERT_NO_FATAL_FAILURE(DragStart(window.get())); 1343 gfx::Vector2d move_vector(40, test_panels() ? -60 : 60); 1344 DragMove(move_vector.x(), move_vector.y()); 1345 EXPECT_EQ(CorrectContainerIdDuringDrag(), window->parent()->id()); 1346 1347 // While still dragging create a modal window and make it a transient child of 1348 // the |window|. 1349 scoped_ptr<aura::Window> child(CreateModalWindow(gfx::Rect(20, 20, 150, 20))); 1350 window->AddTransientChild(child.get()); 1351 EXPECT_EQ(window.get(), child->transient_parent()); 1352 EXPECT_EQ(internal::kShellWindowId_SystemModalContainer, 1353 child->parent()->id()); 1354 1355 // End the drag, the |window| should have moved (if it is a panel it will 1356 // no longer be attached to the shelf since we dragged it above). 1357 DragEnd(); 1358 bounds.Offset(move_vector); 1359 EXPECT_EQ(bounds.ToString(), window->GetBoundsInScreen().ToString()); 1360 1361 // The original |window| should be in the default container (not docked or 1362 // attached). 1363 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id()); 1364 // The transient |child| should still be in system modal container. 1365 EXPECT_EQ(internal::kShellWindowId_SystemModalContainer, 1366 child->parent()->id()); 1367 // The |child| should not have moved. 1368 EXPECT_EQ(gfx::Point(20, 20).ToString(), 1369 child->GetBoundsInScreen().origin().ToString()); 1370 // The |child| should still be a transient child of |window|. 1371 EXPECT_EQ(window.get(), child->transient_parent()); 1372 } 1373 1374 // Tests that side snapping a window undocks it, closes the dock and then snaps. 1375 TEST_P(DockedWindowResizerTest, SideSnapDocked) { 1376 if (!SupportsHostWindowResize() || test_panels()) 1377 return; 1378 1379 scoped_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 201, 201))); 1380 wm::WindowState* window_state = wm::GetWindowState(w1.get()); 1381 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 1382 // A window should be docked at the right edge. 1383 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 1384 w1->GetBoundsInScreen().right()); 1385 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 1386 DockedWindowLayoutManager* manager = 1387 static_cast<DockedWindowLayoutManager*>(w1->parent()->layout_manager()); 1388 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1389 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 1390 EXPECT_TRUE(window_state->IsDocked()); 1391 EXPECT_FALSE(window_state->IsSnapped()); 1392 1393 // Side snap at right edge. 1394 internal::SnapSizer::SnapWindow(window_state, 1395 internal::SnapSizer::RIGHT_EDGE); 1396 // The window should be snapped at the right edge and the dock should close. 1397 gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(w1.get())); 1398 EXPECT_EQ(0, docked_width(manager)); 1399 EXPECT_EQ(work_area.height(), w1->bounds().height()); 1400 EXPECT_EQ(work_area.right(), w1->bounds().right()); 1401 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id()); 1402 EXPECT_FALSE(window_state->IsDocked()); 1403 EXPECT_TRUE(window_state->IsSnapped()); 1404 1405 // Dock again. 1406 DragToVerticalPositionAndToEdge(DOCKED_EDGE_RIGHT, w1.get(), 20); 1407 // A window should be docked at the right edge. 1408 EXPECT_EQ(w1->GetRootWindow()->bounds().right(), 1409 w1->GetBoundsInScreen().right()); 1410 EXPECT_EQ(internal::kShellWindowId_DockedContainer, w1->parent()->id()); 1411 EXPECT_EQ(DOCKED_ALIGNMENT_RIGHT, docked_alignment(manager)); 1412 EXPECT_EQ(w1->bounds().width(), docked_width(manager)); 1413 EXPECT_TRUE(window_state->IsDocked()); 1414 EXPECT_FALSE(window_state->IsSnapped()); 1415 1416 // Side snap at left edge. 1417 internal::SnapSizer::SnapWindow(window_state, 1418 internal::SnapSizer::LEFT_EDGE); 1419 // The window should be snapped at the right edge and the dock should close. 1420 EXPECT_EQ(work_area.ToString(), 1421 ScreenAsh::GetDisplayWorkAreaBoundsInParent(w1.get()).ToString()); 1422 EXPECT_EQ(0, docked_width(manager)); 1423 EXPECT_EQ(work_area.height(), w1->bounds().height()); 1424 EXPECT_EQ(work_area.x(), w1->bounds().x()); 1425 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, w1->parent()->id()); 1426 EXPECT_FALSE(window_state->IsDocked()); 1427 EXPECT_TRUE(window_state->IsSnapped()); 1428 } 1429 1430 // Tests run twice - on both panels and normal windows 1431 INSTANTIATE_TEST_CASE_P(NormalOrPanel, 1432 DockedWindowResizerTest, 1433 testing::Values(aura::client::WINDOW_TYPE_NORMAL, 1434 aura::client::WINDOW_TYPE_PANEL)); 1435 } // namespace internal 1436 } // namespace ash 1437