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.
5 #include "ash/display/mouse_cursor_event_filter.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"
19 class MouseCursorEventFilterTest : public test::AshTestBase {
21 MouseCursorEventFilterTest() {}
22 ~MouseCursorEventFilterTest() override {}
25 MouseCursorEventFilter* event_filter() {
26 return Shell::GetInstance()->mouse_cursor_filter();
29 bool WarpMouseCursorIfNecessary(aura::Window* target_root,
30 gfx::Point point_in_screen) {
31 bool is_warped = event_filter()->WarpMouseCursorIfNecessaryForTest(
32 target_root, point_in_screen);
33 event_filter()->reset_was_mouse_warped_for_test();
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,
44 ui::Event::DispatcherApi(&pressed).set_target(drag_source_root);
45 event_filter()->OnMouseEvent(&pressed);
46 bool is_warped = event_filter()->WarpMouseCursorIfNecessaryForTest(
47 target_root, point_in_screen);
48 event_filter()->reset_was_mouse_warped_for_test();
50 ui::MouseEvent released(ui::ET_MOUSE_RELEASED, location,
52 ui::Event::DispatcherApi(&released).set_target(drag_source_root);
53 event_filter()->OnMouseEvent(&released);
58 MouseCursorEventFilter* event_filter_;
60 DISALLOW_COPY_AND_ASSIGN(MouseCursorEventFilterTest);
63 // Verifies if the mouse pointer correctly moves to another display when there
65 TEST_F(MouseCursorEventFilterTest, WarpMouse) {
66 if (!SupportsMultipleDisplays())
69 UpdateDisplay("500x500,500x500");
73 Shell::GetInstance()->display_manager()->layout_store()->
74 default_display_layout().position);
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)));
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());
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());
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)));
107 // Verifies if the mouse pointer correctly moves to another display even when
108 // two displays are not the same size.
109 TEST_F(MouseCursorEventFilterTest, WarpMouseDifferentSizeDisplays) {
110 if (!SupportsMultipleDisplays())
113 UpdateDisplay("500x500,600x600"); // the second one is larger.
116 DisplayLayout::RIGHT,
117 Shell::GetInstance()->display_manager()->
118 GetCurrentDisplayLayout().position);
120 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
121 aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(623, 123));
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());
129 // Touch the left edge of the secondary root window. Pointer should warp
130 // because 1px left of (0, 480) is inside the primary root window.
132 WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(500, 480)));
133 EXPECT_EQ("498,480", // by 2px.
134 aura::Env::GetInstance()->last_mouse_location().ToString());
137 // Verifies if the mouse pointer correctly moves between displays with
138 // different scale factors. In native coords mode, there is no
139 // difference between drag and move.
140 TEST_F(MouseCursorEventFilterTest, WarpMouseDifferentScaleDisplaysInNative) {
141 if (!SupportsMultipleDisplays())
144 UpdateDisplay("500x500,600x600*2");
146 ASSERT_EQ(DisplayLayout::RIGHT,
149 ->GetCurrentDisplayLayout()
152 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
153 aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(900, 123));
155 EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessaryForTest(
156 root_windows[0], gfx::Point(499, 123)));
158 aura::Env::GetInstance()->last_mouse_location().ToString());
160 event_filter()->reset_was_mouse_warped_for_test();
162 // Touch the edge of 2nd display again and make sure it warps to
164 EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessaryForTest(
165 root_windows[1], gfx::Point(500, 123)));
167 aura::Env::GetInstance()->last_mouse_location().ToString());
170 // Verifies if MouseCursorEventFilter::set_mouse_warp_mode() works as expected.
171 TEST_F(MouseCursorEventFilterTest, SetMouseWarpModeFlag) {
172 if (!SupportsMultipleDisplays())
175 UpdateDisplay("500x500,500x500");
177 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
178 aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(1, 1));
180 event_filter()->set_mouse_warp_mode(MouseCursorEventFilter::WARP_NONE);
181 EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[0],
182 gfx::Point(499, 11)));
184 aura::Env::GetInstance()->last_mouse_location().ToString());
186 event_filter()->set_mouse_warp_mode(MouseCursorEventFilter::WARP_ALWAYS);
187 EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(499, 11)));
189 aura::Env::GetInstance()->last_mouse_location().ToString());
192 // Verifies if MouseCursorEventFilter's bounds calculation works correctly.
193 TEST_F(MouseCursorEventFilterTest, IndicatorBoundsTestOnRight) {
194 if (!SupportsMultipleDisplays())
197 UpdateDisplay("360x360,700x700");
198 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
200 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
201 DisplayLayout layout(DisplayLayout::RIGHT, 0);
202 display_manager->SetLayoutForCurrentDisplays(layout);
203 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
204 EXPECT_EQ("359,16 1x344", event_filter()->src_indicator_bounds_.ToString());
205 EXPECT_EQ("360,0 1x360", event_filter()->dst_indicator_bounds_.ToString());
206 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
207 EXPECT_EQ("360,16 1x344", event_filter()->src_indicator_bounds_.ToString());
208 EXPECT_EQ("359,0 1x360", event_filter()->dst_indicator_bounds_.ToString());
210 // Move 2nd display downwards a bit.
212 display_manager->SetLayoutForCurrentDisplays(layout);
213 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
214 // This is same as before because the 2nd display's y is above
215 // the indicator's x.
216 EXPECT_EQ("359,16 1x344", event_filter()->src_indicator_bounds_.ToString());
217 EXPECT_EQ("360,5 1x355", event_filter()->dst_indicator_bounds_.ToString());
218 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
219 EXPECT_EQ("360,21 1x339", event_filter()->src_indicator_bounds_.ToString());
220 EXPECT_EQ("359,5 1x355", event_filter()->dst_indicator_bounds_.ToString());
222 // Move it down further so that the shared edge is shorter than
223 // minimum hole size (160).
225 display_manager->SetLayoutForCurrentDisplays(layout);
226 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
227 EXPECT_EQ("359,200 1x160", event_filter()->src_indicator_bounds_.ToString());
228 EXPECT_EQ("360,200 1x160", event_filter()->dst_indicator_bounds_.ToString());
229 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
230 EXPECT_EQ("360,200 1x160", event_filter()->src_indicator_bounds_.ToString());
231 EXPECT_EQ("359,200 1x160", event_filter()->dst_indicator_bounds_.ToString());
233 // Now move 2nd display upwards
235 display_manager->SetLayoutForCurrentDisplays(layout);
236 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
237 EXPECT_EQ("359,16 1x344", event_filter()->src_indicator_bounds_.ToString());
238 EXPECT_EQ("360,0 1x360", event_filter()->dst_indicator_bounds_.ToString());
239 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
240 // 16 px are reserved on 2nd display from top, so y must be
242 EXPECT_EQ("360,11 1x349", event_filter()->src_indicator_bounds_.ToString());
243 EXPECT_EQ("359,0 1x360", event_filter()->dst_indicator_bounds_.ToString());
245 event_filter()->HideSharedEdgeIndicator();
248 TEST_F(MouseCursorEventFilterTest, IndicatorBoundsTestOnLeft) {
249 if (!SupportsMultipleDisplays())
252 UpdateDisplay("360x360,700x700");
253 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
255 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
256 DisplayLayout layout(DisplayLayout::LEFT, 0);
257 display_manager->SetLayoutForCurrentDisplays(layout);
258 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
259 EXPECT_EQ("0,16 1x344", event_filter()->src_indicator_bounds_.ToString());
260 EXPECT_EQ("-1,0 1x360", event_filter()->dst_indicator_bounds_.ToString());
261 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
262 EXPECT_EQ("-1,16 1x344", event_filter()->src_indicator_bounds_.ToString());
263 EXPECT_EQ("0,0 1x360", event_filter()->dst_indicator_bounds_.ToString());
266 display_manager->SetLayoutForCurrentDisplays(layout);
267 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
268 EXPECT_EQ("0,250 1x110", event_filter()->src_indicator_bounds_.ToString());
269 EXPECT_EQ("-1,250 1x110", event_filter()->dst_indicator_bounds_.ToString());
270 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
271 EXPECT_EQ("-1,250 1x110", event_filter()->src_indicator_bounds_.ToString());
272 EXPECT_EQ("0,250 1x110", event_filter()->dst_indicator_bounds_.ToString());
273 event_filter()->HideSharedEdgeIndicator();
276 TEST_F(MouseCursorEventFilterTest, IndicatorBoundsTestOnTopBottom) {
277 if (!SupportsMultipleDisplays())
280 UpdateDisplay("360x360,700x700");
281 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
283 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
284 DisplayLayout layout(DisplayLayout::TOP, 0);
285 display_manager->SetLayoutForCurrentDisplays(layout);
286 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
287 EXPECT_EQ("0,0 360x1", event_filter()->src_indicator_bounds_.ToString());
288 EXPECT_EQ("0,-1 360x1", event_filter()->dst_indicator_bounds_.ToString());
289 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
290 EXPECT_EQ("0,-1 360x1", event_filter()->src_indicator_bounds_.ToString());
291 EXPECT_EQ("0,0 360x1", event_filter()->dst_indicator_bounds_.ToString());
294 display_manager->SetLayoutForCurrentDisplays(layout);
295 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
296 EXPECT_EQ("250,0 110x1", event_filter()->src_indicator_bounds_.ToString());
297 EXPECT_EQ("250,-1 110x1", event_filter()->dst_indicator_bounds_.ToString());
298 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
299 EXPECT_EQ("250,-1 110x1", event_filter()->src_indicator_bounds_.ToString());
300 EXPECT_EQ("250,0 110x1", event_filter()->dst_indicator_bounds_.ToString());
302 layout.position = DisplayLayout::BOTTOM;
304 display_manager->SetLayoutForCurrentDisplays(layout);
305 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
306 EXPECT_EQ("0,359 360x1", event_filter()->src_indicator_bounds_.ToString());
307 EXPECT_EQ("0,360 360x1", event_filter()->dst_indicator_bounds_.ToString());
308 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
309 EXPECT_EQ("0,360 360x1", event_filter()->src_indicator_bounds_.ToString());
310 EXPECT_EQ("0,359 360x1", event_filter()->dst_indicator_bounds_.ToString());
312 event_filter()->HideSharedEdgeIndicator();
315 // Verifies cursor's device scale factor is updated when a cursor has moved
316 // across root windows with different device scale factors
317 // (http://crbug.com/154183).
318 TEST_F(MouseCursorEventFilterTest, CursorDeviceScaleFactor) {
319 if (!SupportsMultipleDisplays())
322 UpdateDisplay("400x400,800x800*2");
323 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
324 display_manager->SetLayoutForCurrentDisplays(
325 DisplayLayout(DisplayLayout::RIGHT, 0));
326 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
327 ASSERT_EQ(2U, root_windows.size());
328 test::CursorManagerTestApi cursor_test_api(
329 Shell::GetInstance()->cursor_manager());
331 EXPECT_EQ(1.0f, cursor_test_api.GetCurrentCursor().device_scale_factor());
332 WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(399, 200));
333 EXPECT_EQ(2.0f, cursor_test_api.GetCurrentCursor().device_scale_factor());
334 WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(400, 200));
335 EXPECT_EQ(1.0f, cursor_test_api.GetCurrentCursor().device_scale_factor());