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