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