root_window_transformers_unittest.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
1// Copyright 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/root_window_transformers.h" 6 7#include "ash/display/display_info.h" 8#include "ash/display/display_manager.h" 9#include "ash/launcher/launcher.h" 10#include "ash/magnifier/magnification_controller.h" 11#include "ash/screen_ash.h" 12#include "ash/shelf/shelf_widget.h" 13#include "ash/shell.h" 14#include "ash/test/ash_test_base.h" 15#include "ash/test/cursor_manager_test_api.h" 16#include "ash/test/mirror_window_test_api.h" 17#include "base/synchronization/waitable_event.h" 18#include "ui/aura/env.h" 19#include "ui/aura/root_window.h" 20#include "ui/aura/root_window_transformer.h" 21#include "ui/aura/test/event_generator.h" 22#include "ui/aura/window_tracker.h" 23#include "ui/events/event_handler.h" 24#include "ui/gfx/display.h" 25#include "ui/gfx/rect_conversions.h" 26#include "ui/gfx/screen.h" 27#include "ui/views/widget/widget.h" 28 29namespace ash { 30namespace internal { 31 32namespace { 33 34const char kDesktopBackgroundView[] = "DesktopBackgroundView"; 35 36class TestEventHandler : public ui::EventHandler { 37 public: 38 TestEventHandler() : target_root_(NULL), 39 touch_radius_x_(0.0), 40 touch_radius_y_(0.0), 41 scroll_x_offset_(0.0), 42 scroll_y_offset_(0.0), 43 scroll_x_offset_ordinal_(0.0), 44 scroll_y_offset_ordinal_(0.0) {} 45 virtual ~TestEventHandler() {} 46 47 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE { 48 if (event->flags() & ui::EF_IS_SYNTHESIZED) 49 return; 50 aura::Window* target = static_cast<aura::Window*>(event->target()); 51 mouse_location_ = event->root_location(); 52 target_root_ = target->GetRootWindow(); 53 event->StopPropagation(); 54 } 55 56 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE { 57 aura::Window* target = static_cast<aura::Window*>(event->target()); 58 // Only record when the target is the background which covers 59 // entire root window. 60 if (target->name() != kDesktopBackgroundView) 61 return; 62 touch_radius_x_ = event->radius_x(); 63 touch_radius_y_ = event->radius_y(); 64 event->StopPropagation(); 65 } 66 67 virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE { 68 aura::Window* target = static_cast<aura::Window*>(event->target()); 69 // Only record when the target is the background which covers 70 // entire root window. 71 if (target->name() != kDesktopBackgroundView) 72 return; 73 74 if (event->type() == ui::ET_SCROLL) { 75 scroll_x_offset_ = event->x_offset(); 76 scroll_y_offset_ = event->y_offset(); 77 scroll_x_offset_ordinal_ = event->x_offset_ordinal(); 78 scroll_y_offset_ordinal_ = event->y_offset_ordinal(); 79 } 80 event->StopPropagation(); 81 } 82 83 std::string GetLocationAndReset() { 84 std::string result = mouse_location_.ToString(); 85 mouse_location_.SetPoint(0, 0); 86 target_root_ = NULL; 87 return result; 88 } 89 90 float touch_radius_x() const { return touch_radius_x_; } 91 float touch_radius_y() const { return touch_radius_y_; } 92 float scroll_x_offset() const { return scroll_x_offset_; } 93 float scroll_y_offset() const { return scroll_y_offset_; } 94 float scroll_x_offset_ordinal() const { return scroll_x_offset_ordinal_; } 95 float scroll_y_offset_ordinal() const { return scroll_y_offset_ordinal_; } 96 97 private: 98 gfx::Point mouse_location_; 99 aura::Window* target_root_; 100 101 float touch_radius_x_; 102 float touch_radius_y_; 103 float scroll_x_offset_; 104 float scroll_y_offset_; 105 float scroll_x_offset_ordinal_; 106 float scroll_y_offset_ordinal_; 107 108 DISALLOW_COPY_AND_ASSIGN(TestEventHandler); 109}; 110 111gfx::Display::Rotation GetStoredRotation(int64 id) { 112 return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).rotation(); 113} 114 115float GetStoredUIScale(int64 id) { 116 return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).ui_scale(); 117} 118 119} // namespace 120 121typedef test::AshTestBase RootWindowTransformersTest; 122 123#if defined(OS_WIN) 124// TODO(scottmg): RootWindow doesn't get resized on Windows 125// Ash. http://crbug.com/247916. 126#define MAYBE_RotateAndMagnify DISABLED_RotateAndMagniy 127#define MAYBE_TouchScaleAndMagnify DISABLED_TouchScaleAndMagnify 128#define MAYBE_ConvertHostToRootCoords DISABLED_ConvertHostToRootCoords 129#else 130#define MAYBE_RotateAndMagnify RotateAndMagniy 131#define MAYBE_TouchScaleAndMagnify TouchScaleAndMagnify 132#define MAYBE_ConvertHostToRootCoords ConvertHostToRootCoords 133#endif 134 135TEST_F(RootWindowTransformersTest, MAYBE_RotateAndMagnify) { 136 MagnificationController* magnifier = 137 Shell::GetInstance()->magnification_controller(); 138 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 139 140 TestEventHandler event_handler; 141 Shell::GetInstance()->AddPreTargetHandler(&event_handler); 142 143 UpdateDisplay("120x200,300x400*2"); 144 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay(); 145 int64 display2_id = ScreenAsh::GetSecondaryDisplay().id(); 146 147 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); 148 aura::test::EventGenerator generator1(root_windows[0]); 149 aura::test::EventGenerator generator2(root_windows[1]); 150 151 magnifier->SetEnabled(true); 152 EXPECT_EQ(2.0f, magnifier->GetScale()); 153 EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString()); 154 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString()); 155 EXPECT_EQ("120,0 150x200", 156 ScreenAsh::GetSecondaryDisplay().bounds().ToString()); 157 generator1.MoveMouseToInHost(40, 80); 158 EXPECT_EQ("50,90", event_handler.GetLocationAndReset()); 159 EXPECT_EQ("50,90", 160 aura::Env::GetInstance()->last_mouse_location().ToString()); 161 EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display1.id())); 162 EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id)); 163 magnifier->SetEnabled(false); 164 165 display_manager->SetDisplayRotation(display1.id(), 166 gfx::Display::ROTATE_90); 167 // Move the cursor to the center of the first root window. 168 generator1.MoveMouseToInHost(59, 100); 169 170 magnifier->SetEnabled(true); 171 EXPECT_EQ(2.0f, magnifier->GetScale()); 172 EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString()); 173 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString()); 174 EXPECT_EQ("200,0 150x200", 175 ScreenAsh::GetSecondaryDisplay().bounds().ToString()); 176 generator1.MoveMouseToInHost(39, 120); 177 EXPECT_EQ("110,70", event_handler.GetLocationAndReset()); 178 EXPECT_EQ("110,70", 179 aura::Env::GetInstance()->last_mouse_location().ToString()); 180 EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id())); 181 EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id)); 182 magnifier->SetEnabled(false); 183 184 DisplayLayout display_layout(DisplayLayout::BOTTOM, 50); 185 display_manager->SetLayoutForCurrentDisplays(display_layout); 186 EXPECT_EQ("50,120 150x200", 187 ScreenAsh::GetSecondaryDisplay().bounds().ToString()); 188 189 display_manager->SetDisplayRotation(display2_id, 190 gfx::Display::ROTATE_270); 191 // Move the cursor to the center of the second root window. 192 generator2.MoveMouseToInHost(151, 199); 193 194 magnifier->SetEnabled(true); 195 EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString()); 196 EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString()); 197 EXPECT_EQ("50,120 200x150", 198 ScreenAsh::GetSecondaryDisplay().bounds().ToString()); 199 generator2.MoveMouseToInHost(172, 219); 200 EXPECT_EQ("95,80", event_handler.GetLocationAndReset()); 201 EXPECT_EQ("145,200", 202 aura::Env::GetInstance()->last_mouse_location().ToString()); 203 EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id())); 204 EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id)); 205 magnifier->SetEnabled(false); 206 207 display_manager->SetDisplayRotation(display1.id(), 208 gfx::Display::ROTATE_180); 209 // Move the cursor to the center of the first root window. 210 generator1.MoveMouseToInHost(59, 99); 211 212 magnifier->SetEnabled(true); 213 EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString()); 214 EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString()); 215 // Dislay must share at least 100, so the x's offset becomes 20. 216 EXPECT_EQ("20,200 200x150", 217 ScreenAsh::GetSecondaryDisplay().bounds().ToString()); 218 generator1.MoveMouseToInHost(39, 59); 219 EXPECT_EQ("70,120", event_handler.GetLocationAndReset()); 220 EXPECT_EQ(gfx::Display::ROTATE_180, GetStoredRotation(display1.id())); 221 EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id)); 222 magnifier->SetEnabled(false); 223 224 Shell::GetInstance()->RemovePreTargetHandler(&event_handler); 225} 226 227TEST_F(RootWindowTransformersTest, ScaleAndMagnify) { 228 if (!SupportsMultipleDisplays()) 229 return; 230 231 TestEventHandler event_handler; 232 Shell::GetInstance()->AddPreTargetHandler(&event_handler); 233 234 UpdateDisplay("600x400*2@1.5,500x300"); 235 236 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay(); 237 gfx::Display::SetInternalDisplayId(display1.id()); 238 gfx::Display display2 = ScreenAsh::GetSecondaryDisplay(); 239 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); 240 MagnificationController* magnifier = 241 Shell::GetInstance()->magnification_controller(); 242 243 magnifier->SetEnabled(true); 244 EXPECT_EQ(2.0f, magnifier->GetScale()); 245 EXPECT_EQ("0,0 450x300", display1.bounds().ToString()); 246 EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString()); 247 EXPECT_EQ("450,0 500x300", display2.bounds().ToString()); 248 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id())); 249 EXPECT_EQ(1.0f, GetStoredUIScale(display2.id())); 250 251 aura::test::EventGenerator generator(root_windows[0]); 252 generator.MoveMouseToInHost(500, 200); 253 EXPECT_EQ("299,150", event_handler.GetLocationAndReset()); 254 magnifier->SetEnabled(false); 255 256 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 257 display_manager->SetDisplayUIScale(display1.id(), 1.25); 258 display1 = Shell::GetScreen()->GetPrimaryDisplay(); 259 display2 = ScreenAsh::GetSecondaryDisplay(); 260 magnifier->SetEnabled(true); 261 EXPECT_EQ(2.0f, magnifier->GetScale()); 262 EXPECT_EQ("0,0 375x250", display1.bounds().ToString()); 263 EXPECT_EQ("0,0 375x250", root_windows[0]->bounds().ToString()); 264 EXPECT_EQ("375,0 500x300", display2.bounds().ToString()); 265 EXPECT_EQ(1.25f, GetStoredUIScale(display1.id())); 266 EXPECT_EQ(1.0f, GetStoredUIScale(display2.id())); 267 magnifier->SetEnabled(false); 268 269 Shell::GetInstance()->RemovePreTargetHandler(&event_handler); 270} 271 272TEST_F(RootWindowTransformersTest, MAYBE_TouchScaleAndMagnify) { 273 TestEventHandler event_handler; 274 Shell::GetInstance()->AddPreTargetHandler(&event_handler); 275 276 UpdateDisplay("200x200*2"); 277 gfx::Display display = Shell::GetScreen()->GetPrimaryDisplay(); 278 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); 279 aura::RootWindow* root_window = root_windows[0]; 280 aura::test::EventGenerator generator(root_window); 281 MagnificationController* magnifier = 282 Shell::GetInstance()->magnification_controller(); 283 284 magnifier->SetEnabled(true); 285 EXPECT_FLOAT_EQ(2.0f, magnifier->GetScale()); 286 magnifier->SetScale(2.5f, false); 287 EXPECT_FLOAT_EQ(2.5f, magnifier->GetScale()); 288 generator.PressMoveAndReleaseTouchTo(50, 50); 289 // Default test touches have radius_x/y = 1.0, with device scale 290 // factor = 2, the scaled radius_x/y should be 0.5. 291 EXPECT_FLOAT_EQ(0.2f, event_handler.touch_radius_x()); 292 EXPECT_FLOAT_EQ(0.2f, event_handler.touch_radius_y()); 293 294 generator.ScrollSequence(gfx::Point(0,0), 295 base::TimeDelta::FromMilliseconds(100), 296 10.0, 1.0, 5, 1); 297 298 // ordinal_offset is invariant to the device scale factor. 299 EXPECT_FLOAT_EQ(event_handler.scroll_x_offset(), 300 event_handler.scroll_x_offset_ordinal()); 301 EXPECT_FLOAT_EQ(event_handler.scroll_y_offset(), 302 event_handler.scroll_y_offset_ordinal()); 303 magnifier->SetEnabled(false); 304 305 Shell::GetInstance()->RemovePreTargetHandler(&event_handler); 306} 307 308TEST_F(RootWindowTransformersTest, MAYBE_ConvertHostToRootCoords) { 309 TestEventHandler event_handler; 310 Shell::GetInstance()->AddPreTargetHandler(&event_handler); 311 MagnificationController* magnifier = 312 Shell::GetInstance()->magnification_controller(); 313 314 // Test 1 315 UpdateDisplay("600x400*2/r@1.5"); 316 317 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay(); 318 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); 319 EXPECT_EQ("0,0 300x450", display1.bounds().ToString()); 320 EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString()); 321 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id())); 322 323 aura::test::EventGenerator generator(root_windows[0]); 324 generator.MoveMouseToInHost(300, 200); 325 magnifier->SetEnabled(true); 326 EXPECT_EQ("150,224", event_handler.GetLocationAndReset()); 327 EXPECT_FLOAT_EQ(2.0f, magnifier->GetScale()); 328 329 generator.MoveMouseToInHost(300, 200); 330 EXPECT_EQ("150,224", event_handler.GetLocationAndReset()); 331 generator.MoveMouseToInHost(200, 300); 332 EXPECT_EQ("187,261", event_handler.GetLocationAndReset()); 333 generator.MoveMouseToInHost(100, 400); 334 EXPECT_EQ("237,299", event_handler.GetLocationAndReset()); 335 generator.MoveMouseToInHost(0, 0); 336 EXPECT_EQ("137,348", event_handler.GetLocationAndReset()); 337 338 magnifier->SetEnabled(false); 339 EXPECT_FLOAT_EQ(1.0f, magnifier->GetScale()); 340 341 // Test 2 342 UpdateDisplay("600x400*2/u@1.5"); 343 display1 = Shell::GetScreen()->GetPrimaryDisplay(); 344 root_windows = Shell::GetAllRootWindows(); 345 EXPECT_EQ("0,0 450x300", display1.bounds().ToString()); 346 EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString()); 347 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id())); 348 349 generator.MoveMouseToInHost(300, 200); 350 magnifier->SetEnabled(true); 351 EXPECT_EQ("224,149", event_handler.GetLocationAndReset()); 352 EXPECT_FLOAT_EQ(2.0f, magnifier->GetScale()); 353 354 generator.MoveMouseToInHost(300, 200); 355 EXPECT_EQ("224,148", event_handler.GetLocationAndReset()); 356 generator.MoveMouseToInHost(200, 300); 357 EXPECT_EQ("261,111", event_handler.GetLocationAndReset()); 358 generator.MoveMouseToInHost(100, 400); 359 EXPECT_EQ("299,60", event_handler.GetLocationAndReset()); 360 generator.MoveMouseToInHost(0, 0); 361 EXPECT_EQ("348,159", event_handler.GetLocationAndReset()); 362 363 magnifier->SetEnabled(false); 364 EXPECT_FLOAT_EQ(1.0f, magnifier->GetScale()); 365 366 // Test 3 367 UpdateDisplay("600x400*2/l@1.5"); 368 display1 = Shell::GetScreen()->GetPrimaryDisplay(); 369 root_windows = Shell::GetAllRootWindows(); 370 EXPECT_EQ("0,0 300x450", display1.bounds().ToString()); 371 EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString()); 372 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id())); 373 374 generator.MoveMouseToInHost(300, 200); 375 magnifier->SetEnabled(true); 376 EXPECT_EQ("149,225", event_handler.GetLocationAndReset()); 377 EXPECT_FLOAT_EQ(2.0f, magnifier->GetScale()); 378 379 generator.MoveMouseToInHost(300, 200); 380 EXPECT_EQ("148,224", event_handler.GetLocationAndReset()); 381 generator.MoveMouseToInHost(200, 300); 382 EXPECT_EQ("111,187", event_handler.GetLocationAndReset()); 383 generator.MoveMouseToInHost(100, 400); 384 EXPECT_EQ("60,149", event_handler.GetLocationAndReset()); 385 generator.MoveMouseToInHost(0, 0); 386 EXPECT_EQ("159,99", event_handler.GetLocationAndReset()); 387 388 magnifier->SetEnabled(false); 389 EXPECT_FLOAT_EQ(1.0f, magnifier->GetScale()); 390 391 Shell::GetInstance()->RemovePreTargetHandler(&event_handler); 392} 393 394TEST_F(RootWindowTransformersTest, LetterBoxPillarBox) { 395 if (!SupportsMultipleDisplays()) 396 return; 397 test::MirrorWindowTestApi test_api; 398 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 399 display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING); 400 UpdateDisplay("400x200,500x500"); 401 scoped_ptr<aura::RootWindowTransformer> transformer( 402 test_api.CreateCurrentRootWindowTransformer()); 403 // Y margin must be margin is (500 - 500/400 * 200) / 2 = 125. 404 EXPECT_EQ("0,125,0,125", transformer->GetHostInsets().ToString()); 405 406 UpdateDisplay("200x400,500x500"); 407 // The aspect ratio is flipped, so X margin is now 125. 408 transformer = test_api.CreateCurrentRootWindowTransformer(); 409 EXPECT_EQ("125,0,125,0", transformer->GetHostInsets().ToString()); 410} 411 412} // namespace test 413} // namespace ash 414