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.
5 #include "ash/wm/drag_window_resizer.h"
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/test/test_window_delegate.h"
20 #include "ui/aura/window_event_dispatcher.h"
21 #include "ui/base/hit_test.h"
22 #include "ui/base/ui_base_types.h"
23 #include "ui/compositor/layer_tree_owner.h"
24 #include "ui/gfx/insets.h"
25 #include "ui/gfx/screen.h"
26 #include "ui/views/widget/widget.h"
27 #include "ui/wm/core/window_util.h"
32 const int kRootHeight
= 600;
36 class DragWindowResizerTest
: public test::AshTestBase
{
38 DragWindowResizerTest() {}
39 virtual ~DragWindowResizerTest() {}
41 virtual void SetUp() OVERRIDE
{
43 UpdateDisplay(base::StringPrintf("800x%d", kRootHeight
));
45 aura::Window
* root
= Shell::GetPrimaryRootWindow();
46 gfx::Rect
root_bounds(root
->bounds());
47 EXPECT_EQ(kRootHeight
, root_bounds
.height());
48 EXPECT_EQ(800, root_bounds
.width());
49 Shell::GetInstance()->SetDisplayWorkAreaInsets(root
, gfx::Insets());
50 window_
.reset(new aura::Window(&delegate_
));
51 window_
->SetType(ui::wm::WINDOW_TYPE_NORMAL
);
52 window_
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
53 ParentWindowInPrimaryRootWindow(window_
.get());
56 always_on_top_window_
.reset(new aura::Window(&delegate2_
));
57 always_on_top_window_
->SetType(ui::wm::WINDOW_TYPE_NORMAL
);
58 always_on_top_window_
->SetProperty(aura::client::kAlwaysOnTopKey
, true);
59 always_on_top_window_
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
60 ParentWindowInPrimaryRootWindow(always_on_top_window_
.get());
61 always_on_top_window_
->set_id(2);
63 system_modal_window_
.reset(new aura::Window(&delegate3_
));
64 system_modal_window_
->SetType(ui::wm::WINDOW_TYPE_NORMAL
);
65 system_modal_window_
->SetProperty(aura::client::kModalKey
,
66 ui::MODAL_TYPE_SYSTEM
);
67 system_modal_window_
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
68 ParentWindowInPrimaryRootWindow(system_modal_window_
.get());
69 system_modal_window_
->set_id(3);
71 transient_child_
= new aura::Window(&delegate4_
);
72 transient_child_
->SetType(ui::wm::WINDOW_TYPE_NORMAL
);
73 transient_child_
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
74 ParentWindowInPrimaryRootWindow(transient_child_
);
75 transient_child_
->set_id(4);
77 transient_parent_
.reset(new aura::Window(&delegate5_
));
78 transient_parent_
->SetType(ui::wm::WINDOW_TYPE_NORMAL
);
79 transient_parent_
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
80 ParentWindowInPrimaryRootWindow(transient_parent_
.get());
81 ::wm::AddTransientChild(transient_parent_
.get(), transient_child_
);
82 transient_parent_
->set_id(5);
84 panel_window_
.reset(new aura::Window(&delegate6_
));
85 panel_window_
->SetType(ui::wm::WINDOW_TYPE_PANEL
);
86 panel_window_
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
87 ParentWindowInPrimaryRootWindow(panel_window_
.get());
90 virtual void TearDown() OVERRIDE
{
92 always_on_top_window_
.reset();
93 system_modal_window_
.reset();
94 transient_parent_
.reset();
95 panel_window_
.reset();
96 AshTestBase::TearDown();
100 gfx::Point
CalculateDragPoint(const WindowResizer
& resizer
,
103 gfx::Point location
= resizer
.GetInitialLocation();
104 location
.set_x(location
.x() + delta_x
);
105 location
.set_y(location
.y() + delta_y
);
109 ShelfLayoutManager
* shelf_layout_manager() {
110 return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
113 static WindowResizer
* CreateDragWindowResizer(
114 aura::Window
* window
,
115 const gfx::Point
& point_in_parent
,
116 int window_component
) {
117 return CreateWindowResizer(
121 aura::client::WINDOW_MOVE_SOURCE_MOUSE
).release();
124 bool WarpMouseCursorIfNecessary(aura::Window
* target_root
,
125 const gfx::Point
& point_in_screen
) {
126 MouseCursorEventFilter
* event_filter
=
127 Shell::GetInstance()->mouse_cursor_filter();
128 bool is_warped
= event_filter
->WarpMouseCursorIfNecessaryForTest(
129 target_root
, point_in_screen
);
130 event_filter
->reset_was_mouse_warped_for_test();
134 aura::test::TestWindowDelegate delegate_
;
135 aura::test::TestWindowDelegate delegate2_
;
136 aura::test::TestWindowDelegate delegate3_
;
137 aura::test::TestWindowDelegate delegate4_
;
138 aura::test::TestWindowDelegate delegate5_
;
139 aura::test::TestWindowDelegate delegate6_
;
141 scoped_ptr
<aura::Window
> window_
;
142 scoped_ptr
<aura::Window
> always_on_top_window_
;
143 scoped_ptr
<aura::Window
> system_modal_window_
;
144 scoped_ptr
<aura::Window
> panel_window_
;
145 aura::Window
* transient_child_
;
146 scoped_ptr
<aura::Window
> transient_parent_
;
149 DISALLOW_COPY_AND_ASSIGN(DragWindowResizerTest
);
152 // Verifies a window can be moved from the primary display to another.
153 TEST_F(DragWindowResizerTest
, WindowDragWithMultiDisplays
) {
154 if (!SupportsMultipleDisplays())
157 // The secondary display is logically on the right, but on the system (e.g. X)
158 // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc.
159 UpdateDisplay("800x600,400x300");
160 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
161 ASSERT_EQ(2U, root_windows
.size());
163 window_
->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
164 Shell::GetScreen()->GetPrimaryDisplay());
165 EXPECT_EQ(root_windows
[0], window_
->GetRootWindow());
167 // Grab (0, 0) of the window.
168 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
169 window_
.get(), gfx::Point(), HTCAPTION
));
170 ASSERT_TRUE(resizer
.get());
171 // Drag the pointer to the right. Once it reaches the right edge of the
172 // primary display, it warps to the secondary.
173 resizer
->Drag(CalculateDragPoint(*resizer
, 800, 10), 0);
174 resizer
->CompleteDrag();
175 // The whole window is on the secondary display now. The parent should be
177 EXPECT_EQ(root_windows
[1], window_
->GetRootWindow());
178 EXPECT_EQ("0,10 50x60", window_
->bounds().ToString());
181 window_
->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
182 Shell::GetScreen()->GetPrimaryDisplay());
183 EXPECT_EQ(root_windows
[0], window_
->GetRootWindow());
185 // Grab (0, 0) of the window and move the pointer to (790, 10).
186 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
187 window_
.get(), gfx::Point(), HTCAPTION
));
188 ASSERT_TRUE(resizer
.get());
189 resizer
->Drag(CalculateDragPoint(*resizer
, 795, 10), 0);
190 // Window should be adjusted for minimum visibility (10px) during the drag.
191 EXPECT_EQ("790,10 50x60", window_
->bounds().ToString());
192 resizer
->CompleteDrag();
193 // Since the pointer is still on the primary root window, the parent should
195 // Window origin should be adjusted for minimum visibility (10px).
196 EXPECT_EQ(root_windows
[0], window_
->GetRootWindow());
197 EXPECT_EQ("790,10 50x60", window_
->bounds().ToString());
200 window_
->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
201 Shell::GetScreen()->GetPrimaryDisplay());
202 EXPECT_EQ(root_windows
[0], window_
->GetRootWindow());
204 // Grab the top-right edge of the window and move the pointer to (0, 10)
205 // in the secondary root window's coordinates.
206 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
207 window_
.get(), gfx::Point(49, 0), HTCAPTION
));
208 ASSERT_TRUE(resizer
.get());
209 resizer
->Drag(CalculateDragPoint(*resizer
, 751, 10), ui::EF_CONTROL_DOWN
);
210 resizer
->CompleteDrag();
211 // Since the pointer is on the secondary, the parent should be changed
212 // even though only small fraction of the window is within the secondary
213 // root window's bounds.
214 EXPECT_EQ(root_windows
[1], window_
->GetRootWindow());
215 // Window origin should be adjusted for minimum visibility (10px).
216 int expected_x
= -50 + 10;
217 EXPECT_EQ(base::IntToString(expected_x
) + ",10 50x60",
218 window_
->bounds().ToString());
220 // Dropping a window that is larger than the destination work area
221 // will shrink to fit to the work area.
222 window_
->SetBoundsInScreen(gfx::Rect(0, 0, 700, 500),
223 Shell::GetScreen()->GetPrimaryDisplay());
224 EXPECT_EQ(root_windows
[0], window_
->GetRootWindow());
226 // Grab the top-right edge of the window and move the pointer to (0, 10)
227 // in the secondary root window's coordinates.
228 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
229 window_
.get(), gfx::Point(699, 0), HTCAPTION
));
230 ASSERT_TRUE(resizer
.get());
231 resizer
->Drag(CalculateDragPoint(*resizer
, 101, 10), ui::EF_CONTROL_DOWN
);
232 resizer
->CompleteDrag();
233 EXPECT_EQ(root_windows
[1], window_
->GetRootWindow());
234 // Window size should be adjusted to fit to the work area
235 EXPECT_EQ("400x253", window_
->bounds().size().ToString());
236 gfx::Rect window_bounds_in_screen
= window_
->GetBoundsInScreen();
237 gfx::Rect
intersect(window_
->GetRootWindow()->GetBoundsInScreen());
238 intersect
.Intersect(window_bounds_in_screen
);
240 EXPECT_LE(10, intersect
.width());
241 EXPECT_LE(10, intersect
.height());
242 EXPECT_TRUE(window_bounds_in_screen
.Contains(gfx::Point(800, 10)));
245 // Dropping a window that is larger than the destination work area
246 // will shrink to fit to the work area.
247 window_
->SetBoundsInScreen(gfx::Rect(0, 0, 700, 500),
248 Shell::GetScreen()->GetPrimaryDisplay());
249 EXPECT_EQ(root_windows
[0], window_
->GetRootWindow());
251 // Grab the top-left edge of the window and move the pointer to (150, 10)
252 // in the secondary root window's coordinates. Make sure the window is
253 // shrink in such a way that it keeps the cursor within.
254 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
255 window_
.get(), gfx::Point(0, 0), HTCAPTION
));
256 ASSERT_TRUE(resizer
.get());
257 resizer
->Drag(CalculateDragPoint(*resizer
, 799, 10), ui::EF_CONTROL_DOWN
);
258 resizer
->Drag(CalculateDragPoint(*resizer
, 850, 10), ui::EF_CONTROL_DOWN
);
259 resizer
->CompleteDrag();
260 EXPECT_EQ(root_windows
[1], window_
->GetRootWindow());
261 // Window size should be adjusted to fit to the work area
262 EXPECT_EQ("400x253", window_
->bounds().size().ToString());
263 gfx::Rect window_bounds_in_screen
= window_
->GetBoundsInScreen();
264 gfx::Rect
intersect(window_
->GetRootWindow()->GetBoundsInScreen());
265 intersect
.Intersect(window_bounds_in_screen
);
266 EXPECT_LE(10, intersect
.width());
267 EXPECT_LE(10, intersect
.height());
268 EXPECT_TRUE(window_bounds_in_screen
.Contains(gfx::Point(850, 10)));
272 // Verifies that dragging the active window to another display makes the new
273 // root window the active root window.
274 TEST_F(DragWindowResizerTest
, WindowDragWithMultiDisplaysActiveRoot
) {
275 if (!SupportsMultipleDisplays())
278 // The secondary display is logically on the right, but on the system (e.g. X)
279 // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc.
280 UpdateDisplay("800x600,800x600");
281 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
282 ASSERT_EQ(2U, root_windows
.size());
284 aura::test::TestWindowDelegate delegate
;
285 scoped_ptr
<aura::Window
> window(new aura::Window(&delegate
));
286 window
->SetType(ui::wm::WINDOW_TYPE_NORMAL
);
287 window
->Init(aura::WINDOW_LAYER_TEXTURED
);
288 ParentWindowInPrimaryRootWindow(window
.get());
289 window
->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
290 Shell::GetScreen()->GetPrimaryDisplay());
292 EXPECT_TRUE(ash::wm::CanActivateWindow(window
.get()));
293 ash::wm::ActivateWindow(window
.get());
294 EXPECT_EQ(root_windows
[0], window
->GetRootWindow());
295 EXPECT_EQ(root_windows
[0], ash::Shell::GetTargetRootWindow());
297 // Grab (0, 0) of the window.
298 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
299 window
.get(), gfx::Point(), HTCAPTION
));
300 ASSERT_TRUE(resizer
.get());
301 // Drag the pointer to the right. Once it reaches the right edge of the
302 // primary display, it warps to the secondary.
303 resizer
->Drag(CalculateDragPoint(*resizer
, 800, 10), 0);
304 resizer
->CompleteDrag();
305 // The whole window is on the secondary display now. The parent should be
307 EXPECT_EQ(root_windows
[1], window
->GetRootWindow());
308 EXPECT_EQ(root_windows
[1], ash::Shell::GetTargetRootWindow());
312 // Verifies a window can be moved from the secondary display to primary.
313 TEST_F(DragWindowResizerTest
, WindowDragWithMultiDisplaysRightToLeft
) {
314 if (!SupportsMultipleDisplays())
317 UpdateDisplay("800x600,800x600");
318 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
319 ASSERT_EQ(2U, root_windows
.size());
321 window_
->SetBoundsInScreen(
322 gfx::Rect(800, 00, 50, 60),
323 Shell::GetScreen()->GetDisplayNearestWindow(root_windows
[1]));
324 EXPECT_EQ(root_windows
[1], window_
->GetRootWindow());
326 // Grab (0, 0) of the window.
327 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
328 window_
.get(), gfx::Point(), HTCAPTION
));
329 ASSERT_TRUE(resizer
.get());
330 // Move the mouse near the right edge, (798, 0), of the primary display.
331 resizer
->Drag(CalculateDragPoint(*resizer
, -2, 0), ui::EF_CONTROL_DOWN
);
332 resizer
->CompleteDrag();
333 EXPECT_EQ(root_windows
[0], window_
->GetRootWindow());
334 // Window origin should be adjusted for minimum visibility (10px).
335 int expected_x
= 800 - 10;
336 EXPECT_EQ(base::IntToString(expected_x
) + ",0 50x60",
337 window_
->bounds().ToString());
341 // Verifies the drag window is shown correctly.
342 TEST_F(DragWindowResizerTest
, DragWindowController
) {
343 if (!SupportsMultipleDisplays())
346 UpdateDisplay("800x600,800x600");
347 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
348 ASSERT_EQ(2U, root_windows
.size());
350 window_
->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
351 Shell::GetScreen()->GetPrimaryDisplay());
352 EXPECT_EQ(root_windows
[0], window_
->GetRootWindow());
353 EXPECT_FLOAT_EQ(1.0f
, window_
->layer()->opacity());
355 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
356 window_
.get(), gfx::Point(), HTCAPTION
));
357 ASSERT_TRUE(resizer
.get());
358 DragWindowResizer
* drag_resizer
= DragWindowResizer::instance_
;
359 ASSERT_TRUE(drag_resizer
);
360 EXPECT_FALSE(drag_resizer
->drag_window_controller_
.get());
362 // The pointer is inside the primary root. The drag window controller
364 resizer
->Drag(CalculateDragPoint(*resizer
, 10, 10), 0);
365 EXPECT_FALSE(drag_resizer
->drag_window_controller_
.get());
367 // The window spans both root windows.
368 resizer
->Drag(CalculateDragPoint(*resizer
, 798, 10), 0);
369 DragWindowController
* controller
=
370 drag_resizer
->drag_window_controller_
.get();
371 ASSERT_TRUE(controller
);
373 ASSERT_TRUE(controller
->drag_widget_
);
374 ui::Layer
* drag_layer
=
375 controller
->drag_widget_
->GetNativeWindow()->layer();
376 ASSERT_TRUE(drag_layer
);
377 // Check if |resizer->layer_| is properly set to the drag widget.
378 const std::vector
<ui::Layer
*>& layers
= drag_layer
->children();
379 EXPECT_FALSE(layers
.empty());
380 EXPECT_EQ(controller
->layer_owner_
->root(), layers
.back());
382 // |window_| should be opaque since the pointer is still on the primary
383 // root window. The drag window should be semi-transparent.
384 EXPECT_FLOAT_EQ(1.0f
, window_
->layer()->opacity());
385 ASSERT_TRUE(controller
->drag_widget_
);
386 EXPECT_GT(1.0f
, drag_layer
->opacity());
388 // Enter the pointer to the secondary display.
389 resizer
->Drag(CalculateDragPoint(*resizer
, 800, 10), 0);
390 controller
= drag_resizer
->drag_window_controller_
.get();
391 ASSERT_TRUE(controller
);
392 // |window_| should be transparent, and the drag window should be opaque.
393 EXPECT_GT(1.0f
, window_
->layer()->opacity());
394 EXPECT_FLOAT_EQ(1.0f
, drag_layer
->opacity());
396 resizer
->CompleteDrag();
397 EXPECT_EQ(root_windows
[1], window_
->GetRootWindow());
398 EXPECT_FLOAT_EQ(1.0f
, window_
->layer()->opacity());
401 // Do the same test with RevertDrag().
402 window_
->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
403 Shell::GetScreen()->GetPrimaryDisplay());
404 EXPECT_EQ(root_windows
[0], window_
->GetRootWindow());
405 EXPECT_FLOAT_EQ(1.0f
, window_
->layer()->opacity());
407 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
408 window_
.get(), gfx::Point(), HTCAPTION
));
409 ASSERT_TRUE(resizer
.get());
410 DragWindowResizer
* drag_resizer
= DragWindowResizer::instance_
;
411 ASSERT_TRUE(drag_resizer
);
412 EXPECT_FALSE(drag_resizer
->drag_window_controller_
.get());
414 resizer
->Drag(CalculateDragPoint(*resizer
, 0, 610), 0);
415 resizer
->RevertDrag();
416 EXPECT_EQ(root_windows
[0], window_
->GetRootWindow());
417 EXPECT_FLOAT_EQ(1.0f
, window_
->layer()->opacity());
421 // Verifies if the resizer sets and resets
422 // MouseCursorEventFilter::mouse_warp_mode_ as expected.
423 TEST_F(DragWindowResizerTest
, WarpMousePointer
) {
424 MouseCursorEventFilter
* event_filter
=
425 Shell::GetInstance()->mouse_cursor_filter();
426 ASSERT_TRUE(event_filter
);
427 window_
->SetBounds(gfx::Rect(0, 0, 50, 60));
429 EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS
,
430 event_filter
->mouse_warp_mode_
);
432 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
433 window_
.get(), gfx::Point(), HTCAPTION
));
434 // While dragging a window, warp should be allowed.
435 EXPECT_EQ(MouseCursorEventFilter::WARP_DRAG
,
436 event_filter
->mouse_warp_mode_
);
437 resizer
->CompleteDrag();
439 EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS
,
440 event_filter
->mouse_warp_mode_
);
443 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
444 window_
.get(), gfx::Point(), HTCAPTION
));
445 EXPECT_EQ(MouseCursorEventFilter::WARP_DRAG
,
446 event_filter
->mouse_warp_mode_
);
447 resizer
->RevertDrag();
449 EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS
,
450 event_filter
->mouse_warp_mode_
);
453 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
454 window_
.get(), gfx::Point(), HTRIGHT
));
455 // While resizing a window, warp should NOT be allowed.
456 EXPECT_EQ(MouseCursorEventFilter::WARP_NONE
,
457 event_filter
->mouse_warp_mode_
);
458 resizer
->CompleteDrag();
460 EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS
,
461 event_filter
->mouse_warp_mode_
);
464 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
465 window_
.get(), gfx::Point(), HTRIGHT
));
466 EXPECT_EQ(MouseCursorEventFilter::WARP_NONE
,
467 event_filter
->mouse_warp_mode_
);
468 resizer
->RevertDrag();
470 EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS
,
471 event_filter
->mouse_warp_mode_
);
474 // Verifies cursor's device scale factor is updated whe a window is moved across
475 // root windows with different device scale factors (http://crbug.com/154183).
476 TEST_F(DragWindowResizerTest
, CursorDeviceScaleFactor
) {
477 if (!SupportsMultipleDisplays())
480 // The secondary display is logically on the right, but on the system (e.g. X)
481 // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc.
482 UpdateDisplay("400x400,800x800*2");
483 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
484 ASSERT_EQ(2U, root_windows
.size());
486 test::CursorManagerTestApi
cursor_test_api(
487 Shell::GetInstance()->cursor_manager());
488 // Move window from the root window with 1.0 device scale factor to the root
489 // window with 2.0 device scale factor.
491 window_
->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
492 Shell::GetScreen()->GetPrimaryDisplay());
493 EXPECT_EQ(root_windows
[0], window_
->GetRootWindow());
494 // Grab (0, 0) of the window.
495 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
496 window_
.get(), gfx::Point(), HTCAPTION
));
497 EXPECT_EQ(1.0f
, cursor_test_api
.GetCurrentCursor().device_scale_factor());
498 ASSERT_TRUE(resizer
.get());
499 resizer
->Drag(CalculateDragPoint(*resizer
, 399, 200), 0);
500 WarpMouseCursorIfNecessary(root_windows
[0], gfx::Point(399, 200));
501 EXPECT_EQ(2.0f
, cursor_test_api
.GetCurrentCursor().device_scale_factor());
502 resizer
->CompleteDrag();
503 EXPECT_EQ(2.0f
, cursor_test_api
.GetCurrentCursor().device_scale_factor());
506 // Move window from the root window with 2.0 device scale factor to the root
507 // window with 1.0 device scale factor.
509 // Make sure the window is on the default container first.
510 aura::Window
* default_container
=
511 GetRootWindowController(root_windows
[1])
512 ->GetContainer(kShellWindowId_DefaultContainer
);
513 default_container
->AddChild(window_
.get());
514 window_
->SetBoundsInScreen(
515 gfx::Rect(600, 0, 50, 60),
516 Shell::GetScreen()->GetDisplayNearestWindow(root_windows
[1]));
517 EXPECT_EQ(root_windows
[1], window_
->GetRootWindow());
518 // Grab (0, 0) of the window.
519 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
520 window_
.get(), gfx::Point(), HTCAPTION
));
521 EXPECT_EQ(2.0f
, cursor_test_api
.GetCurrentCursor().device_scale_factor());
522 ASSERT_TRUE(resizer
.get());
523 resizer
->Drag(CalculateDragPoint(*resizer
, -200, 200), 0);
524 WarpMouseCursorIfNecessary(root_windows
[1], gfx::Point(400, 200));
525 EXPECT_EQ(1.0f
, cursor_test_api
.GetCurrentCursor().device_scale_factor());
526 resizer
->CompleteDrag();
527 EXPECT_EQ(1.0f
, cursor_test_api
.GetCurrentCursor().device_scale_factor());
531 // Verifies several kinds of windows can be moved across displays.
532 TEST_F(DragWindowResizerTest
, MoveWindowAcrossDisplays
) {
533 if (!SupportsMultipleDisplays())
536 // The secondary display is logically on the right, but on the system (e.g. X)
537 // layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc.
538 UpdateDisplay("400x400,400x400");
540 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
541 ASSERT_EQ(2U, root_windows
.size());
543 // Normal window can be moved across display.
545 aura::Window
* window
= window_
.get();
546 window
->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
547 Shell::GetScreen()->GetPrimaryDisplay());
548 // Grab (0, 0) of the window.
549 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
550 window
, gfx::Point(), HTCAPTION
));
551 ASSERT_TRUE(resizer
.get());
552 resizer
->Drag(CalculateDragPoint(*resizer
, 399, 200), 0);
553 EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows
[0],
554 gfx::Point(399, 200)));
555 resizer
->CompleteDrag();
558 // Always on top window can be moved across display.
560 aura::Window
* window
= always_on_top_window_
.get();
561 window
->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
562 Shell::GetScreen()->GetPrimaryDisplay());
563 // Grab (0, 0) of the window.
564 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
565 window
, gfx::Point(), HTCAPTION
));
566 ASSERT_TRUE(resizer
.get());
567 resizer
->Drag(CalculateDragPoint(*resizer
, 399, 200), 0);
568 EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows
[0],
569 gfx::Point(399, 200)));
570 resizer
->CompleteDrag();
573 // System modal window can be moved across display.
575 aura::Window
* window
= system_modal_window_
.get();
576 window
->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
577 Shell::GetScreen()->GetPrimaryDisplay());
578 // Grab (0, 0) of the window.
579 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
580 window
, gfx::Point(), HTCAPTION
));
581 ASSERT_TRUE(resizer
.get());
582 resizer
->Drag(CalculateDragPoint(*resizer
, 399, 200), 0);
583 EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows
[0],
584 gfx::Point(399, 200)));
585 resizer
->CompleteDrag();
588 // Transient window cannot be moved across display.
590 aura::Window
* window
= transient_child_
;
591 window
->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
592 Shell::GetScreen()->GetPrimaryDisplay());
593 // Grab (0, 0) of the window.
594 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
595 window
, gfx::Point(), HTCAPTION
));
596 ASSERT_TRUE(resizer
.get());
597 resizer
->Drag(CalculateDragPoint(*resizer
, 399, 200), 0);
598 EXPECT_FALSE(WarpMouseCursorIfNecessary(
600 gfx::Point(399, 200)));
601 resizer
->CompleteDrag();
604 // The parent of transient window can be moved across display.
606 aura::Window
* window
= transient_parent_
.get();
607 window
->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
608 Shell::GetScreen()->GetPrimaryDisplay());
609 // Grab (0, 0) of the window.
610 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
611 window
, gfx::Point(), HTCAPTION
));
612 ASSERT_TRUE(resizer
.get());
613 resizer
->Drag(CalculateDragPoint(*resizer
, 399, 200), 0);
614 EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows
[0],
615 gfx::Point(399, 200)));
616 resizer
->CompleteDrag();
619 // Panel window can be moved across display.
621 aura::Window
* window
= panel_window_
.get();
622 window
->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
623 Shell::GetScreen()->GetPrimaryDisplay());
624 // Grab (0, 0) of the window.
625 scoped_ptr
<WindowResizer
> resizer(CreateDragWindowResizer(
626 window
, gfx::Point(), HTCAPTION
));
627 ASSERT_TRUE(resizer
.get());
628 resizer
->Drag(CalculateDragPoint(*resizer
, 399, 200), 0);
629 EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows
[0],
630 gfx::Point(399, 200)));
631 resizer
->CompleteDrag();