1 // Copyright 2015 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/unified_mouse_warp_controller.h"
7 #include "ash/display/display_manager.h"
8 #include "ash/display/display_util.h"
9 #include "ash/display/mirror_window_controller.h"
10 #include "ash/display/mouse_cursor_event_filter.h"
11 #include "ash/host/ash_window_tree_host.h"
12 #include "ash/shell.h"
13 #include "ash/test/ash_test_base.h"
14 #include "ash/test/display_manager_test_api.h"
15 #include "ui/aura/env.h"
16 #include "ui/aura/window_tree_host.h"
17 #include "ui/events/test/event_generator.h"
18 #include "ui/gfx/display.h"
19 #include "ui/gfx/screen.h"
20 #include "ui/wm/core/coordinate_conversion.h"
24 class UnifiedMouseWarpControllerTest
: public test::AshTestBase
{
26 UnifiedMouseWarpControllerTest() {}
27 ~UnifiedMouseWarpControllerTest() override
{}
29 void SetUp() override
{
30 test::AshTestBase::SetUp();
31 Shell::GetInstance()->display_manager()->SetUnifiedDesktopEnabled(true);
35 bool FindMirrroingDisplayIdContainingNativePoint(
36 const gfx::Point
& point_in_native
,
38 gfx::Point
* point_in_mirroring_host
,
39 gfx::Point
* point_in_unified_host
) {
40 DisplayManager
* display_manager
= Shell::GetInstance()->display_manager();
41 for (auto display
: display_manager
->software_mirroring_display_list()) {
42 DisplayInfo info
= display_manager
->GetDisplayInfo(display
.id());
43 if (info
.bounds_in_native().Contains(point_in_native
)) {
44 *display_id
= info
.id();
45 *point_in_unified_host
= point_in_native
;
46 const gfx::Point
& origin
= info
.bounds_in_native().origin();
47 // Convert to mirroring host.
48 point_in_unified_host
->Offset(-origin
.x(), -origin
.y());
49 *point_in_mirroring_host
= *point_in_unified_host
;
50 // Convert from mirroring host to unified host.
51 AshWindowTreeHost
* ash_host
=
53 ->window_tree_host_manager()
54 ->mirror_window_controller()
55 ->GetAshWindowTreeHostForDisplayId(info
.id());
56 ash_host
->AsWindowTreeHost()->ConvertPointFromHost(
57 point_in_unified_host
);
64 bool TestIfMouseWarpsAt(const gfx::Point
& point_in_native
) {
65 static_cast<UnifiedMouseWarpController
*>(
67 ->mouse_cursor_filter()
68 ->mouse_warp_controller_for_test())
69 ->update_location_for_test();
70 DisplayManager
* display_manager
= Shell::GetInstance()->display_manager();
71 int64 orig_mirroring_display_id
;
72 gfx::Point point_in_unified_host
;
73 gfx::Point point_in_mirroring_host
;
74 if (!FindMirrroingDisplayIdContainingNativePoint(
75 point_in_native
, &orig_mirroring_display_id
,
76 &point_in_mirroring_host
, &point_in_unified_host
)) {
79 #if defined(USE_OZONE)
80 // The location of the ozone's native event is relative to the host.
81 GetEventGenerator().MoveMouseToWithNative(point_in_unified_host
,
82 point_in_mirroring_host
);
84 GetEventGenerator().MoveMouseToWithNative(point_in_unified_host
,
87 aura::Window
* root
= Shell::GetPrimaryRootWindow();
88 gfx::Point new_location_in_unified_host
=
89 aura::Env::GetInstance()->last_mouse_location();
90 // Convert screen to the host.
91 root
->GetHost()->ConvertPointToHost(&new_location_in_unified_host
);
93 int new_index
= FindDisplayIndexContainingPoint(
94 display_manager
->software_mirroring_display_list(),
95 new_location_in_unified_host
);
98 return orig_mirroring_display_id
!=
99 display_manager
->software_mirroring_display_list()[new_index
].id();
102 MouseCursorEventFilter
* event_filter() {
103 return Shell::GetInstance()->mouse_cursor_filter();
106 UnifiedMouseWarpController
* mouse_warp_controller() {
107 return static_cast<UnifiedMouseWarpController
*>(
108 event_filter()->mouse_warp_controller_for_test());
111 void BoundaryTestBody(const std::string
& displays_with_same_height
,
112 const std::string
& displays_with_different_heights
) {
113 UpdateDisplay(displays_with_same_height
);
114 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
115 // Let the UnifiedMouseWarpController compute the bounds by
116 // generating a mouse move event.
117 GetEventGenerator().MoveMouseTo(gfx::Point(0, 0));
118 EXPECT_EQ("399,0 1x400",
119 mouse_warp_controller()->first_edge_bounds_in_native_
.ToString());
122 mouse_warp_controller()->second_edge_bounds_in_native_
.ToString());
125 UpdateDisplay(displays_with_different_heights
);
126 root_windows
= Shell::GetAllRootWindows();
127 // Let the UnifiedMouseWarpController compute the bounds by
128 // generating a mouse move event.
129 GetEventGenerator().MoveMouseTo(gfx::Point(1, 1));
131 EXPECT_EQ("399,0 1x400",
132 mouse_warp_controller()->first_edge_bounds_in_native_
.ToString());
135 mouse_warp_controller()->second_edge_bounds_in_native_
.ToString());
138 void NoWarpTestBody() {
139 // Touch the left edge of the first display.
140 EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(0, 10)));
141 // Touch the top edge of the first display.
142 EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(10, 0)));
143 // Touch the bottom edge of the first display.
144 EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(10, 499)));
146 // Touch the right edge of the second display.
147 EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(1099, 10)));
148 // Touch the top edge of the second display.
149 EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(610, 0)));
150 // Touch the bottom edge of the second display.
151 EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(610, 499)));
155 DISALLOW_COPY_AND_ASSIGN(UnifiedMouseWarpControllerTest
);
158 // Verifies if MouseCursorEventFilter's bounds calculation works correctly.
159 TEST_F(UnifiedMouseWarpControllerTest
, BoundaryTest
) {
160 if (!SupportsMultipleDisplays())
165 BoundaryTestBody("400x400,0+450-700x400", "400x400,0+450-700x600");
169 BoundaryTestBody("400x400*2,0+450-700x400", "400x400*2,0+450-700x600");
173 BoundaryTestBody("400x400,0+450-700x400*2", "400x400,0+450-700x600*2");
177 BoundaryTestBody("400x400*2,0+450-700x400*2", "400x400*2,0+450-700x600*2");
181 // Verifies if the mouse pointer correctly moves to another display in
182 // unified desktop mode.
183 TEST_F(UnifiedMouseWarpControllerTest
, WarpMouse
) {
184 if (!SupportsMultipleDisplays())
186 UpdateDisplay("500x500,600+0-500x500");
187 ASSERT_EQ(1, gfx::Screen::GetScreenFor(Shell::GetPrimaryRootWindow())
190 EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(10, 10)));
191 // Touch the right edge of the first display. Pointer should warp.
192 EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(499, 10)));
193 EXPECT_EQ("501,10", // by 2px.
194 aura::Env::GetInstance()->last_mouse_location().ToString());
196 // Touch the left edge of the second display. Pointer should warp.
197 EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(600, 10)));
198 EXPECT_EQ("498,10", // by 2px.
199 aura::Env::GetInstance()->last_mouse_location().ToString());
201 SCOPED_TRACE("1x1 NO WARP");
205 // With 2X and 1X displays
206 UpdateDisplay("500x500*2,600+0-500x500");
207 ASSERT_EQ(1, gfx::Screen::GetScreenFor(Shell::GetPrimaryRootWindow())
210 EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(10, 10)));
211 // Touch the right edge of the first display. Pointer should warp.
212 EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(499, 10)));
213 EXPECT_EQ("250,5", // moved to 501 by 2px, devided by 2 (dsf).
214 aura::Env::GetInstance()->last_mouse_location().ToString());
216 // Touch the left edge of the second display. Pointer should warp.
217 EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(600, 10)));
218 EXPECT_EQ("249,5", // moved to 498 by 2px, divided by 2 (dsf).
219 aura::Env::GetInstance()->last_mouse_location().ToString());
222 SCOPED_TRACE("2x1 NO WARP");
226 // With 1X and 2X displays
227 UpdateDisplay("500x500,600+0-500x500*2");
228 ASSERT_EQ(1, gfx::Screen::GetScreenFor(Shell::GetPrimaryRootWindow())
231 EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(10, 10)));
232 // Touch the right edge of the first display. Pointer should warp.
233 EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(499, 10)));
234 EXPECT_EQ("501,10", // by 2px.
235 aura::Env::GetInstance()->last_mouse_location().ToString());
237 // Touch the left edge of the second display. Pointer should warp.
238 EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(600, 10)));
239 EXPECT_EQ("498,10", // by 2px.
240 aura::Env::GetInstance()->last_mouse_location().ToString());
242 SCOPED_TRACE("1x2 NO WARP");
246 // With two 2X displays
247 UpdateDisplay("500x500*2,600+0-500x500*2");
248 ASSERT_EQ(1, gfx::Screen::GetScreenFor(Shell::GetPrimaryRootWindow())
251 EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(10, 10)));
252 // Touch the right edge of the first display. Pointer should warp.
253 EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(499, 10)));
254 EXPECT_EQ("250,5", // by 2px.
255 aura::Env::GetInstance()->last_mouse_location().ToString());
257 // Touch the left edge of the second display. Pointer should warp.
258 EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(600, 10)));
259 EXPECT_EQ("249,5", // moved to 498 by 2px, divided by 2 (dsf).
260 aura::Env::GetInstance()->last_mouse_location().ToString());
262 SCOPED_TRACE("1x2 NO WARP");