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