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