mouse_cursor_event_filter_unittest.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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()->WarpMouseCursorIfNecessaryForTest( 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()->WarpMouseCursorIfNecessaryForTest( 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, 480) is inside the primary root window. 131 EXPECT_TRUE( 132 WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(500, 480))); 133 EXPECT_EQ("498,480", // 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 (MouseCursorEventFilter::IsMouseWarpInNativeCoordsEnabled()) 141 return; 142 143 if (!SupportsMultipleDisplays()) 144 return; 145 146 UpdateDisplay("500x500,600x600*2"); 147 148 ASSERT_EQ( 149 DisplayLayout::RIGHT, 150 Shell::GetInstance()->display_manager()-> 151 GetCurrentDisplayLayout().position); 152 153 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 154 aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(900, 123)); 155 156 // This emulates the dragging to the 2nd display, which has 157 // higher scale factor, by having 2nd display's root as target 158 // but have the edge of 1st display. 159 EXPECT_TRUE(WarpMouseCursorIfNecessaryWithDragRoot( 160 root_windows[1], root_windows[1], gfx::Point(498, 123))); 161 EXPECT_EQ("502,123", 162 aura::Env::GetInstance()->last_mouse_location().ToString()); 163 164 // Touch the edge of 2nd display again and make sure it warps to 165 // 1st dislay. 166 EXPECT_TRUE(WarpMouseCursorIfNecessaryWithDragRoot( 167 root_windows[1], root_windows[1], gfx::Point(500, 123))); 168 EXPECT_EQ("496,123", 169 aura::Env::GetInstance()->last_mouse_location().ToString()); 170 171 // Draging back from 1x to 2x. 172 EXPECT_TRUE(WarpMouseCursorIfNecessaryWithDragRoot( 173 root_windows[1], root_windows[0], gfx::Point(500, 123))); 174 EXPECT_EQ("496,123", 175 aura::Env::GetInstance()->last_mouse_location().ToString()); 176 177 UpdateDisplay("500x500*2,600x600"); 178 // Draging back from 1x to 2x. 179 EXPECT_TRUE(WarpMouseCursorIfNecessaryWithDragRoot( 180 root_windows[0], root_windows[1], gfx::Point(250, 123))); 181 EXPECT_EQ("246,123", 182 aura::Env::GetInstance()->last_mouse_location().ToString()); 183} 184 185// Verifies if the mouse pointer correctly moves between displays with 186// different scale factors. In native coords mode, there is no 187// difference between drag and move. 188TEST_F(MouseCursorEventFilterTest, WarpMouseDifferentScaleDisplaysInNative) { 189 if (!MouseCursorEventFilter::IsMouseWarpInNativeCoordsEnabled()) 190 return; 191 192 if (!SupportsMultipleDisplays()) 193 return; 194 195 UpdateDisplay("500x500,600x600*2"); 196 197 ASSERT_EQ(DisplayLayout::RIGHT, 198 Shell::GetInstance() 199 ->display_manager() 200 ->GetCurrentDisplayLayout() 201 .position); 202 203 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 204 aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(900, 123)); 205 206 EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessaryForTest( 207 root_windows[0], gfx::Point(499, 123))); 208 EXPECT_EQ("500,123", 209 aura::Env::GetInstance()->last_mouse_location().ToString()); 210 211 event_filter()->reset_was_mouse_warped_for_test(); 212 213 // Touch the edge of 2nd display again and make sure it warps to 214 // 1st dislay. 215 EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessaryForTest( 216 root_windows[1], gfx::Point(500, 123))); 217 EXPECT_EQ("498,123", 218 aura::Env::GetInstance()->last_mouse_location().ToString()); 219} 220 221TEST_F(MouseCursorEventFilterTest, DoNotWarpTwice) { 222 if (MouseCursorEventFilter::IsMouseWarpInNativeCoordsEnabled()) 223 return; 224 225 if (!SupportsMultipleDisplays()) 226 return; 227 228 UpdateDisplay("500x500,600x600"); 229 230 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 231 aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(623, 123)); 232 233 // Touch the right edge of the primary root window. Pointer should warp. 234 EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessaryForTest( 235 root_windows[0], gfx::Point(499, 11))); 236 EXPECT_EQ("501,11", // by 2px. 237 aura::Env::GetInstance()->last_mouse_location().ToString()); 238 239 // Touch the left edge of the secondary root window immediately. This should 240 // be ignored. 241 EXPECT_FALSE(event_filter()->WarpMouseCursorIfNecessaryForTest( 242 root_windows[1], gfx::Point(500, 11))); 243 244 // Touch the left edge of the secondary root window again, pointer should 245 // warp for this time. 246 EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessaryForTest( 247 root_windows[1], gfx::Point(500, 11))); 248 EXPECT_EQ("498,11", // by 2px. 249 aura::Env::GetInstance()->last_mouse_location().ToString()); 250} 251 252// Verifies if MouseCursorEventFilter::set_mouse_warp_mode() works as expected. 253TEST_F(MouseCursorEventFilterTest, SetMouseWarpModeFlag) { 254 if (!SupportsMultipleDisplays()) 255 return; 256 257 UpdateDisplay("500x500,500x500"); 258 259 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 260 aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(1, 1)); 261 262 event_filter()->set_mouse_warp_mode(MouseCursorEventFilter::WARP_NONE); 263 EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[0], 264 gfx::Point(499, 11))); 265 EXPECT_EQ("1,1", 266 aura::Env::GetInstance()->last_mouse_location().ToString()); 267 268 event_filter()->set_mouse_warp_mode(MouseCursorEventFilter::WARP_ALWAYS); 269 EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(499, 11))); 270 EXPECT_EQ("501,11", 271 aura::Env::GetInstance()->last_mouse_location().ToString()); 272} 273 274// Verifies if MouseCursorEventFilter's bounds calculation works correctly. 275TEST_F(MouseCursorEventFilterTest, IndicatorBoundsTestOnRight) { 276 if (!SupportsMultipleDisplays()) 277 return; 278 279 UpdateDisplay("360x360,700x700"); 280 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 281 282 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 283 DisplayLayout layout(DisplayLayout::RIGHT, 0); 284 display_manager->SetLayoutForCurrentDisplays(layout); 285 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); 286 EXPECT_EQ("359,16 1x344", event_filter()->src_indicator_bounds_.ToString()); 287 EXPECT_EQ("360,0 1x360", event_filter()->dst_indicator_bounds_.ToString()); 288 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); 289 EXPECT_EQ("360,16 1x344", event_filter()->src_indicator_bounds_.ToString()); 290 EXPECT_EQ("359,0 1x360", event_filter()->dst_indicator_bounds_.ToString()); 291 292 // Move 2nd display downwards a bit. 293 layout.offset = 5; 294 display_manager->SetLayoutForCurrentDisplays(layout); 295 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); 296 // This is same as before because the 2nd display's y is above 297 // the indicator's x. 298 EXPECT_EQ("359,16 1x344", event_filter()->src_indicator_bounds_.ToString()); 299 EXPECT_EQ("360,5 1x355", event_filter()->dst_indicator_bounds_.ToString()); 300 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); 301 EXPECT_EQ("360,21 1x339", event_filter()->src_indicator_bounds_.ToString()); 302 EXPECT_EQ("359,5 1x355", event_filter()->dst_indicator_bounds_.ToString()); 303 304 // Move it down further so that the shared edge is shorter than 305 // minimum hole size (160). 306 layout.offset = 200; 307 display_manager->SetLayoutForCurrentDisplays(layout); 308 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); 309 EXPECT_EQ("359,200 1x160", event_filter()->src_indicator_bounds_.ToString()); 310 EXPECT_EQ("360,200 1x160", event_filter()->dst_indicator_bounds_.ToString()); 311 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); 312 EXPECT_EQ("360,200 1x160", event_filter()->src_indicator_bounds_.ToString()); 313 EXPECT_EQ("359,200 1x160", event_filter()->dst_indicator_bounds_.ToString()); 314 315 // Now move 2nd display upwards 316 layout.offset = -5; 317 display_manager->SetLayoutForCurrentDisplays(layout); 318 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); 319 EXPECT_EQ("359,16 1x344", event_filter()->src_indicator_bounds_.ToString()); 320 EXPECT_EQ("360,0 1x360", event_filter()->dst_indicator_bounds_.ToString()); 321 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); 322 // 16 px are reserved on 2nd display from top, so y must be 323 // (16 - 5) = 11 324 EXPECT_EQ("360,11 1x349", event_filter()->src_indicator_bounds_.ToString()); 325 EXPECT_EQ("359,0 1x360", event_filter()->dst_indicator_bounds_.ToString()); 326 327 event_filter()->HideSharedEdgeIndicator(); 328} 329 330TEST_F(MouseCursorEventFilterTest, IndicatorBoundsTestOnLeft) { 331 if (!SupportsMultipleDisplays()) 332 return; 333 334 UpdateDisplay("360x360,700x700"); 335 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 336 337 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 338 DisplayLayout layout(DisplayLayout::LEFT, 0); 339 display_manager->SetLayoutForCurrentDisplays(layout); 340 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); 341 EXPECT_EQ("0,16 1x344", event_filter()->src_indicator_bounds_.ToString()); 342 EXPECT_EQ("-1,0 1x360", event_filter()->dst_indicator_bounds_.ToString()); 343 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); 344 EXPECT_EQ("-1,16 1x344", event_filter()->src_indicator_bounds_.ToString()); 345 EXPECT_EQ("0,0 1x360", event_filter()->dst_indicator_bounds_.ToString()); 346 347 layout.offset = 250; 348 display_manager->SetLayoutForCurrentDisplays(layout); 349 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); 350 EXPECT_EQ("0,250 1x110", event_filter()->src_indicator_bounds_.ToString()); 351 EXPECT_EQ("-1,250 1x110", event_filter()->dst_indicator_bounds_.ToString()); 352 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); 353 EXPECT_EQ("-1,250 1x110", event_filter()->src_indicator_bounds_.ToString()); 354 EXPECT_EQ("0,250 1x110", event_filter()->dst_indicator_bounds_.ToString()); 355 event_filter()->HideSharedEdgeIndicator(); 356} 357 358TEST_F(MouseCursorEventFilterTest, IndicatorBoundsTestOnTopBottom) { 359 if (!SupportsMultipleDisplays()) 360 return; 361 362 UpdateDisplay("360x360,700x700"); 363 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 364 365 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 366 DisplayLayout layout(DisplayLayout::TOP, 0); 367 display_manager->SetLayoutForCurrentDisplays(layout); 368 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); 369 EXPECT_EQ("0,0 360x1", event_filter()->src_indicator_bounds_.ToString()); 370 EXPECT_EQ("0,-1 360x1", event_filter()->dst_indicator_bounds_.ToString()); 371 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); 372 EXPECT_EQ("0,-1 360x1", event_filter()->src_indicator_bounds_.ToString()); 373 EXPECT_EQ("0,0 360x1", event_filter()->dst_indicator_bounds_.ToString()); 374 375 layout.offset = 250; 376 display_manager->SetLayoutForCurrentDisplays(layout); 377 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); 378 EXPECT_EQ("250,0 110x1", event_filter()->src_indicator_bounds_.ToString()); 379 EXPECT_EQ("250,-1 110x1", event_filter()->dst_indicator_bounds_.ToString()); 380 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); 381 EXPECT_EQ("250,-1 110x1", event_filter()->src_indicator_bounds_.ToString()); 382 EXPECT_EQ("250,0 110x1", event_filter()->dst_indicator_bounds_.ToString()); 383 384 layout.position = DisplayLayout::BOTTOM; 385 layout.offset = 0; 386 display_manager->SetLayoutForCurrentDisplays(layout); 387 event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); 388 EXPECT_EQ("0,359 360x1", event_filter()->src_indicator_bounds_.ToString()); 389 EXPECT_EQ("0,360 360x1", event_filter()->dst_indicator_bounds_.ToString()); 390 event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); 391 EXPECT_EQ("0,360 360x1", event_filter()->src_indicator_bounds_.ToString()); 392 EXPECT_EQ("0,359 360x1", event_filter()->dst_indicator_bounds_.ToString()); 393 394 event_filter()->HideSharedEdgeIndicator(); 395} 396 397// Verifies cursor's device scale factor is updated when a cursor has moved 398// across root windows with different device scale factors 399// (http://crbug.com/154183). 400TEST_F(MouseCursorEventFilterTest, CursorDeviceScaleFactor) { 401 if (!SupportsMultipleDisplays()) 402 return; 403 404 UpdateDisplay("400x400,800x800*2"); 405 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 406 display_manager->SetLayoutForCurrentDisplays( 407 DisplayLayout(DisplayLayout::RIGHT, 0)); 408 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 409 ASSERT_EQ(2U, root_windows.size()); 410 test::CursorManagerTestApi cursor_test_api( 411 Shell::GetInstance()->cursor_manager()); 412 413 EXPECT_EQ(1.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); 414 WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(399, 200)); 415 EXPECT_EQ(2.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); 416 WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(400, 200)); 417 EXPECT_EQ(1.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); 418} 419 420} // namespace ash 421