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