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