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