Home | History | Annotate | Download | only in display
      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 
     18 namespace ash {
     19 namespace internal {
     20 namespace {
     21 
     22 gfx::Display GetPrimaryDisplay() {
     23   return Shell::GetScreen()->GetDisplayNearestWindow(
     24       Shell::GetAllRootWindows()[0]);
     25 }
     26 
     27 gfx::Display GetSecondaryDisplay() {
     28   return Shell::GetScreen()->GetDisplayNearestWindow(
     29       Shell::GetAllRootWindows()[1]);
     30 }
     31 
     32 }  // namespace
     33 
     34 typedef test::AshTestBase MouseCursorEventFilterTest;
     35 
     36 // Verifies if the mouse pointer correctly moves to another display when there
     37 // are two displays.
     38 TEST_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.
    101 TEST_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.
    136 TEST_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.
    172 TEST_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.
    200 TEST_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 
    258 TEST_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 
    289 TEST_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).
    334 TEST_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