1 // Copyright (c) 2012 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/drag_window_resizer.h" 6 7 #include "ash/display/mouse_cursor_event_filter.h" 8 #include "ash/root_window_controller.h" 9 #include "ash/shelf/shelf_layout_manager.h" 10 #include "ash/shell.h" 11 #include "ash/shell_window_ids.h" 12 #include "ash/test/ash_test_base.h" 13 #include "ash/test/cursor_manager_test_api.h" 14 #include "ash/wm/drag_window_controller.h" 15 #include "ash/wm/window_util.h" 16 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/stringprintf.h" 18 #include "ui/aura/client/aura_constants.h" 19 #include "ui/aura/root_window.h" 20 #include "ui/aura/test/test_window_delegate.h" 21 #include "ui/base/hit_test.h" 22 #include "ui/base/ui_base_types.h" 23 #include "ui/gfx/insets.h" 24 #include "ui/gfx/screen.h" 25 #include "ui/views/widget/widget.h" 26 27 #if defined(OS_CHROMEOS) 28 #include "ash/system/tray/system_tray.h" 29 #include "ash/system/user/tray_user.h" 30 #include "ash/test/test_session_state_delegate.h" 31 #include "ash/test/test_shell_delegate.h" 32 #endif 33 34 namespace ash { 35 namespace internal { 36 namespace { 37 38 const int kRootHeight = 600; 39 40 } // namespace 41 42 class DragWindowResizerTest : public test::AshTestBase { 43 public: 44 DragWindowResizerTest() {} 45 virtual ~DragWindowResizerTest() {} 46 47 virtual void SetUp() OVERRIDE { 48 AshTestBase::SetUp(); 49 UpdateDisplay(base::StringPrintf("800x%d", kRootHeight)); 50 51 aura::Window* root = Shell::GetPrimaryRootWindow(); 52 gfx::Rect root_bounds(root->bounds()); 53 EXPECT_EQ(kRootHeight, root_bounds.height()); 54 EXPECT_EQ(800, root_bounds.width()); 55 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); 56 window_.reset(new aura::Window(&delegate_)); 57 window_->SetType(aura::client::WINDOW_TYPE_NORMAL); 58 window_->Init(ui::LAYER_NOT_DRAWN); 59 ParentWindowInPrimaryRootWindow(window_.get()); 60 window_->set_id(1); 61 62 always_on_top_window_.reset(new aura::Window(&delegate2_)); 63 always_on_top_window_->SetType(aura::client::WINDOW_TYPE_NORMAL); 64 always_on_top_window_->SetProperty(aura::client::kAlwaysOnTopKey, true); 65 always_on_top_window_->Init(ui::LAYER_NOT_DRAWN); 66 ParentWindowInPrimaryRootWindow(always_on_top_window_.get()); 67 always_on_top_window_->set_id(2); 68 69 system_modal_window_.reset(new aura::Window(&delegate3_)); 70 system_modal_window_->SetType(aura::client::WINDOW_TYPE_NORMAL); 71 system_modal_window_->SetProperty(aura::client::kModalKey, 72 ui::MODAL_TYPE_SYSTEM); 73 system_modal_window_->Init(ui::LAYER_NOT_DRAWN); 74 ParentWindowInPrimaryRootWindow(system_modal_window_.get()); 75 system_modal_window_->set_id(3); 76 77 transient_child_ = new aura::Window(&delegate4_); 78 transient_child_->SetType(aura::client::WINDOW_TYPE_NORMAL); 79 transient_child_->Init(ui::LAYER_NOT_DRAWN); 80 ParentWindowInPrimaryRootWindow(transient_child_); 81 transient_child_->set_id(4); 82 83 transient_parent_.reset(new aura::Window(&delegate5_)); 84 transient_parent_->SetType(aura::client::WINDOW_TYPE_NORMAL); 85 transient_parent_->Init(ui::LAYER_NOT_DRAWN); 86 ParentWindowInPrimaryRootWindow(transient_parent_.get()); 87 transient_parent_->AddTransientChild(transient_child_); 88 transient_parent_->set_id(5); 89 90 panel_window_.reset(new aura::Window(&delegate6_)); 91 panel_window_->SetType(aura::client::WINDOW_TYPE_PANEL); 92 panel_window_->Init(ui::LAYER_NOT_DRAWN); 93 ParentWindowInPrimaryRootWindow(panel_window_.get()); 94 } 95 96 virtual void TearDown() OVERRIDE { 97 window_.reset(); 98 always_on_top_window_.reset(); 99 system_modal_window_.reset(); 100 transient_parent_.reset(); 101 panel_window_.reset(); 102 AshTestBase::TearDown(); 103 } 104 105 protected: 106 gfx::Point CalculateDragPoint(const WindowResizer& resizer, 107 int delta_x, 108 int delta_y) const { 109 gfx::Point location = resizer.GetInitialLocation(); 110 location.set_x(location.x() + delta_x); 111 location.set_y(location.y() + delta_y); 112 return location; 113 } 114 115 internal::ShelfLayoutManager* shelf_layout_manager() { 116 return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager(); 117 } 118 119 static WindowResizer* CreateDragWindowResizer( 120 aura::Window* window, 121 const gfx::Point& point_in_parent, 122 int window_component) { 123 return CreateWindowResizer( 124 window, 125 point_in_parent, 126 window_component, 127 aura::client::WINDOW_MOVE_SOURCE_MOUSE).release(); 128 } 129 130 bool WarpMouseCursorIfNecessary(aura::Window* target_root, 131 const gfx::Point& point_in_screen) { 132 MouseCursorEventFilter* event_filter = 133 Shell::GetInstance()->mouse_cursor_filter(); 134 bool is_warped = event_filter->WarpMouseCursorIfNecessary(target_root, 135 point_in_screen); 136 event_filter->reset_was_mouse_warped_for_test(); 137 return is_warped; 138 } 139 140 aura::test::TestWindowDelegate delegate_; 141 aura::test::TestWindowDelegate delegate2_; 142 aura::test::TestWindowDelegate delegate3_; 143 aura::test::TestWindowDelegate delegate4_; 144 aura::test::TestWindowDelegate delegate5_; 145 aura::test::TestWindowDelegate delegate6_; 146 147 scoped_ptr<aura::Window> window_; 148 scoped_ptr<aura::Window> always_on_top_window_; 149 scoped_ptr<aura::Window> system_modal_window_; 150 scoped_ptr<aura::Window> panel_window_; 151 aura::Window* transient_child_; 152 scoped_ptr<aura::Window> transient_parent_; 153 154 private: 155 DISALLOW_COPY_AND_ASSIGN(DragWindowResizerTest); 156 }; 157 158 // Verifies a window can be moved from the primary display to another. 159 TEST_F(DragWindowResizerTest, WindowDragWithMultiDisplays) { 160 if (!SupportsMultipleDisplays()) 161 return; 162 163 // The secondary display is logically on the right, but on the system (e.g. X) 164 // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc. 165 UpdateDisplay("800x600,800x600"); 166 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 167 ASSERT_EQ(2U, root_windows.size()); 168 169 window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), 170 Shell::GetScreen()->GetPrimaryDisplay()); 171 EXPECT_EQ(root_windows[0], window_->GetRootWindow()); 172 { 173 // Grab (0, 0) of the window. 174 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 175 window_.get(), gfx::Point(), HTCAPTION)); 176 ASSERT_TRUE(resizer.get()); 177 // Drag the pointer to the right. Once it reaches the right edge of the 178 // primary display, it warps to the secondary. 179 resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0); 180 resizer->CompleteDrag(0); 181 // The whole window is on the secondary display now. The parent should be 182 // changed. 183 EXPECT_EQ(root_windows[1], window_->GetRootWindow()); 184 EXPECT_EQ("0,10 50x60", window_->bounds().ToString()); 185 } 186 187 window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), 188 Shell::GetScreen()->GetPrimaryDisplay()); 189 EXPECT_EQ(root_windows[0], window_->GetRootWindow()); 190 { 191 // Grab (0, 0) of the window and move the pointer to (790, 10). 192 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 193 window_.get(), gfx::Point(), HTCAPTION)); 194 ASSERT_TRUE(resizer.get()); 195 resizer->Drag(CalculateDragPoint(*resizer, 795, 10), 0); 196 // Window should be adjusted for minimum visibility (10px) during the drag. 197 EXPECT_EQ("790,10 50x60", window_->bounds().ToString()); 198 resizer->CompleteDrag(0); 199 // Since the pointer is still on the primary root window, the parent should 200 // not be changed. 201 // Window origin should be adjusted for minimum visibility (10px). 202 EXPECT_EQ(root_windows[0], window_->GetRootWindow()); 203 EXPECT_EQ("790,10 50x60", window_->bounds().ToString()); 204 } 205 206 window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), 207 Shell::GetScreen()->GetPrimaryDisplay()); 208 EXPECT_EQ(root_windows[0], window_->GetRootWindow()); 209 { 210 // Grab the top-right edge of the window and move the pointer to (0, 10) 211 // in the secondary root window's coordinates. 212 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 213 window_.get(), gfx::Point(49, 0), HTCAPTION)); 214 ASSERT_TRUE(resizer.get()); 215 resizer->Drag(CalculateDragPoint(*resizer, 751, 10), ui::EF_CONTROL_DOWN); 216 resizer->CompleteDrag(0); 217 // Since the pointer is on the secondary, the parent should be changed 218 // even though only small fraction of the window is within the secondary 219 // root window's bounds. 220 EXPECT_EQ(root_windows[1], window_->GetRootWindow()); 221 // Window origin should be adjusted for minimum visibility (10px). 222 int expected_x = -50 + 10; 223 EXPECT_EQ(base::IntToString(expected_x) + ",10 50x60", 224 window_->bounds().ToString()); 225 } 226 } 227 228 // Verifies that dragging the active window to another display makes the new 229 // root window the active root window. 230 TEST_F(DragWindowResizerTest, WindowDragWithMultiDisplaysActiveRoot) { 231 if (!SupportsMultipleDisplays()) 232 return; 233 234 // The secondary display is logically on the right, but on the system (e.g. X) 235 // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc. 236 UpdateDisplay("800x600,800x600"); 237 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 238 ASSERT_EQ(2U, root_windows.size()); 239 240 aura::test::TestWindowDelegate delegate; 241 scoped_ptr<aura::Window> window(new aura::Window(&delegate)); 242 window->SetType(aura::client::WINDOW_TYPE_NORMAL); 243 window->Init(ui::LAYER_TEXTURED); 244 ParentWindowInPrimaryRootWindow(window.get()); 245 window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), 246 Shell::GetScreen()->GetPrimaryDisplay()); 247 window->Show(); 248 EXPECT_TRUE(ash::wm::CanActivateWindow(window.get())); 249 ash::wm::ActivateWindow(window.get()); 250 EXPECT_EQ(root_windows[0], window->GetRootWindow()); 251 EXPECT_EQ(root_windows[0], ash::Shell::GetTargetRootWindow()); 252 { 253 // Grab (0, 0) of the window. 254 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 255 window.get(), gfx::Point(), HTCAPTION)); 256 ASSERT_TRUE(resizer.get()); 257 // Drag the pointer to the right. Once it reaches the right edge of the 258 // primary display, it warps to the secondary. 259 resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0); 260 resizer->CompleteDrag(0); 261 // The whole window is on the secondary display now. The parent should be 262 // changed. 263 EXPECT_EQ(root_windows[1], window->GetRootWindow()); 264 EXPECT_EQ(root_windows[1], ash::Shell::GetTargetRootWindow()); 265 } 266 } 267 268 // Verifies a window can be moved from the secondary display to primary. 269 TEST_F(DragWindowResizerTest, WindowDragWithMultiDisplaysRightToLeft) { 270 if (!SupportsMultipleDisplays()) 271 return; 272 273 UpdateDisplay("800x600,800x600"); 274 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 275 ASSERT_EQ(2U, root_windows.size()); 276 277 window_->SetBoundsInScreen( 278 gfx::Rect(800, 00, 50, 60), 279 Shell::GetScreen()->GetDisplayNearestWindow(root_windows[1])); 280 EXPECT_EQ(root_windows[1], window_->GetRootWindow()); 281 { 282 // Grab (0, 0) of the window. 283 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 284 window_.get(), gfx::Point(), HTCAPTION)); 285 ASSERT_TRUE(resizer.get()); 286 // Move the mouse near the right edge, (798, 0), of the primary display. 287 resizer->Drag(CalculateDragPoint(*resizer, -2, 0), ui::EF_CONTROL_DOWN); 288 resizer->CompleteDrag(0); 289 EXPECT_EQ(root_windows[0], window_->GetRootWindow()); 290 // Window origin should be adjusted for minimum visibility (10px). 291 int expected_x = 800 - 10; 292 EXPECT_EQ(base::IntToString(expected_x) + ",0 50x60", 293 window_->bounds().ToString()); 294 } 295 } 296 297 // Verifies the drag window is shown correctly. 298 TEST_F(DragWindowResizerTest, DragWindowController) { 299 if (!SupportsMultipleDisplays()) 300 return; 301 302 UpdateDisplay("800x600,800x600"); 303 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 304 ASSERT_EQ(2U, root_windows.size()); 305 306 window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), 307 Shell::GetScreen()->GetPrimaryDisplay()); 308 EXPECT_EQ(root_windows[0], window_->GetRootWindow()); 309 EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity()); 310 { 311 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 312 window_.get(), gfx::Point(), HTCAPTION)); 313 ASSERT_TRUE(resizer.get()); 314 internal::DragWindowResizer* drag_resizer = DragWindowResizer::instance_; 315 ASSERT_TRUE(drag_resizer); 316 EXPECT_FALSE(drag_resizer->drag_window_controller_.get()); 317 318 // The pointer is inside the primary root. The drag window controller 319 // should be NULL. 320 resizer->Drag(CalculateDragPoint(*resizer, 10, 10), 0); 321 EXPECT_FALSE(drag_resizer->drag_window_controller_.get()); 322 323 // The window spans both root windows. 324 resizer->Drag(CalculateDragPoint(*resizer, 798, 10), 0); 325 DragWindowController* controller = 326 drag_resizer->drag_window_controller_.get(); 327 ASSERT_TRUE(controller); 328 329 ASSERT_TRUE(controller->drag_widget_); 330 ui::Layer* drag_layer = 331 controller->drag_widget_->GetNativeWindow()->layer(); 332 ASSERT_TRUE(drag_layer); 333 // Check if |resizer->layer_| is properly set to the drag widget. 334 const std::vector<ui::Layer*>& layers = drag_layer->children(); 335 EXPECT_FALSE(layers.empty()); 336 EXPECT_EQ(controller->layer_, layers.back()); 337 338 // |window_| should be opaque since the pointer is still on the primary 339 // root window. The drag window should be semi-transparent. 340 EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity()); 341 ASSERT_TRUE(controller->drag_widget_); 342 EXPECT_GT(1.0f, drag_layer->opacity()); 343 344 // Enter the pointer to the secondary display. 345 resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0); 346 controller = drag_resizer->drag_window_controller_.get(); 347 ASSERT_TRUE(controller); 348 // |window_| should be transparent, and the drag window should be opaque. 349 EXPECT_GT(1.0f, window_->layer()->opacity()); 350 EXPECT_FLOAT_EQ(1.0f, drag_layer->opacity()); 351 352 resizer->CompleteDrag(0); 353 EXPECT_EQ(root_windows[1], window_->GetRootWindow()); 354 EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity()); 355 } 356 357 // Do the same test with RevertDrag(). 358 window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), 359 Shell::GetScreen()->GetPrimaryDisplay()); 360 EXPECT_EQ(root_windows[0], window_->GetRootWindow()); 361 EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity()); 362 { 363 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 364 window_.get(), gfx::Point(), HTCAPTION)); 365 ASSERT_TRUE(resizer.get()); 366 internal::DragWindowResizer* drag_resizer = DragWindowResizer::instance_; 367 ASSERT_TRUE(drag_resizer); 368 EXPECT_FALSE(drag_resizer->drag_window_controller_.get()); 369 370 resizer->Drag(CalculateDragPoint(*resizer, 0, 610), 0); 371 resizer->RevertDrag(); 372 EXPECT_EQ(root_windows[0], window_->GetRootWindow()); 373 EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity()); 374 } 375 } 376 377 // Verifies if the resizer sets and resets 378 // MouseCursorEventFilter::mouse_warp_mode_ as expected. 379 TEST_F(DragWindowResizerTest, WarpMousePointer) { 380 MouseCursorEventFilter* event_filter = 381 Shell::GetInstance()->mouse_cursor_filter(); 382 ASSERT_TRUE(event_filter); 383 window_->SetBounds(gfx::Rect(0, 0, 50, 60)); 384 385 EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS, 386 event_filter->mouse_warp_mode_); 387 { 388 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 389 window_.get(), gfx::Point(), HTCAPTION)); 390 // While dragging a window, warp should be allowed. 391 EXPECT_EQ(MouseCursorEventFilter::WARP_DRAG, 392 event_filter->mouse_warp_mode_); 393 resizer->CompleteDrag(0); 394 } 395 EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS, 396 event_filter->mouse_warp_mode_); 397 398 { 399 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 400 window_.get(), gfx::Point(), HTCAPTION)); 401 EXPECT_EQ(MouseCursorEventFilter::WARP_DRAG, 402 event_filter->mouse_warp_mode_); 403 resizer->RevertDrag(); 404 } 405 EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS, 406 event_filter->mouse_warp_mode_); 407 408 { 409 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 410 window_.get(), gfx::Point(), HTRIGHT)); 411 // While resizing a window, warp should NOT be allowed. 412 EXPECT_EQ(MouseCursorEventFilter::WARP_NONE, 413 event_filter->mouse_warp_mode_); 414 resizer->CompleteDrag(0); 415 } 416 EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS, 417 event_filter->mouse_warp_mode_); 418 419 { 420 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 421 window_.get(), gfx::Point(), HTRIGHT)); 422 EXPECT_EQ(MouseCursorEventFilter::WARP_NONE, 423 event_filter->mouse_warp_mode_); 424 resizer->RevertDrag(); 425 } 426 EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS, 427 event_filter->mouse_warp_mode_); 428 } 429 430 // Verifies cursor's device scale factor is updated whe a window is moved across 431 // root windows with different device scale factors (http://crbug.com/154183). 432 TEST_F(DragWindowResizerTest, CursorDeviceScaleFactor) { 433 if (!SupportsMultipleDisplays()) 434 return; 435 436 // The secondary display is logically on the right, but on the system (e.g. X) 437 // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc. 438 UpdateDisplay("400x400,800x800*2"); 439 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 440 ASSERT_EQ(2U, root_windows.size()); 441 442 test::CursorManagerTestApi cursor_test_api( 443 Shell::GetInstance()->cursor_manager()); 444 // Move window from the root window with 1.0 device scale factor to the root 445 // window with 2.0 device scale factor. 446 { 447 window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), 448 Shell::GetScreen()->GetPrimaryDisplay()); 449 EXPECT_EQ(root_windows[0], window_->GetRootWindow()); 450 // Grab (0, 0) of the window. 451 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 452 window_.get(), gfx::Point(), HTCAPTION)); 453 EXPECT_EQ(1.0f, cursor_test_api.GetDisplay().device_scale_factor()); 454 ASSERT_TRUE(resizer.get()); 455 resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); 456 WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(399, 200)); 457 EXPECT_EQ(2.0f, cursor_test_api.GetDisplay().device_scale_factor()); 458 resizer->CompleteDrag(0); 459 EXPECT_EQ(2.0f, cursor_test_api.GetDisplay().device_scale_factor()); 460 } 461 462 // Move window from the root window with 2.0 device scale factor to the root 463 // window with 1.0 device scale factor. 464 { 465 window_->SetBoundsInScreen( 466 gfx::Rect(600, 0, 50, 60), 467 Shell::GetScreen()->GetDisplayNearestWindow(root_windows[1])); 468 EXPECT_EQ(root_windows[1], window_->GetRootWindow()); 469 // Grab (0, 0) of the window. 470 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 471 window_.get(), gfx::Point(), HTCAPTION)); 472 EXPECT_EQ(2.0f, cursor_test_api.GetDisplay().device_scale_factor()); 473 ASSERT_TRUE(resizer.get()); 474 resizer->Drag(CalculateDragPoint(*resizer, -200, 200), 0); 475 WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(400, 200)); 476 EXPECT_EQ(1.0f, cursor_test_api.GetDisplay().device_scale_factor()); 477 resizer->CompleteDrag(0); 478 EXPECT_EQ(1.0f, cursor_test_api.GetDisplay().device_scale_factor()); 479 } 480 } 481 482 // Verifies several kinds of windows can be moved across displays. 483 TEST_F(DragWindowResizerTest, MoveWindowAcrossDisplays) { 484 if (!SupportsMultipleDisplays()) 485 return; 486 487 // The secondary display is logically on the right, but on the system (e.g. X) 488 // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc. 489 UpdateDisplay("400x400,400x400"); 490 491 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 492 ASSERT_EQ(2U, root_windows.size()); 493 494 // Normal window can be moved across display. 495 { 496 aura::Window* window = window_.get(); 497 window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), 498 Shell::GetScreen()->GetPrimaryDisplay()); 499 // Grab (0, 0) of the window. 500 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 501 window, gfx::Point(), HTCAPTION)); 502 ASSERT_TRUE(resizer.get()); 503 resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); 504 EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], 505 gfx::Point(399, 200))); 506 resizer->CompleteDrag(0); 507 } 508 509 // Always on top window can be moved across display. 510 { 511 aura::Window* window = always_on_top_window_.get(); 512 window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), 513 Shell::GetScreen()->GetPrimaryDisplay()); 514 // Grab (0, 0) of the window. 515 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 516 window, gfx::Point(), HTCAPTION)); 517 ASSERT_TRUE(resizer.get()); 518 resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); 519 EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], 520 gfx::Point(399, 200))); 521 resizer->CompleteDrag(0); 522 } 523 524 // System modal window can be moved across display. 525 { 526 aura::Window* window = system_modal_window_.get(); 527 window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), 528 Shell::GetScreen()->GetPrimaryDisplay()); 529 // Grab (0, 0) of the window. 530 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 531 window, gfx::Point(), HTCAPTION)); 532 ASSERT_TRUE(resizer.get()); 533 resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); 534 EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], 535 gfx::Point(399, 200))); 536 resizer->CompleteDrag(0); 537 } 538 539 // Transient window cannot be moved across display. 540 { 541 aura::Window* window = transient_child_; 542 window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), 543 Shell::GetScreen()->GetPrimaryDisplay()); 544 // Grab (0, 0) of the window. 545 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 546 window, gfx::Point(), HTCAPTION)); 547 ASSERT_TRUE(resizer.get()); 548 resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); 549 EXPECT_FALSE(WarpMouseCursorIfNecessary( 550 root_windows[0], 551 gfx::Point(399, 200))); 552 resizer->CompleteDrag(0); 553 } 554 555 // The parent of transient window can be moved across display. 556 { 557 aura::Window* window = transient_parent_.get(); 558 window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), 559 Shell::GetScreen()->GetPrimaryDisplay()); 560 // Grab (0, 0) of the window. 561 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 562 window, gfx::Point(), HTCAPTION)); 563 ASSERT_TRUE(resizer.get()); 564 resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); 565 EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], 566 gfx::Point(399, 200))); 567 resizer->CompleteDrag(0); 568 } 569 570 // Panel window can be moved across display. 571 { 572 aura::Window* window = panel_window_.get(); 573 window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), 574 Shell::GetScreen()->GetPrimaryDisplay()); 575 // Grab (0, 0) of the window. 576 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 577 window, gfx::Point(), HTCAPTION)); 578 ASSERT_TRUE(resizer.get()); 579 resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); 580 EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], 581 gfx::Point(399, 200))); 582 resizer->CompleteDrag(0); 583 } 584 } 585 586 #if defined(OS_CHROMEOS) 587 // Checks that moving a window to another desktop will properly set and reset 588 // the transparency. 589 TEST_F(DragWindowResizerTest, DragToOtherDesktopOpacity) { 590 // Set up a few things we need for multi profile. 591 ash::test::TestSessionStateDelegate* session_delegate = 592 static_cast<ash::test::TestSessionStateDelegate*>( 593 ash::Shell::GetInstance()->session_state_delegate()); 594 session_delegate->set_logged_in_users(2); 595 ash::test::TestShellDelegate* shell_delegate = 596 static_cast<ash::test::TestShellDelegate*>( 597 ash::Shell::GetInstance()->delegate()); 598 shell_delegate->set_multi_profiles_enabled(true); 599 600 // Create one other user where we can drag our stuff onto. 601 SystemTray* tray = Shell::GetPrimaryRootWindowController()->GetSystemTray(); 602 TrayUser* tray_user = new TrayUser(tray, 1); 603 tray->AddTrayUserItemForTest(tray_user); 604 605 // Move the view somewhere where we can hit it. 606 views::View* view = tray->GetTrayItemViewForTest(tray_user); 607 view->SetBounds(80, 0, 20, 20); 608 gfx::Point center = view->GetBoundsInScreen().CenterPoint(); 609 610 gfx::Rect initial_bounds = gfx::Rect(0, 0, 50, 60); 611 // Drag the window over the icon and let it drop. Test that the window's 612 // layer gets transparent and reverts back. 613 { 614 aura::Window* window = window_.get(); 615 window->SetBoundsInScreen(initial_bounds, 616 Shell::GetScreen()->GetPrimaryDisplay()); 617 // Grab (0, 0) of the window. 618 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 619 window, gfx::Point(), HTCAPTION)); 620 ASSERT_TRUE(resizer.get()); 621 EXPECT_EQ(1.0, window->layer()->opacity()); 622 resizer->Drag(center, 0); 623 EXPECT_NE(1.0, window->layer()->opacity()); 624 EXPECT_EQ(0, session_delegate->num_transfer_to_desktop_of_user_calls()); 625 resizer->CompleteDrag(0); 626 EXPECT_EQ(1.0, window->layer()->opacity()); 627 EXPECT_EQ(1, session_delegate->num_transfer_to_desktop_of_user_calls()); 628 EXPECT_EQ(initial_bounds.ToString(), window->bounds().ToString()); 629 } 630 631 // Drag the window over the icon and cancel the operation. Test that the 632 // window's layer gets transparent and reverts back. 633 { 634 aura::Window* window = window_.get(); 635 window->SetBoundsInScreen(initial_bounds, 636 Shell::GetScreen()->GetPrimaryDisplay()); 637 // Grab (0, 0) of the window. 638 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 639 window, gfx::Point(), HTCAPTION)); 640 ASSERT_TRUE(resizer.get()); 641 EXPECT_EQ(1.0, window->layer()->opacity()); 642 resizer->Drag(center, 0); 643 EXPECT_NE(1.0, window->layer()->opacity()); 644 resizer->RevertDrag(); 645 EXPECT_EQ(1.0, window->layer()->opacity()); 646 EXPECT_EQ(1, session_delegate->num_transfer_to_desktop_of_user_calls()); 647 EXPECT_EQ(initial_bounds.ToString(), window->bounds().ToString()); 648 } 649 650 // Drag the window over the icon and somewhere else and see that it properly 651 // reverts its transparency. 652 { 653 aura::Window* window = window_.get(); 654 window->SetBoundsInScreen(initial_bounds, 655 Shell::GetScreen()->GetPrimaryDisplay()); 656 // Grab (0, 0) of the window. 657 scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( 658 window, gfx::Point(), HTCAPTION)); 659 ASSERT_TRUE(resizer.get()); 660 EXPECT_EQ(1.0, window->layer()->opacity()); 661 resizer->Drag(center, 0); 662 EXPECT_NE(1.0, window->layer()->opacity()); 663 resizer->Drag(gfx::Point(), 0); 664 EXPECT_EQ(1.0, window->layer()->opacity()); 665 resizer->CompleteDrag(0); 666 EXPECT_EQ(1, session_delegate->num_transfer_to_desktop_of_user_calls()); 667 EXPECT_NE(initial_bounds.ToString(), window->bounds().ToString()); 668 } 669 } 670 #endif 671 672 673 } // namespace internal 674 } // namespace ash 675