Don't preload rarely seen large images
[chromium-blink-merge.git] / ash / display / display_controller_unittest.cc
blob6b0407746807c23941a6cc8ab372e1b85958db4e
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 namespace ash {
40 namespace {
42 const char kDesktopBackgroundView[] = "DesktopBackgroundView";
44 template<typename T>
45 class Resetter {
46 public:
47 explicit Resetter(T* value) : value_(*value) {
48 *value = 0;
50 ~Resetter() { }
51 T value() { return value_; }
53 private:
54 T value_;
55 DISALLOW_COPY_AND_ASSIGN(Resetter);
58 class TestObserver : public DisplayController::Observer,
59 public gfx::DisplayObserver,
60 public aura::client::FocusChangeObserver,
61 public aura::client::ActivationChangeObserver {
62 public:
63 TestObserver()
64 : changing_count_(0),
65 changed_count_(0),
66 bounds_changed_count_(0),
67 rotation_changed_count_(0),
68 workarea_changed_count_(0),
69 primary_changed_count_(0),
70 changed_display_id_(0),
71 focus_changed_count_(0),
72 activation_changed_count_(0) {
73 Shell::GetInstance()->display_controller()->AddObserver(this);
74 Shell::GetScreen()->AddObserver(this);
75 aura::client::GetFocusClient(Shell::GetPrimaryRootWindow())->
76 AddObserver(this);
77 aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
78 AddObserver(this);
81 ~TestObserver() override {
82 Shell::GetInstance()->display_controller()->RemoveObserver(this);
83 Shell::GetScreen()->RemoveObserver(this);
84 aura::client::GetFocusClient(Shell::GetPrimaryRootWindow())->
85 RemoveObserver(this);
86 aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
87 RemoveObserver(this);
90 // Overridden from DisplayController::Observer
91 void OnDisplayConfigurationChanging() override { ++changing_count_; }
92 void OnDisplayConfigurationChanged() override { ++changed_count_; }
94 // Overrideen from gfx::DisplayObserver
95 void OnDisplayMetricsChanged(const gfx::Display& display,
96 uint32_t metrics) override {
97 changed_display_id_ = display.id();
98 if (metrics & DISPLAY_METRIC_BOUNDS)
99 ++bounds_changed_count_;
100 if (metrics & DISPLAY_METRIC_ROTATION)
101 ++rotation_changed_count_;
102 if (metrics & DISPLAY_METRIC_WORK_AREA)
103 ++workarea_changed_count_;
104 if (metrics & DISPLAY_METRIC_PRIMARY)
105 ++primary_changed_count_;
107 void OnDisplayAdded(const gfx::Display& new_display) override {}
108 void OnDisplayRemoved(const gfx::Display& old_display) override {}
110 // Overridden from aura::client::FocusChangeObserver
111 void OnWindowFocused(aura::Window* gained_focus,
112 aura::Window* lost_focus) override {
113 focus_changed_count_++;
116 // Overridden from aura::client::ActivationChangeObserver
117 void OnWindowActivated(
118 aura::client::ActivationChangeObserver::ActivationReason reason,
119 aura::Window* gained_active,
120 aura::Window* lost_active) override {
121 activation_changed_count_++;
123 void OnAttemptToReactivateWindow(aura::Window* request_active,
124 aura::Window* actual_active) override {}
126 int CountAndReset() {
127 EXPECT_EQ(changing_count_, changed_count_);
128 changed_count_ = 0;
129 return Resetter<int>(&changing_count_).value();
132 int64 GetBoundsChangedCountAndReset() {
133 return Resetter<int>(&bounds_changed_count_).value();
136 int64 GetRotationChangedCountAndReset() {
137 return Resetter<int>(&rotation_changed_count_).value();
140 int64 GetWorkareaChangedCountAndReset() {
141 return Resetter<int>(&workarea_changed_count_).value();
144 int64 GetPrimaryChangedCountAndReset() {
145 return Resetter<int>(&primary_changed_count_).value();
148 int64 GetChangedDisplayIdAndReset() {
149 return Resetter<int64>(&changed_display_id_).value();
152 int GetFocusChangedCountAndReset() {
153 return Resetter<int>(&focus_changed_count_).value();
156 int GetActivationChangedCountAndReset() {
157 return Resetter<int>(&activation_changed_count_).value();
160 private:
161 int changing_count_;
162 int changed_count_;
164 int bounds_changed_count_;
165 int rotation_changed_count_;
166 int workarea_changed_count_;
167 int primary_changed_count_;
168 int64 changed_display_id_;
170 int focus_changed_count_;
171 int activation_changed_count_;
173 DISALLOW_COPY_AND_ASSIGN(TestObserver);
176 gfx::Display GetPrimaryDisplay() {
177 return Shell::GetScreen()->GetDisplayNearestWindow(
178 Shell::GetAllRootWindows()[0]);
181 gfx::Display GetSecondaryDisplay() {
182 return Shell::GetScreen()->GetDisplayNearestWindow(
183 Shell::GetAllRootWindows()[1]);
186 void SetSecondaryDisplayLayoutAndOffset(DisplayLayout::Position position,
187 int offset) {
188 DisplayLayout layout(position, offset);
189 ASSERT_GT(Shell::GetScreen()->GetNumDisplays(), 1);
190 Shell::GetInstance()->display_manager()->
191 SetLayoutForCurrentDisplays(layout);
194 void SetSecondaryDisplayLayout(DisplayLayout::Position position) {
195 SetSecondaryDisplayLayoutAndOffset(position, 0);
198 void SetDefaultDisplayLayout(DisplayLayout::Position position) {
199 Shell::GetInstance()->display_manager()->layout_store()->
200 SetDefaultDisplayLayout(DisplayLayout(position, 0));
203 class DisplayControllerShutdownTest : public test::AshTestBase {
204 public:
205 DisplayControllerShutdownTest() {}
206 ~DisplayControllerShutdownTest() override {}
208 void TearDown() override {
209 test::AshTestBase::TearDown();
210 if (!SupportsMultipleDisplays())
211 return;
213 // Make sure that primary display is accessible after shutdown.
214 gfx::Display primary = Shell::GetScreen()->GetPrimaryDisplay();
215 EXPECT_EQ("0,0 444x333", primary.bounds().ToString());
216 EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
219 private:
220 DISALLOW_COPY_AND_ASSIGN(DisplayControllerShutdownTest);
223 class StartupHelper : public test::TestShellDelegate,
224 public DisplayController::Observer {
225 public:
226 StartupHelper() : displays_initialized_(false) {}
227 ~StartupHelper() override {}
229 // ash::ShellSelegate:
230 void PreInit() override {
231 Shell::GetInstance()->display_controller()->AddObserver(this);
234 // ash::DisplayController::Observer:
235 void OnDisplaysInitialized() override {
236 DCHECK(!displays_initialized_);
237 displays_initialized_ = true;
240 bool displays_initialized() const {
241 return displays_initialized_;
244 private:
245 bool displays_initialized_;
247 DISALLOW_COPY_AND_ASSIGN(StartupHelper);
250 class DisplayControllerStartupTest : public test::AshTestBase {
251 public:
252 DisplayControllerStartupTest() : startup_helper_(new StartupHelper) {}
253 ~DisplayControllerStartupTest() override {}
255 // ash::test::AshTestBase:
256 void SetUp() override {
257 ash_test_helper()->set_test_shell_delegate(startup_helper_);
258 test::AshTestBase::SetUp();
260 void TearDown() override {
261 Shell::GetInstance()->display_controller()->RemoveObserver(startup_helper_);
262 test::AshTestBase::TearDown();
265 const StartupHelper* startup_helper() const { return startup_helper_; }
267 private:
268 StartupHelper* startup_helper_; // Owned by ash::Shell.
270 DISALLOW_COPY_AND_ASSIGN(DisplayControllerStartupTest);
273 class TestEventHandler : public ui::EventHandler {
274 public:
275 TestEventHandler() : target_root_(NULL),
276 touch_radius_x_(0.0),
277 touch_radius_y_(0.0),
278 scroll_x_offset_(0.0),
279 scroll_y_offset_(0.0),
280 scroll_x_offset_ordinal_(0.0),
281 scroll_y_offset_ordinal_(0.0) {}
282 ~TestEventHandler() override {}
284 void OnMouseEvent(ui::MouseEvent* event) override {
285 if (event->flags() & ui::EF_IS_SYNTHESIZED &&
286 event->type() != ui::ET_MOUSE_EXITED &&
287 event->type() != ui::ET_MOUSE_ENTERED) {
288 return;
290 aura::Window* target = static_cast<aura::Window*>(event->target());
291 mouse_location_ = event->root_location();
292 target_root_ = target->GetRootWindow();
293 event->StopPropagation();
296 void OnTouchEvent(ui::TouchEvent* event) override {
297 aura::Window* target = static_cast<aura::Window*>(event->target());
298 // Only record when the target is the background which covers
299 // entire root window.
300 if (target->name() != kDesktopBackgroundView)
301 return;
302 touch_radius_x_ = event->radius_x();
303 touch_radius_y_ = event->radius_y();
304 event->StopPropagation();
307 void OnScrollEvent(ui::ScrollEvent* event) override {
308 aura::Window* target = static_cast<aura::Window*>(event->target());
309 // Only record when the target is the background which covers
310 // entire root window.
311 if (target->name() != kDesktopBackgroundView)
312 return;
314 if (event->type() == ui::ET_SCROLL) {
315 scroll_x_offset_ = event->x_offset();
316 scroll_y_offset_ = event->y_offset();
317 scroll_x_offset_ordinal_ = event->x_offset_ordinal();
318 scroll_y_offset_ordinal_ = event->y_offset_ordinal();
320 event->StopPropagation();
323 std::string GetLocationAndReset() {
324 std::string result = mouse_location_.ToString();
325 mouse_location_.SetPoint(0, 0);
326 target_root_ = NULL;
327 return result;
330 float touch_radius_x() { return touch_radius_x_; }
331 float touch_radius_y() { return touch_radius_y_; }
332 float scroll_x_offset() { return scroll_x_offset_; }
333 float scroll_y_offset() { return scroll_y_offset_; }
334 float scroll_x_offset_ordinal() { return scroll_x_offset_ordinal_; }
335 float scroll_y_offset_ordinal() { return scroll_y_offset_ordinal_; }
337 private:
338 gfx::Point mouse_location_;
339 aura::Window* target_root_;
341 float touch_radius_x_;
342 float touch_radius_y_;
343 float scroll_x_offset_;
344 float scroll_y_offset_;
345 float scroll_x_offset_ordinal_;
346 float scroll_y_offset_ordinal_;
348 DISALLOW_COPY_AND_ASSIGN(TestEventHandler);
351 float GetStoredUIScale(int64 id) {
352 return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).
353 GetEffectiveUIScale();
356 class TestMouseWatcherListener : public views::MouseWatcherListener {
357 public:
358 TestMouseWatcherListener() {}
360 private:
361 // views::MouseWatcherListener:
362 void MouseMovedOutOfHost() override {}
364 DISALLOW_COPY_AND_ASSIGN(TestMouseWatcherListener);
367 } // namespace
369 typedef test::AshTestBase DisplayControllerTest;
371 TEST_F(DisplayControllerShutdownTest, Shutdown) {
372 if (!SupportsMultipleDisplays())
373 return;
375 UpdateDisplay("444x333, 200x200");
378 TEST_F(DisplayControllerStartupTest, Startup) {
379 if (!SupportsMultipleDisplays())
380 return;
382 EXPECT_TRUE(startup_helper()->displays_initialized());
385 TEST_F(DisplayControllerTest, SecondaryDisplayLayout) {
386 if (!SupportsMultipleDisplays())
387 return;
389 // Creates windows to catch activation change event.
390 scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
391 w1->Focus();
393 TestObserver observer;
394 UpdateDisplay("500x500,400x400");
395 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
396 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
397 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
398 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
399 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
400 gfx::Insets insets(5, 5, 5, 5);
401 int64 secondary_display_id = ScreenUtil::GetSecondaryDisplay().id();
402 Shell::GetInstance()->display_manager()->UpdateWorkAreaOfDisplay(
403 secondary_display_id, insets);
405 // Default layout is RIGHT.
406 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
407 EXPECT_EQ("500,0 400x400", GetSecondaryDisplay().bounds().ToString());
408 EXPECT_EQ("505,5 390x390", GetSecondaryDisplay().work_area().ToString());
409 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
410 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
412 // Layout the secondary display to the bottom of the primary.
413 SetSecondaryDisplayLayout(DisplayLayout::BOTTOM);
414 EXPECT_EQ(1, observer.CountAndReset());
415 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
416 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
417 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
418 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
419 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
420 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
421 EXPECT_EQ("0,500 400x400", GetSecondaryDisplay().bounds().ToString());
422 EXPECT_EQ("5,505 390x390", GetSecondaryDisplay().work_area().ToString());
424 // Layout the secondary display to the left of the primary.
425 SetSecondaryDisplayLayout(DisplayLayout::LEFT);
426 EXPECT_EQ(1, observer.CountAndReset());
427 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
428 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
429 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
430 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
431 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
432 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
433 EXPECT_EQ("-400,0 400x400", GetSecondaryDisplay().bounds().ToString());
434 EXPECT_EQ("-395,5 390x390", GetSecondaryDisplay().work_area().ToString());
436 // Layout the secondary display to the top of the primary.
437 SetSecondaryDisplayLayout(DisplayLayout::TOP);
438 EXPECT_EQ(1, observer.CountAndReset());
439 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
440 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
441 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
442 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
443 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
444 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
445 EXPECT_EQ("0,-400 400x400", GetSecondaryDisplay().bounds().ToString());
446 EXPECT_EQ("5,-395 390x390", GetSecondaryDisplay().work_area().ToString());
448 // Layout to the right with an offset.
449 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, 300);
450 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
451 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
452 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
453 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
454 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
455 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
456 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
457 EXPECT_EQ("500,300 400x400", GetSecondaryDisplay().bounds().ToString());
459 // Keep the minimum 100.
460 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, 490);
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,400 400x400", GetSecondaryDisplay().bounds().ToString());
470 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, -400);
471 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
472 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
473 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
474 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
475 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
476 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
477 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
478 EXPECT_EQ("500,-300 400x400", GetSecondaryDisplay().bounds().ToString());
480 // Layout to the bottom with an offset.
481 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -200);
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("-200,500 400x400", GetSecondaryDisplay().bounds().ToString());
491 // Keep the minimum 100.
492 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, 490);
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("400,500 400x400", GetSecondaryDisplay().bounds().ToString());
502 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -400);
503 EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
504 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
505 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
506 EXPECT_EQ(1, observer.CountAndReset()); // resize and add
507 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
508 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
509 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
510 EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString());
512 // Setting the same layout shouldn't invoke observers.
513 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -400);
514 EXPECT_EQ(0, observer.GetChangedDisplayIdAndReset());
515 EXPECT_EQ(0, observer.GetBoundsChangedCountAndReset());
516 EXPECT_EQ(0, observer.GetWorkareaChangedCountAndReset());
517 EXPECT_EQ(0, 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 UpdateDisplay("500x500");
524 EXPECT_LE(1, observer.GetFocusChangedCountAndReset());
525 EXPECT_LE(1, observer.GetActivationChangedCountAndReset());
528 namespace {
530 DisplayInfo CreateDisplayInfo(int64 id,
531 int y,
532 gfx::Display::Rotation rotation) {
533 DisplayInfo info(id, "", false);
534 info.SetBounds(gfx::Rect(0, y, 500, 500));
535 info.SetRotation(rotation, gfx::Display::ROTATION_SOURCE_ACTIVE);
536 return info;
539 DisplayInfo CreateMirroredDisplayInfo(int64 id,
540 float device_scale_factor) {
541 DisplayInfo info = CreateDisplayInfo(id, 0, gfx::Display::ROTATE_0);
542 info.set_device_scale_factor(device_scale_factor);
543 return info;
546 } // namespace
548 TEST_F(DisplayControllerTest, MirrorToDockedWithFullscreen) {
549 if (!SupportsMultipleDisplays())
550 return;
552 // Creates windows to catch activation change event.
553 scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
554 w1->Focus();
556 // Docked mode.
557 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
559 const DisplayInfo internal_display_info =
560 CreateMirroredDisplayInfo(1, 2.0f);
561 const DisplayInfo external_display_info =
562 CreateMirroredDisplayInfo(2, 1.0f);
564 std::vector<DisplayInfo> display_info_list;
565 // Mirror.
566 display_info_list.push_back(internal_display_info);
567 display_info_list.push_back(external_display_info);
568 display_manager->OnNativeDisplaysChanged(display_info_list);
569 const int64 internal_display_id =
570 test::DisplayManagerTestApi(display_manager).
571 SetFirstDisplayAsInternalDisplay();
572 EXPECT_EQ(1, internal_display_id);
573 EXPECT_EQ(2U, display_manager->num_connected_displays());
574 EXPECT_EQ(1U, display_manager->GetNumDisplays());
576 wm::WindowState* window_state = wm::GetWindowState(w1.get());
577 const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
578 window_state->OnWMEvent(&toggle_fullscreen_event);
579 EXPECT_TRUE(window_state->IsFullscreen());
580 EXPECT_EQ("0,0 250x250", w1->bounds().ToString());
581 // Dock mode.
582 TestObserver observer;
583 display_info_list.clear();
584 display_info_list.push_back(external_display_info);
585 display_manager->OnNativeDisplaysChanged(display_info_list);
586 EXPECT_EQ(1U, display_manager->GetNumDisplays());
587 EXPECT_EQ(1U, display_manager->num_connected_displays());
588 // Observers are called due to primary change.
589 EXPECT_EQ(2, observer.GetChangedDisplayIdAndReset());
590 EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
591 EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
592 EXPECT_EQ(1, observer.GetPrimaryChangedCountAndReset());
593 EXPECT_EQ(1, observer.CountAndReset());
594 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
595 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
597 EXPECT_TRUE(window_state->IsFullscreen());
598 EXPECT_EQ("0,0 500x500", w1->bounds().ToString());
601 TEST_F(DisplayControllerTest, BoundsUpdated) {
602 if (!SupportsMultipleDisplays())
603 return;
605 // Creates windows to catch activation change event.
606 scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
607 w1->Focus();
609 TestObserver observer;
610 SetDefaultDisplayLayout(DisplayLayout::BOTTOM);
611 UpdateDisplay("200x200,300x300"); // layout, resize and add.
612 EXPECT_EQ(1, observer.CountAndReset());
613 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
614 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
616 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
617 gfx::Insets insets(5, 5, 5, 5);
618 display_manager->UpdateWorkAreaOfDisplay(
619 ScreenUtil::GetSecondaryDisplay().id(), insets);
621 EXPECT_EQ("0,0 200x200", GetPrimaryDisplay().bounds().ToString());
622 EXPECT_EQ("0,200 300x300", GetSecondaryDisplay().bounds().ToString());
623 EXPECT_EQ("5,205 290x290", GetSecondaryDisplay().work_area().ToString());
625 UpdateDisplay("400x400,200x200");
626 EXPECT_EQ(1, observer.CountAndReset()); // two resizes
627 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
628 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
629 EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
630 EXPECT_EQ("0,400 200x200", GetSecondaryDisplay().bounds().ToString());
632 UpdateDisplay("400x400,300x300");
633 EXPECT_EQ(1, observer.CountAndReset());
634 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
635 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
636 EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
637 EXPECT_EQ("0,400 300x300", GetSecondaryDisplay().bounds().ToString());
639 UpdateDisplay("400x400");
640 EXPECT_EQ(1, observer.CountAndReset());
641 EXPECT_LE(1, observer.GetFocusChangedCountAndReset());
642 EXPECT_LE(1, observer.GetActivationChangedCountAndReset());
643 EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
644 EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
646 UpdateDisplay("400x500*2,300x300");
647 EXPECT_EQ(1, observer.CountAndReset());
648 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
649 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
650 ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());
651 EXPECT_EQ("0,0 200x250", GetPrimaryDisplay().bounds().ToString());
652 EXPECT_EQ("0,250 300x300", GetSecondaryDisplay().bounds().ToString());
654 // No change
655 UpdateDisplay("400x500*2,300x300");
656 // We still call into Pre/PostDisplayConfigurationChange().
657 EXPECT_EQ(1, observer.CountAndReset());
658 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
659 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
661 // Rotation
662 observer.GetRotationChangedCountAndReset(); // we only want to reset.
663 int64 primary_id = GetPrimaryDisplay().id();
664 display_manager->SetDisplayRotation(primary_id, gfx::Display::ROTATE_90,
665 gfx::Display::ROTATION_SOURCE_ACTIVE);
666 EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
667 EXPECT_EQ(1, observer.CountAndReset());
668 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
669 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
670 display_manager->SetDisplayRotation(primary_id, gfx::Display::ROTATE_90,
671 gfx::Display::ROTATION_SOURCE_ACTIVE);
672 EXPECT_EQ(0, observer.GetRotationChangedCountAndReset());
673 EXPECT_EQ(0, observer.CountAndReset());
674 EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
675 EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
677 // UI scale is eanbled only on internal display.
678 int64 secondary_id = GetSecondaryDisplay().id();
679 test::DisplayManagerTestApi(display_manager)
680 .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, OverscanInsets) {
956 if (!SupportsMultipleDisplays())
957 return;
959 DisplayController* display_controller =
960 Shell::GetInstance()->display_controller();
961 TestEventHandler event_handler;
962 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
964 UpdateDisplay("120x200,300x400*2");
965 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
966 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
968 display_controller->SetOverscanInsets(display1.id(),
969 gfx::Insets(10, 15, 20, 25));
970 EXPECT_EQ("0,0 80x170", root_windows[0]->bounds().ToString());
971 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
972 EXPECT_EQ("80,0 150x200",
973 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
975 ui::test::EventGenerator generator(root_windows[0]);
976 generator.MoveMouseToInHost(20, 25);
977 EXPECT_EQ("5,15", event_handler.GetLocationAndReset());
979 display_controller->SetOverscanInsets(display1.id(), gfx::Insets());
980 EXPECT_EQ("0,0 120x200", root_windows[0]->bounds().ToString());
981 EXPECT_EQ("120,0 150x200",
982 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
984 generator.MoveMouseToInHost(30, 20);
985 EXPECT_EQ("30,20", event_handler.GetLocationAndReset());
987 // Make sure the root window transformer uses correct scale
988 // factor when swapping display. Test crbug.com/253690.
989 UpdateDisplay("400x300*2,600x400/o");
990 root_windows = Shell::GetAllRootWindows();
991 gfx::Point point;
992 Shell::GetAllRootWindows()[1]->GetHost()->
993 GetRootTransform().TransformPoint(&point);
994 EXPECT_EQ("15,10", point.ToString());
996 display_controller->SwapPrimaryDisplay();
997 point.SetPoint(0, 0);
998 Shell::GetAllRootWindows()[1]->GetHost()->
999 GetRootTransform().TransformPoint(&point);
1000 EXPECT_EQ("15,10", point.ToString());
1002 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1005 TEST_F(DisplayControllerTest, Rotate) {
1006 if (!SupportsMultipleDisplays())
1007 return;
1009 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1010 TestEventHandler event_handler;
1011 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1013 UpdateDisplay("120x200,300x400*2");
1014 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
1015 int64 display2_id = ScreenUtil::GetSecondaryDisplay().id();
1016 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1017 ui::test::EventGenerator generator1(root_windows[0]);
1019 TestObserver observer;
1020 EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString());
1021 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
1022 EXPECT_EQ("120,0 150x200",
1023 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1024 generator1.MoveMouseToInHost(50, 40);
1025 EXPECT_EQ("50,40", event_handler.GetLocationAndReset());
1026 EXPECT_EQ(gfx::Display::ROTATE_0, GetActiveDisplayRotation(display1.id()));
1027 EXPECT_EQ(gfx::Display::ROTATE_0, GetActiveDisplayRotation(display2_id));
1028 EXPECT_EQ(0, observer.GetRotationChangedCountAndReset());
1030 display_manager->SetDisplayRotation(display1.id(), gfx::Display::ROTATE_90,
1031 gfx::Display::ROTATION_SOURCE_ACTIVE);
1032 EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString());
1033 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
1034 EXPECT_EQ("200,0 150x200",
1035 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1036 generator1.MoveMouseToInHost(50, 40);
1037 EXPECT_EQ("40,69", event_handler.GetLocationAndReset());
1038 EXPECT_EQ(gfx::Display::ROTATE_90, GetActiveDisplayRotation(display1.id()));
1039 EXPECT_EQ(gfx::Display::ROTATE_0, GetActiveDisplayRotation(display2_id));
1040 EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
1042 DisplayLayout display_layout(DisplayLayout::BOTTOM, 50);
1043 display_manager->SetLayoutForCurrentDisplays(display_layout);
1044 EXPECT_EQ("50,120 150x200",
1045 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1047 display_manager->SetDisplayRotation(display2_id, gfx::Display::ROTATE_270,
1048 gfx::Display::ROTATION_SOURCE_ACTIVE);
1049 EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString());
1050 EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString());
1051 EXPECT_EQ("50,120 200x150",
1052 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1053 EXPECT_EQ(gfx::Display::ROTATE_90, GetActiveDisplayRotation(display1.id()));
1054 EXPECT_EQ(gfx::Display::ROTATE_270, GetActiveDisplayRotation(display2_id));
1055 EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
1057 #if !defined(OS_WIN)
1058 ui::test::EventGenerator generator2(root_windows[1]);
1059 generator2.MoveMouseToInHost(50, 40);
1060 EXPECT_EQ("179,25", event_handler.GetLocationAndReset());
1061 display_manager->SetDisplayRotation(display1.id(), gfx::Display::ROTATE_180,
1062 gfx::Display::ROTATION_SOURCE_ACTIVE);
1064 EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString());
1065 EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString());
1066 // Dislay must share at least 100, so the x's offset becomes 20.
1067 EXPECT_EQ("20,200 200x150",
1068 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1069 EXPECT_EQ(gfx::Display::ROTATE_180, GetActiveDisplayRotation(display1.id()));
1070 EXPECT_EQ(gfx::Display::ROTATE_270, GetActiveDisplayRotation(display2_id));
1071 EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
1073 generator1.MoveMouseToInHost(50, 40);
1074 EXPECT_EQ("69,159", event_handler.GetLocationAndReset());
1075 #endif
1077 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1080 TEST_F(DisplayControllerTest, ScaleRootWindow) {
1081 if (!SupportsMultipleDisplays())
1082 return;
1084 TestEventHandler event_handler;
1085 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1087 UpdateDisplay("600x400*2@1.5,500x300");
1089 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1090 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
1091 test::DisplayManagerTestApi(display_manager)
1092 .SetInternalDisplayId(display1.id());
1094 gfx::Display display2 = ScreenUtil::GetSecondaryDisplay();
1095 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1096 EXPECT_EQ("0,0 450x300", display1.bounds().ToString());
1097 EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString());
1098 EXPECT_EQ("450,0 500x300", display2.bounds().ToString());
1099 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1100 EXPECT_EQ(1.0f, GetStoredUIScale(display2.id()));
1102 ui::test::EventGenerator generator(root_windows[0]);
1103 generator.MoveMouseToInHost(599, 200);
1104 EXPECT_EQ("449,150", event_handler.GetLocationAndReset());
1106 display_manager->SetDisplayUIScale(display1.id(), 1.25f);
1107 display1 = Shell::GetScreen()->GetPrimaryDisplay();
1108 display2 = ScreenUtil::GetSecondaryDisplay();
1109 EXPECT_EQ("0,0 375x250", display1.bounds().ToString());
1110 EXPECT_EQ("0,0 375x250", root_windows[0]->bounds().ToString());
1111 EXPECT_EQ("375,0 500x300", display2.bounds().ToString());
1112 EXPECT_EQ(1.25f, GetStoredUIScale(display1.id()));
1113 EXPECT_EQ(1.0f, GetStoredUIScale(display2.id()));
1115 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1118 TEST_F(DisplayControllerTest, TouchScale) {
1119 if (!SupportsMultipleDisplays())
1120 return;
1122 TestEventHandler event_handler;
1123 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1125 UpdateDisplay("200x200*2");
1126 gfx::Display display = Shell::GetScreen()->GetPrimaryDisplay();
1127 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1128 aura::Window* root_window = root_windows[0];
1129 ui::test::EventGenerator generator(root_window);
1131 generator.PressMoveAndReleaseTouchTo(50, 50);
1132 // Default test touches have radius_x/y = 1.0, with device scale
1133 // factor = 2, the scaled radius_x/y should be 0.5.
1134 EXPECT_EQ(0.5, event_handler.touch_radius_x());
1135 EXPECT_EQ(0.5, event_handler.touch_radius_y());
1137 generator.ScrollSequence(gfx::Point(0,0),
1138 base::TimeDelta::FromMilliseconds(100),
1139 10.0, 1.0, 5, 1);
1141 // ordinal_offset is invariant to the device scale factor.
1142 EXPECT_EQ(event_handler.scroll_x_offset(),
1143 event_handler.scroll_x_offset_ordinal());
1144 EXPECT_EQ(event_handler.scroll_y_offset(),
1145 event_handler.scroll_y_offset_ordinal());
1147 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1150 TEST_F(DisplayControllerTest, ConvertHostToRootCoords) {
1151 if (!SupportsMultipleDisplays())
1152 return;
1154 TestEventHandler event_handler;
1155 Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1157 UpdateDisplay("600x400*2/r@1.5");
1159 gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
1160 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1161 EXPECT_EQ("0,0 300x450", display1.bounds().ToString());
1162 EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString());
1163 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1165 ui::test::EventGenerator generator(root_windows[0]);
1166 generator.MoveMouseToInHost(0, 0);
1167 EXPECT_EQ("0,449", event_handler.GetLocationAndReset());
1168 generator.MoveMouseToInHost(599, 0);
1169 EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
1170 generator.MoveMouseToInHost(599, 399);
1171 EXPECT_EQ("299,0", event_handler.GetLocationAndReset());
1172 generator.MoveMouseToInHost(0, 399);
1173 EXPECT_EQ("299,449", event_handler.GetLocationAndReset());
1175 UpdateDisplay("600x400*2/u@1.5");
1176 display1 = Shell::GetScreen()->GetPrimaryDisplay();
1177 root_windows = Shell::GetAllRootWindows();
1178 EXPECT_EQ("0,0 450x300", display1.bounds().ToString());
1179 EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString());
1180 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1182 generator.MoveMouseToInHost(0, 0);
1183 EXPECT_EQ("449,299", event_handler.GetLocationAndReset());
1184 generator.MoveMouseToInHost(599, 0);
1185 EXPECT_EQ("0,299", event_handler.GetLocationAndReset());
1186 generator.MoveMouseToInHost(599, 399);
1187 EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
1188 generator.MoveMouseToInHost(0, 399);
1189 EXPECT_EQ("449,0", event_handler.GetLocationAndReset());
1191 UpdateDisplay("600x400*2/l@1.5");
1192 display1 = Shell::GetScreen()->GetPrimaryDisplay();
1193 root_windows = Shell::GetAllRootWindows();
1194 EXPECT_EQ("0,0 300x450", display1.bounds().ToString());
1195 EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString());
1196 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1198 generator.MoveMouseToInHost(0, 0);
1199 EXPECT_EQ("299,0", event_handler.GetLocationAndReset());
1200 generator.MoveMouseToInHost(599, 0);
1201 EXPECT_EQ("299,449", event_handler.GetLocationAndReset());
1202 generator.MoveMouseToInHost(599, 399);
1203 EXPECT_EQ("0,449", event_handler.GetLocationAndReset());
1204 generator.MoveMouseToInHost(0, 399);
1205 EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
1207 Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1210 // Make sure that the compositor based mirroring can switch
1211 // from/to dock mode.
1212 TEST_F(DisplayControllerTest, DockToSingle) {
1213 if (!SupportsMultipleDisplays())
1214 return;
1216 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1218 const int64 internal_id = 1;
1220 const DisplayInfo internal_display_info =
1221 CreateDisplayInfo(internal_id, 0, gfx::Display::ROTATE_0);
1222 const DisplayInfo external_display_info =
1223 CreateDisplayInfo(2, 1, gfx::Display::ROTATE_90);
1225 std::vector<DisplayInfo> display_info_list;
1226 // Extended
1227 display_info_list.push_back(internal_display_info);
1228 display_info_list.push_back(external_display_info);
1229 display_manager->OnNativeDisplaysChanged(display_info_list);
1230 const int64 internal_display_id =
1231 test::DisplayManagerTestApi(display_manager).
1232 SetFirstDisplayAsInternalDisplay();
1233 EXPECT_EQ(internal_id, internal_display_id);
1234 EXPECT_EQ(2U, display_manager->GetNumDisplays());
1236 // Dock mode.
1237 display_info_list.clear();
1238 display_info_list.push_back(external_display_info);
1239 display_manager->OnNativeDisplaysChanged(display_info_list);
1240 EXPECT_EQ(1U, display_manager->GetNumDisplays());
1241 EXPECT_FALSE(Shell::GetPrimaryRootWindow()->GetHost()->
1242 GetRootTransform().IsIdentityOrIntegerTranslation());
1244 // Switch to single mode and make sure the transform is the one
1245 // for the internal display.
1246 display_info_list.clear();
1247 display_info_list.push_back(internal_display_info);
1248 display_manager->OnNativeDisplaysChanged(display_info_list);
1249 EXPECT_TRUE(Shell::GetPrimaryRootWindow()->GetHost()->
1250 GetRootTransform().IsIdentityOrIntegerTranslation());
1253 // Tests if switching two displays at the same time while the primary display
1254 // is swapped should not cause a crash. (crbug.com/426292)
1255 TEST_F(DisplayControllerTest, ReplaceSwappedPrimary) {
1256 if (!SupportsMultipleDisplays())
1257 return;
1258 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1260 const DisplayInfo first_display_info =
1261 CreateDisplayInfo(10, 0, gfx::Display::ROTATE_0);
1262 const DisplayInfo second_display_info =
1263 CreateDisplayInfo(11, 1, gfx::Display::ROTATE_0);
1265 std::vector<DisplayInfo> display_info_list;
1266 // Extended
1267 display_info_list.push_back(first_display_info);
1268 display_info_list.push_back(second_display_info);
1269 display_manager->OnNativeDisplaysChanged(display_info_list);
1271 Shell::GetInstance()->display_controller()->SwapPrimaryDisplay();
1273 EXPECT_EQ(11, Shell::GetScreen()->GetPrimaryDisplay().id());
1275 display_info_list.clear();
1276 const DisplayInfo new_first_display_info =
1277 CreateDisplayInfo(20, 0, gfx::Display::ROTATE_0);
1278 const DisplayInfo new_second_display_info =
1279 CreateDisplayInfo(21, 1, gfx::Display::ROTATE_0);
1280 display_info_list.push_back(new_first_display_info);
1281 display_info_list.push_back(new_second_display_info);
1282 display_manager->OnNativeDisplaysChanged(display_info_list);
1284 EXPECT_EQ(20, Shell::GetScreen()->GetPrimaryDisplay().id());
1287 TEST_F(DisplayControllerTest, UpdateMouseLocationAfterDisplayChange) {
1288 if (!SupportsMultipleDisplays())
1289 return;
1291 UpdateDisplay("200x200,300x300");
1292 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1294 aura::Env* env = aura::Env::GetInstance();
1296 ui::test::EventGenerator generator(root_windows[0]);
1298 // Set the initial position.
1299 generator.MoveMouseToInHost(350, 150);
1300 EXPECT_EQ("350,150", env->last_mouse_location().ToString());
1302 // A mouse pointer will stay in the 2nd display.
1303 UpdateDisplay("300x300,200x200");
1304 EXPECT_EQ("450,50", env->last_mouse_location().ToString());
1306 // A mouse pointer will be outside of displays and move to the
1307 // center of 2nd display.
1308 UpdateDisplay("300x300,100x100");
1309 EXPECT_EQ("350,50", env->last_mouse_location().ToString());
1311 // 2nd display was disconnected, and the cursor is
1312 // now in the 1st display.
1313 UpdateDisplay("400x400");
1314 EXPECT_EQ("50,350", env->last_mouse_location().ToString());
1316 // 1st display's resolution has changed, and the mouse pointer is
1317 // now outside. Move the mouse pointer to the center of 1st display.
1318 UpdateDisplay("300x300");
1319 EXPECT_EQ("150,150", env->last_mouse_location().ToString());
1321 // Move the mouse pointer to the bottom of 1st display.
1322 generator.MoveMouseToInHost(150, 290);
1323 EXPECT_EQ("150,290", env->last_mouse_location().ToString());
1325 // The mouse pointer is now on 2nd display.
1326 UpdateDisplay("300x280,200x200");
1327 EXPECT_EQ("450,10", env->last_mouse_location().ToString());
1330 TEST_F(DisplayControllerTest, UpdateMouseLocationAfterDisplayChange_2ndOnLeft) {
1331 if (!SupportsMultipleDisplays())
1332 return;
1334 // Set the 2nd display on the left.
1335 DisplayLayoutStore* layout_store =
1336 Shell::GetInstance()->display_manager()->layout_store();
1337 DisplayLayout layout = layout_store->default_display_layout();
1338 layout.position = DisplayLayout::LEFT;
1339 layout_store->SetDefaultDisplayLayout(layout);
1341 UpdateDisplay("200x200,300x300");
1342 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1344 EXPECT_EQ("-300,0 300x300",
1345 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1347 aura::Env* env = aura::Env::GetInstance();
1349 // Set the initial position.
1350 root_windows[0]->MoveCursorTo(gfx::Point(-150, 250));
1351 EXPECT_EQ("-150,250", env->last_mouse_location().ToString());
1353 // A mouse pointer will stay in 2nd display.
1354 UpdateDisplay("300x300,200x300");
1355 EXPECT_EQ("-50,150", env->last_mouse_location().ToString());
1357 // A mouse pointer will be outside of displays and move to the
1358 // center of 2nd display.
1359 UpdateDisplay("300x300,200x100");
1360 EXPECT_EQ("-100,50", env->last_mouse_location().ToString());
1362 // 2nd display was disconnected. Mouse pointer should move to
1363 // 1st display.
1364 UpdateDisplay("300x300");
1365 EXPECT_EQ("150,150", env->last_mouse_location().ToString());
1368 // Test that the cursor swaps displays and that its scale factor and rotation
1369 // are updated when the primary display is swapped.
1370 TEST_F(DisplayControllerTest,
1371 UpdateMouseLocationAfterDisplayChange_SwapPrimary) {
1372 if (!SupportsMultipleDisplays())
1373 return;
1375 UpdateDisplay("200x200,200x200*2/r");
1377 aura::Env* env = aura::Env::GetInstance();
1378 Shell* shell = Shell::GetInstance();
1379 DisplayController* display_controller = shell->display_controller();
1380 test::CursorManagerTestApi test_api(shell->cursor_manager());
1382 display_controller->GetPrimaryRootWindow()->MoveCursorTo(gfx::Point(20, 50));
1384 EXPECT_EQ("20,50", env->last_mouse_location().ToString());
1385 EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
1386 EXPECT_EQ(gfx::Display::ROTATE_0, test_api.GetCurrentCursorRotation());
1388 display_controller->SwapPrimaryDisplay();
1390 EXPECT_EQ("20,50", env->last_mouse_location().ToString());
1391 EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor());
1392 EXPECT_EQ(gfx::Display::ROTATE_90, test_api.GetCurrentCursorRotation());
1395 // Test that the cursor moves to the other display and that its scale factor
1396 // and rotation are updated when the primary display is disconnected.
1397 TEST_F(DisplayControllerTest,
1398 UpdateMouseLocationAfterDisplayChange_PrimaryDisconnected) {
1399 if (!SupportsMultipleDisplays())
1400 return;
1402 aura::Env* env = aura::Env::GetInstance();
1403 Shell* shell = Shell::GetInstance();
1404 DisplayController* display_controller = shell->display_controller();
1405 test::CursorManagerTestApi test_api(shell->cursor_manager());
1407 UpdateDisplay("300x300*2/r,200x200");
1408 // Swap the primary display to make it possible to remove the primary display
1409 // via UpdateDisplay().
1410 display_controller->SwapPrimaryDisplay();
1411 int primary_display_id = display_controller->GetPrimaryDisplayId();
1413 display_controller->GetPrimaryRootWindow()->MoveCursorTo(gfx::Point(20, 50));
1415 EXPECT_EQ("20,50", env->last_mouse_location().ToString());
1416 EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
1417 EXPECT_EQ(gfx::Display::ROTATE_0, test_api.GetCurrentCursorRotation());
1419 UpdateDisplay("300x300*2/r");
1420 ASSERT_NE(primary_display_id, display_controller->GetPrimaryDisplayId());
1422 // Cursor should be centered on the remaining display.
1423 EXPECT_EQ("75,75", env->last_mouse_location().ToString());
1424 EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor());
1425 EXPECT_EQ(gfx::Display::ROTATE_90, test_api.GetCurrentCursorRotation());
1428 // GetRootWindowForDisplayId() for removed gfx::Display during
1429 // OnDisplayRemoved() should not cause crash. See http://crbug.com/415222
1430 TEST_F(DisplayControllerTest,
1431 GetRootWindowForDisplayIdDuringDisplayDisconnection) {
1432 if (!SupportsMultipleDisplays())
1433 return;
1435 UpdateDisplay("300x300,200x200");
1436 aura::Window* root2 =
1437 Shell::GetInstance()->display_controller()->GetRootWindowForDisplayId(
1438 ScreenUtil::GetSecondaryDisplay().id());
1439 views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
1440 nullptr, root2, gfx::Rect(350, 0, 100, 100));
1441 views::View* view = new views::View();
1442 widget->GetContentsView()->AddChildView(view);
1443 view->SetBounds(0, 0, 100, 100);
1444 widget->Show();
1446 TestMouseWatcherListener listener;
1447 views::MouseWatcher watcher(
1448 new views::MouseWatcherViewHost(view, gfx::Insets()), &listener);
1449 watcher.Start();
1451 ui::test::EventGenerator event_generator(
1452 widget->GetNativeWindow()->GetRootWindow());
1453 event_generator.MoveMouseToCenterOf(widget->GetNativeWindow());
1455 UpdateDisplay("300x300");
1456 watcher.Stop();
1458 widget->CloseNow();
1461 } // namespace ash