Roll src/third_party/WebKit f36d5e0:68b67cd (svn 193299:193303)
[chromium-blink-merge.git] / ash / display / display_controller_unittest.cc
blob6945fac2c30fc4e3803f5fda559d3646d8eabe95
1 // Copyright (c) 2012 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/display_controller.h"
7 #include "ash/ash_switches.h"
8 #include "ash/display/display_info.h"
9 #include "ash/display/display_layout_store.h"
10 #include "ash/display/display_manager.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/ash_test_helper.h"
17 #include "ash/test/cursor_manager_test_api.h"
18 #include "ash/test/display_manager_test_api.h"
19 #include "ash/test/test_shell_delegate.h"
20 #include "ash/wm/window_state.h"
21 #include "ash/wm/wm_event.h"
22 #include "base/command_line.h"
23 #include "ui/aura/client/focus_change_observer.h"
24 #include "ui/aura/client/focus_client.h"
25 #include "ui/aura/env.h"
26 #include "ui/aura/window_tracker.h"
27 #include "ui/aura/window_tree_host.h"
28 #include "ui/events/event_handler.h"
29 #include "ui/events/test/event_generator.h"
30 #include "ui/gfx/display.h"
31 #include "ui/gfx/screen.h"
32 #include "ui/views/mouse_watcher.h"
33 #include "ui/views/mouse_watcher_view_host.h"
34 #include "ui/views/view.h"
35 #include "ui/views/widget/widget.h"
36 #include "ui/wm/public/activation_change_observer.h"
37 #include "ui/wm/public/activation_client.h"
39 #if defined(USE_X11)
40 #include <X11/Xlib.h>
41 #include "ui/gfx/x/x11_types.h"
42 #undef RootWindow
43 #endif
45 namespace ash {
46 namespace {
48 const char kDesktopBackgroundView[] = "DesktopBackgroundView";
50 template<typename T>
51 class Resetter {
52 public:
53 explicit Resetter(T* value) : value_(*value) {
54 *value = 0;
56 ~Resetter() { }
57 T value() { return value_; }
59 private:
60 T value_;
61 DISALLOW_COPY_AND_ASSIGN(Resetter);
64 class TestObserver : public DisplayController::Observer,
65 public gfx::DisplayObserver,
66 public aura::client::FocusChangeObserver,
67 public aura::client::ActivationChangeObserver {
68 public:
69 TestObserver()
70 : changing_count_(0),
71 changed_count_(0),
72 bounds_changed_count_(0),
73 rotation_changed_count_(0),
74 workarea_changed_count_(0),
75 primary_changed_count_(0),
76 changed_display_id_(0),
77 focus_changed_count_(0),
78 activation_changed_count_(0) {
79 Shell::GetInstance()->display_controller()->AddObserver(this);
80 Shell::GetScreen()->AddObserver(this);
81 aura::client::GetFocusClient(Shell::GetPrimaryRootWindow())->
82 AddObserver(this);
83 aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
84 AddObserver(this);
87 ~TestObserver() override {
88 Shell::GetInstance()->display_controller()->RemoveObserver(this);
89 Shell::GetScreen()->RemoveObserver(this);
90 aura::client::GetFocusClient(Shell::GetPrimaryRootWindow())->
91 RemoveObserver(this);
92 aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
93 RemoveObserver(this);
96 // Overridden from DisplayController::Observer
97 void OnDisplayConfigurationChanging() override { ++changing_count_; }
98 void OnDisplayConfigurationChanged() override { ++changed_count_; }
100 // Overrideen from gfx::DisplayObserver
101 void OnDisplayMetricsChanged(const gfx::Display& display,
102 uint32_t metrics) override {
103 changed_display_id_ = display.id();
104 if (metrics & DISPLAY_METRIC_BOUNDS)
105 ++bounds_changed_count_;
106 if (metrics & DISPLAY_METRIC_ROTATION)
107 ++rotation_changed_count_;
108 if (metrics & DISPLAY_METRIC_WORK_AREA)
109 ++workarea_changed_count_;
110 if (metrics & DISPLAY_METRIC_PRIMARY)
111 ++primary_changed_count_;
113 void OnDisplayAdded(const gfx::Display& new_display) override {}
114 void OnDisplayRemoved(const gfx::Display& old_display) override {}
116 // Overridden from aura::client::FocusChangeObserver
117 void OnWindowFocused(aura::Window* gained_focus,
118 aura::Window* lost_focus) override {
119 focus_changed_count_++;
122 // Overridden from aura::client::ActivationChangeObserver
123 void OnWindowActivated(aura::Window* gained_active,
124 aura::Window* lost_active) override {
125 activation_changed_count_++;
127 void OnAttemptToReactivateWindow(aura::Window* request_active,
128 aura::Window* actual_active) override {}
130 int CountAndReset() {
131 EXPECT_EQ(changing_count_, changed_count_);
132 changed_count_ = 0;
133 return Resetter<int>(&changing_count_).value();
136 int64 GetBoundsChangedCountAndReset() {
137 return Resetter<int>(&bounds_changed_count_).value();
140 int64 GetRotationChangedCountAndReset() {
141 return Resetter<int>(&rotation_changed_count_).value();
144 int64 GetWorkareaChangedCountAndReset() {
145 return Resetter<int>(&workarea_changed_count_).value();
148 int64 GetPrimaryChangedCountAndReset() {
149 return Resetter<int>(&primary_changed_count_).value();
152 int64 GetChangedDisplayIdAndReset() {
153 return Resetter<int64>(&changed_display_id_).value();
156 int GetFocusChangedCountAndReset() {
157 return Resetter<int>(&focus_changed_count_).value();
160 int GetActivationChangedCountAndReset() {
161 return Resetter<int>(&activation_changed_count_).value();
164 private:
165 int changing_count_;
166 int changed_count_;
168 int bounds_changed_count_;
169 int rotation_changed_count_;
170 int workarea_changed_count_;
171 int primary_changed_count_;
172 int64 changed_display_id_;
174 int focus_changed_count_;
175 int activation_changed_count_;
177 DISALLOW_COPY_AND_ASSIGN(TestObserver);
180 gfx::Display GetPrimaryDisplay() {
181 return Shell::GetScreen()->GetDisplayNearestWindow(
182 Shell::GetAllRootWindows()[0]);
185 gfx::Display GetSecondaryDisplay() {
186 return Shell::GetScreen()->GetDisplayNearestWindow(
187 Shell::GetAllRootWindows()[1]);
190 void SetSecondaryDisplayLayoutAndOffset(DisplayLayout::Position position,
191 int offset) {
192 DisplayLayout layout(position, offset);
193 ASSERT_GT(Shell::GetScreen()->GetNumDisplays(), 1);
194 Shell::GetInstance()->display_manager()->
195 SetLayoutForCurrentDisplays(layout);
198 void SetSecondaryDisplayLayout(DisplayLayout::Position position) {
199 SetSecondaryDisplayLayoutAndOffset(position, 0);
202 void SetDefaultDisplayLayout(DisplayLayout::Position position) {
203 Shell::GetInstance()->display_manager()->layout_store()->
204 SetDefaultDisplayLayout(DisplayLayout(position, 0));
207 class DisplayControllerShutdownTest : public test::AshTestBase {
208 public:
209 DisplayControllerShutdownTest() {}
210 ~DisplayControllerShutdownTest() override {}
212 void TearDown() override {
213 test::AshTestBase::TearDown();
214 if (!SupportsMultipleDisplays())
215 return;
217 // Make sure that primary display is accessible after shutdown.
218 gfx::Display primary = Shell::GetScreen()->GetPrimaryDisplay();
219 EXPECT_EQ("0,0 444x333", primary.bounds().ToString());
220 EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
223 private:
224 DISALLOW_COPY_AND_ASSIGN(DisplayControllerShutdownTest);
227 class StartupHelper : public test::TestShellDelegate,
228 public DisplayController::Observer {
229 public:
230 StartupHelper() : displays_initialized_(false) {}
231 ~StartupHelper() override {}
233 // ash::ShellSelegate:
234 void PreInit() override {
235 Shell::GetInstance()->display_controller()->AddObserver(this);
238 // ash::DisplayController::Observer:
239 void OnDisplaysInitialized() override {
240 DCHECK(!displays_initialized_);
241 displays_initialized_ = true;
244 bool displays_initialized() const {
245 return displays_initialized_;
248 private:
249 bool displays_initialized_;
251 DISALLOW_COPY_AND_ASSIGN(StartupHelper);
254 class DisplayControllerStartupTest : public test::AshTestBase {
255 public:
256 DisplayControllerStartupTest() : startup_helper_(new StartupHelper) {}
257 ~DisplayControllerStartupTest() override {}
259 // ash::test::AshTestBase:
260 void SetUp() override {
261 ash_test_helper()->set_test_shell_delegate(startup_helper_);
262 test::AshTestBase::SetUp();
264 void TearDown() override {
265 Shell::GetInstance()->display_controller()->RemoveObserver(startup_helper_);
266 test::AshTestBase::TearDown();
269 const StartupHelper* startup_helper() const { return startup_helper_; }
271 private:
272 StartupHelper* startup_helper_; // Owned by ash::Shell.
274 DISALLOW_COPY_AND_ASSIGN(DisplayControllerStartupTest);
277 class TestEventHandler : public ui::EventHandler {
278 public:
279 TestEventHandler() : target_root_(NULL),
280 touch_radius_x_(0.0),
281 touch_radius_y_(0.0),
282 scroll_x_offset_(0.0),
283 scroll_y_offset_(0.0),
284 scroll_x_offset_ordinal_(0.0),
285 scroll_y_offset_ordinal_(0.0) {}
286 ~TestEventHandler() override {}
288 void OnMouseEvent(ui::MouseEvent* event) override {
289 if (event->flags() & ui::EF_IS_SYNTHESIZED &&
290 event->type() != ui::ET_MOUSE_EXITED &&
291 event->type() != ui::ET_MOUSE_ENTERED) {
292 return;
294 aura::Window* target = static_cast<aura::Window*>(event->target());
295 mouse_location_ = event->root_location();
296 target_root_ = target->GetRootWindow();
297 event->StopPropagation();
300 void OnTouchEvent(ui::TouchEvent* event) override {
301 aura::Window* target = static_cast<aura::Window*>(event->target());
302 // Only record when the target is the background which covers
303 // entire root window.
304 if (target->name() != kDesktopBackgroundView)
305 return;
306 touch_radius_x_ = event->radius_x();
307 touch_radius_y_ = event->radius_y();
308 event->StopPropagation();
311 void OnScrollEvent(ui::ScrollEvent* event) override {
312 aura::Window* target = static_cast<aura::Window*>(event->target());
313 // Only record when the target is the background which covers
314 // entire root window.
315 if (target->name() != kDesktopBackgroundView)
316 return;
318 if (event->type() == ui::ET_SCROLL) {
319 scroll_x_offset_ = event->x_offset();
320 scroll_y_offset_ = event->y_offset();
321 scroll_x_offset_ordinal_ = event->x_offset_ordinal();
322 scroll_y_offset_ordinal_ = event->y_offset_ordinal();
324 event->StopPropagation();
327 std::string GetLocationAndReset() {
328 std::string result = mouse_location_.ToString();
329 mouse_location_.SetPoint(0, 0);
330 target_root_ = NULL;
331 return result;
334 float touch_radius_x() { return touch_radius_x_; }
335 float touch_radius_y() { return touch_radius_y_; }
336 float scroll_x_offset() { return scroll_x_offset_; }
337 float scroll_y_offset() { return scroll_y_offset_; }
338 float scroll_x_offset_ordinal() { return scroll_x_offset_ordinal_; }
339 float scroll_y_offset_ordinal() { return scroll_y_offset_ordinal_; }
341 private:
342 gfx::Point mouse_location_;
343 aura::Window* target_root_;
345 float touch_radius_x_;
346 float touch_radius_y_;
347 float scroll_x_offset_;
348 float scroll_y_offset_;
349 float scroll_x_offset_ordinal_;
350 float scroll_y_offset_ordinal_;
352 DISALLOW_COPY_AND_ASSIGN(TestEventHandler);
355 gfx::Display::Rotation GetStoredRotation(int64 id) {
356 return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).rotation();
359 float GetStoredUIScale(int64 id) {
360 return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).
361 GetEffectiveUIScale();
364 #if defined(USE_X11)
365 void GetPrimaryAndSeconary(aura::Window** primary,
366 aura::Window** secondary) {
367 *primary = Shell::GetPrimaryRootWindow();
368 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
369 *secondary = root_windows[0] == *primary ? root_windows[1] : root_windows[0];
372 std::string GetXWindowName(aura::WindowTreeHost* host) {
373 char* name = NULL;
374 XFetchName(gfx::GetXDisplay(), host->GetAcceleratedWidget(), &name);
375 std::string ret(name);
376 XFree(name);
377 return ret;
379 #endif
381 class TestMouseWatcherListener : public views::MouseWatcherListener {
382 public:
383 TestMouseWatcherListener() {}
385 private:
386 // views::MouseWatcherListener:
387 void MouseMovedOutOfHost() override {}
389 DISALLOW_COPY_AND_ASSIGN(TestMouseWatcherListener);
392 } // namespace
394 typedef test::AshTestBase DisplayControllerTest;
396 TEST_F(DisplayControllerShutdownTest, Shutdown) {
397 if (!SupportsMultipleDisplays())
398 return;
400 UpdateDisplay("444x333, 200x200");
403 TEST_F(DisplayControllerStartupTest, Startup) {
404 if (!SupportsMultipleDisplays())
405 return;
407 EXPECT_TRUE(startup_helper()->displays_initialized());
410 TEST_F(DisplayControllerTest, SecondaryDisplayLayout) {
411 if (!SupportsMultipleDisplays())
412 return;
414 // Creates windows to catch activation change event.
415 scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
416 w1->Focus();
418 TestObserver observer;
419 UpdateDisplay("500x500,400x400");
420 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
421 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
422 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
423 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
424 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
425 gfx::Insets insets(5, 5, 5, 5);
426 int64 secondary_display_id = ScreenUtil::GetSecondaryDisplay().id();
427 Shell::GetInstance()->display_manager()->UpdateWorkAreaOfDisplay(
428 secondary_display_id, insets);
430 // Default layout is RIGHT.
431 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
432 EXPECT_EQ("500,0 400x400", GetSecondaryDisplay().bounds().ToString());
433 EXPECT_EQ("505,5 390x390", GetSecondaryDisplay().work_area().ToString());
434 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
435 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
437 // Layout the secondary display to the bottom of the primary.
438 SetSecondaryDisplayLayout(DisplayLayout::BOTTOM);
439 EXPECT_EQ(1, observer.CountAndReset());
440 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
441 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
442 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
443 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
444 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
445 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
446 EXPECT_EQ("0,500 400x400", GetSecondaryDisplay().bounds().ToString());
447 EXPECT_EQ("5,505 390x390", GetSecondaryDisplay().work_area().ToString());
449 // Layout the secondary display to the left of the primary.
450 SetSecondaryDisplayLayout(DisplayLayout::LEFT);
451 EXPECT_EQ(1, observer.CountAndReset());
452 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
453 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
454 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
455 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
456 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
457 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
458 EXPECT_EQ("-400,0 400x400", GetSecondaryDisplay().bounds().ToString());
459 EXPECT_EQ("-395,5 390x390", GetSecondaryDisplay().work_area().ToString());
461 // Layout the secondary display to the top of the primary.
462 SetSecondaryDisplayLayout(DisplayLayout::TOP);
463 EXPECT_EQ(1, observer.CountAndReset());
464 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
465 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
466 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
467 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
468 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
469 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
470 EXPECT_EQ("0,-400 400x400", GetSecondaryDisplay().bounds().ToString());
471 EXPECT_EQ("5,-395 390x390", GetSecondaryDisplay().work_area().ToString());
473 // Layout to the right with an offset.
474 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, 300);
475 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
476 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
477 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
478 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
479 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
480 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
481 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
482 EXPECT_EQ("500,300 400x400", GetSecondaryDisplay().bounds().ToString());
484 // Keep the minimum 100.
485 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, 490);
486 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
487 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
488 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
489 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
490 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
491 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
492 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
493 EXPECT_EQ("500,400 400x400", GetSecondaryDisplay().bounds().ToString());
495 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, -400);
496 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
497 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
498 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
499 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
500 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
501 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
502 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
503 EXPECT_EQ("500,-300 400x400", GetSecondaryDisplay().bounds().ToString());
505 // Layout to the bottom with an offset.
506 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -200);
507 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
508 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
509 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
510 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
511 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
512 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
513 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
514 EXPECT_EQ("-200,500 400x400", GetSecondaryDisplay().bounds().ToString());
516 // Keep the minimum 100.
517 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, 490);
518 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
519 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
520 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
521 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
522 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
523 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
524 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
525 EXPECT_EQ("400,500 400x400", GetSecondaryDisplay().bounds().ToString());
527 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -400);
528 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
529 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
530 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
531 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
532 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
533 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
534 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
535 EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString());
537 // Setting the same layout shouldn't invoke observers.
538 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -400);
539 EXPECT_EQ(0, observer.GetChangedDisplayIdAndReset());
540 EXPECT_EQ(0, observer.GetBoundsChangedCountAndReset());
541 EXPECT_EQ(0, observer.GetWorkareaChangedCountAndReset());
542 EXPECT_EQ(0, observer.CountAndReset()); // resize and add
543 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
544 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
545 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
546 EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString());
548 UpdateDisplay("500x500");
549 EXPECT_LE(1, observer.GetFocusChangedCountAndReset());
550 EXPECT_LE(1, observer.GetActivationChangedCountAndReset());
553 namespace {
555 DisplayInfo CreateDisplayInfo(int64 id,
556 int y,
557 gfx::Display::Rotation rotation) {
558 DisplayInfo info(id, "", false);
559 info.SetBounds(gfx::Rect(0, y, 500, 500));
560 info.set_rotation(rotation);
561 return info;
564 DisplayInfo CreateMirroredDisplayInfo(int64 id,
565 float device_scale_factor) {
566 DisplayInfo info = CreateDisplayInfo(id, 0, gfx::Display::ROTATE_0);
567 info.set_device_scale_factor(device_scale_factor);
568 return info;
571 } // namespace
573 TEST_F(DisplayControllerTest, MirrorToDockedWithFullscreen) {
574 if (!SupportsMultipleDisplays())
575 return;
577 // Creates windows to catch activation change event.
578 scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
579 w1->Focus();
581 // Docked mode.
582 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
584 const DisplayInfo internal_display_info =
585 CreateMirroredDisplayInfo(1, 2.0f);
586 const DisplayInfo external_display_info =
587 CreateMirroredDisplayInfo(2, 1.0f);
589 std::vector<DisplayInfo> display_info_list;
590 // Mirror.
591 display_info_list.push_back(internal_display_info);
592 display_info_list.push_back(external_display_info);
593 display_manager->OnNativeDisplaysChanged(display_info_list);
594 const int64 internal_display_id =
595 test::DisplayManagerTestApi(display_manager).
596 SetFirstDisplayAsInternalDisplay();
597 EXPECT_EQ(1, internal_display_id);
598 EXPECT_EQ(2U, display_manager->num_connected_displays());
599 EXPECT_EQ(1U, display_manager->GetNumDisplays());
601 wm::WindowState* window_state = wm::GetWindowState(w1.get());
602 const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
603 window_state->OnWMEvent(&toggle_fullscreen_event);
604 EXPECT_TRUE(window_state->IsFullscreen());
605 EXPECT_EQ("0,0 250x250", w1->bounds().ToString());
606 // Dock mode.
607 TestObserver observer;
608 display_info_list.clear();
609 display_info_list.push_back(external_display_info);
610 display_manager->OnNativeDisplaysChanged(display_info_list);
611 EXPECT_EQ(1U, display_manager->GetNumDisplays());
612 EXPECT_EQ(1U, display_manager->num_connected_displays());
613 // Observers are called due to primary change.
614 EXPECT_EQ(2, observer.GetChangedDisplayIdAndReset());
615 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
616 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
617 EXPECT_EQ(1, observer.GetPrimaryChangedCountAndReset());
618 EXPECT_EQ(1, observer.CountAndReset());
619 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
620 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
622 EXPECT_TRUE(window_state->IsFullscreen());
623 EXPECT_EQ("0,0 500x500", w1->bounds().ToString());
626 TEST_F(DisplayControllerTest, BoundsUpdated) {
627 if (!SupportsMultipleDisplays())
628 return;
630 // Creates windows to catch activation change event.
631 scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
632 w1->Focus();
634 TestObserver observer;
635 SetDefaultDisplayLayout(DisplayLayout::BOTTOM);
636 UpdateDisplay("200x200,300x300"); // layout, resize and add.
637 EXPECT_EQ(1, observer.CountAndReset());
638 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
639 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
641 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
642 gfx::Insets insets(5, 5, 5, 5);
643 display_manager->UpdateWorkAreaOfDisplay(
644 ScreenUtil::GetSecondaryDisplay().id(), insets);
646 EXPECT_EQ("0,0 200x200", GetPrimaryDisplay().bounds().ToString());
647 EXPECT_EQ("0,200 300x300", GetSecondaryDisplay().bounds().ToString());
648 EXPECT_EQ("5,205 290x290", GetSecondaryDisplay().work_area().ToString());
650 UpdateDisplay("400x400,200x200");
651 EXPECT_EQ(1, observer.CountAndReset()); // two resizes
652 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
653 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
654 EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
655 EXPECT_EQ("0,400 200x200", GetSecondaryDisplay().bounds().ToString());
657 UpdateDisplay("400x400,300x300");
658 EXPECT_EQ(1, observer.CountAndReset());
659 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
660 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
661 EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
662 EXPECT_EQ("0,400 300x300", GetSecondaryDisplay().bounds().ToString());
664 UpdateDisplay("400x400");
665 EXPECT_EQ(1, observer.CountAndReset());
666 EXPECT_LE(1, observer.GetFocusChangedCountAndReset());
667 EXPECT_LE(1, observer.GetActivationChangedCountAndReset());
668 EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
669 EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
671 UpdateDisplay("400x500*2,300x300");
672 EXPECT_EQ(1, observer.CountAndReset());
673 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
674 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
675 ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());
676 EXPECT_EQ("0,0 200x250", GetPrimaryDisplay().bounds().ToString());
677 EXPECT_EQ("0,250 300x300", GetSecondaryDisplay().bounds().ToString());
679 // No change
680 UpdateDisplay("400x500*2,300x300");
681 // We still call into Pre/PostDisplayConfigurationChange().
682 EXPECT_EQ(1, observer.CountAndReset());
683 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
684 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
686 // Rotation
687 observer.GetRotationChangedCountAndReset(); // we only want to reset.
688 int64 primary_id = GetPrimaryDisplay().id();
689 display_manager->SetDisplayRotation(primary_id, gfx::Display::ROTATE_90);
690 EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
691 EXPECT_EQ(1, observer.CountAndReset());
692 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
693 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
694 display_manager->SetDisplayRotation(primary_id, gfx::Display::ROTATE_90);
695 EXPECT_EQ(0, observer.GetRotationChangedCountAndReset());
696 EXPECT_EQ(0, observer.CountAndReset());
697 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
698 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
700 // UI scale is eanbled only on internal display.
701 int64 secondary_id = GetSecondaryDisplay().id();
702 test::DisplayManagerTestApi(display_manager)
703 .SetInternalDisplayId(secondary_id);
705 display_manager->SetDisplayUIScale(secondary_id, 1.125f);
706 EXPECT_EQ(1, observer.CountAndReset());
707 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
708 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
709 display_manager->SetDisplayUIScale(secondary_id, 1.125f);
710 EXPECT_EQ(0, observer.CountAndReset());
711 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
712 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
713 display_manager->SetDisplayUIScale(primary_id, 1.125f);
714 EXPECT_EQ(0, observer.CountAndReset());
715 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
716 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
717 display_manager->SetDisplayUIScale(primary_id, 1.125f);
718 EXPECT_EQ(0, observer.CountAndReset());
719 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
720 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
723 TEST_F(DisplayControllerTest, SwapPrimary) {
724 if (!SupportsMultipleDisplays())
725 return;
727 DisplayController* display_controller =
728 Shell::GetInstance()->display_controller();
729 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
731 UpdateDisplay("200x200,300x300");
732 gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay();
733 gfx::Display secondary_display = ScreenUtil::GetSecondaryDisplay();
735 DisplayLayout display_layout(DisplayLayout::RIGHT, 50);
736 display_manager->SetLayoutForCurrentDisplays(display_layout);
738 EXPECT_NE(primary_display.id(), secondary_display.id());
739 aura::Window* primary_root =
740 display_controller->GetRootWindowForDisplayId(primary_display.id());
741 aura::Window* secondary_root =
742 display_controller->GetRootWindowForDisplayId(secondary_display.id());
743 EXPECT_NE(primary_root, secondary_root);
744 aura::Window* shelf_window =
745 Shelf::ForPrimaryDisplay()->shelf_widget()->GetNativeView();
746 EXPECT_TRUE(primary_root->Contains(shelf_window));
747 EXPECT_FALSE(secondary_root->Contains(shelf_window));
748 EXPECT_EQ(primary_display.id(),
749 Shell::GetScreen()->GetDisplayNearestPoint(
750 gfx::Point(-100, -100)).id());
751 EXPECT_EQ(primary_display.id(),
752 Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
754 EXPECT_EQ("0,0 200x200", primary_display.bounds().ToString());
755 EXPECT_EQ("0,0 200x153", primary_display.work_area().ToString());
756 EXPECT_EQ("200,0 300x300", secondary_display.bounds().ToString());
757 EXPECT_EQ("200,0 300x253", secondary_display.work_area().ToString());
758 EXPECT_EQ("right, 50",
759 display_manager->GetCurrentDisplayLayout().ToString());
761 // Switch primary and secondary
762 display_controller->SetPrimaryDisplay(secondary_display);
763 const DisplayLayout& inverted_layout =
764 display_manager->GetCurrentDisplayLayout();
765 EXPECT_EQ("left, -50", inverted_layout.ToString());
767 EXPECT_EQ(secondary_display.id(),
768 Shell::GetScreen()->GetPrimaryDisplay().id());
769 EXPECT_EQ(primary_display.id(), ScreenUtil::GetSecondaryDisplay().id());
770 EXPECT_EQ(primary_display.id(),
771 Shell::GetScreen()->GetDisplayNearestPoint(
772 gfx::Point(-100, -100)).id());
773 EXPECT_EQ(secondary_display.id(),
774 Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
776 EXPECT_EQ(
777 primary_root,
778 display_controller->GetRootWindowForDisplayId(secondary_display.id()));
779 EXPECT_EQ(
780 secondary_root,
781 display_controller->GetRootWindowForDisplayId(primary_display.id()));
782 EXPECT_TRUE(primary_root->Contains(shelf_window));
783 EXPECT_FALSE(secondary_root->Contains(shelf_window));
785 // Test if the bounds are correctly swapped.
786 gfx::Display swapped_primary = Shell::GetScreen()->GetPrimaryDisplay();
787 gfx::Display swapped_secondary = ScreenUtil::GetSecondaryDisplay();
788 EXPECT_EQ("0,0 300x300", swapped_primary.bounds().ToString());
789 EXPECT_EQ("0,0 300x253", swapped_primary.work_area().ToString());
790 EXPECT_EQ("-200,-50 200x200", swapped_secondary.bounds().ToString());
792 EXPECT_EQ("-200,-50 200x153", swapped_secondary.work_area().ToString());
794 aura::WindowTracker tracker;
795 tracker.Add(primary_root);
796 tracker.Add(secondary_root);
798 // Deleting 2nd display should move the primary to original primary display.
799 UpdateDisplay("200x200");
800 RunAllPendingInMessageLoop(); // RootWindow is deleted in a posted task.
801 EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
802 EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetPrimaryDisplay().id());
803 EXPECT_EQ(primary_display.id(),
804 Shell::GetScreen()->GetDisplayNearestPoint(
805 gfx::Point(-100, -100)).id());
806 EXPECT_EQ(primary_display.id(),
807 Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
808 EXPECT_TRUE(tracker.Contains(primary_root));
809 EXPECT_FALSE(tracker.Contains(secondary_root));
810 EXPECT_TRUE(primary_root->Contains(shelf_window));
813 TEST_F(DisplayControllerTest, FindNearestDisplay) {
814 if (!SupportsMultipleDisplays())
815 return;
817 DisplayController* display_controller =
818 Shell::GetInstance()->display_controller();
819 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
821 UpdateDisplay("200x200,300x300");
822 DisplayLayout display_layout(DisplayLayout::RIGHT, 50);
823 display_manager->SetLayoutForCurrentDisplays(display_layout);
825 gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay();
826 gfx::Display secondary_display = ScreenUtil::GetSecondaryDisplay();
827 EXPECT_NE(primary_display.id(), secondary_display.id());
828 aura::Window* primary_root =
829 display_controller->GetRootWindowForDisplayId(primary_display.id());
830 aura::Window* secondary_root =
831 display_controller->GetRootWindowForDisplayId(secondary_display.id());
832 EXPECT_NE(primary_root, secondary_root);
834 // Test that points outside of any display return the nearest display.
835 EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
836 gfx::Point(-100, 0)).id());
837 EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
838 gfx::Point(0, -100)).id());
839 EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
840 gfx::Point(100, 100)).id());
841 EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
842 gfx::Point(224, 25)).id());
843 EXPECT_EQ(secondary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
844 gfx::Point(226, 25)).id());
845 EXPECT_EQ(secondary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
846 gfx::Point(600, 100)).id());
847 EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
848 gfx::Point(174, 225)).id());
849 EXPECT_EQ(secondary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
850 gfx::Point(176, 225)).id());
851 EXPECT_EQ(secondary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
852 gfx::Point(300, 400)).id());
855 TEST_F(DisplayControllerTest, SwapPrimaryById) {
856 if (!SupportsMultipleDisplays())
857 return;
859 DisplayController* display_controller =
860 Shell::GetInstance()->display_controller();
861 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
863 UpdateDisplay("200x200,300x300");
864 gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay();
865 gfx::Display secondary_display = ScreenUtil::GetSecondaryDisplay();
867 DisplayLayout display_layout(DisplayLayout::RIGHT, 50);
868 display_manager->SetLayoutForCurrentDisplays(display_layout);
870 EXPECT_NE(primary_display.id(), secondary_display.id());
871 aura::Window* primary_root =
872 display_controller->GetRootWindowForDisplayId(primary_display.id());
873 aura::Window* secondary_root =
874 display_controller->GetRootWindowForDisplayId(secondary_display.id());
875 aura::Window* shelf_window =
876 Shelf::ForPrimaryDisplay()->shelf_widget()->GetNativeView();
877 EXPECT_TRUE(primary_root->Contains(shelf_window));
878 EXPECT_FALSE(secondary_root->Contains(shelf_window));
879 EXPECT_NE(primary_root, secondary_root);
880 EXPECT_EQ(primary_display.id(),
881 Shell::GetScreen()->GetDisplayNearestPoint(
882 gfx::Point(-100, -100)).id());
883 EXPECT_EQ(primary_display.id(),
884 Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
886 // Switch primary and secondary by display ID.
887 TestObserver observer;
888 display_controller->SetPrimaryDisplayId(secondary_display.id());
889 EXPECT_EQ(secondary_display.id(),
890 Shell::GetScreen()->GetPrimaryDisplay().id());
891 EXPECT_EQ(primary_display.id(), ScreenUtil::GetSecondaryDisplay().id());
892 EXPECT_LT(0, observer.CountAndReset());
894 EXPECT_EQ(
895 primary_root,
896 display_controller->GetRootWindowForDisplayId(secondary_display.id()));
897 EXPECT_EQ(
898 secondary_root,
899 display_controller->GetRootWindowForDisplayId(primary_display.id()));
900 EXPECT_TRUE(primary_root->Contains(shelf_window));
901 EXPECT_FALSE(secondary_root->Contains(shelf_window));
903 const DisplayLayout& inverted_layout =
904 display_manager->GetCurrentDisplayLayout();
906 EXPECT_EQ("left, -50", inverted_layout.ToString());
908 // Calling the same ID don't do anything.
909 display_controller->SetPrimaryDisplayId(secondary_display.id());
910 EXPECT_EQ(0, observer.CountAndReset());
912 aura::WindowTracker tracker;
913 tracker.Add(primary_root);
914 tracker.Add(secondary_root);
916 // Deleting 2nd display should move the primary to original primary display.
917 UpdateDisplay("200x200");
918 RunAllPendingInMessageLoop(); // RootWindow is deleted in a posted task.
919 EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
920 EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetPrimaryDisplay().id());
921 EXPECT_EQ(primary_display.id(),
922 Shell::GetScreen()->GetDisplayNearestPoint(
923 gfx::Point(-100, -100)).id());
924 EXPECT_EQ(primary_display.id(),
925 Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
926 EXPECT_TRUE(tracker.Contains(primary_root));
927 EXPECT_FALSE(tracker.Contains(secondary_root));
928 EXPECT_TRUE(primary_root->Contains(shelf_window));
930 // Adding 2nd display with the same ID. The 2nd display should become primary
931 // since secondary id is still stored as desirable_primary_id.
932 std::vector<DisplayInfo> display_info_list;
933 display_info_list.push_back(
934 display_manager->GetDisplayInfo(primary_display.id()));
935 display_info_list.push_back(
936 display_manager->GetDisplayInfo(secondary_display.id()));
937 display_manager->OnNativeDisplaysChanged(display_info_list);
939 EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
940 EXPECT_EQ(secondary_display.id(),
941 Shell::GetScreen()->GetPrimaryDisplay().id());
942 EXPECT_EQ(primary_display.id(), ScreenUtil::GetSecondaryDisplay().id());
943 EXPECT_EQ(
944 primary_root,
945 display_controller->GetRootWindowForDisplayId(secondary_display.id()));
946 EXPECT_NE(
947 primary_root,
948 display_controller->GetRootWindowForDisplayId(primary_display.id()));
949 EXPECT_TRUE(primary_root->Contains(shelf_window));
951 // Deleting 2nd display and adding 2nd display with a different ID. The 2nd
952 // display shouldn't become primary.
953 UpdateDisplay("200x200");
954 DisplayInfo third_display_info(
955 secondary_display.id() + 1, std::string(), false);
956 third_display_info.SetBounds(secondary_display.bounds());
957 ASSERT_NE(primary_display.id(), third_display_info.id());
959 const DisplayInfo& primary_display_info =
960 display_manager->GetDisplayInfo(primary_display.id());
961 std::vector<DisplayInfo> display_info_list2;
962 display_info_list2.push_back(primary_display_info);
963 display_info_list2.push_back(third_display_info);
964 display_manager->OnNativeDisplaysChanged(display_info_list2);
965 EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
966 EXPECT_EQ(primary_display.id(),
967 Shell::GetScreen()->GetPrimaryDisplay().id());
968 EXPECT_EQ(third_display_info.id(), ScreenUtil::GetSecondaryDisplay().id());
969 EXPECT_EQ(
970 primary_root,
971 display_controller->GetRootWindowForDisplayId(primary_display.id()));
972 EXPECT_NE(
973 primary_root,
974 display_controller->GetRootWindowForDisplayId(third_display_info.id()));
975 EXPECT_TRUE(primary_root->Contains(shelf_window));
978 TEST_F(DisplayControllerTest, OverscanInsets) {
979 if (!SupportsMultipleDisplays())
980 return;
982 DisplayController* display_controller =
983 Shell::GetInstance()->display_controller();
984 TestEventHandler event_handler;
985 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
987 UpdateDisplay("120x200,300x400*2");
988 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
989 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
991 display_controller->SetOverscanInsets(display1.id(),
992 gfx::Insets(10, 15, 20, 25));
993 EXPECT_EQ("0,0 80x170", root_windows[0]->bounds().ToString());
994 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
995 EXPECT_EQ("80,0 150x200",
996 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
998 ui::test::EventGenerator generator(root_windows[0]);
999 generator.MoveMouseToInHost(20, 25);
1000 EXPECT_EQ("5,15", event_handler.GetLocationAndReset());
1002 display_controller->SetOverscanInsets(display1.id(), gfx::Insets());
1003 EXPECT_EQ("0,0 120x200", root_windows[0]->bounds().ToString());
1004 EXPECT_EQ("120,0 150x200",
1005 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1007 generator.MoveMouseToInHost(30, 20);
1008 EXPECT_EQ("30,20", event_handler.GetLocationAndReset());
1010 // Make sure the root window transformer uses correct scale
1011 // factor when swapping display. Test crbug.com/253690.
1012 UpdateDisplay("400x300*2,600x400/o");
1013 root_windows = Shell::GetAllRootWindows();
1014 gfx::Point point;
1015 Shell::GetAllRootWindows()[1]->GetHost()->
1016 GetRootTransform().TransformPoint(&point);
1017 EXPECT_EQ("15,10", point.ToString());
1019 display_controller->SwapPrimaryDisplay();
1020 point.SetPoint(0, 0);
1021 Shell::GetAllRootWindows()[1]->GetHost()->
1022 GetRootTransform().TransformPoint(&point);
1023 EXPECT_EQ("15,10", point.ToString());
1025 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1028 TEST_F(DisplayControllerTest, Rotate) {
1029 if (!SupportsMultipleDisplays())
1030 return;
1032 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1033 TestEventHandler event_handler;
1034 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1036 UpdateDisplay("120x200,300x400*2");
1037 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
1038 int64 display2_id = ScreenUtil::GetSecondaryDisplay().id();
1039 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1040 ui::test::EventGenerator generator1(root_windows[0]);
1042 TestObserver observer;
1043 EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString());
1044 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
1045 EXPECT_EQ("120,0 150x200",
1046 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1047 generator1.MoveMouseToInHost(50, 40);
1048 EXPECT_EQ("50,40", event_handler.GetLocationAndReset());
1049 EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display1.id()));
1050 EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id));
1051 EXPECT_EQ(0, observer.GetRotationChangedCountAndReset());
1053 display_manager->SetDisplayRotation(display1.id(),
1054 gfx::Display::ROTATE_90);
1055 EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString());
1056 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
1057 EXPECT_EQ("200,0 150x200",
1058 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1059 generator1.MoveMouseToInHost(50, 40);
1060 EXPECT_EQ("40,69", event_handler.GetLocationAndReset());
1061 EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id()));
1062 EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id));
1063 EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
1065 DisplayLayout display_layout(DisplayLayout::BOTTOM, 50);
1066 display_manager->SetLayoutForCurrentDisplays(display_layout);
1067 EXPECT_EQ("50,120 150x200",
1068 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1070 display_manager->SetDisplayRotation(display2_id,
1071 gfx::Display::ROTATE_270);
1072 EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString());
1073 EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString());
1074 EXPECT_EQ("50,120 200x150",
1075 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1076 EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id()));
1077 EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id));
1078 EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
1080 #if !defined(OS_WIN)
1081 ui::test::EventGenerator generator2(root_windows[1]);
1082 generator2.MoveMouseToInHost(50, 40);
1083 EXPECT_EQ("179,25", event_handler.GetLocationAndReset());
1084 display_manager->SetDisplayRotation(display1.id(),
1085 gfx::Display::ROTATE_180);
1087 EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString());
1088 EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString());
1089 // Dislay must share at least 100, so the x's offset becomes 20.
1090 EXPECT_EQ("20,200 200x150",
1091 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1092 EXPECT_EQ(gfx::Display::ROTATE_180, GetStoredRotation(display1.id()));
1093 EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id));
1094 EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
1096 generator1.MoveMouseToInHost(50, 40);
1097 EXPECT_EQ("69,159", event_handler.GetLocationAndReset());
1098 #endif
1100 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1103 TEST_F(DisplayControllerTest, ScaleRootWindow) {
1104 if (!SupportsMultipleDisplays())
1105 return;
1107 TestEventHandler event_handler;
1108 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1110 UpdateDisplay("600x400*2@1.5,500x300");
1112 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1113 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
1114 test::DisplayManagerTestApi(display_manager)
1115 .SetInternalDisplayId(display1.id());
1117 gfx::Display display2 = ScreenUtil::GetSecondaryDisplay();
1118 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1119 EXPECT_EQ("0,0 450x300", display1.bounds().ToString());
1120 EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString());
1121 EXPECT_EQ("450,0 500x300", display2.bounds().ToString());
1122 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1123 EXPECT_EQ(1.0f, GetStoredUIScale(display2.id()));
1125 ui::test::EventGenerator generator(root_windows[0]);
1126 generator.MoveMouseToInHost(599, 200);
1127 EXPECT_EQ("449,150", event_handler.GetLocationAndReset());
1129 display_manager->SetDisplayUIScale(display1.id(), 1.25f);
1130 display1 = Shell::GetScreen()->GetPrimaryDisplay();
1131 display2 = ScreenUtil::GetSecondaryDisplay();
1132 EXPECT_EQ("0,0 375x250", display1.bounds().ToString());
1133 EXPECT_EQ("0,0 375x250", root_windows[0]->bounds().ToString());
1134 EXPECT_EQ("375,0 500x300", display2.bounds().ToString());
1135 EXPECT_EQ(1.25f, GetStoredUIScale(display1.id()));
1136 EXPECT_EQ(1.0f, GetStoredUIScale(display2.id()));
1138 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1141 TEST_F(DisplayControllerTest, TouchScale) {
1142 if (!SupportsMultipleDisplays())
1143 return;
1145 TestEventHandler event_handler;
1146 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1148 UpdateDisplay("200x200*2");
1149 gfx::Display display = Shell::GetScreen()->GetPrimaryDisplay();
1150 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1151 aura::Window* root_window = root_windows[0];
1152 ui::test::EventGenerator generator(root_window);
1154 generator.PressMoveAndReleaseTouchTo(50, 50);
1155 // Default test touches have radius_x/y = 1.0, with device scale
1156 // factor = 2, the scaled radius_x/y should be 0.5.
1157 EXPECT_EQ(0.5, event_handler.touch_radius_x());
1158 EXPECT_EQ(0.5, event_handler.touch_radius_y());
1160 generator.ScrollSequence(gfx::Point(0,0),
1161 base::TimeDelta::FromMilliseconds(100),
1162 10.0, 1.0, 5, 1);
1164 // ordinal_offset is invariant to the device scale factor.
1165 EXPECT_EQ(event_handler.scroll_x_offset(),
1166 event_handler.scroll_x_offset_ordinal());
1167 EXPECT_EQ(event_handler.scroll_y_offset(),
1168 event_handler.scroll_y_offset_ordinal());
1170 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1173 TEST_F(DisplayControllerTest, ConvertHostToRootCoords) {
1174 if (!SupportsMultipleDisplays())
1175 return;
1177 TestEventHandler event_handler;
1178 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1180 UpdateDisplay("600x400*2/r@1.5");
1182 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
1183 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1184 EXPECT_EQ("0,0 300x450", display1.bounds().ToString());
1185 EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString());
1186 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1188 ui::test::EventGenerator generator(root_windows[0]);
1189 generator.MoveMouseToInHost(0, 0);
1190 EXPECT_EQ("0,449", event_handler.GetLocationAndReset());
1191 generator.MoveMouseToInHost(599, 0);
1192 EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
1193 generator.MoveMouseToInHost(599, 399);
1194 EXPECT_EQ("299,0", event_handler.GetLocationAndReset());
1195 generator.MoveMouseToInHost(0, 399);
1196 EXPECT_EQ("299,449", event_handler.GetLocationAndReset());
1198 UpdateDisplay("600x400*2/u@1.5");
1199 display1 = Shell::GetScreen()->GetPrimaryDisplay();
1200 root_windows = Shell::GetAllRootWindows();
1201 EXPECT_EQ("0,0 450x300", display1.bounds().ToString());
1202 EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString());
1203 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1205 generator.MoveMouseToInHost(0, 0);
1206 EXPECT_EQ("449,299", event_handler.GetLocationAndReset());
1207 generator.MoveMouseToInHost(599, 0);
1208 EXPECT_EQ("0,299", event_handler.GetLocationAndReset());
1209 generator.MoveMouseToInHost(599, 399);
1210 EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
1211 generator.MoveMouseToInHost(0, 399);
1212 EXPECT_EQ("449,0", event_handler.GetLocationAndReset());
1214 UpdateDisplay("600x400*2/l@1.5");
1215 display1 = Shell::GetScreen()->GetPrimaryDisplay();
1216 root_windows = Shell::GetAllRootWindows();
1217 EXPECT_EQ("0,0 300x450", display1.bounds().ToString());
1218 EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString());
1219 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1221 generator.MoveMouseToInHost(0, 0);
1222 EXPECT_EQ("299,0", event_handler.GetLocationAndReset());
1223 generator.MoveMouseToInHost(599, 0);
1224 EXPECT_EQ("299,449", event_handler.GetLocationAndReset());
1225 generator.MoveMouseToInHost(599, 399);
1226 EXPECT_EQ("0,449", event_handler.GetLocationAndReset());
1227 generator.MoveMouseToInHost(0, 399);
1228 EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
1230 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1233 // Make sure that the compositor based mirroring can switch
1234 // from/to dock mode.
1235 TEST_F(DisplayControllerTest, DockToSingle) {
1236 if (!SupportsMultipleDisplays())
1237 return;
1239 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1241 const int64 internal_id = 1;
1243 const DisplayInfo internal_display_info =
1244 CreateDisplayInfo(internal_id, 0, gfx::Display::ROTATE_0);
1245 const DisplayInfo external_display_info =
1246 CreateDisplayInfo(2, 1, gfx::Display::ROTATE_90);
1248 std::vector<DisplayInfo> display_info_list;
1249 // Extended
1250 display_info_list.push_back(internal_display_info);
1251 display_info_list.push_back(external_display_info);
1252 display_manager->OnNativeDisplaysChanged(display_info_list);
1253 const int64 internal_display_id =
1254 test::DisplayManagerTestApi(display_manager).
1255 SetFirstDisplayAsInternalDisplay();
1256 EXPECT_EQ(internal_id, internal_display_id);
1257 EXPECT_EQ(2U, display_manager->GetNumDisplays());
1259 // Dock mode.
1260 display_info_list.clear();
1261 display_info_list.push_back(external_display_info);
1262 display_manager->OnNativeDisplaysChanged(display_info_list);
1263 EXPECT_EQ(1U, display_manager->GetNumDisplays());
1264 EXPECT_FALSE(Shell::GetPrimaryRootWindow()->GetHost()->
1265 GetRootTransform().IsIdentityOrIntegerTranslation());
1267 // Switch to single mode and make sure the transform is the one
1268 // for the internal display.
1269 display_info_list.clear();
1270 display_info_list.push_back(internal_display_info);
1271 display_manager->OnNativeDisplaysChanged(display_info_list);
1272 EXPECT_TRUE(Shell::GetPrimaryRootWindow()->GetHost()->
1273 GetRootTransform().IsIdentityOrIntegerTranslation());
1276 // Tests if switching two displays at the same time while the primary display
1277 // is swapped should not cause a crash. (crbug.com/426292)
1278 TEST_F(DisplayControllerTest, ReplaceSwappedPrimary) {
1279 if (!SupportsMultipleDisplays())
1280 return;
1281 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1283 const DisplayInfo first_display_info =
1284 CreateDisplayInfo(10, 0, gfx::Display::ROTATE_0);
1285 const DisplayInfo second_display_info =
1286 CreateDisplayInfo(11, 1, gfx::Display::ROTATE_0);
1288 std::vector<DisplayInfo> display_info_list;
1289 // Extended
1290 display_info_list.push_back(first_display_info);
1291 display_info_list.push_back(second_display_info);
1292 display_manager->OnNativeDisplaysChanged(display_info_list);
1294 Shell::GetInstance()->display_controller()->SwapPrimaryDisplay();
1296 EXPECT_EQ(11, Shell::GetScreen()->GetPrimaryDisplay().id());
1298 display_info_list.clear();
1299 const DisplayInfo new_first_display_info =
1300 CreateDisplayInfo(20, 0, gfx::Display::ROTATE_0);
1301 const DisplayInfo new_second_display_info =
1302 CreateDisplayInfo(21, 1, gfx::Display::ROTATE_0);
1303 display_info_list.push_back(new_first_display_info);
1304 display_info_list.push_back(new_second_display_info);
1305 display_manager->OnNativeDisplaysChanged(display_info_list);
1307 EXPECT_EQ(20, Shell::GetScreen()->GetPrimaryDisplay().id());
1310 #if defined(USE_X11)
1311 TEST_F(DisplayControllerTest, XWidowNameForRootWindow) {
1312 EXPECT_EQ("aura_root_0", GetXWindowName(
1313 Shell::GetPrimaryRootWindow()->GetHost()));
1315 // Multiple display.
1316 UpdateDisplay("200x200,300x300");
1317 aura::Window* primary, *secondary;
1318 GetPrimaryAndSeconary(&primary, &secondary);
1319 EXPECT_EQ("aura_root_0", GetXWindowName(primary->GetHost()));
1320 EXPECT_EQ("aura_root_x", GetXWindowName(secondary->GetHost()));
1322 // Swap primary.
1323 primary = secondary = NULL;
1324 Shell::GetInstance()->display_controller()->SwapPrimaryDisplay();
1325 GetPrimaryAndSeconary(&primary, &secondary);
1326 EXPECT_EQ("aura_root_0", GetXWindowName(primary->GetHost()));
1327 EXPECT_EQ("aura_root_x", GetXWindowName(secondary->GetHost()));
1329 // Switching back to single display.
1330 UpdateDisplay("300x400");
1331 EXPECT_EQ("aura_root_0", GetXWindowName(
1332 Shell::GetPrimaryRootWindow()->GetHost()));
1334 #endif
1336 TEST_F(DisplayControllerTest, UpdateMouseLocationAfterDisplayChange) {
1337 if (!SupportsMultipleDisplays())
1338 return;
1340 UpdateDisplay("200x200,300x300");
1341 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1343 aura::Env* env = aura::Env::GetInstance();
1345 ui::test::EventGenerator generator(root_windows[0]);
1347 // Set the initial position.
1348 generator.MoveMouseToInHost(350, 150);
1349 EXPECT_EQ("350,150", env->last_mouse_location().ToString());
1351 // A mouse pointer will stay in the 2nd display.
1352 UpdateDisplay("300x300,200x200");
1353 EXPECT_EQ("450,50", env->last_mouse_location().ToString());
1355 // A mouse pointer will be outside of displays and move to the
1356 // center of 2nd display.
1357 UpdateDisplay("300x300,100x100");
1358 EXPECT_EQ("350,50", env->last_mouse_location().ToString());
1360 // 2nd display was disconnected, and the cursor is
1361 // now in the 1st display.
1362 UpdateDisplay("400x400");
1363 EXPECT_EQ("50,350", env->last_mouse_location().ToString());
1365 // 1st display's resolution has changed, and the mouse pointer is
1366 // now outside. Move the mouse pointer to the center of 1st display.
1367 UpdateDisplay("300x300");
1368 EXPECT_EQ("150,150", env->last_mouse_location().ToString());
1370 // Move the mouse pointer to the bottom of 1st display.
1371 generator.MoveMouseToInHost(150, 290);
1372 EXPECT_EQ("150,290", env->last_mouse_location().ToString());
1374 // The mouse pointer is now on 2nd display.
1375 UpdateDisplay("300x280,200x200");
1376 EXPECT_EQ("450,10", env->last_mouse_location().ToString());
1379 TEST_F(DisplayControllerTest, UpdateMouseLocationAfterDisplayChange_2ndOnLeft) {
1380 if (!SupportsMultipleDisplays())
1381 return;
1383 // Set the 2nd display on the left.
1384 DisplayLayoutStore* layout_store =
1385 Shell::GetInstance()->display_manager()->layout_store();
1386 DisplayLayout layout = layout_store->default_display_layout();
1387 layout.position = DisplayLayout::LEFT;
1388 layout_store->SetDefaultDisplayLayout(layout);
1390 UpdateDisplay("200x200,300x300");
1391 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1393 EXPECT_EQ("-300,0 300x300",
1394 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1396 aura::Env* env = aura::Env::GetInstance();
1398 // Set the initial position.
1399 root_windows[0]->MoveCursorTo(gfx::Point(-150, 250));
1400 EXPECT_EQ("-150,250", env->last_mouse_location().ToString());
1402 // A mouse pointer will stay in 2nd display.
1403 UpdateDisplay("300x300,200x300");
1404 EXPECT_EQ("-50,150", env->last_mouse_location().ToString());
1406 // A mouse pointer will be outside of displays and move to the
1407 // center of 2nd display.
1408 UpdateDisplay("300x300,200x100");
1409 EXPECT_EQ("-100,50", env->last_mouse_location().ToString());
1411 // 2nd display was disconnected. Mouse pointer should move to
1412 // 1st display.
1413 UpdateDisplay("300x300");
1414 EXPECT_EQ("150,150", env->last_mouse_location().ToString());
1417 // Test that the cursor swaps displays and that its scale factor and rotation
1418 // are updated when the primary display is swapped.
1419 TEST_F(DisplayControllerTest,
1420 UpdateMouseLocationAfterDisplayChange_SwapPrimary) {
1421 if (!SupportsMultipleDisplays())
1422 return;
1424 UpdateDisplay("200x200,200x200*2/r");
1426 aura::Env* env = aura::Env::GetInstance();
1427 Shell* shell = Shell::GetInstance();
1428 DisplayController* display_controller = shell->display_controller();
1429 test::CursorManagerTestApi test_api(shell->cursor_manager());
1431 display_controller->GetPrimaryRootWindow()->MoveCursorTo(gfx::Point(20, 50));
1433 EXPECT_EQ("20,50", env->last_mouse_location().ToString());
1434 EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
1435 EXPECT_EQ(gfx::Display::ROTATE_0, test_api.GetCurrentCursorRotation());
1437 display_controller->SwapPrimaryDisplay();
1439 EXPECT_EQ("20,50", env->last_mouse_location().ToString());
1440 EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor());
1441 EXPECT_EQ(gfx::Display::ROTATE_90, test_api.GetCurrentCursorRotation());
1444 // Test that the cursor moves to the other display and that its scale factor
1445 // and rotation are updated when the primary display is disconnected.
1446 TEST_F(DisplayControllerTest,
1447 UpdateMouseLocationAfterDisplayChange_PrimaryDisconnected) {
1448 if (!SupportsMultipleDisplays())
1449 return;
1451 aura::Env* env = aura::Env::GetInstance();
1452 Shell* shell = Shell::GetInstance();
1453 DisplayController* display_controller = shell->display_controller();
1454 test::CursorManagerTestApi test_api(shell->cursor_manager());
1456 UpdateDisplay("300x300*2/r,200x200");
1457 // Swap the primary display to make it possible to remove the primary display
1458 // via UpdateDisplay().
1459 display_controller->SwapPrimaryDisplay();
1460 int primary_display_id = display_controller->GetPrimaryDisplayId();
1462 display_controller->GetPrimaryRootWindow()->MoveCursorTo(gfx::Point(20, 50));
1464 EXPECT_EQ("20,50", env->last_mouse_location().ToString());
1465 EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
1466 EXPECT_EQ(gfx::Display::ROTATE_0, test_api.GetCurrentCursorRotation());
1468 UpdateDisplay("300x300*2/r");
1469 ASSERT_NE(primary_display_id, display_controller->GetPrimaryDisplayId());
1471 // Cursor should be centered on the remaining display.
1472 EXPECT_EQ("75,75", env->last_mouse_location().ToString());
1473 EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor());
1474 EXPECT_EQ(gfx::Display::ROTATE_90, test_api.GetCurrentCursorRotation());
1477 // GetRootWindowForDisplayId() for removed gfx::Display during
1478 // OnDisplayRemoved() should not cause crash. See http://crbug.com/415222
1479 TEST_F(DisplayControllerTest,
1480 GetRootWindowForDisplayIdDuringDisplayDisconnection) {
1481 if (!SupportsMultipleDisplays())
1482 return;
1484 UpdateDisplay("300x300,200x200");
1485 aura::Window* root2 =
1486 Shell::GetInstance()->display_controller()->GetRootWindowForDisplayId(
1487 ScreenUtil::GetSecondaryDisplay().id());
1488 views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
1489 nullptr, root2, gfx::Rect(350, 0, 100, 100));
1490 views::View* view = new views::View();
1491 widget->GetContentsView()->AddChildView(view);
1492 view->SetBounds(0, 0, 100, 100);
1493 widget->Show();
1495 TestMouseWatcherListener listener;
1496 views::MouseWatcher watcher(
1497 new views::MouseWatcherViewHost(view, gfx::Insets()), &listener);
1498 watcher.Start();
1500 ui::test::EventGenerator event_generator(
1501 widget->GetNativeWindow()->GetRootWindow());
1502 event_generator.MoveMouseToCenterOf(widget->GetNativeWindow());
1504 UpdateDisplay("300x300");
1505 watcher.Stop();
1507 widget->CloseNow();
1510 } // namespace ash