panel_window_resizer_unittest.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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/panels/panel_window_resizer.h" 6 7#include "ash/launcher/launcher.h" 8#include "ash/launcher/launcher_model.h" 9#include "ash/root_window_controller.h" 10#include "ash/shelf/shelf_layout_manager.h" 11#include "ash/shelf/shelf_types.h" 12#include "ash/shelf/shelf_widget.h" 13#include "ash/shell.h" 14#include "ash/shell_window_ids.h" 15#include "ash/test/ash_test_base.h" 16#include "ash/test/cursor_manager_test_api.h" 17#include "ash/test/shell_test_api.h" 18#include "ash/test/test_launcher_delegate.h" 19#include "ash/wm/drag_window_resizer.h" 20#include "ash/wm/panels/panel_layout_manager.h" 21#include "ash/wm/window_settings.h" 22#include "ui/aura/client/aura_constants.h" 23#include "ui/aura/root_window.h" 24#include "ui/base/hit_test.h" 25#include "ui/base/l10n/l10n_util.h" 26#include "ui/base/ui_base_types.h" 27#include "ui/views/widget/widget.h" 28 29namespace ash { 30namespace internal { 31 32class PanelWindowResizerTest : public test::AshTestBase { 33 public: 34 PanelWindowResizerTest() {} 35 virtual ~PanelWindowResizerTest() {} 36 37 virtual void SetUp() OVERRIDE { 38 AshTestBase::SetUp(); 39 UpdateDisplay("600x400"); 40 test::ShellTestApi test_api(Shell::GetInstance()); 41 model_ = test_api.launcher_model(); 42 launcher_delegate_ = test::TestLauncherDelegate::instance(); 43 } 44 45 virtual void TearDown() OVERRIDE { 46 AshTestBase::TearDown(); 47 } 48 49 protected: 50 gfx::Point CalculateDragPoint(const WindowResizer& resizer, 51 int delta_x, 52 int delta_y) const { 53 gfx::Point location = resizer.GetInitialLocation(); 54 location.set_x(location.x() + delta_x); 55 location.set_y(location.y() + delta_y); 56 return location; 57 } 58 59 aura::Window* CreatePanelWindow(const gfx::Rect& bounds) { 60 aura::Window* window = CreateTestWindowInShellWithDelegateAndType( 61 NULL, 62 aura::client::WINDOW_TYPE_PANEL, 63 0, 64 bounds); 65 launcher_delegate_->AddLauncherItem(window); 66 PanelLayoutManager* manager = 67 static_cast<PanelLayoutManager*>( 68 Shell::GetContainer(window->GetRootWindow(), 69 internal::kShellWindowId_PanelContainer)-> 70 layout_manager()); 71 manager->Relayout(); 72 return window; 73 } 74 75 void DragStart(aura::Window* window) { 76 resizer_.reset(CreateWindowResizer( 77 window, 78 window->bounds().origin(), 79 HTCAPTION, 80 aura::client::WINDOW_MOVE_SOURCE_MOUSE).release()); 81 ASSERT_TRUE(resizer_.get()); 82 } 83 84 void DragMove(int dx, int dy) { 85 resizer_->Drag(CalculateDragPoint(*resizer_, dx, dy), 0); 86 } 87 88 void DragEnd() { 89 resizer_->CompleteDrag(0); 90 resizer_.reset(); 91 } 92 93 void DragRevert() { 94 resizer_->RevertDrag(); 95 resizer_.reset(); 96 } 97 98 // Test dragging the panel slightly, then detaching, and then reattaching 99 // dragging out by the vector (dx, dy). 100 void DetachReattachTest(aura::Window* window, int dx, int dy) { 101 EXPECT_TRUE(wm::GetWindowSettings(window)->panel_attached()); 102 aura::RootWindow* root_window = window->GetRootWindow(); 103 EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); 104 DragStart(window); 105 gfx::Rect initial_bounds = window->GetBoundsInScreen(); 106 107 // Drag the panel slightly. The window should still be snapped to the 108 // launcher. 109 DragMove(dx * 5, dy * 5); 110 EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x()); 111 EXPECT_EQ(initial_bounds.y(), window->GetBoundsInScreen().y()); 112 113 // Drag further out and the window should now move to the cursor. 114 DragMove(dx * 100, dy * 100); 115 EXPECT_EQ(initial_bounds.x() + dx * 100, window->GetBoundsInScreen().x()); 116 EXPECT_EQ(initial_bounds.y() + dy * 100, window->GetBoundsInScreen().y()); 117 118 // The panel should be detached when the drag completes. 119 DragEnd(); 120 121 EXPECT_FALSE(wm::GetWindowSettings(window)->panel_attached()); 122 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 123 window->parent()->id()); 124 EXPECT_EQ(root_window, window->GetRootWindow()); 125 126 DragStart(window); 127 // Drag the panel down. 128 DragMove(dx * -95, dy * -95); 129 // Release the mouse and the panel should be reattached. 130 DragEnd(); 131 132 // The panel should be reattached and have snapped to the launcher. 133 EXPECT_TRUE(wm::GetWindowSettings(window)->panel_attached()); 134 EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x()); 135 EXPECT_EQ(initial_bounds.y(), window->GetBoundsInScreen().y()); 136 EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); 137 } 138 139 void TestWindowOrder(const std::vector<aura::Window*>& window_order) { 140 int panel_index = model_->FirstPanelIndex(); 141 EXPECT_EQ((int)(panel_index + window_order.size()), model_->item_count()); 142 for (std::vector<aura::Window*>::const_iterator iter = 143 window_order.begin(); iter != window_order.end(); 144 ++iter, ++panel_index) { 145 LauncherID id = launcher_delegate_->GetIDByWindow(*iter); 146 EXPECT_EQ(id, model_->items()[panel_index].id); 147 } 148 } 149 150 // Test dragging panel window along the shelf and verify that panel icons 151 // are reordered appropriately. 152 void DragAlongShelfReorder(int dx, int dy) { 153 gfx::Rect bounds(0, 0, 201, 201); 154 scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds)); 155 scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds)); 156 std::vector<aura::Window*> window_order_original; 157 std::vector<aura::Window*> window_order_swapped; 158 window_order_original.push_back(w1.get()); 159 window_order_original.push_back(w2.get()); 160 window_order_swapped.push_back(w2.get()); 161 window_order_swapped.push_back(w1.get()); 162 TestWindowOrder(window_order_original); 163 164 // Drag window #2 to the beginning of the shelf. 165 DragStart(w2.get()); 166 DragMove(400 * dx, 400 * dy); 167 TestWindowOrder(window_order_swapped); 168 DragEnd(); 169 170 // Expect swapped window order. 171 TestWindowOrder(window_order_swapped); 172 173 // Drag window #2 back to the end. 174 DragStart(w2.get()); 175 DragMove(-400 * dx, -400 * dy); 176 TestWindowOrder(window_order_original); 177 DragEnd(); 178 179 // Expect original order. 180 TestWindowOrder(window_order_original); 181 } 182 183 private: 184 scoped_ptr<WindowResizer> resizer_; 185 internal::PanelLayoutManager* panel_layout_manager_; 186 LauncherModel* model_; 187 test::TestLauncherDelegate* launcher_delegate_; 188 189 DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTest); 190}; 191 192class PanelWindowResizerTextDirectionTest 193 : public PanelWindowResizerTest, 194 public testing::WithParamInterface<bool> { 195 public: 196 PanelWindowResizerTextDirectionTest() : is_rtl_(GetParam()) {} 197 virtual ~PanelWindowResizerTextDirectionTest() {} 198 199 virtual void SetUp() OVERRIDE { 200 original_locale = l10n_util::GetApplicationLocale(std::string()); 201 if (is_rtl_) 202 base::i18n::SetICUDefaultLocale("he"); 203 PanelWindowResizerTest::SetUp(); 204 ASSERT_EQ(is_rtl_, base::i18n::IsRTL()); 205 } 206 207 virtual void TearDown() OVERRIDE { 208 if (is_rtl_) 209 base::i18n::SetICUDefaultLocale(original_locale); 210 PanelWindowResizerTest::TearDown(); 211 } 212 213 private: 214 bool is_rtl_; 215 std::string original_locale; 216 217 DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTextDirectionTest); 218}; 219 220// Verifies a window can be dragged from the panel and detached and then 221// reattached. 222TEST_F(PanelWindowResizerTest, PanelDetachReattachBottom) { 223 if (!SupportsHostWindowResize()) 224 return; 225 226 scoped_ptr<aura::Window> window( 227 CreatePanelWindow(gfx::Rect(0, 0, 201, 201))); 228 DetachReattachTest(window.get(), 0, -1); 229} 230 231TEST_F(PanelWindowResizerTest, PanelDetachReattachLeft) { 232 if (!SupportsHostWindowResize()) 233 return; 234 235 ash::Shell* shell = ash::Shell::GetInstance(); 236 shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, shell->GetPrimaryRootWindow()); 237 scoped_ptr<aura::Window> window( 238 CreatePanelWindow(gfx::Rect(0, 0, 201, 201))); 239 DetachReattachTest(window.get(), 1, 0); 240} 241 242TEST_F(PanelWindowResizerTest, PanelDetachReattachRight) { 243 if (!SupportsHostWindowResize()) 244 return; 245 246 ash::Shell* shell = ash::Shell::GetInstance(); 247 shell->SetShelfAlignment(SHELF_ALIGNMENT_RIGHT, 248 shell->GetPrimaryRootWindow()); 249 scoped_ptr<aura::Window> window( 250 CreatePanelWindow(gfx::Rect(0, 0, 201, 201))); 251 DetachReattachTest(window.get(), -1, 0); 252} 253 254TEST_F(PanelWindowResizerTest, PanelDetachReattachTop) { 255 if (!SupportsHostWindowResize()) 256 return; 257 258 ash::Shell* shell = ash::Shell::GetInstance(); 259 shell->SetShelfAlignment(SHELF_ALIGNMENT_TOP, shell->GetPrimaryRootWindow()); 260 scoped_ptr<aura::Window> window( 261 CreatePanelWindow(gfx::Rect(0, 0, 201, 201))); 262 DetachReattachTest(window.get(), 0, 1); 263} 264 265TEST_F(PanelWindowResizerTest, PanelDetachReattachMultipleDisplays) { 266 if (!SupportsMultipleDisplays()) 267 return; 268 269 UpdateDisplay("600x400,600x400"); 270 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); 271 scoped_ptr<aura::Window> window( 272 CreatePanelWindow(gfx::Rect(600, 0, 201, 201))); 273 EXPECT_EQ(root_windows[1], window->GetRootWindow()); 274 DetachReattachTest(window.get(), 0, -1); 275} 276 277TEST_F(PanelWindowResizerTest, DetachThenDragAcrossDisplays) { 278 if (!SupportsMultipleDisplays()) 279 return; 280 281 UpdateDisplay("600x400,600x400"); 282 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); 283 scoped_ptr<aura::Window> window( 284 CreatePanelWindow(gfx::Rect(0, 0, 201, 201))); 285 gfx::Rect initial_bounds = window->GetBoundsInScreen(); 286 EXPECT_EQ(root_windows[0], window->GetRootWindow()); 287 DragStart(window.get()); 288 DragMove(0, -100); 289 DragEnd(); 290 EXPECT_EQ(root_windows[0], window->GetRootWindow()); 291 EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x()); 292 EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y()); 293 EXPECT_FALSE(wm::GetWindowSettings(window.get())->panel_attached()); 294 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 295 window->parent()->id()); 296 297 DragStart(window.get()); 298 DragMove(500, 0); 299 DragEnd(); 300 EXPECT_EQ(root_windows[1], window->GetRootWindow()); 301 EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x()); 302 EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y()); 303 EXPECT_FALSE(wm::GetWindowSettings(window.get())->panel_attached()); 304 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 305 window->parent()->id()); 306} 307 308TEST_F(PanelWindowResizerTest, DetachAcrossDisplays) { 309 if (!SupportsMultipleDisplays()) 310 return; 311 312 UpdateDisplay("600x400,600x400"); 313 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); 314 scoped_ptr<aura::Window> window( 315 CreatePanelWindow(gfx::Rect(0, 0, 201, 201))); 316 gfx::Rect initial_bounds = window->GetBoundsInScreen(); 317 EXPECT_EQ(root_windows[0], window->GetRootWindow()); 318 DragStart(window.get()); 319 DragMove(500, -100); 320 DragEnd(); 321 EXPECT_EQ(root_windows[1], window->GetRootWindow()); 322 EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x()); 323 EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y()); 324 EXPECT_FALSE(wm::GetWindowSettings(window.get())->panel_attached()); 325 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 326 window->parent()->id()); 327} 328 329TEST_F(PanelWindowResizerTest, DetachThenAttachToSecondDisplay) { 330 if (!SupportsMultipleDisplays()) 331 return; 332 333 UpdateDisplay("600x400,600x600"); 334 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); 335 scoped_ptr<aura::Window> window( 336 CreatePanelWindow(gfx::Rect(0, 0, 201, 201))); 337 gfx::Rect initial_bounds = window->GetBoundsInScreen(); 338 EXPECT_EQ(root_windows[0], window->GetRootWindow()); 339 340 // Detach the window. 341 DragStart(window.get()); 342 DragMove(0, -100); 343 DragEnd(); 344 EXPECT_EQ(root_windows[0], window->GetRootWindow()); 345 EXPECT_FALSE(wm::GetWindowSettings(window.get())->panel_attached()); 346 347 // Drag the window just above the other display's launcher. 348 DragStart(window.get()); 349 DragMove(500, 295); 350 EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x()); 351 352 // Should stick to other launcher. 353 EXPECT_EQ(initial_bounds.y() + 200, window->GetBoundsInScreen().y()); 354 DragEnd(); 355 356 // When dropped should move to second display's panel container. 357 EXPECT_EQ(root_windows[1], window->GetRootWindow()); 358 EXPECT_TRUE(wm::GetWindowSettings(window.get())->panel_attached()); 359 EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); 360} 361 362TEST_F(PanelWindowResizerTest, AttachToSecondDisplay) { 363 if (!SupportsMultipleDisplays()) 364 return; 365 366 UpdateDisplay("600x400,600x600"); 367 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); 368 scoped_ptr<aura::Window> window( 369 CreatePanelWindow(gfx::Rect(0, 0, 201, 201))); 370 gfx::Rect initial_bounds = window->GetBoundsInScreen(); 371 EXPECT_EQ(root_windows[0], window->GetRootWindow()); 372 373 // Drag the window just above the other display's launcher. 374 DragStart(window.get()); 375 DragMove(500, 195); 376 EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x()); 377 378 // Should stick to other launcher. 379 EXPECT_EQ(initial_bounds.y() + 200, window->GetBoundsInScreen().y()); 380 DragEnd(); 381 382 // When dropped should move to second display's panel container. 383 EXPECT_EQ(root_windows[1], window->GetRootWindow()); 384 EXPECT_TRUE(wm::GetWindowSettings(window.get())->panel_attached()); 385 EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); 386} 387 388TEST_F(PanelWindowResizerTest, RevertDragRestoresAttachment) { 389 scoped_ptr<aura::Window> window( 390 CreatePanelWindow(gfx::Rect(0, 0, 201, 201))); 391 EXPECT_TRUE(wm::GetWindowSettings(window.get())->panel_attached()); 392 EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); 393 DragStart(window.get()); 394 DragMove(0, -100); 395 DragRevert(); 396 EXPECT_TRUE(wm::GetWindowSettings(window.get())->panel_attached()); 397 EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); 398 399 // Detach panel. 400 DragStart(window.get()); 401 DragMove(0, -100); 402 DragEnd(); 403 EXPECT_FALSE(wm::GetWindowSettings(window.get())->panel_attached()); 404 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 405 window->parent()->id()); 406 407 // Drag back to launcher. 408 DragStart(window.get()); 409 DragMove(0, 100); 410 411 // When the drag is reverted it should remain detached. 412 DragRevert(); 413 EXPECT_FALSE(wm::GetWindowSettings(window.get())->panel_attached()); 414 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 415 window->parent()->id()); 416} 417 418TEST_F(PanelWindowResizerTest, DragMovesToPanelLayer) { 419 scoped_ptr<aura::Window> window(CreatePanelWindow(gfx::Rect(0, 0, 201, 201))); 420 DragStart(window.get()); 421 DragMove(0, -100); 422 DragEnd(); 423 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 424 window->parent()->id()); 425 426 // While moving the panel window should be moved to the panel container. 427 DragStart(window.get()); 428 DragMove(20, 0); 429 EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id()); 430 DragEnd(); 431 432 // When dropped it should return to the default container. 433 EXPECT_EQ(internal::kShellWindowId_DefaultContainer, 434 window->parent()->id()); 435} 436 437TEST_P(PanelWindowResizerTextDirectionTest, DragReordersPanelsHorizontal) { 438 if (!SupportsHostWindowResize()) 439 return; 440 441 DragAlongShelfReorder(base::i18n::IsRTL() ? 1 : -1, 0); 442} 443 444TEST_F(PanelWindowResizerTest, DragReordersPanelsVertical) { 445 if (!SupportsHostWindowResize()) 446 return; 447 448 ash::Shell* shell = ash::Shell::GetInstance(); 449 shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, shell->GetPrimaryRootWindow()); 450 DragAlongShelfReorder(0, -1); 451} 452 453INSTANTIATE_TEST_CASE_P(LtrRtl, PanelWindowResizerTextDirectionTest, 454 testing::Bool()); 455 456} // namespace internal 457} // namespace ash 458