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