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