Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ash / wm / drag_window_resizer_unittest.cc
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/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"
28
29 namespace ash {
30 namespace {
31
32 const int kRootHeight = 600;
33
34 }  // namespace
35
36 class DragWindowResizerTest : public test::AshTestBase {
37  public:
38   DragWindowResizerTest() {}
39   virtual ~DragWindowResizerTest() {}
40
41   virtual void SetUp() override {
42     AshTestBase::SetUp();
43     UpdateDisplay(base::StringPrintf("800x%d", kRootHeight));
44
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());
54     window_->set_id(1);
55
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);
62
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);
70
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);
76
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);
83
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());
88   }
89
90   virtual void TearDown() override {
91     window_.reset();
92     always_on_top_window_.reset();
93     system_modal_window_.reset();
94     transient_parent_.reset();
95     panel_window_.reset();
96     AshTestBase::TearDown();
97   }
98
99  protected:
100   gfx::Point CalculateDragPoint(const WindowResizer& resizer,
101                                 int delta_x,
102                                 int delta_y) const {
103     gfx::Point location = resizer.GetInitialLocation();
104     location.set_x(location.x() + delta_x);
105     location.set_y(location.y() + delta_y);
106     return location;
107   }
108
109   ShelfLayoutManager* shelf_layout_manager() {
110     return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
111   }
112
113   static WindowResizer* CreateDragWindowResizer(
114       aura::Window* window,
115       const gfx::Point& point_in_parent,
116       int window_component) {
117     return CreateWindowResizer(
118         window,
119         point_in_parent,
120         window_component,
121         aura::client::WINDOW_MOVE_SOURCE_MOUSE).release();
122   }
123
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();
131     return is_warped;
132   }
133
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_;
140
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_;
147
148  private:
149   DISALLOW_COPY_AND_ASSIGN(DragWindowResizerTest);
150 };
151
152 // Verifies a window can be moved from the primary display to another.
153 TEST_F(DragWindowResizerTest, WindowDragWithMultiDisplays) {
154   if (!SupportsMultipleDisplays())
155     return;
156
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());
162
163   window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
164                              Shell::GetScreen()->GetPrimaryDisplay());
165   EXPECT_EQ(root_windows[0], window_->GetRootWindow());
166   {
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
176     // changed.
177     EXPECT_EQ(root_windows[1], window_->GetRootWindow());
178     EXPECT_EQ("0,10 50x60", window_->bounds().ToString());
179   }
180
181   window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
182                              Shell::GetScreen()->GetPrimaryDisplay());
183   EXPECT_EQ(root_windows[0], window_->GetRootWindow());
184   {
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
194     // not be changed.
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());
198   }
199
200   window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
201                              Shell::GetScreen()->GetPrimaryDisplay());
202   EXPECT_EQ(root_windows[0], window_->GetRootWindow());
203   {
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());
219   }
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());
225   {
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);
239
240     EXPECT_LE(10, intersect.width());
241     EXPECT_LE(10, intersect.height());
242     EXPECT_TRUE(window_bounds_in_screen.Contains(gfx::Point(800, 10)));
243   }
244
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());
250   {
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)));
269   }
270 }
271
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())
276     return;
277
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());
283
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());
291   window->Show();
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());
296   {
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
306     // changed.
307     EXPECT_EQ(root_windows[1], window->GetRootWindow());
308     EXPECT_EQ(root_windows[1], ash::Shell::GetTargetRootWindow());
309   }
310 }
311
312 // Verifies a window can be moved from the secondary display to primary.
313 TEST_F(DragWindowResizerTest, WindowDragWithMultiDisplaysRightToLeft) {
314   if (!SupportsMultipleDisplays())
315     return;
316
317   UpdateDisplay("800x600,800x600");
318   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
319   ASSERT_EQ(2U, root_windows.size());
320
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());
325   {
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());
338   }
339 }
340
341 // Verifies the drag window is shown correctly.
342 TEST_F(DragWindowResizerTest, DragWindowController) {
343   if (!SupportsMultipleDisplays())
344     return;
345
346   UpdateDisplay("800x600,800x600");
347   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
348   ASSERT_EQ(2U, root_windows.size());
349
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());
354   {
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());
361
362     // The pointer is inside the primary root. The drag window controller
363     // should be NULL.
364     resizer->Drag(CalculateDragPoint(*resizer, 10, 10), 0);
365     EXPECT_FALSE(drag_resizer->drag_window_controller_.get());
366
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);
372
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());
381
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());
387
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());
395
396     resizer->CompleteDrag();
397     EXPECT_EQ(root_windows[1], window_->GetRootWindow());
398     EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
399   }
400
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());
406   {
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());
413
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());
418   }
419 }
420
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));
428
429   EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
430             event_filter->mouse_warp_mode_);
431   {
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();
438   }
439   EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
440             event_filter->mouse_warp_mode_);
441
442   {
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();
448   }
449   EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
450             event_filter->mouse_warp_mode_);
451
452   {
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();
459   }
460   EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
461             event_filter->mouse_warp_mode_);
462
463   {
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();
469   }
470   EXPECT_EQ(MouseCursorEventFilter::WARP_ALWAYS,
471             event_filter->mouse_warp_mode_);
472 }
473
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())
478     return;
479
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());
485
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.
490   {
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());
504   }
505
506   // Move window from the root window with 2.0 device scale factor to the root
507   // window with 1.0 device scale factor.
508   {
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());
528   }
529 }
530
531 // Verifies several kinds of windows can be moved across displays.
532 TEST_F(DragWindowResizerTest, MoveWindowAcrossDisplays) {
533   if (!SupportsMultipleDisplays())
534     return;
535
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");
539
540   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
541   ASSERT_EQ(2U, root_windows.size());
542
543   // Normal window can be moved across display.
544   {
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();
556   }
557
558   // Always on top window can be moved across display.
559   {
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();
571   }
572
573   // System modal window can be moved across display.
574   {
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();
586   }
587
588   // Transient window cannot be moved across display.
589   {
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(
599         root_windows[0],
600         gfx::Point(399, 200)));
601     resizer->CompleteDrag();
602   }
603
604   // The parent of transient window can be moved across display.
605   {
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();
617   }
618
619   // Panel window can be moved across display.
620   {
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();
632   }
633 }
634
635 }  // namespace ash