Home | History | Annotate | Download | only in display
      1 // Copyright (c) 2013 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/mirror_window_controller.h"
      6 
      7 #include "ash/ash_switches.h"
      8 #include "ash/display/display_manager.h"
      9 #include "ash/shell.h"
     10 #include "ash/test/ash_test_base.h"
     11 #include "ash/test/display_manager_test_api.h"
     12 #include "ash/test/mirror_window_test_api.h"
     13 #include "base/command_line.h"
     14 #include "base/strings/stringprintf.h"
     15 #include "ui/aura/test/test_window_delegate.h"
     16 #include "ui/aura/test/test_windows.h"
     17 #include "ui/aura/window.h"
     18 #include "ui/aura/window_event_dispatcher.h"
     19 #include "ui/base/hit_test.h"
     20 #include "ui/events/test/event_generator.h"
     21 
     22 namespace ash {
     23 
     24 namespace {
     25 DisplayInfo CreateDisplayInfo(int64 id, const gfx::Rect& bounds) {
     26   DisplayInfo info(id, base::StringPrintf("x-%d", static_cast<int>(id)), false);
     27   info.SetBounds(bounds);
     28   return info;
     29 }
     30 
     31 class MirrorOnBootTest : public test::AshTestBase {
     32  public:
     33   MirrorOnBootTest() {}
     34   virtual ~MirrorOnBootTest() {}
     35 
     36   virtual void SetUp() OVERRIDE {
     37     CommandLine::ForCurrentProcess()->AppendSwitchASCII(
     38         switches::kAshHostWindowBounds, "1+1-300x300,1+301-300x300");
     39     CommandLine::ForCurrentProcess()->AppendSwitch(
     40         switches::kAshEnableSoftwareMirroring);
     41     test::AshTestBase::SetUp();
     42   }
     43   virtual void TearDown() OVERRIDE {
     44     test::AshTestBase::TearDown();
     45   }
     46 
     47  private:
     48   DISALLOW_COPY_AND_ASSIGN(MirrorOnBootTest);
     49 };
     50 
     51 }
     52 
     53 typedef test::AshTestBase MirrorWindowControllerTest;
     54 
     55 #if defined(OS_WIN)
     56 // Software mirroring does not work on win.
     57 #define MAYBE_MirrorCursorBasic DISABLED_MirrorCursorBasic
     58 #define MAYBE_MirrorCursorLocations DISABLED_MirrorCursorLocations
     59 #define MAYBE_MirrorCursorRotate DISABLED_MirrorCursorRotate
     60 #define MAYBE_DockMode DISABLED_DockMode
     61 #define MAYBE_MirrorOnBoot DISABLED_MirrorOnBoot
     62 #else
     63 #define MAYBE_MirrorCursorBasic MirrorCursorBasic
     64 #define MAYBE_MirrorCursorLocations MirrorCursorLocations
     65 #define MAYBE_MirrorCursorRotate MirrorCursorRotate
     66 #define MAYBE_DockMode DockMode
     67 #define MAYBE_MirrorOnBoot MirrorOnBoot
     68 #endif
     69 
     70 TEST_F(MirrorWindowControllerTest, MAYBE_MirrorCursorBasic) {
     71   test::MirrorWindowTestApi test_api;
     72   aura::test::TestWindowDelegate test_window_delegate;
     73   test_window_delegate.set_window_component(HTTOP);
     74 
     75   DisplayManager* display_manager = Shell::GetInstance()->display_manager();
     76   display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING);
     77   UpdateDisplay("400x400,400x400");
     78   aura::Window* root = Shell::GetInstance()->GetPrimaryRootWindow();
     79   scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithDelegate(
     80       &test_window_delegate,
     81       0,
     82       gfx::Rect(50, 50, 100, 100),
     83       root));
     84   window->Show();
     85   window->SetName("foo");
     86 
     87   EXPECT_TRUE(test_api.GetCursorWindow());
     88   EXPECT_EQ("50,50 100x100", window->bounds().ToString());
     89 
     90   ui::test::EventGenerator generator(root);
     91   generator.MoveMouseTo(10, 10);
     92 
     93   // Test if cursor movement is propertly reflected in mirror window.
     94   gfx::Point hot_point = test_api.GetCursorHotPoint();
     95   gfx::Point cursor_window_origin =
     96       test_api.GetCursorWindow()->bounds().origin();
     97   EXPECT_EQ("4,4", hot_point.ToString());
     98   EXPECT_EQ(10 - hot_point.x(), cursor_window_origin.x());
     99   EXPECT_EQ(10 - hot_point.y(), cursor_window_origin.y());
    100   EXPECT_EQ(ui::kCursorNull, test_api.GetCurrentCursorType());
    101   EXPECT_TRUE(test_api.GetCursorWindow()->IsVisible());
    102 
    103   // Test if cursor type change is propertly reflected in mirror window.
    104   generator.MoveMouseTo(100, 100);
    105   hot_point = test_api.GetCursorHotPoint();
    106   cursor_window_origin = test_api.GetCursorWindow()->bounds().origin();
    107   EXPECT_EQ(100 - hot_point.x(), cursor_window_origin.x());
    108   EXPECT_EQ(100 - hot_point.y(), cursor_window_origin.y());
    109   EXPECT_EQ(ui::kCursorNorthResize, test_api.GetCurrentCursorType());
    110 
    111   // Test if visibility change is propertly reflected in mirror window.
    112   // A key event hides cursor.
    113   generator.PressKey(ui::VKEY_A, 0);
    114   generator.ReleaseKey(ui::VKEY_A, 0);
    115   EXPECT_FALSE(test_api.GetCursorWindow()->IsVisible());
    116 
    117   // Mouse event makes it visible again.
    118   generator.MoveMouseTo(300, 300);
    119   hot_point = test_api.GetCursorHotPoint();
    120   cursor_window_origin = test_api.GetCursorWindow()->bounds().origin();
    121   EXPECT_EQ(300 - hot_point.x(), cursor_window_origin.x());
    122   EXPECT_EQ(300 - hot_point.y(), cursor_window_origin.y());
    123   EXPECT_EQ(ui::kCursorNull, test_api.GetCurrentCursorType());
    124   EXPECT_TRUE(test_api.GetCursorWindow()->IsVisible());
    125 }
    126 
    127 TEST_F(MirrorWindowControllerTest, MAYBE_MirrorCursorRotate) {
    128   test::MirrorWindowTestApi test_api;
    129   aura::test::TestWindowDelegate test_window_delegate;
    130   test_window_delegate.set_window_component(HTTOP);
    131 
    132   DisplayManager* display_manager = Shell::GetInstance()->display_manager();
    133   display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING);
    134   UpdateDisplay("400x400,400x400");
    135   aura::Window* root = Shell::GetInstance()->GetPrimaryRootWindow();
    136   scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithDelegate(
    137       &test_window_delegate,
    138       0,
    139       gfx::Rect(50, 50, 100, 100),
    140       root));
    141   window->Show();
    142   window->SetName("foo");
    143 
    144   EXPECT_TRUE(test_api.GetCursorWindow());
    145   EXPECT_EQ("50,50 100x100", window->bounds().ToString());
    146 
    147   ui::test::EventGenerator generator(root);
    148   generator.MoveMouseToInHost(100, 100);
    149 
    150   // Test if cursor movement is propertly reflected in mirror window.
    151   gfx::Point hot_point = test_api.GetCursorHotPoint();
    152   gfx::Point cursor_window_origin =
    153       test_api.GetCursorWindow()->bounds().origin();
    154   EXPECT_EQ("11,12", hot_point.ToString());
    155   EXPECT_EQ(100 - hot_point.x(), cursor_window_origin.x());
    156   EXPECT_EQ(100 - hot_point.y(), cursor_window_origin.y());
    157   EXPECT_EQ(ui::kCursorNorthResize, test_api.GetCurrentCursorType());
    158 
    159   UpdateDisplay("400x400/r,400x400");  // 90 degrees.
    160   generator.MoveMouseToInHost(300, 100);
    161   hot_point = test_api.GetCursorHotPoint();
    162   cursor_window_origin = test_api.GetCursorWindow()->bounds().origin();
    163   EXPECT_EQ(ui::kCursorNorthResize, test_api.GetCurrentCursorType());
    164   // The size of cursor image is 25x25, so the rotated hot point must
    165   // be (25-12, 11).
    166   EXPECT_EQ("13,11", hot_point.ToString());
    167   EXPECT_EQ(300 - hot_point.x(), cursor_window_origin.x());
    168   EXPECT_EQ(100 - hot_point.y(), cursor_window_origin.y());
    169 
    170   UpdateDisplay("400x400/u,400x400");  // 180 degrees.
    171   generator.MoveMouseToInHost(300, 300);
    172   hot_point = test_api.GetCursorHotPoint();
    173   cursor_window_origin = test_api.GetCursorWindow()->bounds().origin();
    174   EXPECT_EQ(ui::kCursorNorthResize, test_api.GetCurrentCursorType());
    175   // Rotated hot point must be (25-11, 25-12).
    176   EXPECT_EQ("14,13", hot_point.ToString());
    177   EXPECT_EQ(300 - hot_point.x(), cursor_window_origin.x());
    178   EXPECT_EQ(300 - hot_point.y(), cursor_window_origin.y());
    179 
    180   UpdateDisplay("400x400/l,400x400");  // 270 degrees.
    181   generator.MoveMouseToInHost(100, 300);
    182   hot_point = test_api.GetCursorHotPoint();
    183   cursor_window_origin = test_api.GetCursorWindow()->bounds().origin();
    184   EXPECT_EQ(ui::kCursorNorthResize, test_api.GetCurrentCursorType());
    185   // Rotated hot point must be (12, 25-11).
    186   EXPECT_EQ("12,14", hot_point.ToString());
    187   EXPECT_EQ(100 - hot_point.x(), cursor_window_origin.x());
    188   EXPECT_EQ(300 - hot_point.y(), cursor_window_origin.y());
    189 }
    190 
    191 // Make sure that the mirror cursor's location is same as
    192 // the source display's host location in the mirror root window's
    193 // coordinates.
    194 TEST_F(MirrorWindowControllerTest, MAYBE_MirrorCursorLocations) {
    195   test::MirrorWindowTestApi test_api;
    196   DisplayManager* display_manager = Shell::GetInstance()->display_manager();
    197   display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING);
    198 
    199   // Test with device scale factor.
    200   UpdateDisplay("400x600*2,400x600");
    201 
    202   aura::Window* root = Shell::GetInstance()->GetPrimaryRootWindow();
    203   ui::test::EventGenerator generator(root);
    204   generator.MoveMouseToInHost(10, 20);
    205 
    206   gfx::Point hot_point = test_api.GetCursorHotPoint();
    207   EXPECT_EQ("8,9", hot_point.ToString());
    208   gfx::Point cursor_window_origin =
    209       test_api.GetCursorWindow()->bounds().origin();
    210   EXPECT_EQ(10 - hot_point.x(), cursor_window_origin.x());
    211   EXPECT_EQ(20 - hot_point.y(), cursor_window_origin.y());
    212 
    213   // Test with ui scale
    214   UpdateDisplay("400x600*0.5,400x600");
    215   generator.MoveMouseToInHost(20, 30);
    216 
    217   hot_point = test_api.GetCursorHotPoint();
    218   EXPECT_EQ("4,4", hot_point.ToString());
    219   cursor_window_origin = test_api.GetCursorWindow()->bounds().origin();
    220   EXPECT_EQ(20 - hot_point.x(), cursor_window_origin.x());
    221   EXPECT_EQ(30 - hot_point.y(), cursor_window_origin.y());
    222 
    223   // Test with rotation
    224   UpdateDisplay("400x600/r,400x600");
    225   generator.MoveMouseToInHost(30, 40);
    226 
    227   hot_point = test_api.GetCursorHotPoint();
    228   EXPECT_EQ("21,4", hot_point.ToString());
    229   cursor_window_origin = test_api.GetCursorWindow()->bounds().origin();
    230   EXPECT_EQ(30 - hot_point.x(), cursor_window_origin.x());
    231   EXPECT_EQ(40 - hot_point.y(), cursor_window_origin.y());
    232 }
    233 
    234 // Make sure that the compositor based mirroring can switch
    235 // from/to dock mode.
    236 TEST_F(MirrorWindowControllerTest, MAYBE_DockMode) {
    237   DisplayManager* display_manager = Shell::GetInstance()->display_manager();
    238   const int64 internal_id = 1;
    239   const int64 external_id = 2;
    240 
    241   const DisplayInfo internal_display_info =
    242       CreateDisplayInfo(internal_id, gfx::Rect(0, 0, 500, 500));
    243   const DisplayInfo external_display_info =
    244       CreateDisplayInfo(external_id, gfx::Rect(1, 1, 100, 100));
    245   std::vector<DisplayInfo> display_info_list;
    246 
    247   display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING);
    248 
    249   // software mirroring.
    250   display_info_list.push_back(internal_display_info);
    251   display_info_list.push_back(external_display_info);
    252   display_manager->OnNativeDisplaysChanged(display_info_list);
    253   const int64 internal_display_id =
    254       test::DisplayManagerTestApi(display_manager).
    255       SetFirstDisplayAsInternalDisplay();
    256   EXPECT_EQ(internal_id, internal_display_id);
    257 
    258   EXPECT_EQ(1U, display_manager->GetNumDisplays());
    259   EXPECT_TRUE(display_manager->IsMirrored());
    260   EXPECT_EQ(external_id, display_manager->mirrored_display_id());
    261 
    262   // dock mode.
    263   display_info_list.clear();
    264   display_info_list.push_back(external_display_info);
    265   display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING);
    266   display_manager->OnNativeDisplaysChanged(display_info_list);
    267   EXPECT_EQ(1U, display_manager->GetNumDisplays());
    268   EXPECT_FALSE(display_manager->IsMirrored());
    269 
    270   // back to software mirroring.
    271   display_info_list.clear();
    272   display_info_list.push_back(internal_display_info);
    273   display_info_list.push_back(external_display_info);
    274   display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING);
    275   display_manager->OnNativeDisplaysChanged(display_info_list);
    276   EXPECT_EQ(1U, display_manager->GetNumDisplays());
    277   EXPECT_TRUE(display_manager->IsMirrored());
    278   EXPECT_EQ(external_id, display_manager->mirrored_display_id());
    279 }
    280 
    281 TEST_F(MirrorOnBootTest, MAYBE_MirrorOnBoot) {
    282   DisplayManager* display_manager = Shell::GetInstance()->display_manager();
    283   EXPECT_TRUE(display_manager->IsMirrored());
    284   RunAllPendingInMessageLoop();
    285   test::MirrorWindowTestApi test_api;
    286   EXPECT_TRUE(test_api.GetHost());
    287 }
    288 
    289 }  // namespace ash
    290