Mac: Fix performance issues with remote CoreAnimation
[chromium-blink-merge.git] / ash / display / display_controller_unittest.cc
blob05a977b62e3eb7ee0a415ac6dab380e4351e360c
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/widget/widget.h"
33 #include "ui/wm/public/activation_change_observer.h"
34 #include "ui/wm/public/activation_client.h"
36 #if defined(USE_X11)
37 #include <X11/Xlib.h>
38 #include "ui/gfx/x/x11_types.h"
39 #undef RootWindow
40 #endif
42 namespace ash {
43 namespace {
45 const char kDesktopBackgroundView[] = "DesktopBackgroundView";
47 template<typename T>
48 class Resetter {
49 public:
50 explicit Resetter(T* value) : value_(*value) {
51 *value = 0;
53 ~Resetter() { }
54 T value() { return value_; }
56 private:
57 T value_;
58 DISALLOW_COPY_AND_ASSIGN(Resetter);
61 class TestObserver : public DisplayController::Observer,
62 public gfx::DisplayObserver,
63 public aura::client::FocusChangeObserver,
64 public aura::client::ActivationChangeObserver {
65 public:
66 TestObserver()
67 : changing_count_(0),
68 changed_count_(0),
69 bounds_changed_count_(0),
70 rotation_changed_count_(0),
71 workarea_changed_count_(0),
72 primary_changed_count_(0),
73 changed_display_id_(0),
74 focus_changed_count_(0),
75 activation_changed_count_(0) {
76 Shell::GetInstance()->display_controller()->AddObserver(this);
77 Shell::GetScreen()->AddObserver(this);
78 aura::client::GetFocusClient(Shell::GetPrimaryRootWindow())->
79 AddObserver(this);
80 aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
81 AddObserver(this);
84 ~TestObserver() override {
85 Shell::GetInstance()->display_controller()->RemoveObserver(this);
86 Shell::GetScreen()->RemoveObserver(this);
87 aura::client::GetFocusClient(Shell::GetPrimaryRootWindow())->
88 RemoveObserver(this);
89 aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
90 RemoveObserver(this);
93 // Overridden from DisplayController::Observer
94 void OnDisplayConfigurationChanging() override { ++changing_count_; }
95 void OnDisplayConfigurationChanged() override { ++changed_count_; }
97 // Overrideen from gfx::DisplayObserver
98 void OnDisplayMetricsChanged(const gfx::Display& display,
99 uint32_t metrics) override {
100 changed_display_id_ = display.id();
101 if (metrics & DISPLAY_METRIC_BOUNDS)
102 ++bounds_changed_count_;
103 if (metrics & DISPLAY_METRIC_ROTATION)
104 ++rotation_changed_count_;
105 if (metrics & DISPLAY_METRIC_WORK_AREA)
106 ++workarea_changed_count_;
107 if (metrics & DISPLAY_METRIC_PRIMARY)
108 ++primary_changed_count_;
110 void OnDisplayAdded(const gfx::Display& new_display) override {}
111 void OnDisplayRemoved(const gfx::Display& old_display) override {}
113 // Overridden from aura::client::FocusChangeObserver
114 void OnWindowFocused(aura::Window* gained_focus,
115 aura::Window* lost_focus) override {
116 focus_changed_count_++;
119 // Overridden from aura::client::ActivationChangeObserver
120 void OnWindowActivated(aura::Window* gained_active,
121 aura::Window* lost_active) override {
122 activation_changed_count_++;
124 void OnAttemptToReactivateWindow(aura::Window* request_active,
125 aura::Window* actual_active) override {}
127 int CountAndReset() {
128 EXPECT_EQ(changing_count_, changed_count_);
129 changed_count_ = 0;
130 return Resetter<int>(&changing_count_).value();
133 int64 GetBoundsChangedCountAndReset() {
134 return Resetter<int>(&bounds_changed_count_).value();
137 int64 GetRotationChangedCountAndReset() {
138 return Resetter<int>(&rotation_changed_count_).value();
141 int64 GetWorkareaChangedCountAndReset() {
142 return Resetter<int>(&workarea_changed_count_).value();
145 int64 GetPrimaryChangedCountAndReset() {
146 return Resetter<int>(&primary_changed_count_).value();
149 int64 GetChangedDisplayIdAndReset() {
150 return Resetter<int64>(&changed_display_id_).value();
153 int GetFocusChangedCountAndReset() {
154 return Resetter<int>(&focus_changed_count_).value();
157 int GetActivationChangedCountAndReset() {
158 return Resetter<int>(&activation_changed_count_).value();
161 private:
162 int changing_count_;
163 int changed_count_;
165 int bounds_changed_count_;
166 int rotation_changed_count_;
167 int workarea_changed_count_;
168 int primary_changed_count_;
169 int64 changed_display_id_;
171 int focus_changed_count_;
172 int activation_changed_count_;
174 DISALLOW_COPY_AND_ASSIGN(TestObserver);
177 gfx::Display GetPrimaryDisplay() {
178 return Shell::GetScreen()->GetDisplayNearestWindow(
179 Shell::GetAllRootWindows()[0]);
182 gfx::Display GetSecondaryDisplay() {
183 return Shell::GetScreen()->GetDisplayNearestWindow(
184 Shell::GetAllRootWindows()[1]);
187 void SetSecondaryDisplayLayoutAndOffset(DisplayLayout::Position position,
188 int offset) {
189 DisplayLayout layout(position, offset);
190 ASSERT_GT(Shell::GetScreen()->GetNumDisplays(), 1);
191 Shell::GetInstance()->display_manager()->
192 SetLayoutForCurrentDisplays(layout);
195 void SetSecondaryDisplayLayout(DisplayLayout::Position position) {
196 SetSecondaryDisplayLayoutAndOffset(position, 0);
199 void SetDefaultDisplayLayout(DisplayLayout::Position position) {
200 Shell::GetInstance()->display_manager()->layout_store()->
201 SetDefaultDisplayLayout(DisplayLayout(position, 0));
204 class DisplayControllerShutdownTest : public test::AshTestBase {
205 public:
206 DisplayControllerShutdownTest() {}
207 ~DisplayControllerShutdownTest() override {}
209 void TearDown() override {
210 test::AshTestBase::TearDown();
211 if (!SupportsMultipleDisplays())
212 return;
214 // Make sure that primary display is accessible after shutdown.
215 gfx::Display primary = Shell::GetScreen()->GetPrimaryDisplay();
216 EXPECT_EQ("0,0 444x333", primary.bounds().ToString());
217 EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
220 private:
221 DISALLOW_COPY_AND_ASSIGN(DisplayControllerShutdownTest);
224 class StartupHelper : public test::TestShellDelegate,
225 public DisplayController::Observer {
226 public:
227 StartupHelper() : displays_initialized_(false) {}
228 ~StartupHelper() override {}
230 // ash::ShellSelegate:
231 void PreInit() override {
232 Shell::GetInstance()->display_controller()->AddObserver(this);
235 // ash::DisplayController::Observer:
236 void OnDisplaysInitialized() override {
237 DCHECK(!displays_initialized_);
238 displays_initialized_ = true;
241 bool displays_initialized() const {
242 return displays_initialized_;
245 private:
246 bool displays_initialized_;
248 DISALLOW_COPY_AND_ASSIGN(StartupHelper);
251 class DisplayControllerStartupTest : public test::AshTestBase {
252 public:
253 DisplayControllerStartupTest() : startup_helper_(new StartupHelper) {}
254 ~DisplayControllerStartupTest() override {}
256 // ash::test::AshTestBase:
257 void SetUp() override {
258 ash_test_helper()->set_test_shell_delegate(startup_helper_);
259 test::AshTestBase::SetUp();
261 void TearDown() override {
262 Shell::GetInstance()->display_controller()->RemoveObserver(startup_helper_);
263 test::AshTestBase::TearDown();
266 const StartupHelper* startup_helper() const { return startup_helper_; }
268 private:
269 StartupHelper* startup_helper_; // Owned by ash::Shell.
271 DISALLOW_COPY_AND_ASSIGN(DisplayControllerStartupTest);
274 class TestEventHandler : public ui::EventHandler {
275 public:
276 TestEventHandler() : target_root_(NULL),
277 touch_radius_x_(0.0),
278 touch_radius_y_(0.0),
279 scroll_x_offset_(0.0),
280 scroll_y_offset_(0.0),
281 scroll_x_offset_ordinal_(0.0),
282 scroll_y_offset_ordinal_(0.0) {}
283 ~TestEventHandler() override {}
285 void OnMouseEvent(ui::MouseEvent* event) override {
286 if (event->flags() & ui::EF_IS_SYNTHESIZED &&
287 event->type() != ui::ET_MOUSE_EXITED &&
288 event->type() != ui::ET_MOUSE_ENTERED) {
289 return;
291 aura::Window* target = static_cast<aura::Window*>(event->target());
292 mouse_location_ = event->root_location();
293 target_root_ = target->GetRootWindow();
294 event->StopPropagation();
297 void OnTouchEvent(ui::TouchEvent* event) override {
298 aura::Window* target = static_cast<aura::Window*>(event->target());
299 // Only record when the target is the background which covers
300 // entire root window.
301 if (target->name() != kDesktopBackgroundView)
302 return;
303 touch_radius_x_ = event->radius_x();
304 touch_radius_y_ = event->radius_y();
305 event->StopPropagation();
308 void OnScrollEvent(ui::ScrollEvent* event) override {
309 aura::Window* target = static_cast<aura::Window*>(event->target());
310 // Only record when the target is the background which covers
311 // entire root window.
312 if (target->name() != kDesktopBackgroundView)
313 return;
315 if (event->type() == ui::ET_SCROLL) {
316 scroll_x_offset_ = event->x_offset();
317 scroll_y_offset_ = event->y_offset();
318 scroll_x_offset_ordinal_ = event->x_offset_ordinal();
319 scroll_y_offset_ordinal_ = event->y_offset_ordinal();
321 event->StopPropagation();
324 std::string GetLocationAndReset() {
325 std::string result = mouse_location_.ToString();
326 mouse_location_.SetPoint(0, 0);
327 target_root_ = NULL;
328 return result;
331 float touch_radius_x() { return touch_radius_x_; }
332 float touch_radius_y() { return touch_radius_y_; }
333 float scroll_x_offset() { return scroll_x_offset_; }
334 float scroll_y_offset() { return scroll_y_offset_; }
335 float scroll_x_offset_ordinal() { return scroll_x_offset_ordinal_; }
336 float scroll_y_offset_ordinal() { return scroll_y_offset_ordinal_; }
338 private:
339 gfx::Point mouse_location_;
340 aura::Window* target_root_;
342 float touch_radius_x_;
343 float touch_radius_y_;
344 float scroll_x_offset_;
345 float scroll_y_offset_;
346 float scroll_x_offset_ordinal_;
347 float scroll_y_offset_ordinal_;
349 DISALLOW_COPY_AND_ASSIGN(TestEventHandler);
352 gfx::Display::Rotation GetStoredRotation(int64 id) {
353 return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).rotation();
356 float GetStoredUIScale(int64 id) {
357 return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).
358 GetEffectiveUIScale();
361 #if defined(USE_X11)
362 void GetPrimaryAndSeconary(aura::Window** primary,
363 aura::Window** secondary) {
364 *primary = Shell::GetPrimaryRootWindow();
365 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
366 *secondary = root_windows[0] == *primary ? root_windows[1] : root_windows[0];
369 std::string GetXWindowName(aura::WindowTreeHost* host) {
370 char* name = NULL;
371 XFetchName(gfx::GetXDisplay(), host->GetAcceleratedWidget(), &name);
372 std::string ret(name);
373 XFree(name);
374 return ret;
376 #endif
378 } // namespace
380 typedef test::AshTestBase DisplayControllerTest;
382 TEST_F(DisplayControllerShutdownTest, Shutdown) {
383 if (!SupportsMultipleDisplays())
384 return;
386 UpdateDisplay("444x333, 200x200");
389 TEST_F(DisplayControllerStartupTest, Startup) {
390 if (!SupportsMultipleDisplays())
391 return;
393 EXPECT_TRUE(startup_helper()->displays_initialized());
396 TEST_F(DisplayControllerTest, SecondaryDisplayLayout) {
397 if (!SupportsMultipleDisplays())
398 return;
400 // Creates windows to catch activation change event.
401 scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
402 w1->Focus();
404 TestObserver observer;
405 UpdateDisplay("500x500,400x400");
406 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
407 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
408 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
409 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
410 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
411 gfx::Insets insets(5, 5, 5, 5);
412 int64 secondary_display_id = ScreenUtil::GetSecondaryDisplay().id();
413 Shell::GetInstance()->display_manager()->UpdateWorkAreaOfDisplay(
414 secondary_display_id, insets);
416 // Default layout is RIGHT.
417 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
418 EXPECT_EQ("500,0 400x400", GetSecondaryDisplay().bounds().ToString());
419 EXPECT_EQ("505,5 390x390", GetSecondaryDisplay().work_area().ToString());
420 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
421 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
423 // Layout the secondary display to the bottom of the primary.
424 SetSecondaryDisplayLayout(DisplayLayout::BOTTOM);
425 EXPECT_EQ(1, observer.CountAndReset());
426 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
427 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
428 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
429 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
430 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
431 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
432 EXPECT_EQ("0,500 400x400", GetSecondaryDisplay().bounds().ToString());
433 EXPECT_EQ("5,505 390x390", GetSecondaryDisplay().work_area().ToString());
435 // Layout the secondary display to the left of the primary.
436 SetSecondaryDisplayLayout(DisplayLayout::LEFT);
437 EXPECT_EQ(1, observer.CountAndReset());
438 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
439 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
440 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
441 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
442 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
443 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
444 EXPECT_EQ("-400,0 400x400", GetSecondaryDisplay().bounds().ToString());
445 EXPECT_EQ("-395,5 390x390", GetSecondaryDisplay().work_area().ToString());
447 // Layout the secondary display to the top of the primary.
448 SetSecondaryDisplayLayout(DisplayLayout::TOP);
449 EXPECT_EQ(1, observer.CountAndReset());
450 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
451 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
452 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
453 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
454 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
455 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
456 EXPECT_EQ("0,-400 400x400", GetSecondaryDisplay().bounds().ToString());
457 EXPECT_EQ("5,-395 390x390", GetSecondaryDisplay().work_area().ToString());
459 // Layout to the right with an offset.
460 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, 300);
461 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
462 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
463 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
464 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
465 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
466 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
467 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
468 EXPECT_EQ("500,300 400x400", GetSecondaryDisplay().bounds().ToString());
470 // Keep the minimum 100.
471 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, 490);
472 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
473 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
474 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
475 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
476 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
477 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
478 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
479 EXPECT_EQ("500,400 400x400", GetSecondaryDisplay().bounds().ToString());
481 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, -400);
482 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
483 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
484 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
485 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
486 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
487 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
488 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
489 EXPECT_EQ("500,-300 400x400", GetSecondaryDisplay().bounds().ToString());
491 // Layout to the bottom with an offset.
492 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -200);
493 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
494 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
495 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
496 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
497 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
498 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
499 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
500 EXPECT_EQ("-200,500 400x400", GetSecondaryDisplay().bounds().ToString());
502 // Keep the minimum 100.
503 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, 490);
504 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
505 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
506 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
507 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
508 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
509 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
510 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
511 EXPECT_EQ("400,500 400x400", GetSecondaryDisplay().bounds().ToString());
513 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -400);
514 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
515 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
516 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
517 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
518 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
519 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
520 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
521 EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString());
523 // Setting the same layout shouldn't invoke observers.
524 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -400);
525 EXPECT_EQ(0, observer.GetChangedDisplayIdAndReset());
526 EXPECT_EQ(0, observer.GetBoundsChangedCountAndReset());
527 EXPECT_EQ(0, observer.GetWorkareaChangedCountAndReset());
528 EXPECT_EQ(0, observer.CountAndReset()); // resize and add
529 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
530 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
531 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
532 EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString());
534 UpdateDisplay("500x500");
535 EXPECT_LE(1, observer.GetFocusChangedCountAndReset());
536 EXPECT_LE(1, observer.GetActivationChangedCountAndReset());
539 namespace {
541 DisplayInfo CreateDisplayInfo(int64 id,
542 const gfx::Rect& bounds,
543 float device_scale_factor) {
544 DisplayInfo info(id, "", false);
545 info.SetBounds(bounds);
546 info.set_device_scale_factor(device_scale_factor);
547 return info;
550 } // namespace
552 TEST_F(DisplayControllerTest, MirrorToDockedWithFullscreen) {
553 if (!SupportsMultipleDisplays())
554 return;
556 // Creates windows to catch activation change event.
557 scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
558 w1->Focus();
560 // Docked mode.
561 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
563 const DisplayInfo internal_display_info =
564 CreateDisplayInfo(1, gfx::Rect(0, 0, 500, 500), 2.0f);
565 const DisplayInfo external_display_info =
566 CreateDisplayInfo(2, gfx::Rect(0, 0, 500, 500), 1.0f);
568 std::vector<DisplayInfo> display_info_list;
569 // Mirror.
570 display_info_list.push_back(internal_display_info);
571 display_info_list.push_back(external_display_info);
572 display_manager->OnNativeDisplaysChanged(display_info_list);
573 const int64 internal_display_id =
574 test::DisplayManagerTestApi(display_manager).
575 SetFirstDisplayAsInternalDisplay();
576 EXPECT_EQ(1, internal_display_id);
577 EXPECT_EQ(2U, display_manager->num_connected_displays());
578 EXPECT_EQ(1U, display_manager->GetNumDisplays());
580 wm::WindowState* window_state = wm::GetWindowState(w1.get());
581 const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
582 window_state->OnWMEvent(&toggle_fullscreen_event);
583 EXPECT_TRUE(window_state->IsFullscreen());
584 EXPECT_EQ("0,0 250x250", w1->bounds().ToString());
585 // Dock mode.
586 TestObserver observer;
587 display_info_list.clear();
588 display_info_list.push_back(external_display_info);
589 display_manager->OnNativeDisplaysChanged(display_info_list);
590 EXPECT_EQ(1U, display_manager->GetNumDisplays());
591 EXPECT_EQ(1U, display_manager->num_connected_displays());
592 // Observers are called due to primary change.
593 EXPECT_EQ(2, observer.GetChangedDisplayIdAndReset());
594 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
595 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
596 EXPECT_EQ(1, observer.GetPrimaryChangedCountAndReset());
597 EXPECT_EQ(1, observer.CountAndReset());
598 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
599 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
601 EXPECT_TRUE(window_state->IsFullscreen());
602 EXPECT_EQ("0,0 500x500", w1->bounds().ToString());
605 TEST_F(DisplayControllerTest, BoundsUpdated) {
606 if (!SupportsMultipleDisplays())
607 return;
609 // Creates windows to catch activation change event.
610 scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
611 w1->Focus();
613 TestObserver observer;
614 SetDefaultDisplayLayout(DisplayLayout::BOTTOM);
615 UpdateDisplay("200x200,300x300"); // layout, resize and add.
616 EXPECT_EQ(1, observer.CountAndReset());
617 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
618 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
620 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
621 gfx::Insets insets(5, 5, 5, 5);
622 display_manager->UpdateWorkAreaOfDisplay(
623 ScreenUtil::GetSecondaryDisplay().id(), insets);
625 EXPECT_EQ("0,0 200x200", GetPrimaryDisplay().bounds().ToString());
626 EXPECT_EQ("0,200 300x300", GetSecondaryDisplay().bounds().ToString());
627 EXPECT_EQ("5,205 290x290", GetSecondaryDisplay().work_area().ToString());
629 UpdateDisplay("400x400,200x200");
630 EXPECT_EQ(1, observer.CountAndReset()); // two resizes
631 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
632 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
633 EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
634 EXPECT_EQ("0,400 200x200", GetSecondaryDisplay().bounds().ToString());
636 UpdateDisplay("400x400,300x300");
637 EXPECT_EQ(1, observer.CountAndReset());
638 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
639 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
640 EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
641 EXPECT_EQ("0,400 300x300", GetSecondaryDisplay().bounds().ToString());
643 UpdateDisplay("400x400");
644 EXPECT_EQ(1, observer.CountAndReset());
645 EXPECT_LE(1, observer.GetFocusChangedCountAndReset());
646 EXPECT_LE(1, observer.GetActivationChangedCountAndReset());
647 EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
648 EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
650 UpdateDisplay("400x500*2,300x300");
651 EXPECT_EQ(1, observer.CountAndReset());
652 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
653 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
654 ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());
655 EXPECT_EQ("0,0 200x250", GetPrimaryDisplay().bounds().ToString());
656 EXPECT_EQ("0,250 300x300", GetSecondaryDisplay().bounds().ToString());
658 // No change
659 UpdateDisplay("400x500*2,300x300");
660 // We still call into Pre/PostDisplayConfigurationChange().
661 EXPECT_EQ(1, observer.CountAndReset());
662 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
663 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
665 // Rotation
666 observer.GetRotationChangedCountAndReset(); // we only want to reset.
667 int64 primary_id = GetPrimaryDisplay().id();
668 display_manager->SetDisplayRotation(primary_id, gfx::Display::ROTATE_90);
669 EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
670 EXPECT_EQ(1, observer.CountAndReset());
671 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
672 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
673 display_manager->SetDisplayRotation(primary_id, gfx::Display::ROTATE_90);
674 EXPECT_EQ(0, observer.GetRotationChangedCountAndReset());
675 EXPECT_EQ(0, observer.CountAndReset());
676 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
677 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
679 // UI scale is eanbled only on internal display.
680 int64 secondary_id = GetSecondaryDisplay().id();
681 gfx::Display::SetInternalDisplayId(secondary_id);
682 display_manager->SetDisplayUIScale(secondary_id, 1.125f);
683 EXPECT_EQ(1, observer.CountAndReset());
684 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
685 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
686 display_manager->SetDisplayUIScale(secondary_id, 1.125f);
687 EXPECT_EQ(0, observer.CountAndReset());
688 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
689 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
690 display_manager->SetDisplayUIScale(primary_id, 1.125f);
691 EXPECT_EQ(0, observer.CountAndReset());
692 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
693 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
694 display_manager->SetDisplayUIScale(primary_id, 1.125f);
695 EXPECT_EQ(0, observer.CountAndReset());
696 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
697 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
700 TEST_F(DisplayControllerTest, SwapPrimary) {
701 if (!SupportsMultipleDisplays())
702 return;
704 DisplayController* display_controller =
705 Shell::GetInstance()->display_controller();
706 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
708 UpdateDisplay("200x200,300x300");
709 gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay();
710 gfx::Display secondary_display = ScreenUtil::GetSecondaryDisplay();
712 DisplayLayout display_layout(DisplayLayout::RIGHT, 50);
713 display_manager->SetLayoutForCurrentDisplays(display_layout);
715 EXPECT_NE(primary_display.id(), secondary_display.id());
716 aura::Window* primary_root =
717 display_controller->GetRootWindowForDisplayId(primary_display.id());
718 aura::Window* secondary_root =
719 display_controller->GetRootWindowForDisplayId(secondary_display.id());
720 EXPECT_NE(primary_root, secondary_root);
721 aura::Window* shelf_window =
722 Shelf::ForPrimaryDisplay()->shelf_widget()->GetNativeView();
723 EXPECT_TRUE(primary_root->Contains(shelf_window));
724 EXPECT_FALSE(secondary_root->Contains(shelf_window));
725 EXPECT_EQ(primary_display.id(),
726 Shell::GetScreen()->GetDisplayNearestPoint(
727 gfx::Point(-100, -100)).id());
728 EXPECT_EQ(primary_display.id(),
729 Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
731 EXPECT_EQ("0,0 200x200", primary_display.bounds().ToString());
732 EXPECT_EQ("0,0 200x153", primary_display.work_area().ToString());
733 EXPECT_EQ("200,0 300x300", secondary_display.bounds().ToString());
734 EXPECT_EQ("200,0 300x253", secondary_display.work_area().ToString());
735 EXPECT_EQ("right, 50",
736 display_manager->GetCurrentDisplayLayout().ToString());
738 // Switch primary and secondary
739 display_controller->SetPrimaryDisplay(secondary_display);
740 const DisplayLayout& inverted_layout =
741 display_manager->GetCurrentDisplayLayout();
742 EXPECT_EQ("left, -50", inverted_layout.ToString());
744 EXPECT_EQ(secondary_display.id(),
745 Shell::GetScreen()->GetPrimaryDisplay().id());
746 EXPECT_EQ(primary_display.id(), ScreenUtil::GetSecondaryDisplay().id());
747 EXPECT_EQ(primary_display.id(),
748 Shell::GetScreen()->GetDisplayNearestPoint(
749 gfx::Point(-100, -100)).id());
750 EXPECT_EQ(secondary_display.id(),
751 Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
753 EXPECT_EQ(
754 primary_root,
755 display_controller->GetRootWindowForDisplayId(secondary_display.id()));
756 EXPECT_EQ(
757 secondary_root,
758 display_controller->GetRootWindowForDisplayId(primary_display.id()));
759 EXPECT_TRUE(primary_root->Contains(shelf_window));
760 EXPECT_FALSE(secondary_root->Contains(shelf_window));
762 // Test if the bounds are correctly swapped.
763 gfx::Display swapped_primary = Shell::GetScreen()->GetPrimaryDisplay();
764 gfx::Display swapped_secondary = ScreenUtil::GetSecondaryDisplay();
765 EXPECT_EQ("0,0 300x300", swapped_primary.bounds().ToString());
766 EXPECT_EQ("0,0 300x253", swapped_primary.work_area().ToString());
767 EXPECT_EQ("-200,-50 200x200", swapped_secondary.bounds().ToString());
769 EXPECT_EQ("-200,-50 200x153", swapped_secondary.work_area().ToString());
771 aura::WindowTracker tracker;
772 tracker.Add(primary_root);
773 tracker.Add(secondary_root);
775 // Deleting 2nd display should move the primary to original primary display.
776 UpdateDisplay("200x200");
777 RunAllPendingInMessageLoop(); // RootWindow is deleted in a posted task.
778 EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
779 EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetPrimaryDisplay().id());
780 EXPECT_EQ(primary_display.id(),
781 Shell::GetScreen()->GetDisplayNearestPoint(
782 gfx::Point(-100, -100)).id());
783 EXPECT_EQ(primary_display.id(),
784 Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
785 EXPECT_TRUE(tracker.Contains(primary_root));
786 EXPECT_FALSE(tracker.Contains(secondary_root));
787 EXPECT_TRUE(primary_root->Contains(shelf_window));
790 TEST_F(DisplayControllerTest, FindNearestDisplay) {
791 if (!SupportsMultipleDisplays())
792 return;
794 DisplayController* display_controller =
795 Shell::GetInstance()->display_controller();
796 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
798 UpdateDisplay("200x200,300x300");
799 DisplayLayout display_layout(DisplayLayout::RIGHT, 50);
800 display_manager->SetLayoutForCurrentDisplays(display_layout);
802 gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay();
803 gfx::Display secondary_display = ScreenUtil::GetSecondaryDisplay();
804 EXPECT_NE(primary_display.id(), secondary_display.id());
805 aura::Window* primary_root =
806 display_controller->GetRootWindowForDisplayId(primary_display.id());
807 aura::Window* secondary_root =
808 display_controller->GetRootWindowForDisplayId(secondary_display.id());
809 EXPECT_NE(primary_root, secondary_root);
811 // Test that points outside of any display return the nearest display.
812 EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
813 gfx::Point(-100, 0)).id());
814 EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
815 gfx::Point(0, -100)).id());
816 EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
817 gfx::Point(100, 100)).id());
818 EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
819 gfx::Point(224, 25)).id());
820 EXPECT_EQ(secondary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
821 gfx::Point(226, 25)).id());
822 EXPECT_EQ(secondary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
823 gfx::Point(600, 100)).id());
824 EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
825 gfx::Point(174, 225)).id());
826 EXPECT_EQ(secondary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
827 gfx::Point(176, 225)).id());
828 EXPECT_EQ(secondary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
829 gfx::Point(300, 400)).id());
832 TEST_F(DisplayControllerTest, SwapPrimaryById) {
833 if (!SupportsMultipleDisplays())
834 return;
836 DisplayController* display_controller =
837 Shell::GetInstance()->display_controller();
838 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
840 UpdateDisplay("200x200,300x300");
841 gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay();
842 gfx::Display secondary_display = ScreenUtil::GetSecondaryDisplay();
844 DisplayLayout display_layout(DisplayLayout::RIGHT, 50);
845 display_manager->SetLayoutForCurrentDisplays(display_layout);
847 EXPECT_NE(primary_display.id(), secondary_display.id());
848 aura::Window* primary_root =
849 display_controller->GetRootWindowForDisplayId(primary_display.id());
850 aura::Window* secondary_root =
851 display_controller->GetRootWindowForDisplayId(secondary_display.id());
852 aura::Window* shelf_window =
853 Shelf::ForPrimaryDisplay()->shelf_widget()->GetNativeView();
854 EXPECT_TRUE(primary_root->Contains(shelf_window));
855 EXPECT_FALSE(secondary_root->Contains(shelf_window));
856 EXPECT_NE(primary_root, secondary_root);
857 EXPECT_EQ(primary_display.id(),
858 Shell::GetScreen()->GetDisplayNearestPoint(
859 gfx::Point(-100, -100)).id());
860 EXPECT_EQ(primary_display.id(),
861 Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
863 // Switch primary and secondary by display ID.
864 TestObserver observer;
865 display_controller->SetPrimaryDisplayId(secondary_display.id());
866 EXPECT_EQ(secondary_display.id(),
867 Shell::GetScreen()->GetPrimaryDisplay().id());
868 EXPECT_EQ(primary_display.id(), ScreenUtil::GetSecondaryDisplay().id());
869 EXPECT_LT(0, observer.CountAndReset());
871 EXPECT_EQ(
872 primary_root,
873 display_controller->GetRootWindowForDisplayId(secondary_display.id()));
874 EXPECT_EQ(
875 secondary_root,
876 display_controller->GetRootWindowForDisplayId(primary_display.id()));
877 EXPECT_TRUE(primary_root->Contains(shelf_window));
878 EXPECT_FALSE(secondary_root->Contains(shelf_window));
880 const DisplayLayout& inverted_layout =
881 display_manager->GetCurrentDisplayLayout();
883 EXPECT_EQ("left, -50", inverted_layout.ToString());
885 // Calling the same ID don't do anything.
886 display_controller->SetPrimaryDisplayId(secondary_display.id());
887 EXPECT_EQ(0, observer.CountAndReset());
889 aura::WindowTracker tracker;
890 tracker.Add(primary_root);
891 tracker.Add(secondary_root);
893 // Deleting 2nd display should move the primary to original primary display.
894 UpdateDisplay("200x200");
895 RunAllPendingInMessageLoop(); // RootWindow is deleted in a posted task.
896 EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
897 EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetPrimaryDisplay().id());
898 EXPECT_EQ(primary_display.id(),
899 Shell::GetScreen()->GetDisplayNearestPoint(
900 gfx::Point(-100, -100)).id());
901 EXPECT_EQ(primary_display.id(),
902 Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
903 EXPECT_TRUE(tracker.Contains(primary_root));
904 EXPECT_FALSE(tracker.Contains(secondary_root));
905 EXPECT_TRUE(primary_root->Contains(shelf_window));
907 // Adding 2nd display with the same ID. The 2nd display should become primary
908 // since secondary id is still stored as desirable_primary_id.
909 std::vector<DisplayInfo> display_info_list;
910 display_info_list.push_back(
911 display_manager->GetDisplayInfo(primary_display.id()));
912 display_info_list.push_back(
913 display_manager->GetDisplayInfo(secondary_display.id()));
914 display_manager->OnNativeDisplaysChanged(display_info_list);
916 EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
917 EXPECT_EQ(secondary_display.id(),
918 Shell::GetScreen()->GetPrimaryDisplay().id());
919 EXPECT_EQ(primary_display.id(), ScreenUtil::GetSecondaryDisplay().id());
920 EXPECT_EQ(
921 primary_root,
922 display_controller->GetRootWindowForDisplayId(secondary_display.id()));
923 EXPECT_NE(
924 primary_root,
925 display_controller->GetRootWindowForDisplayId(primary_display.id()));
926 EXPECT_TRUE(primary_root->Contains(shelf_window));
928 // Deleting 2nd display and adding 2nd display with a different ID. The 2nd
929 // display shouldn't become primary.
930 UpdateDisplay("200x200");
931 DisplayInfo third_display_info(
932 secondary_display.id() + 1, std::string(), false);
933 third_display_info.SetBounds(secondary_display.bounds());
934 ASSERT_NE(primary_display.id(), third_display_info.id());
936 const DisplayInfo& primary_display_info =
937 display_manager->GetDisplayInfo(primary_display.id());
938 std::vector<DisplayInfo> display_info_list2;
939 display_info_list2.push_back(primary_display_info);
940 display_info_list2.push_back(third_display_info);
941 display_manager->OnNativeDisplaysChanged(display_info_list2);
942 EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
943 EXPECT_EQ(primary_display.id(),
944 Shell::GetScreen()->GetPrimaryDisplay().id());
945 EXPECT_EQ(third_display_info.id(), ScreenUtil::GetSecondaryDisplay().id());
946 EXPECT_EQ(
947 primary_root,
948 display_controller->GetRootWindowForDisplayId(primary_display.id()));
949 EXPECT_NE(
950 primary_root,
951 display_controller->GetRootWindowForDisplayId(third_display_info.id()));
952 EXPECT_TRUE(primary_root->Contains(shelf_window));
955 TEST_F(DisplayControllerTest, CursorDeviceScaleFactorSwapPrimary) {
956 if (!SupportsMultipleDisplays())
957 return;
959 DisplayController* display_controller =
960 Shell::GetInstance()->display_controller();
962 UpdateDisplay("200x200,200x200*2");
963 gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay();
964 gfx::Display secondary_display = ScreenUtil::GetSecondaryDisplay();
966 aura::Window* primary_root =
967 display_controller->GetRootWindowForDisplayId(primary_display.id());
968 aura::Window* secondary_root =
969 display_controller->GetRootWindowForDisplayId(secondary_display.id());
970 EXPECT_NE(primary_root, secondary_root);
972 test::CursorManagerTestApi test_api(Shell::GetInstance()->cursor_manager());
974 EXPECT_EQ(1.0f, primary_root->GetHost()->compositor()->
975 device_scale_factor());
976 primary_root->MoveCursorTo(gfx::Point(50, 50));
977 EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
978 EXPECT_EQ(2.0f, secondary_root->GetHost()->compositor()->
979 device_scale_factor());
980 secondary_root->MoveCursorTo(gfx::Point(50, 50));
981 EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor());
983 // Switch primary and secondary
984 display_controller->SetPrimaryDisplay(secondary_display);
986 // Cursor's device scale factor should be updated accroding to the swap of
987 // primary and secondary.
988 EXPECT_EQ(1.0f, secondary_root->GetHost()->compositor()->
989 device_scale_factor());
990 secondary_root->MoveCursorTo(gfx::Point(50, 50));
991 EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
992 primary_root->MoveCursorTo(gfx::Point(50, 50));
993 EXPECT_EQ(2.0f, primary_root->GetHost()->compositor()->
994 device_scale_factor());
995 EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor());
997 // Deleting 2nd display.
998 UpdateDisplay("200x200");
999 RunAllPendingInMessageLoop(); // RootWindow is deleted in a posted task.
1001 // Cursor's device scale factor should be updated even without moving cursor.
1002 EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
1004 primary_root->MoveCursorTo(gfx::Point(50, 50));
1005 EXPECT_EQ(1.0f, primary_root->GetHost()->compositor()->
1006 device_scale_factor());
1007 EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
1010 TEST_F(DisplayControllerTest, OverscanInsets) {
1011 if (!SupportsMultipleDisplays())
1012 return;
1014 DisplayController* display_controller =
1015 Shell::GetInstance()->display_controller();
1016 TestEventHandler event_handler;
1017 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1019 UpdateDisplay("120x200,300x400*2");
1020 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
1021 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1023 display_controller->SetOverscanInsets(display1.id(),
1024 gfx::Insets(10, 15, 20, 25));
1025 EXPECT_EQ("0,0 80x170", root_windows[0]->bounds().ToString());
1026 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
1027 EXPECT_EQ("80,0 150x200",
1028 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1030 ui::test::EventGenerator generator(root_windows[0]);
1031 generator.MoveMouseToInHost(20, 25);
1032 EXPECT_EQ("5,15", event_handler.GetLocationAndReset());
1034 display_controller->SetOverscanInsets(display1.id(), gfx::Insets());
1035 EXPECT_EQ("0,0 120x200", root_windows[0]->bounds().ToString());
1036 EXPECT_EQ("120,0 150x200",
1037 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1039 generator.MoveMouseToInHost(30, 20);
1040 EXPECT_EQ("30,20", event_handler.GetLocationAndReset());
1042 // Make sure the root window transformer uses correct scale
1043 // factor when swapping display. Test crbug.com/253690.
1044 UpdateDisplay("400x300*2,600x400/o");
1045 root_windows = Shell::GetAllRootWindows();
1046 gfx::Point point;
1047 Shell::GetAllRootWindows()[1]->GetHost()->
1048 GetRootTransform().TransformPoint(&point);
1049 EXPECT_EQ("15,10", point.ToString());
1051 display_controller->SwapPrimaryDisplay();
1052 point.SetPoint(0, 0);
1053 Shell::GetAllRootWindows()[1]->GetHost()->
1054 GetRootTransform().TransformPoint(&point);
1055 EXPECT_EQ("15,10", point.ToString());
1057 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1060 TEST_F(DisplayControllerTest, Rotate) {
1061 if (!SupportsMultipleDisplays())
1062 return;
1064 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1065 TestEventHandler event_handler;
1066 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1068 UpdateDisplay("120x200,300x400*2");
1069 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
1070 int64 display2_id = ScreenUtil::GetSecondaryDisplay().id();
1071 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1072 ui::test::EventGenerator generator1(root_windows[0]);
1074 TestObserver observer;
1075 EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString());
1076 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
1077 EXPECT_EQ("120,0 150x200",
1078 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1079 generator1.MoveMouseToInHost(50, 40);
1080 EXPECT_EQ("50,40", event_handler.GetLocationAndReset());
1081 EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display1.id()));
1082 EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id));
1083 EXPECT_EQ(0, observer.GetRotationChangedCountAndReset());
1085 display_manager->SetDisplayRotation(display1.id(),
1086 gfx::Display::ROTATE_90);
1087 EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString());
1088 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
1089 EXPECT_EQ("200,0 150x200",
1090 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1091 generator1.MoveMouseToInHost(50, 40);
1092 EXPECT_EQ("40,69", event_handler.GetLocationAndReset());
1093 EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id()));
1094 EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id));
1095 EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
1097 DisplayLayout display_layout(DisplayLayout::BOTTOM, 50);
1098 display_manager->SetLayoutForCurrentDisplays(display_layout);
1099 EXPECT_EQ("50,120 150x200",
1100 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1102 display_manager->SetDisplayRotation(display2_id,
1103 gfx::Display::ROTATE_270);
1104 EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString());
1105 EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString());
1106 EXPECT_EQ("50,120 200x150",
1107 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1108 EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id()));
1109 EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id));
1110 EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
1112 #if !defined(OS_WIN)
1113 ui::test::EventGenerator generator2(root_windows[1]);
1114 generator2.MoveMouseToInHost(50, 40);
1115 EXPECT_EQ("179,25", event_handler.GetLocationAndReset());
1116 display_manager->SetDisplayRotation(display1.id(),
1117 gfx::Display::ROTATE_180);
1119 EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString());
1120 EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString());
1121 // Dislay must share at least 100, so the x's offset becomes 20.
1122 EXPECT_EQ("20,200 200x150",
1123 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1124 EXPECT_EQ(gfx::Display::ROTATE_180, GetStoredRotation(display1.id()));
1125 EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id));
1126 EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
1128 generator1.MoveMouseToInHost(50, 40);
1129 EXPECT_EQ("69,159", event_handler.GetLocationAndReset());
1130 #endif
1132 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1135 TEST_F(DisplayControllerTest, ScaleRootWindow) {
1136 if (!SupportsMultipleDisplays())
1137 return;
1139 TestEventHandler event_handler;
1140 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1142 UpdateDisplay("600x400*2@1.5,500x300");
1144 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
1145 gfx::Display::SetInternalDisplayId(display1.id());
1147 gfx::Display display2 = ScreenUtil::GetSecondaryDisplay();
1148 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1149 EXPECT_EQ("0,0 450x300", display1.bounds().ToString());
1150 EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString());
1151 EXPECT_EQ("450,0 500x300", display2.bounds().ToString());
1152 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1153 EXPECT_EQ(1.0f, GetStoredUIScale(display2.id()));
1155 ui::test::EventGenerator generator(root_windows[0]);
1156 generator.MoveMouseToInHost(599, 200);
1157 EXPECT_EQ("449,150", event_handler.GetLocationAndReset());
1159 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1160 display_manager->SetDisplayUIScale(display1.id(), 1.25f);
1161 display1 = Shell::GetScreen()->GetPrimaryDisplay();
1162 display2 = ScreenUtil::GetSecondaryDisplay();
1163 EXPECT_EQ("0,0 375x250", display1.bounds().ToString());
1164 EXPECT_EQ("0,0 375x250", root_windows[0]->bounds().ToString());
1165 EXPECT_EQ("375,0 500x300", display2.bounds().ToString());
1166 EXPECT_EQ(1.25f, GetStoredUIScale(display1.id()));
1167 EXPECT_EQ(1.0f, GetStoredUIScale(display2.id()));
1169 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1172 TEST_F(DisplayControllerTest, TouchScale) {
1173 if (!SupportsMultipleDisplays())
1174 return;
1176 TestEventHandler event_handler;
1177 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1179 UpdateDisplay("200x200*2");
1180 gfx::Display display = Shell::GetScreen()->GetPrimaryDisplay();
1181 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1182 aura::Window* root_window = root_windows[0];
1183 ui::test::EventGenerator generator(root_window);
1185 generator.PressMoveAndReleaseTouchTo(50, 50);
1186 // Default test touches have radius_x/y = 1.0, with device scale
1187 // factor = 2, the scaled radius_x/y should be 0.5.
1188 EXPECT_EQ(0.5, event_handler.touch_radius_x());
1189 EXPECT_EQ(0.5, event_handler.touch_radius_y());
1191 generator.ScrollSequence(gfx::Point(0,0),
1192 base::TimeDelta::FromMilliseconds(100),
1193 10.0, 1.0, 5, 1);
1195 // ordinal_offset is invariant to the device scale factor.
1196 EXPECT_EQ(event_handler.scroll_x_offset(),
1197 event_handler.scroll_x_offset_ordinal());
1198 EXPECT_EQ(event_handler.scroll_y_offset(),
1199 event_handler.scroll_y_offset_ordinal());
1201 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1204 TEST_F(DisplayControllerTest, ConvertHostToRootCoords) {
1205 if (!SupportsMultipleDisplays())
1206 return;
1208 TestEventHandler event_handler;
1209 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1211 UpdateDisplay("600x400*2/r@1.5");
1213 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
1214 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1215 EXPECT_EQ("0,0 300x450", display1.bounds().ToString());
1216 EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString());
1217 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1219 ui::test::EventGenerator generator(root_windows[0]);
1220 generator.MoveMouseToInHost(0, 0);
1221 EXPECT_EQ("0,449", event_handler.GetLocationAndReset());
1222 generator.MoveMouseToInHost(599, 0);
1223 EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
1224 generator.MoveMouseToInHost(599, 399);
1225 EXPECT_EQ("299,0", event_handler.GetLocationAndReset());
1226 generator.MoveMouseToInHost(0, 399);
1227 EXPECT_EQ("299,449", event_handler.GetLocationAndReset());
1229 UpdateDisplay("600x400*2/u@1.5");
1230 display1 = Shell::GetScreen()->GetPrimaryDisplay();
1231 root_windows = Shell::GetAllRootWindows();
1232 EXPECT_EQ("0,0 450x300", display1.bounds().ToString());
1233 EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString());
1234 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1236 generator.MoveMouseToInHost(0, 0);
1237 EXPECT_EQ("449,299", event_handler.GetLocationAndReset());
1238 generator.MoveMouseToInHost(599, 0);
1239 EXPECT_EQ("0,299", event_handler.GetLocationAndReset());
1240 generator.MoveMouseToInHost(599, 399);
1241 EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
1242 generator.MoveMouseToInHost(0, 399);
1243 EXPECT_EQ("449,0", event_handler.GetLocationAndReset());
1245 UpdateDisplay("600x400*2/l@1.5");
1246 display1 = Shell::GetScreen()->GetPrimaryDisplay();
1247 root_windows = Shell::GetAllRootWindows();
1248 EXPECT_EQ("0,0 300x450", display1.bounds().ToString());
1249 EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString());
1250 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1252 generator.MoveMouseToInHost(0, 0);
1253 EXPECT_EQ("299,0", event_handler.GetLocationAndReset());
1254 generator.MoveMouseToInHost(599, 0);
1255 EXPECT_EQ("299,449", event_handler.GetLocationAndReset());
1256 generator.MoveMouseToInHost(599, 399);
1257 EXPECT_EQ("0,449", event_handler.GetLocationAndReset());
1258 generator.MoveMouseToInHost(0, 399);
1259 EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
1261 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1264 namespace {
1266 DisplayInfo CreateDisplayInfo(int64 id,
1267 int y,
1268 gfx::Display::Rotation rotation) {
1269 DisplayInfo info(id, "", false);
1270 info.SetBounds(gfx::Rect(0, y, 500, 500));
1271 info.set_rotation(rotation);
1272 return info;
1275 } // namespace
1277 // Make sure that the compositor based mirroring can switch
1278 // from/to dock mode.
1279 TEST_F(DisplayControllerTest, DockToSingle) {
1280 if (!SupportsMultipleDisplays())
1281 return;
1283 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1285 const int64 internal_id = 1;
1287 const DisplayInfo internal_display_info =
1288 CreateDisplayInfo(internal_id, 0, gfx::Display::ROTATE_0);
1289 const DisplayInfo external_display_info =
1290 CreateDisplayInfo(2, 1, gfx::Display::ROTATE_90);
1292 std::vector<DisplayInfo> display_info_list;
1293 // Extended
1294 display_info_list.push_back(internal_display_info);
1295 display_info_list.push_back(external_display_info);
1296 display_manager->OnNativeDisplaysChanged(display_info_list);
1297 const int64 internal_display_id =
1298 test::DisplayManagerTestApi(display_manager).
1299 SetFirstDisplayAsInternalDisplay();
1300 EXPECT_EQ(internal_id, internal_display_id);
1301 EXPECT_EQ(2U, display_manager->GetNumDisplays());
1303 // Dock mode.
1304 display_info_list.clear();
1305 display_info_list.push_back(external_display_info);
1306 display_manager->OnNativeDisplaysChanged(display_info_list);
1307 EXPECT_EQ(1U, display_manager->GetNumDisplays());
1308 EXPECT_FALSE(Shell::GetPrimaryRootWindow()->GetHost()->
1309 GetRootTransform().IsIdentityOrIntegerTranslation());
1311 // Switch to single mode and make sure the transform is the one
1312 // for the internal display.
1313 display_info_list.clear();
1314 display_info_list.push_back(internal_display_info);
1315 display_manager->OnNativeDisplaysChanged(display_info_list);
1316 EXPECT_TRUE(Shell::GetPrimaryRootWindow()->GetHost()->
1317 GetRootTransform().IsIdentityOrIntegerTranslation());
1320 #if defined(USE_X11)
1321 TEST_F(DisplayControllerTest, XWidowNameForRootWindow) {
1322 EXPECT_EQ("aura_root_0", GetXWindowName(
1323 Shell::GetPrimaryRootWindow()->GetHost()));
1325 // Multiple display.
1326 UpdateDisplay("200x200,300x300");
1327 aura::Window* primary, *secondary;
1328 GetPrimaryAndSeconary(&primary, &secondary);
1329 EXPECT_EQ("aura_root_0", GetXWindowName(primary->GetHost()));
1330 EXPECT_EQ("aura_root_x", GetXWindowName(secondary->GetHost()));
1332 // Swap primary.
1333 primary = secondary = NULL;
1334 Shell::GetInstance()->display_controller()->SwapPrimaryDisplay();
1335 GetPrimaryAndSeconary(&primary, &secondary);
1336 EXPECT_EQ("aura_root_0", GetXWindowName(primary->GetHost()));
1337 EXPECT_EQ("aura_root_x", GetXWindowName(secondary->GetHost()));
1339 // Switching back to single display.
1340 UpdateDisplay("300x400");
1341 EXPECT_EQ("aura_root_0", GetXWindowName(
1342 Shell::GetPrimaryRootWindow()->GetHost()));
1344 #endif
1346 } // namespace ash