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