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 17 namespace ash { 18 namespace internal { 19 20 class 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. 66 TEST_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. 110 TEST_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. 140 TEST_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 183 TEST_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. 212 TEST_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. 234 TEST_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 289 TEST_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 317 TEST_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). 359 TEST_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