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