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