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