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