mouse_cursor_event_filter_unittest.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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/display/mouse_cursor_event_filter.h"
6
7#include "ash/shell.h"
8#include "ash/test/ash_test_base.h"
9#include "ash/test/cursor_manager_test_api.h"
10#include "ash/display/display_controller.h"
11#include "ash/display/display_layout_store.h"
12#include "ash/display/display_manager.h"
13#include "ui/aura/env.h"
14#include "ui/aura/root_window.h"
15#include "ui/gfx/display.h"
16#include "ui/gfx/screen.h"
17
18namespace ash {
19namespace internal {
20namespace {
21
22gfx::Display GetPrimaryDisplay() {
23  return Shell::GetScreen()->GetDisplayNearestWindow(
24      Shell::GetAllRootWindows()[0]);
25}
26
27gfx::Display GetSecondaryDisplay() {
28  return Shell::GetScreen()->GetDisplayNearestWindow(
29      Shell::GetAllRootWindows()[1]);
30}
31
32}  // namespace
33
34class MouseCursorEventFilterTest : public test::AshTestBase {
35 public:
36  MouseCursorEventFilterTest() {}
37  virtual ~MouseCursorEventFilterTest() {}
38
39 protected:
40  MouseCursorEventFilter* event_filter() {
41    return Shell::GetInstance()->mouse_cursor_filter();
42  }
43
44  bool WarpMouseCursorIfNecessary(aura::RootWindow* target_root,
45                                  gfx::Point point_in_screen) {
46    bool is_warped = event_filter()->WarpMouseCursorIfNecessary(
47        target_root, point_in_screen);
48    event_filter()->reset_was_mouse_warped_for_test();
49    return is_warped;
50  }
51
52 private:
53  MouseCursorEventFilter* event_filter_;
54
55  DISALLOW_COPY_AND_ASSIGN(MouseCursorEventFilterTest);
56};
57
58// Verifies if the mouse pointer correctly moves to another display when there
59// are two displays.
60TEST_F(MouseCursorEventFilterTest, WarpMouse) {
61  if (!SupportsMultipleDisplays())
62    return;
63
64  UpdateDisplay("500x500,500x500");
65
66  ASSERT_EQ(
67      DisplayLayout::RIGHT,
68      Shell::GetInstance()->display_manager()->layout_store()->
69          default_display_layout().position);
70
71  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
72  EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(11, 11)));
73  EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(11, 11)));
74
75  // Touch the right edge of the primary root window. Pointer should warp.
76  EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(499, 11)));
77  EXPECT_EQ("501,11",  // by 2px.
78            aura::Env::GetInstance()->last_mouse_location().ToString());
79
80  // Touch the left edge of the secondary root window. Pointer should warp.
81  EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(500, 11)));
82  EXPECT_EQ("498,11",  // by 2px.
83            aura::Env::GetInstance()->last_mouse_location().ToString());
84
85  // Touch the left edge of the primary root window.
86  EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(0, 11)));
87  // Touch the top edge of the primary root window.
88  EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(11, 0)));
89  // Touch the bottom edge of the primary root window.
90  EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[0],
91                                          gfx::Point(11, 499)));
92  // Touch the right edge of the secondary root window.
93  EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[1],
94                                          gfx::Point(999, 11)));
95  // Touch the top edge of the secondary root window.
96  EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(11, 0)));
97  // Touch the bottom edge of the secondary root window.
98  EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[1],
99                                          gfx::Point(11, 499)));
100}
101
102// Verifies if the mouse pointer correctly moves to another display even when
103// two displays are not the same size.
104TEST_F(MouseCursorEventFilterTest, WarpMouseDifferentSizeDisplays) {
105  if (!SupportsMultipleDisplays())
106    return;
107
108  UpdateDisplay("500x500,600x600");  // the second one is larger.
109
110  ASSERT_EQ(
111      DisplayLayout::RIGHT,
112      Shell::GetInstance()->display_manager()->
113          GetCurrentDisplayLayout().position);
114
115  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
116  aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(623, 123));
117
118  // Touch the left edge of the secondary root window. Pointer should NOT warp
119  // because 1px left of (0, 500) is outside the primary root window.
120  EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(0, 500)));
121  EXPECT_EQ("623,123",  // by 2px.
122            aura::Env::GetInstance()->last_mouse_location().ToString());
123
124  // Touch the left edge of the secondary root window. Pointer should warp
125  // because 1px left of (0, 499) is inside the primary root window.
126  EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[1],
127                                         gfx::Point(500, 499)));
128  EXPECT_EQ("498,499",  // by 2px.
129            aura::Env::GetInstance()->last_mouse_location().ToString());
130}
131
132// Verifies if the mouse pointer correctly moves between displays with
133// different scale factors.
134TEST_F(MouseCursorEventFilterTest, WarpMouseDifferentScaleDisplays) {
135  if (!SupportsMultipleDisplays())
136    return;
137
138  UpdateDisplay("500x500,600x600*2");
139
140  ASSERT_EQ(
141      DisplayLayout::RIGHT,
142      Shell::GetInstance()->display_manager()->
143          GetCurrentDisplayLayout().position);
144
145  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
146  aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(900, 123));
147
148  // This emulates the dragging back to the 2nd display, which has
149  // higher scale factor, by having 2nd display's root as target
150  // but have the edge of 1st display.
151  EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[1],
152                                         gfx::Point(498, 123)));
153  EXPECT_EQ("502,123",
154            aura::Env::GetInstance()->last_mouse_location().ToString());
155
156  // Touch the edge of 2nd display again and make sure it warps to
157  // 1st dislay.
158  EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[1],
159                                         gfx::Point(500, 123)));
160  EXPECT_EQ("496,123",
161            aura::Env::GetInstance()->last_mouse_location().ToString());
162}
163
164TEST_F(MouseCursorEventFilterTest, DoNotWarpTwice) {
165  if (!SupportsMultipleDisplays())
166    return;
167
168  UpdateDisplay("500x500,600x600");
169
170  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
171  aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(623, 123));
172
173  // Touch the right edge of the primary root window. Pointer should warp.
174  EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessary(root_windows[0],
175                                                         gfx::Point(499, 11)));
176  EXPECT_EQ("501,11",  // by 2px.
177            aura::Env::GetInstance()->last_mouse_location().ToString());
178
179  // Touch the left edge of the secondary root window immediately. This should
180  // be ignored.
181  EXPECT_FALSE(event_filter()->WarpMouseCursorIfNecessary(root_windows[1],
182                                                          gfx::Point(500, 11)));
183
184  // Touch the left edge of the secondary root window again, pointer should
185  // warp for this time.
186  EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessary(root_windows[1],
187                                                         gfx::Point(500, 11)));
188  EXPECT_EQ("498,11",  // by 2px.
189            aura::Env::GetInstance()->last_mouse_location().ToString());
190}
191
192// Verifies if MouseCursorEventFilter::set_mouse_warp_mode() works as expected.
193TEST_F(MouseCursorEventFilterTest, SetMouseWarpModeFlag) {
194  if (!SupportsMultipleDisplays())
195    return;
196
197  UpdateDisplay("500x500,500x500");
198
199  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
200  aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(1, 1));
201
202  event_filter()->set_mouse_warp_mode(MouseCursorEventFilter::WARP_NONE);
203  EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[0],
204                                          gfx::Point(499, 11)));
205  EXPECT_EQ("1,1",
206            aura::Env::GetInstance()->last_mouse_location().ToString());
207
208  event_filter()->set_mouse_warp_mode(MouseCursorEventFilter::WARP_ALWAYS);
209  EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(499, 11)));
210  EXPECT_EQ("501,11",
211            aura::Env::GetInstance()->last_mouse_location().ToString());
212}
213
214// Verifies if MouseCursorEventFilter's bounds calculation works correctly.
215TEST_F(MouseCursorEventFilterTest, IndicatorBoundsTestOnRight) {
216  if (!SupportsMultipleDisplays())
217    return;
218
219  UpdateDisplay("360x360,700x700");
220  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
221
222  DisplayController* controller =
223      Shell::GetInstance()->display_controller();
224  DisplayLayout layout(DisplayLayout::RIGHT, 0);
225  controller->SetLayoutForCurrentDisplays(layout);
226  event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
227  EXPECT_EQ("359,16 1x344", event_filter()->src_indicator_bounds_.ToString());
228  EXPECT_EQ("360,0 1x360", event_filter()->dst_indicator_bounds_.ToString());
229  event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
230  EXPECT_EQ("360,16 1x344", event_filter()->src_indicator_bounds_.ToString());
231  EXPECT_EQ("359,0 1x360", event_filter()->dst_indicator_bounds_.ToString());
232
233  // Move 2nd display downwards a bit.
234  layout.offset = 5;
235  controller->SetLayoutForCurrentDisplays(layout);
236  event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
237  // This is same as before because the 2nd display's y is above
238  // the indicator's x.
239  EXPECT_EQ("359,16 1x344", event_filter()->src_indicator_bounds_.ToString());
240  EXPECT_EQ("360,5 1x355", event_filter()->dst_indicator_bounds_.ToString());
241  event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
242  EXPECT_EQ("360,21 1x339", event_filter()->src_indicator_bounds_.ToString());
243  EXPECT_EQ("359,5 1x355", event_filter()->dst_indicator_bounds_.ToString());
244
245  // Move it down further so that the shared edge is shorter than
246  // minimum hole size (160).
247  layout.offset = 200;
248  controller->SetLayoutForCurrentDisplays(layout);
249  event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
250  EXPECT_EQ("359,200 1x160", event_filter()->src_indicator_bounds_.ToString());
251  EXPECT_EQ("360,200 1x160", event_filter()->dst_indicator_bounds_.ToString());
252  event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
253  EXPECT_EQ("360,200 1x160", event_filter()->src_indicator_bounds_.ToString());
254  EXPECT_EQ("359,200 1x160", event_filter()->dst_indicator_bounds_.ToString());
255
256  // Now move 2nd display upwards
257  layout.offset = -5;
258  controller->SetLayoutForCurrentDisplays(layout);
259  event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
260  EXPECT_EQ("359,16 1x344", event_filter()->src_indicator_bounds_.ToString());
261  EXPECT_EQ("360,0 1x360", event_filter()->dst_indicator_bounds_.ToString());
262  event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
263  // 16 px are reserved on 2nd display from top, so y must be
264  // (16 - 5) = 11
265  EXPECT_EQ("360,11 1x349", event_filter()->src_indicator_bounds_.ToString());
266  EXPECT_EQ("359,0 1x360", event_filter()->dst_indicator_bounds_.ToString());
267
268  event_filter()->HideSharedEdgeIndicator();
269}
270
271TEST_F(MouseCursorEventFilterTest, IndicatorBoundsTestOnLeft) {
272  if (!SupportsMultipleDisplays())
273    return;
274
275  UpdateDisplay("360x360,700x700");
276  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
277
278  DisplayController* controller =
279      Shell::GetInstance()->display_controller();
280  DisplayLayout layout(DisplayLayout::LEFT, 0);
281  controller->SetLayoutForCurrentDisplays(layout);
282  event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
283  EXPECT_EQ("0,16 1x344", event_filter()->src_indicator_bounds_.ToString());
284  EXPECT_EQ("-1,0 1x360", event_filter()->dst_indicator_bounds_.ToString());
285  event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
286  EXPECT_EQ("-1,16 1x344", event_filter()->src_indicator_bounds_.ToString());
287  EXPECT_EQ("0,0 1x360", event_filter()->dst_indicator_bounds_.ToString());
288
289  layout.offset = 250;
290  controller->SetLayoutForCurrentDisplays(layout);
291  event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
292  EXPECT_EQ("0,250 1x110", event_filter()->src_indicator_bounds_.ToString());
293  EXPECT_EQ("-1,250 1x110", event_filter()->dst_indicator_bounds_.ToString());
294  event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
295  EXPECT_EQ("-1,250 1x110", event_filter()->src_indicator_bounds_.ToString());
296  EXPECT_EQ("0,250 1x110", event_filter()->dst_indicator_bounds_.ToString());
297  event_filter()->HideSharedEdgeIndicator();
298}
299
300TEST_F(MouseCursorEventFilterTest, IndicatorBoundsTestOnTopBottom) {
301  if (!SupportsMultipleDisplays())
302    return;
303
304  UpdateDisplay("360x360,700x700");
305  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
306
307  DisplayController* controller =
308      Shell::GetInstance()->display_controller();
309  DisplayLayout layout(DisplayLayout::TOP, 0);
310  controller->SetLayoutForCurrentDisplays(layout);
311  event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
312  EXPECT_EQ("0,0 360x1", event_filter()->src_indicator_bounds_.ToString());
313  EXPECT_EQ("0,-1 360x1", event_filter()->dst_indicator_bounds_.ToString());
314  event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
315  EXPECT_EQ("0,-1 360x1", event_filter()->src_indicator_bounds_.ToString());
316  EXPECT_EQ("0,0 360x1", event_filter()->dst_indicator_bounds_.ToString());
317
318  layout.offset = 250;
319  controller->SetLayoutForCurrentDisplays(layout);
320  event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
321  EXPECT_EQ("250,0 110x1", event_filter()->src_indicator_bounds_.ToString());
322  EXPECT_EQ("250,-1 110x1", event_filter()->dst_indicator_bounds_.ToString());
323  event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
324  EXPECT_EQ("250,-1 110x1", event_filter()->src_indicator_bounds_.ToString());
325  EXPECT_EQ("250,0 110x1", event_filter()->dst_indicator_bounds_.ToString());
326
327  layout.position = DisplayLayout::BOTTOM;
328  layout.offset = 0;
329  controller->SetLayoutForCurrentDisplays(layout);
330  event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
331  EXPECT_EQ("0,359 360x1", event_filter()->src_indicator_bounds_.ToString());
332  EXPECT_EQ("0,360 360x1", event_filter()->dst_indicator_bounds_.ToString());
333  event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
334  EXPECT_EQ("0,360 360x1", event_filter()->src_indicator_bounds_.ToString());
335  EXPECT_EQ("0,359 360x1", event_filter()->dst_indicator_bounds_.ToString());
336
337  event_filter()->HideSharedEdgeIndicator();
338}
339
340// Verifies cursor's device scale factor is updated when a cursor has moved
341// across root windows with different device scale factors
342// (http://crbug.com/154183).
343TEST_F(MouseCursorEventFilterTest, CursorDeviceScaleFactor) {
344  if (!SupportsMultipleDisplays())
345    return;
346
347  UpdateDisplay("400x400,800x800*2");
348  DisplayController* controller =
349      Shell::GetInstance()->display_controller();
350  controller->SetLayoutForCurrentDisplays(
351      DisplayLayout(DisplayLayout::RIGHT, 0));
352  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
353  ASSERT_EQ(2U, root_windows.size());
354  test::CursorManagerTestApi cursor_test_api(
355      Shell::GetInstance()->cursor_manager());
356
357  EXPECT_EQ(1.0f, cursor_test_api.GetDisplay().device_scale_factor());
358  WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(399, 200));
359  EXPECT_EQ(2.0f, cursor_test_api.GetDisplay().device_scale_factor());
360  WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(400, 200));
361  EXPECT_EQ(1.0f, cursor_test_api.GetDisplay().device_scale_factor());
362}
363
364}  // namespace internal
365}  // namespace ash
366