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/window_tree_host_manager.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/display/display_util.h"
12 #include "ash/screen_util.h"
13 #include "ash/shelf/shelf.h"
14 #include "ash/shelf/shelf_widget.h"
15 #include "ash/shell.h"
16 #include "ash/test/ash_test_base.h"
17 #include "ash/test/ash_test_helper.h"
18 #include "ash/test/cursor_manager_test_api.h"
19 #include "ash/test/display_manager_test_api.h"
20 #include "ash/test/test_shell_delegate.h"
21 #include "ash/wm/window_state.h"
22 #include "ash/wm/wm_event.h"
23 #include "base/command_line.h"
24 #include "ui/aura/client/focus_change_observer.h"
25 #include "ui/aura/client/focus_client.h"
26 #include "ui/aura/env.h"
27 #include "ui/aura/window_tracker.h"
28 #include "ui/aura/window_tree_host.h"
29 #include "ui/events/event_handler.h"
30 #include "ui/events/test/event_generator.h"
31 #include "ui/gfx/display.h"
32 #include "ui/gfx/screen.h"
33 #include "ui/views/mouse_watcher.h"
34 #include "ui/views/mouse_watcher_view_host.h"
35 #include "ui/views/view.h"
36 #include "ui/views/widget/widget.h"
37 #include "ui/wm/public/activation_change_observer.h"
38 #include "ui/wm/public/activation_client.h"
43 const char kDesktopBackgroundView
[] = "DesktopBackgroundView";
48 explicit Resetter(T
* value
) : value_(*value
) { *value
= 0; }
50 T
value() { return value_
; }
54 DISALLOW_COPY_AND_ASSIGN(Resetter
);
57 class TestObserver
: public WindowTreeHostManager::Observer
,
58 public gfx::DisplayObserver
,
59 public aura::client::FocusChangeObserver
,
60 public aura::client::ActivationChangeObserver
{
65 bounds_changed_count_(0),
66 rotation_changed_count_(0),
67 workarea_changed_count_(0),
68 primary_changed_count_(0),
69 changed_display_id_(0),
70 focus_changed_count_(0),
71 activation_changed_count_(0) {
72 Shell::GetInstance()->window_tree_host_manager()->AddObserver(this);
73 Shell::GetScreen()->AddObserver(this);
74 aura::client::GetFocusClient(Shell::GetPrimaryRootWindow())
76 aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())
80 ~TestObserver() override
{
81 Shell::GetInstance()->window_tree_host_manager()->RemoveObserver(this);
82 Shell::GetScreen()->RemoveObserver(this);
83 aura::client::GetFocusClient(Shell::GetPrimaryRootWindow())
84 ->RemoveObserver(this);
85 aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())
86 ->RemoveObserver(this);
89 // Overridden from WindowTreeHostManager::Observer
90 void OnDisplayConfigurationChanging() override
{ ++changing_count_
; }
91 void OnDisplayConfigurationChanged() override
{ ++changed_count_
; }
93 // Overrideen from gfx::DisplayObserver
94 void OnDisplayMetricsChanged(const gfx::Display
& display
,
95 uint32_t metrics
) override
{
96 changed_display_id_
= display
.id();
97 if (metrics
& DISPLAY_METRIC_BOUNDS
)
98 ++bounds_changed_count_
;
99 if (metrics
& DISPLAY_METRIC_ROTATION
)
100 ++rotation_changed_count_
;
101 if (metrics
& DISPLAY_METRIC_WORK_AREA
)
102 ++workarea_changed_count_
;
103 if (metrics
& DISPLAY_METRIC_PRIMARY
)
104 ++primary_changed_count_
;
106 void OnDisplayAdded(const gfx::Display
& new_display
) override
{}
107 void OnDisplayRemoved(const gfx::Display
& old_display
) override
{}
109 // Overridden from aura::client::FocusChangeObserver
110 void OnWindowFocused(aura::Window
* gained_focus
,
111 aura::Window
* lost_focus
) override
{
112 focus_changed_count_
++;
115 // Overridden from aura::client::ActivationChangeObserver
116 void OnWindowActivated(
117 aura::client::ActivationChangeObserver::ActivationReason reason
,
118 aura::Window
* gained_active
,
119 aura::Window
* lost_active
) override
{
120 activation_changed_count_
++;
122 void OnAttemptToReactivateWindow(aura::Window
* request_active
,
123 aura::Window
* actual_active
) override
{}
125 int CountAndReset() {
126 EXPECT_EQ(changing_count_
, changed_count_
);
128 return Resetter
<int>(&changing_count_
).value();
131 int64
GetBoundsChangedCountAndReset() {
132 return Resetter
<int>(&bounds_changed_count_
).value();
135 int64
GetRotationChangedCountAndReset() {
136 return Resetter
<int>(&rotation_changed_count_
).value();
139 int64
GetWorkareaChangedCountAndReset() {
140 return Resetter
<int>(&workarea_changed_count_
).value();
143 int64
GetPrimaryChangedCountAndReset() {
144 return Resetter
<int>(&primary_changed_count_
).value();
147 int64
GetChangedDisplayIdAndReset() {
148 return Resetter
<int64
>(&changed_display_id_
).value();
151 int GetFocusChangedCountAndReset() {
152 return Resetter
<int>(&focus_changed_count_
).value();
155 int GetActivationChangedCountAndReset() {
156 return Resetter
<int>(&activation_changed_count_
).value();
163 int bounds_changed_count_
;
164 int rotation_changed_count_
;
165 int workarea_changed_count_
;
166 int primary_changed_count_
;
167 int64 changed_display_id_
;
169 int focus_changed_count_
;
170 int activation_changed_count_
;
172 DISALLOW_COPY_AND_ASSIGN(TestObserver
);
175 gfx::Display
GetPrimaryDisplay() {
176 return Shell::GetScreen()->GetDisplayNearestWindow(
177 Shell::GetAllRootWindows()[0]);
180 gfx::Display
GetSecondaryDisplay() {
181 return Shell::GetScreen()->GetDisplayNearestWindow(
182 Shell::GetAllRootWindows()[1]);
185 void SetSecondaryDisplayLayoutAndOffset(DisplayLayout::Position position
,
187 DisplayLayout
layout(position
, offset
);
188 ASSERT_GT(Shell::GetScreen()->GetNumDisplays(), 1);
189 Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays(layout
);
192 void SetSecondaryDisplayLayout(DisplayLayout::Position position
) {
193 SetSecondaryDisplayLayoutAndOffset(position
, 0);
196 void SetDefaultDisplayLayout(DisplayLayout::Position position
) {
200 ->SetDefaultDisplayLayout(DisplayLayout(position
, 0));
203 class WindowTreeHostManagerShutdownTest
: public test::AshTestBase
{
205 WindowTreeHostManagerShutdownTest() {}
206 ~WindowTreeHostManagerShutdownTest() override
{}
208 void TearDown() override
{
209 test::AshTestBase::TearDown();
210 if (!SupportsMultipleDisplays())
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());
220 DISALLOW_COPY_AND_ASSIGN(WindowTreeHostManagerShutdownTest
);
223 class StartupHelper
: public test::TestShellDelegate
,
224 public WindowTreeHostManager::Observer
{
226 StartupHelper() : displays_initialized_(false) {}
227 ~StartupHelper() override
{}
229 // ash::ShellSelegate:
230 void PreInit() override
{
231 Shell::GetInstance()->window_tree_host_manager()->AddObserver(this);
234 // ash::WindowTreeHostManager::Observer:
235 void OnDisplaysInitialized() override
{
236 DCHECK(!displays_initialized_
);
237 displays_initialized_
= true;
240 bool displays_initialized() const { return displays_initialized_
; }
243 bool displays_initialized_
;
245 DISALLOW_COPY_AND_ASSIGN(StartupHelper
);
248 class WindowTreeHostManagerStartupTest
: public test::AshTestBase
{
250 WindowTreeHostManagerStartupTest() : startup_helper_(new StartupHelper
) {}
251 ~WindowTreeHostManagerStartupTest() override
{}
253 // ash::test::AshTestBase:
254 void SetUp() override
{
255 ash_test_helper()->set_test_shell_delegate(startup_helper_
);
256 test::AshTestBase::SetUp();
258 void TearDown() override
{
259 Shell::GetInstance()->window_tree_host_manager()->RemoveObserver(
261 test::AshTestBase::TearDown();
264 const StartupHelper
* startup_helper() const { return startup_helper_
; }
267 StartupHelper
* startup_helper_
; // Owned by ash::Shell.
269 DISALLOW_COPY_AND_ASSIGN(WindowTreeHostManagerStartupTest
);
272 class TestEventHandler
: public ui::EventHandler
{
275 : 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
) {
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
)
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
)
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);
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_
; }
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()
355 .GetEffectiveUIScale();
358 class TestMouseWatcherListener
: public views::MouseWatcherListener
{
360 TestMouseWatcherListener() {}
363 // views::MouseWatcherListener:
364 void MouseMovedOutOfHost() override
{}
366 DISALLOW_COPY_AND_ASSIGN(TestMouseWatcherListener
);
371 typedef test::AshTestBase WindowTreeHostManagerTest
;
373 TEST_F(WindowTreeHostManagerShutdownTest
, Shutdown
) {
374 if (!SupportsMultipleDisplays())
377 UpdateDisplay("444x333, 200x200");
380 TEST_F(WindowTreeHostManagerStartupTest
, Startup
) {
381 if (!SupportsMultipleDisplays())
384 EXPECT_TRUE(startup_helper()->displays_initialized());
387 TEST_F(WindowTreeHostManagerTest
, SecondaryDisplayLayout
) {
388 if (!SupportsMultipleDisplays())
391 // Creates windows to catch activation change event.
392 scoped_ptr
<aura::Window
> w1(CreateTestWindowInShellWithId(1));
395 TestObserver observer
;
396 UpdateDisplay("500x500,400x400");
397 EXPECT_EQ(1, observer
.CountAndReset()); // resize and add
398 EXPECT_EQ(1, observer
.GetBoundsChangedCountAndReset());
399 EXPECT_EQ(1, observer
.GetWorkareaChangedCountAndReset());
400 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
401 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
402 gfx::Insets
insets(5, 5, 5, 5);
403 int64 secondary_display_id
= ScreenUtil::GetSecondaryDisplay().id();
404 Shell::GetInstance()->display_manager()->UpdateWorkAreaOfDisplay(
405 secondary_display_id
, insets
);
407 // Default layout is RIGHT.
408 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
409 EXPECT_EQ("500,0 400x400", GetSecondaryDisplay().bounds().ToString());
410 EXPECT_EQ("505,5 390x390", GetSecondaryDisplay().work_area().ToString());
411 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
412 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
414 // Layout the secondary display to the bottom of the primary.
415 SetSecondaryDisplayLayout(DisplayLayout::BOTTOM
);
416 EXPECT_EQ(1, observer
.CountAndReset());
417 EXPECT_EQ(1, observer
.GetBoundsChangedCountAndReset());
418 EXPECT_EQ(1, observer
.GetWorkareaChangedCountAndReset());
419 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
420 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
421 EXPECT_EQ(secondary_display_id
, observer
.GetChangedDisplayIdAndReset());
422 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
423 EXPECT_EQ("0,500 400x400", GetSecondaryDisplay().bounds().ToString());
424 EXPECT_EQ("5,505 390x390", GetSecondaryDisplay().work_area().ToString());
426 // Layout the secondary display to the left of the primary.
427 SetSecondaryDisplayLayout(DisplayLayout::LEFT
);
428 EXPECT_EQ(1, observer
.CountAndReset());
429 EXPECT_EQ(1, observer
.GetBoundsChangedCountAndReset());
430 EXPECT_EQ(1, observer
.GetWorkareaChangedCountAndReset());
431 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
432 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
433 EXPECT_EQ(secondary_display_id
, observer
.GetChangedDisplayIdAndReset());
434 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
435 EXPECT_EQ("-400,0 400x400", GetSecondaryDisplay().bounds().ToString());
436 EXPECT_EQ("-395,5 390x390", GetSecondaryDisplay().work_area().ToString());
438 // Layout the secondary display to the top of the primary.
439 SetSecondaryDisplayLayout(DisplayLayout::TOP
);
440 EXPECT_EQ(1, observer
.CountAndReset());
441 EXPECT_EQ(1, observer
.GetBoundsChangedCountAndReset());
442 EXPECT_EQ(1, observer
.GetWorkareaChangedCountAndReset());
443 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
444 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
445 EXPECT_EQ(secondary_display_id
, observer
.GetChangedDisplayIdAndReset());
446 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
447 EXPECT_EQ("0,-400 400x400", GetSecondaryDisplay().bounds().ToString());
448 EXPECT_EQ("5,-395 390x390", GetSecondaryDisplay().work_area().ToString());
450 // Layout to the right with an offset.
451 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT
, 300);
452 EXPECT_EQ(1, observer
.CountAndReset()); // resize and add
453 EXPECT_EQ(1, observer
.GetBoundsChangedCountAndReset());
454 EXPECT_EQ(1, observer
.GetWorkareaChangedCountAndReset());
455 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
456 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
457 EXPECT_EQ(secondary_display_id
, observer
.GetChangedDisplayIdAndReset());
458 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
459 EXPECT_EQ("500,300 400x400", GetSecondaryDisplay().bounds().ToString());
461 // Keep the minimum 100.
462 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT
, 490);
463 EXPECT_EQ(1, observer
.CountAndReset()); // resize and add
464 EXPECT_EQ(1, observer
.GetBoundsChangedCountAndReset());
465 EXPECT_EQ(1, observer
.GetWorkareaChangedCountAndReset());
466 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
467 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
468 EXPECT_EQ(secondary_display_id
, observer
.GetChangedDisplayIdAndReset());
469 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
470 EXPECT_EQ("500,400 400x400", GetSecondaryDisplay().bounds().ToString());
472 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT
, -400);
473 EXPECT_EQ(secondary_display_id
, observer
.GetChangedDisplayIdAndReset());
474 EXPECT_EQ(1, observer
.GetBoundsChangedCountAndReset());
475 EXPECT_EQ(1, observer
.GetWorkareaChangedCountAndReset());
476 EXPECT_EQ(1, observer
.CountAndReset()); // resize and add
477 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
478 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
479 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
480 EXPECT_EQ("500,-300 400x400", GetSecondaryDisplay().bounds().ToString());
482 // Layout to the bottom with an offset.
483 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM
, -200);
484 EXPECT_EQ(secondary_display_id
, observer
.GetChangedDisplayIdAndReset());
485 EXPECT_EQ(1, observer
.GetBoundsChangedCountAndReset());
486 EXPECT_EQ(1, observer
.GetWorkareaChangedCountAndReset());
487 EXPECT_EQ(1, observer
.CountAndReset()); // resize and add
488 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
489 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
490 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
491 EXPECT_EQ("-200,500 400x400", GetSecondaryDisplay().bounds().ToString());
493 // Keep the minimum 100.
494 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM
, 490);
495 EXPECT_EQ(secondary_display_id
, observer
.GetChangedDisplayIdAndReset());
496 EXPECT_EQ(1, observer
.GetBoundsChangedCountAndReset());
497 EXPECT_EQ(1, observer
.GetWorkareaChangedCountAndReset());
498 EXPECT_EQ(1, observer
.CountAndReset()); // resize and add
499 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
500 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
501 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
502 EXPECT_EQ("400,500 400x400", GetSecondaryDisplay().bounds().ToString());
504 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM
, -400);
505 EXPECT_EQ(secondary_display_id
, observer
.GetChangedDisplayIdAndReset());
506 EXPECT_EQ(1, observer
.GetBoundsChangedCountAndReset());
507 EXPECT_EQ(1, observer
.GetWorkareaChangedCountAndReset());
508 EXPECT_EQ(1, observer
.CountAndReset()); // resize and add
509 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
510 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
511 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
512 EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString());
514 // Setting the same layout shouldn't invoke observers.
515 SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM
, -400);
516 EXPECT_EQ(0, observer
.GetChangedDisplayIdAndReset());
517 EXPECT_EQ(0, observer
.GetBoundsChangedCountAndReset());
518 EXPECT_EQ(0, observer
.GetWorkareaChangedCountAndReset());
519 EXPECT_EQ(0, observer
.CountAndReset()); // resize and add
520 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
521 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
522 EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
523 EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString());
525 UpdateDisplay("500x500");
526 EXPECT_LE(1, observer
.GetFocusChangedCountAndReset());
527 EXPECT_LE(1, observer
.GetActivationChangedCountAndReset());
532 DisplayInfo
CreateDisplayInfo(int64 id
,
534 gfx::Display::Rotation rotation
) {
535 DisplayInfo
info(id
, "", false);
536 info
.SetBounds(gfx::Rect(0, y
, 500, 500));
537 info
.SetRotation(rotation
, gfx::Display::ROTATION_SOURCE_ACTIVE
);
541 DisplayInfo
CreateMirroredDisplayInfo(int64 id
, float device_scale_factor
) {
542 DisplayInfo info
= CreateDisplayInfo(id
, 0, gfx::Display::ROTATE_0
);
543 info
.set_device_scale_factor(device_scale_factor
);
549 TEST_F(WindowTreeHostManagerTest
, MirrorToDockedWithFullscreen
) {
550 if (!SupportsMultipleDisplays())
553 // Creates windows to catch activation change event.
554 scoped_ptr
<aura::Window
> w1(CreateTestWindowInShellWithId(1));
558 DisplayManager
* display_manager
= Shell::GetInstance()->display_manager();
560 const DisplayInfo internal_display_info
= CreateMirroredDisplayInfo(1, 2.0f
);
561 const DisplayInfo external_display_info
= CreateMirroredDisplayInfo(2, 1.0f
);
563 std::vector
<DisplayInfo
> display_info_list
;
565 display_info_list
.push_back(internal_display_info
);
566 display_info_list
.push_back(external_display_info
);
567 display_manager
->OnNativeDisplaysChanged(display_info_list
);
568 const int64 internal_display_id
=
569 test::DisplayManagerTestApi().SetFirstDisplayAsInternalDisplay();
570 EXPECT_EQ(1, internal_display_id
);
571 EXPECT_EQ(2U, display_manager
->num_connected_displays());
572 EXPECT_EQ(1U, display_manager
->GetNumDisplays());
574 wm::WindowState
* window_state
= wm::GetWindowState(w1
.get());
575 const wm::WMEvent
toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN
);
576 window_state
->OnWMEvent(&toggle_fullscreen_event
);
577 EXPECT_TRUE(window_state
->IsFullscreen());
578 EXPECT_EQ("0,0 250x250", w1
->bounds().ToString());
580 TestObserver observer
;
581 display_info_list
.clear();
582 display_info_list
.push_back(external_display_info
);
583 display_manager
->OnNativeDisplaysChanged(display_info_list
);
584 EXPECT_EQ(1U, display_manager
->GetNumDisplays());
585 EXPECT_EQ(1U, display_manager
->num_connected_displays());
586 // Observers are called due to primary change.
587 EXPECT_EQ(2, observer
.GetChangedDisplayIdAndReset());
588 EXPECT_EQ(1, observer
.GetBoundsChangedCountAndReset());
589 EXPECT_EQ(1, observer
.GetWorkareaChangedCountAndReset());
590 EXPECT_EQ(1, observer
.GetPrimaryChangedCountAndReset());
591 EXPECT_EQ(1, observer
.CountAndReset());
592 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
593 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
595 EXPECT_TRUE(window_state
->IsFullscreen());
596 EXPECT_EQ("0,0 500x500", w1
->bounds().ToString());
599 TEST_F(WindowTreeHostManagerTest
, BoundsUpdated
) {
600 if (!SupportsMultipleDisplays())
603 // Creates windows to catch activation change event.
604 scoped_ptr
<aura::Window
> w1(CreateTestWindowInShellWithId(1));
607 TestObserver observer
;
608 SetDefaultDisplayLayout(DisplayLayout::BOTTOM
);
609 UpdateDisplay("200x200,300x300"); // layout, resize and add.
610 EXPECT_EQ(1, observer
.CountAndReset());
611 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
612 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
614 DisplayManager
* display_manager
= Shell::GetInstance()->display_manager();
615 gfx::Insets
insets(5, 5, 5, 5);
616 display_manager
->UpdateWorkAreaOfDisplay(
617 ScreenUtil::GetSecondaryDisplay().id(), insets
);
619 EXPECT_EQ("0,0 200x200", GetPrimaryDisplay().bounds().ToString());
620 EXPECT_EQ("0,200 300x300", GetSecondaryDisplay().bounds().ToString());
621 EXPECT_EQ("5,205 290x290", GetSecondaryDisplay().work_area().ToString());
623 UpdateDisplay("400x400,200x200");
624 EXPECT_EQ(1, observer
.CountAndReset()); // two resizes
625 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
626 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
627 EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
628 EXPECT_EQ("0,400 200x200", GetSecondaryDisplay().bounds().ToString());
630 UpdateDisplay("400x400,300x300");
631 EXPECT_EQ(1, observer
.CountAndReset());
632 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
633 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
634 EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
635 EXPECT_EQ("0,400 300x300", GetSecondaryDisplay().bounds().ToString());
637 UpdateDisplay("400x400");
638 EXPECT_EQ(1, observer
.CountAndReset());
639 EXPECT_LE(1, observer
.GetFocusChangedCountAndReset());
640 EXPECT_LE(1, observer
.GetActivationChangedCountAndReset());
641 EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
642 EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
644 UpdateDisplay("400x500*2,300x300");
645 EXPECT_EQ(1, observer
.CountAndReset());
646 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
647 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
648 ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());
649 EXPECT_EQ("0,0 200x250", GetPrimaryDisplay().bounds().ToString());
650 EXPECT_EQ("0,250 300x300", GetSecondaryDisplay().bounds().ToString());
653 UpdateDisplay("400x500*2,300x300");
654 // We still call into Pre/PostDisplayConfigurationChange().
655 EXPECT_EQ(1, observer
.CountAndReset());
656 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
657 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
660 observer
.GetRotationChangedCountAndReset(); // we only want to reset.
661 int64 primary_id
= GetPrimaryDisplay().id();
662 display_manager
->SetDisplayRotation(primary_id
, gfx::Display::ROTATE_90
,
663 gfx::Display::ROTATION_SOURCE_ACTIVE
);
664 EXPECT_EQ(1, observer
.GetRotationChangedCountAndReset());
665 EXPECT_EQ(1, observer
.CountAndReset());
666 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
667 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
668 display_manager
->SetDisplayRotation(primary_id
, gfx::Display::ROTATE_90
,
669 gfx::Display::ROTATION_SOURCE_ACTIVE
);
670 EXPECT_EQ(0, observer
.GetRotationChangedCountAndReset());
671 EXPECT_EQ(0, observer
.CountAndReset());
672 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
673 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
675 // UI scale is eanbled only on internal display.
676 int64 secondary_id
= GetSecondaryDisplay().id();
677 test::ScopedSetInternalDisplayId
set_internal(secondary_id
);
678 // Changing internal ID display changes the DisplayIdPair (it comes
679 // first), which also changes the primary display candidate. Update
680 // the primary display manually to update the primary display to
681 // avoid getting the OnDisplayConfigurationChanged() call twice in
682 // SetDisplayUIScale. Note that this scenario will never happen on
684 Shell::GetInstance()->window_tree_host_manager()->SetPrimaryDisplayId(
686 EXPECT_EQ(1, observer
.CountAndReset());
688 SetDisplayUIScale(secondary_id
, 1.125f
);
689 EXPECT_EQ(1, observer
.CountAndReset());
690 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
691 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
692 SetDisplayUIScale(secondary_id
, 1.125f
);
693 EXPECT_EQ(0, observer
.CountAndReset());
694 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
695 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
696 SetDisplayUIScale(primary_id
, 1.125f
);
697 EXPECT_EQ(0, observer
.CountAndReset());
698 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
699 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
700 SetDisplayUIScale(primary_id
, 1.125f
);
701 EXPECT_EQ(0, observer
.CountAndReset());
702 EXPECT_EQ(0, observer
.GetFocusChangedCountAndReset());
703 EXPECT_EQ(0, observer
.GetActivationChangedCountAndReset());
706 TEST_F(WindowTreeHostManagerTest
, SwapPrimary
) {
707 if (!SupportsMultipleDisplays())
710 WindowTreeHostManager
* window_tree_host_manager
=
711 Shell::GetInstance()->window_tree_host_manager();
712 DisplayManager
* display_manager
= Shell::GetInstance()->display_manager();
714 UpdateDisplay("200x200,300x300");
715 gfx::Display primary_display
= Shell::GetScreen()->GetPrimaryDisplay();
716 gfx::Display secondary_display
= ScreenUtil::GetSecondaryDisplay();
718 DisplayLayout
display_layout(DisplayLayout::RIGHT
, 50);
719 display_manager
->SetLayoutForCurrentDisplays(display_layout
);
721 EXPECT_NE(primary_display
.id(), secondary_display
.id());
722 aura::Window
* primary_root
=
723 window_tree_host_manager
->GetRootWindowForDisplayId(primary_display
.id());
724 aura::Window
* secondary_root
=
725 window_tree_host_manager
->GetRootWindowForDisplayId(
726 secondary_display
.id());
727 EXPECT_NE(primary_root
, secondary_root
);
728 aura::Window
* shelf_window
=
729 Shelf::ForPrimaryDisplay()->shelf_widget()->GetNativeView();
730 EXPECT_TRUE(primary_root
->Contains(shelf_window
));
731 EXPECT_FALSE(secondary_root
->Contains(shelf_window
));
733 primary_display
.id(),
734 Shell::GetScreen()->GetDisplayNearestPoint(gfx::Point(-100, -100)).id());
735 EXPECT_EQ(primary_display
.id(),
736 Shell::GetScreen()->GetDisplayNearestWindow(NULL
).id());
738 EXPECT_EQ("0,0 200x200", primary_display
.bounds().ToString());
739 EXPECT_EQ("0,0 200x153", primary_display
.work_area().ToString());
740 EXPECT_EQ("200,0 300x300", secondary_display
.bounds().ToString());
741 EXPECT_EQ("200,0 300x253", secondary_display
.work_area().ToString());
742 EXPECT_EQ("right, 50", display_manager
->GetCurrentDisplayLayout().ToString());
744 // Switch primary and secondary
745 window_tree_host_manager
->SetPrimaryDisplay(secondary_display
);
746 const DisplayLayout
& inverted_layout
=
747 display_manager
->GetCurrentDisplayLayout();
748 EXPECT_EQ("left, -50", inverted_layout
.ToString());
750 EXPECT_EQ(secondary_display
.id(),
751 Shell::GetScreen()->GetPrimaryDisplay().id());
752 EXPECT_EQ(primary_display
.id(), ScreenUtil::GetSecondaryDisplay().id());
754 primary_display
.id(),
755 Shell::GetScreen()->GetDisplayNearestPoint(gfx::Point(-100, -100)).id());
756 EXPECT_EQ(secondary_display
.id(),
757 Shell::GetScreen()->GetDisplayNearestWindow(NULL
).id());
759 EXPECT_EQ(primary_root
, window_tree_host_manager
->GetRootWindowForDisplayId(
760 secondary_display
.id()));
761 EXPECT_EQ(secondary_root
, window_tree_host_manager
->GetRootWindowForDisplayId(
762 primary_display
.id()));
763 EXPECT_TRUE(primary_root
->Contains(shelf_window
));
764 EXPECT_FALSE(secondary_root
->Contains(shelf_window
));
766 // Test if the bounds are correctly swapped.
767 gfx::Display swapped_primary
= Shell::GetScreen()->GetPrimaryDisplay();
768 gfx::Display swapped_secondary
= ScreenUtil::GetSecondaryDisplay();
769 EXPECT_EQ("0,0 300x300", swapped_primary
.bounds().ToString());
770 EXPECT_EQ("0,0 300x253", swapped_primary
.work_area().ToString());
771 EXPECT_EQ("-200,-50 200x200", swapped_secondary
.bounds().ToString());
773 EXPECT_EQ("-200,-50 200x153", swapped_secondary
.work_area().ToString());
775 aura::WindowTracker tracker
;
776 tracker
.Add(primary_root
);
777 tracker
.Add(secondary_root
);
779 // Deleting 2nd display should move the primary to original primary display.
780 UpdateDisplay("200x200");
781 RunAllPendingInMessageLoop(); // RootWindow is deleted in a posted task.
782 EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
783 EXPECT_EQ(primary_display
.id(), Shell::GetScreen()->GetPrimaryDisplay().id());
785 primary_display
.id(),
786 Shell::GetScreen()->GetDisplayNearestPoint(gfx::Point(-100, -100)).id());
787 EXPECT_EQ(primary_display
.id(),
788 Shell::GetScreen()->GetDisplayNearestWindow(NULL
).id());
789 EXPECT_TRUE(tracker
.Contains(primary_root
));
790 EXPECT_FALSE(tracker
.Contains(secondary_root
));
791 EXPECT_TRUE(primary_root
->Contains(shelf_window
));
794 TEST_F(WindowTreeHostManagerTest
, FindNearestDisplay
) {
795 if (!SupportsMultipleDisplays())
798 WindowTreeHostManager
* window_tree_host_manager
=
799 Shell::GetInstance()->window_tree_host_manager();
800 DisplayManager
* display_manager
= Shell::GetInstance()->display_manager();
802 UpdateDisplay("200x200,300x300");
803 DisplayLayout
display_layout(DisplayLayout::RIGHT
, 50);
804 display_manager
->SetLayoutForCurrentDisplays(display_layout
);
806 gfx::Display primary_display
= Shell::GetScreen()->GetPrimaryDisplay();
807 gfx::Display secondary_display
= ScreenUtil::GetSecondaryDisplay();
808 EXPECT_NE(primary_display
.id(), secondary_display
.id());
809 aura::Window
* primary_root
=
810 window_tree_host_manager
->GetRootWindowForDisplayId(primary_display
.id());
811 aura::Window
* secondary_root
=
812 window_tree_host_manager
->GetRootWindowForDisplayId(
813 secondary_display
.id());
814 EXPECT_NE(primary_root
, secondary_root
);
816 // Test that points outside of any display return the nearest display.
818 primary_display
.id(),
819 Shell::GetScreen()->GetDisplayNearestPoint(gfx::Point(-100, 0)).id());
821 primary_display
.id(),
822 Shell::GetScreen()->GetDisplayNearestPoint(gfx::Point(0, -100)).id());
824 primary_display
.id(),
825 Shell::GetScreen()->GetDisplayNearestPoint(gfx::Point(100, 100)).id());
827 primary_display
.id(),
828 Shell::GetScreen()->GetDisplayNearestPoint(gfx::Point(224, 25)).id());
830 secondary_display
.id(),
831 Shell::GetScreen()->GetDisplayNearestPoint(gfx::Point(226, 25)).id());
833 secondary_display
.id(),
834 Shell::GetScreen()->GetDisplayNearestPoint(gfx::Point(600, 100)).id());
836 primary_display
.id(),
837 Shell::GetScreen()->GetDisplayNearestPoint(gfx::Point(174, 225)).id());
839 secondary_display
.id(),
840 Shell::GetScreen()->GetDisplayNearestPoint(gfx::Point(176, 225)).id());
842 secondary_display
.id(),
843 Shell::GetScreen()->GetDisplayNearestPoint(gfx::Point(300, 400)).id());
846 TEST_F(WindowTreeHostManagerTest
, SwapPrimaryById
) {
847 if (!SupportsMultipleDisplays())
850 WindowTreeHostManager
* window_tree_host_manager
=
851 Shell::GetInstance()->window_tree_host_manager();
852 DisplayManager
* display_manager
= Shell::GetInstance()->display_manager();
854 UpdateDisplay("200x200,300x300");
855 gfx::Display primary_display
= Shell::GetScreen()->GetPrimaryDisplay();
856 gfx::Display secondary_display
= ScreenUtil::GetSecondaryDisplay();
858 DisplayLayout
display_layout(DisplayLayout::RIGHT
, 50);
859 display_manager
->SetLayoutForCurrentDisplays(display_layout
);
861 EXPECT_NE(primary_display
.id(), secondary_display
.id());
862 aura::Window
* primary_root
=
863 window_tree_host_manager
->GetRootWindowForDisplayId(primary_display
.id());
864 aura::Window
* secondary_root
=
865 window_tree_host_manager
->GetRootWindowForDisplayId(
866 secondary_display
.id());
867 aura::Window
* shelf_window
=
868 Shelf::ForPrimaryDisplay()->shelf_widget()->GetNativeView();
869 EXPECT_TRUE(primary_root
->Contains(shelf_window
));
870 EXPECT_FALSE(secondary_root
->Contains(shelf_window
));
871 EXPECT_NE(primary_root
, secondary_root
);
873 primary_display
.id(),
874 Shell::GetScreen()->GetDisplayNearestPoint(gfx::Point(-100, -100)).id());
875 EXPECT_EQ(primary_display
.id(),
876 Shell::GetScreen()->GetDisplayNearestWindow(NULL
).id());
878 // Switch primary and secondary by display ID.
879 TestObserver observer
;
880 window_tree_host_manager
->SetPrimaryDisplayId(secondary_display
.id());
881 EXPECT_EQ(secondary_display
.id(),
882 Shell::GetScreen()->GetPrimaryDisplay().id());
883 EXPECT_EQ(primary_display
.id(), ScreenUtil::GetSecondaryDisplay().id());
884 EXPECT_LT(0, observer
.CountAndReset());
886 EXPECT_EQ(primary_root
, window_tree_host_manager
->GetRootWindowForDisplayId(
887 secondary_display
.id()));
888 EXPECT_EQ(secondary_root
, window_tree_host_manager
->GetRootWindowForDisplayId(
889 primary_display
.id()));
890 EXPECT_TRUE(primary_root
->Contains(shelf_window
));
891 EXPECT_FALSE(secondary_root
->Contains(shelf_window
));
893 const DisplayLayout
& inverted_layout
=
894 display_manager
->GetCurrentDisplayLayout();
896 EXPECT_EQ("left, -50", inverted_layout
.ToString());
898 // Calling the same ID don't do anything.
899 window_tree_host_manager
->SetPrimaryDisplayId(secondary_display
.id());
900 EXPECT_EQ(0, observer
.CountAndReset());
902 aura::WindowTracker tracker
;
903 tracker
.Add(primary_root
);
904 tracker
.Add(secondary_root
);
906 // Deleting 2nd display should move the primary to original primary display.
907 UpdateDisplay("200x200");
908 RunAllPendingInMessageLoop(); // RootWindow is deleted in a posted task.
909 EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
910 EXPECT_EQ(primary_display
.id(), Shell::GetScreen()->GetPrimaryDisplay().id());
912 primary_display
.id(),
913 Shell::GetScreen()->GetDisplayNearestPoint(gfx::Point(-100, -100)).id());
914 EXPECT_EQ(primary_display
.id(),
915 Shell::GetScreen()->GetDisplayNearestWindow(NULL
).id());
916 EXPECT_TRUE(tracker
.Contains(primary_root
));
917 EXPECT_FALSE(tracker
.Contains(secondary_root
));
918 EXPECT_TRUE(primary_root
->Contains(shelf_window
));
920 // Adding 2nd display with the same ID. The 2nd display should become primary
921 // since secondary id is still stored as desirable_primary_id.
922 std::vector
<DisplayInfo
> display_info_list
;
923 display_info_list
.push_back(
924 display_manager
->GetDisplayInfo(primary_display
.id()));
925 display_info_list
.push_back(
926 display_manager
->GetDisplayInfo(secondary_display
.id()));
927 display_manager
->OnNativeDisplaysChanged(display_info_list
);
929 EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
930 EXPECT_EQ(secondary_display
.id(),
931 Shell::GetScreen()->GetPrimaryDisplay().id());
932 EXPECT_EQ(primary_display
.id(), ScreenUtil::GetSecondaryDisplay().id());
933 EXPECT_EQ(primary_root
, window_tree_host_manager
->GetRootWindowForDisplayId(
934 secondary_display
.id()));
935 EXPECT_NE(primary_root
, window_tree_host_manager
->GetRootWindowForDisplayId(
936 primary_display
.id()));
937 EXPECT_TRUE(primary_root
->Contains(shelf_window
));
939 // Deleting 2nd display and adding 2nd display with a different ID. The 2nd
940 // display shouldn't become primary.
941 UpdateDisplay("200x200");
942 DisplayInfo
third_display_info(secondary_display
.id() + 1, std::string(),
944 third_display_info
.SetBounds(secondary_display
.bounds());
945 ASSERT_NE(primary_display
.id(), third_display_info
.id());
947 const DisplayInfo
& primary_display_info
=
948 display_manager
->GetDisplayInfo(primary_display
.id());
949 std::vector
<DisplayInfo
> display_info_list2
;
950 display_info_list2
.push_back(primary_display_info
);
951 display_info_list2
.push_back(third_display_info
);
952 display_manager
->OnNativeDisplaysChanged(display_info_list2
);
953 EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
954 EXPECT_EQ(primary_display
.id(), Shell::GetScreen()->GetPrimaryDisplay().id());
955 EXPECT_EQ(third_display_info
.id(), ScreenUtil::GetSecondaryDisplay().id());
956 EXPECT_EQ(primary_root
, window_tree_host_manager
->GetRootWindowForDisplayId(
957 primary_display
.id()));
958 EXPECT_NE(primary_root
, window_tree_host_manager
->GetRootWindowForDisplayId(
959 third_display_info
.id()));
960 EXPECT_TRUE(primary_root
->Contains(shelf_window
));
963 TEST_F(WindowTreeHostManagerTest
, OverscanInsets
) {
964 if (!SupportsMultipleDisplays())
967 WindowTreeHostManager
* window_tree_host_manager
=
968 Shell::GetInstance()->window_tree_host_manager();
969 TestEventHandler event_handler
;
970 Shell::GetInstance()->AddPreTargetHandler(&event_handler
);
972 UpdateDisplay("120x200,300x400*2");
973 gfx::Display display1
= Shell::GetScreen()->GetPrimaryDisplay();
974 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
976 window_tree_host_manager
->SetOverscanInsets(display1
.id(),
977 gfx::Insets(10, 15, 20, 25));
978 EXPECT_EQ("0,0 80x170", root_windows
[0]->bounds().ToString());
979 EXPECT_EQ("150x200", root_windows
[1]->bounds().size().ToString());
980 EXPECT_EQ("80,0 150x200",
981 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
983 ui::test::EventGenerator
generator(root_windows
[0]);
984 generator
.MoveMouseToInHost(20, 25);
985 EXPECT_EQ("5,15", event_handler
.GetLocationAndReset());
987 window_tree_host_manager
->SetOverscanInsets(display1
.id(), gfx::Insets());
988 EXPECT_EQ("0,0 120x200", root_windows
[0]->bounds().ToString());
989 EXPECT_EQ("120,0 150x200",
990 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
992 generator
.MoveMouseToInHost(30, 20);
993 EXPECT_EQ("30,20", event_handler
.GetLocationAndReset());
995 // Make sure the root window transformer uses correct scale
996 // factor when swapping display. Test crbug.com/253690.
997 UpdateDisplay("400x300*2,600x400/o");
998 root_windows
= Shell::GetAllRootWindows();
1000 Shell::GetAllRootWindows()[1]->GetHost()->GetRootTransform().TransformPoint(
1002 EXPECT_EQ("15,10", point
.ToString());
1004 window_tree_host_manager
->SwapPrimaryDisplay();
1005 point
.SetPoint(0, 0);
1006 Shell::GetAllRootWindows()[1]->GetHost()->GetRootTransform().TransformPoint(
1008 EXPECT_EQ("15,10", point
.ToString());
1010 Shell::GetInstance()->RemovePreTargetHandler(&event_handler
);
1013 TEST_F(WindowTreeHostManagerTest
, Rotate
) {
1014 if (!SupportsMultipleDisplays())
1017 DisplayManager
* display_manager
= Shell::GetInstance()->display_manager();
1018 TestEventHandler event_handler
;
1019 Shell::GetInstance()->AddPreTargetHandler(&event_handler
);
1021 UpdateDisplay("120x200,300x400*2");
1022 gfx::Display display1
= Shell::GetScreen()->GetPrimaryDisplay();
1023 int64 display2_id
= ScreenUtil::GetSecondaryDisplay().id();
1024 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
1025 ui::test::EventGenerator
generator1(root_windows
[0]);
1027 TestObserver observer
;
1028 EXPECT_EQ("120x200", root_windows
[0]->bounds().size().ToString());
1029 EXPECT_EQ("150x200", root_windows
[1]->bounds().size().ToString());
1030 EXPECT_EQ("120,0 150x200",
1031 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1032 generator1
.MoveMouseToInHost(50, 40);
1033 EXPECT_EQ("50,40", event_handler
.GetLocationAndReset());
1034 EXPECT_EQ(gfx::Display::ROTATE_0
, GetActiveDisplayRotation(display1
.id()));
1035 EXPECT_EQ(gfx::Display::ROTATE_0
, GetActiveDisplayRotation(display2_id
));
1036 EXPECT_EQ(0, observer
.GetRotationChangedCountAndReset());
1038 display_manager
->SetDisplayRotation(display1
.id(), gfx::Display::ROTATE_90
,
1039 gfx::Display::ROTATION_SOURCE_ACTIVE
);
1040 EXPECT_EQ("200x120", root_windows
[0]->bounds().size().ToString());
1041 EXPECT_EQ("150x200", root_windows
[1]->bounds().size().ToString());
1042 EXPECT_EQ("200,0 150x200",
1043 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1044 generator1
.MoveMouseToInHost(50, 40);
1045 EXPECT_EQ("40,69", event_handler
.GetLocationAndReset());
1046 EXPECT_EQ(gfx::Display::ROTATE_90
, GetActiveDisplayRotation(display1
.id()));
1047 EXPECT_EQ(gfx::Display::ROTATE_0
, GetActiveDisplayRotation(display2_id
));
1048 EXPECT_EQ(1, observer
.GetRotationChangedCountAndReset());
1050 DisplayLayout
display_layout(DisplayLayout::BOTTOM
, 50);
1051 display_manager
->SetLayoutForCurrentDisplays(display_layout
);
1052 EXPECT_EQ("50,120 150x200",
1053 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1055 display_manager
->SetDisplayRotation(display2_id
, gfx::Display::ROTATE_270
,
1056 gfx::Display::ROTATION_SOURCE_ACTIVE
);
1057 EXPECT_EQ("200x120", root_windows
[0]->bounds().size().ToString());
1058 EXPECT_EQ("200x150", root_windows
[1]->bounds().size().ToString());
1059 EXPECT_EQ("50,120 200x150",
1060 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1061 EXPECT_EQ(gfx::Display::ROTATE_90
, GetActiveDisplayRotation(display1
.id()));
1062 EXPECT_EQ(gfx::Display::ROTATE_270
, GetActiveDisplayRotation(display2_id
));
1063 EXPECT_EQ(1, observer
.GetRotationChangedCountAndReset());
1065 #if !defined(OS_WIN)
1066 ui::test::EventGenerator
generator2(root_windows
[1]);
1067 generator2
.MoveMouseToInHost(50, 40);
1068 EXPECT_EQ("179,25", event_handler
.GetLocationAndReset());
1069 display_manager
->SetDisplayRotation(display1
.id(), gfx::Display::ROTATE_180
,
1070 gfx::Display::ROTATION_SOURCE_ACTIVE
);
1072 EXPECT_EQ("120x200", root_windows
[0]->bounds().size().ToString());
1073 EXPECT_EQ("200x150", root_windows
[1]->bounds().size().ToString());
1074 // Dislay must share at least 100, so the x's offset becomes 20.
1075 EXPECT_EQ("20,200 200x150",
1076 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1077 EXPECT_EQ(gfx::Display::ROTATE_180
, GetActiveDisplayRotation(display1
.id()));
1078 EXPECT_EQ(gfx::Display::ROTATE_270
, GetActiveDisplayRotation(display2_id
));
1079 EXPECT_EQ(1, observer
.GetRotationChangedCountAndReset());
1081 generator1
.MoveMouseToInHost(50, 40);
1082 EXPECT_EQ("69,159", event_handler
.GetLocationAndReset());
1085 Shell::GetInstance()->RemovePreTargetHandler(&event_handler
);
1088 TEST_F(WindowTreeHostManagerTest
, ScaleRootWindow
) {
1089 if (!SupportsMultipleDisplays())
1092 TestEventHandler event_handler
;
1093 Shell::GetInstance()->AddPreTargetHandler(&event_handler
);
1095 UpdateDisplay("600x400*2@1.5,500x300");
1097 gfx::Display display1
= Shell::GetScreen()->GetPrimaryDisplay();
1098 test::ScopedSetInternalDisplayId
set_internal(display1
.id());
1100 gfx::Display display2
= ScreenUtil::GetSecondaryDisplay();
1101 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
1102 EXPECT_EQ("0,0 450x300", display1
.bounds().ToString());
1103 EXPECT_EQ("0,0 450x300", root_windows
[0]->bounds().ToString());
1104 EXPECT_EQ("450,0 500x300", display2
.bounds().ToString());
1105 EXPECT_EQ(1.5f
, GetStoredUIScale(display1
.id()));
1106 EXPECT_EQ(1.0f
, GetStoredUIScale(display2
.id()));
1108 ui::test::EventGenerator
generator(root_windows
[0]);
1109 generator
.MoveMouseToInHost(599, 200);
1110 EXPECT_EQ("449,150", event_handler
.GetLocationAndReset());
1112 SetDisplayUIScale(display1
.id(), 1.25f
);
1113 display1
= Shell::GetScreen()->GetPrimaryDisplay();
1114 display2
= ScreenUtil::GetSecondaryDisplay();
1115 EXPECT_EQ("0,0 375x250", display1
.bounds().ToString());
1116 EXPECT_EQ("0,0 375x250", root_windows
[0]->bounds().ToString());
1117 EXPECT_EQ("375,0 500x300", display2
.bounds().ToString());
1118 EXPECT_EQ(1.25f
, GetStoredUIScale(display1
.id()));
1119 EXPECT_EQ(1.0f
, GetStoredUIScale(display2
.id()));
1121 Shell::GetInstance()->RemovePreTargetHandler(&event_handler
);
1124 TEST_F(WindowTreeHostManagerTest
, TouchScale
) {
1125 if (!SupportsMultipleDisplays())
1128 TestEventHandler event_handler
;
1129 Shell::GetInstance()->AddPreTargetHandler(&event_handler
);
1131 UpdateDisplay("200x200*2");
1132 gfx::Display display
= Shell::GetScreen()->GetPrimaryDisplay();
1133 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
1134 aura::Window
* root_window
= root_windows
[0];
1135 ui::test::EventGenerator
generator(root_window
);
1137 generator
.PressMoveAndReleaseTouchTo(50, 50);
1138 // Default test touches have radius_x/y = 1.0, with device scale
1139 // factor = 2, the scaled radius_x/y should be 0.5.
1140 EXPECT_EQ(0.5, event_handler
.touch_radius_x());
1141 EXPECT_EQ(0.5, event_handler
.touch_radius_y());
1143 generator
.ScrollSequence(gfx::Point(0, 0),
1144 base::TimeDelta::FromMilliseconds(100), 10.0, 1.0, 5,
1147 // ordinal_offset is invariant to the device scale factor.
1148 EXPECT_EQ(event_handler
.scroll_x_offset(),
1149 event_handler
.scroll_x_offset_ordinal());
1150 EXPECT_EQ(event_handler
.scroll_y_offset(),
1151 event_handler
.scroll_y_offset_ordinal());
1153 Shell::GetInstance()->RemovePreTargetHandler(&event_handler
);
1156 TEST_F(WindowTreeHostManagerTest
, ConvertHostToRootCoords
) {
1157 if (!SupportsMultipleDisplays())
1160 TestEventHandler event_handler
;
1161 Shell::GetInstance()->AddPreTargetHandler(&event_handler
);
1163 UpdateDisplay("600x400*2/r@1.5");
1165 gfx::Display display1
= Shell::GetScreen()->GetPrimaryDisplay();
1166 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
1167 EXPECT_EQ("0,0 300x450", display1
.bounds().ToString());
1168 EXPECT_EQ("0,0 300x450", root_windows
[0]->bounds().ToString());
1169 EXPECT_EQ(1.5f
, GetStoredUIScale(display1
.id()));
1171 ui::test::EventGenerator
generator(root_windows
[0]);
1172 generator
.MoveMouseToInHost(0, 0);
1173 EXPECT_EQ("0,449", event_handler
.GetLocationAndReset());
1174 generator
.MoveMouseToInHost(599, 0);
1175 EXPECT_EQ("0,0", event_handler
.GetLocationAndReset());
1176 generator
.MoveMouseToInHost(599, 399);
1177 EXPECT_EQ("299,0", event_handler
.GetLocationAndReset());
1178 generator
.MoveMouseToInHost(0, 399);
1179 EXPECT_EQ("299,449", event_handler
.GetLocationAndReset());
1181 UpdateDisplay("600x400*2/u@1.5");
1182 display1
= Shell::GetScreen()->GetPrimaryDisplay();
1183 root_windows
= Shell::GetAllRootWindows();
1184 EXPECT_EQ("0,0 450x300", display1
.bounds().ToString());
1185 EXPECT_EQ("0,0 450x300", root_windows
[0]->bounds().ToString());
1186 EXPECT_EQ(1.5f
, GetStoredUIScale(display1
.id()));
1188 generator
.MoveMouseToInHost(0, 0);
1189 EXPECT_EQ("449,299", event_handler
.GetLocationAndReset());
1190 generator
.MoveMouseToInHost(599, 0);
1191 EXPECT_EQ("0,299", event_handler
.GetLocationAndReset());
1192 generator
.MoveMouseToInHost(599, 399);
1193 EXPECT_EQ("0,0", event_handler
.GetLocationAndReset());
1194 generator
.MoveMouseToInHost(0, 399);
1195 EXPECT_EQ("449,0", event_handler
.GetLocationAndReset());
1197 UpdateDisplay("600x400*2/l@1.5");
1198 display1
= Shell::GetScreen()->GetPrimaryDisplay();
1199 root_windows
= Shell::GetAllRootWindows();
1200 EXPECT_EQ("0,0 300x450", display1
.bounds().ToString());
1201 EXPECT_EQ("0,0 300x450", root_windows
[0]->bounds().ToString());
1202 EXPECT_EQ(1.5f
, GetStoredUIScale(display1
.id()));
1204 generator
.MoveMouseToInHost(0, 0);
1205 EXPECT_EQ("299,0", event_handler
.GetLocationAndReset());
1206 generator
.MoveMouseToInHost(599, 0);
1207 EXPECT_EQ("299,449", event_handler
.GetLocationAndReset());
1208 generator
.MoveMouseToInHost(599, 399);
1209 EXPECT_EQ("0,449", event_handler
.GetLocationAndReset());
1210 generator
.MoveMouseToInHost(0, 399);
1211 EXPECT_EQ("0,0", event_handler
.GetLocationAndReset());
1213 Shell::GetInstance()->RemovePreTargetHandler(&event_handler
);
1216 // Make sure that the compositor based mirroring can switch
1217 // from/to dock mode.
1218 TEST_F(WindowTreeHostManagerTest
, DockToSingle
) {
1219 if (!SupportsMultipleDisplays())
1222 DisplayManager
* display_manager
= Shell::GetInstance()->display_manager();
1224 const int64 internal_id
= 1;
1226 const DisplayInfo internal_display_info
=
1227 CreateDisplayInfo(internal_id
, 0, gfx::Display::ROTATE_0
);
1228 const DisplayInfo external_display_info
=
1229 CreateDisplayInfo(2, 1, gfx::Display::ROTATE_90
);
1231 std::vector
<DisplayInfo
> display_info_list
;
1233 display_info_list
.push_back(internal_display_info
);
1234 display_info_list
.push_back(external_display_info
);
1235 display_manager
->OnNativeDisplaysChanged(display_info_list
);
1236 const int64 internal_display_id
=
1237 test::DisplayManagerTestApi().SetFirstDisplayAsInternalDisplay();
1238 EXPECT_EQ(internal_id
, internal_display_id
);
1239 EXPECT_EQ(2U, display_manager
->GetNumDisplays());
1242 display_info_list
.clear();
1243 display_info_list
.push_back(external_display_info
);
1244 display_manager
->OnNativeDisplaysChanged(display_info_list
);
1245 EXPECT_EQ(1U, display_manager
->GetNumDisplays());
1246 EXPECT_FALSE(Shell::GetPrimaryRootWindow()
1248 ->GetRootTransform()
1249 .IsIdentityOrIntegerTranslation());
1251 // Switch to single mode and make sure the transform is the one
1252 // for the internal display.
1253 display_info_list
.clear();
1254 display_info_list
.push_back(internal_display_info
);
1255 display_manager
->OnNativeDisplaysChanged(display_info_list
);
1256 EXPECT_TRUE(Shell::GetPrimaryRootWindow()
1258 ->GetRootTransform()
1259 .IsIdentityOrIntegerTranslation());
1262 // Tests if switching two displays at the same time while the primary display
1263 // is swapped should not cause a crash. (crbug.com/426292)
1264 TEST_F(WindowTreeHostManagerTest
, ReplaceSwappedPrimary
) {
1265 if (!SupportsMultipleDisplays())
1267 DisplayManager
* display_manager
= Shell::GetInstance()->display_manager();
1269 const DisplayInfo first_display_info
=
1270 CreateDisplayInfo(10, 0, gfx::Display::ROTATE_0
);
1271 const DisplayInfo second_display_info
=
1272 CreateDisplayInfo(11, 1, gfx::Display::ROTATE_0
);
1274 std::vector
<DisplayInfo
> display_info_list
;
1276 display_info_list
.push_back(first_display_info
);
1277 display_info_list
.push_back(second_display_info
);
1278 display_manager
->OnNativeDisplaysChanged(display_info_list
);
1280 Shell::GetInstance()->window_tree_host_manager()->SwapPrimaryDisplay();
1282 EXPECT_EQ(11, Shell::GetScreen()->GetPrimaryDisplay().id());
1284 display_info_list
.clear();
1285 const DisplayInfo new_first_display_info
=
1286 CreateDisplayInfo(20, 0, gfx::Display::ROTATE_0
);
1287 const DisplayInfo new_second_display_info
=
1288 CreateDisplayInfo(21, 1, gfx::Display::ROTATE_0
);
1289 display_info_list
.push_back(new_first_display_info
);
1290 display_info_list
.push_back(new_second_display_info
);
1291 display_manager
->OnNativeDisplaysChanged(display_info_list
);
1293 EXPECT_EQ(20, Shell::GetScreen()->GetPrimaryDisplay().id());
1296 TEST_F(WindowTreeHostManagerTest
, UpdateMouseLocationAfterDisplayChange
) {
1297 if (!SupportsMultipleDisplays())
1300 UpdateDisplay("200x200,300x300");
1301 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
1303 aura::Env
* env
= aura::Env::GetInstance();
1305 ui::test::EventGenerator
generator(root_windows
[0]);
1307 // Set the initial position.
1308 generator
.MoveMouseToInHost(350, 150);
1309 EXPECT_EQ("350,150", env
->last_mouse_location().ToString());
1311 // A mouse pointer will stay in the 2nd display.
1312 UpdateDisplay("300x300,200x200");
1313 EXPECT_EQ("450,50", env
->last_mouse_location().ToString());
1315 // A mouse pointer will be outside of displays and move to the
1316 // center of 2nd display.
1317 UpdateDisplay("300x300,100x100");
1318 EXPECT_EQ("350,50", env
->last_mouse_location().ToString());
1320 // 2nd display was disconnected, and the cursor is
1321 // now in the 1st display.
1322 UpdateDisplay("400x400");
1323 EXPECT_EQ("50,350", env
->last_mouse_location().ToString());
1325 // 1st display's resolution has changed, and the mouse pointer is
1326 // now outside. Move the mouse pointer to the center of 1st display.
1327 UpdateDisplay("300x300");
1328 EXPECT_EQ("150,150", env
->last_mouse_location().ToString());
1330 // Move the mouse pointer to the bottom of 1st display.
1331 generator
.MoveMouseToInHost(150, 290);
1332 EXPECT_EQ("150,290", env
->last_mouse_location().ToString());
1334 // The mouse pointer is now on 2nd display.
1335 UpdateDisplay("300x280,200x200");
1336 EXPECT_EQ("450,10", env
->last_mouse_location().ToString());
1339 TEST_F(WindowTreeHostManagerTest
,
1340 UpdateMouseLocationAfterDisplayChange_2ndOnLeft
) {
1341 if (!SupportsMultipleDisplays())
1344 // Set the 2nd display on the left.
1345 DisplayLayoutStore
* layout_store
=
1346 Shell::GetInstance()->display_manager()->layout_store();
1347 DisplayLayout layout
= layout_store
->default_display_layout();
1348 layout
.position
= DisplayLayout::LEFT
;
1349 layout_store
->SetDefaultDisplayLayout(layout
);
1351 UpdateDisplay("200x200,300x300");
1352 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
1354 EXPECT_EQ("-300,0 300x300",
1355 ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1357 aura::Env
* env
= aura::Env::GetInstance();
1359 // Set the initial position.
1360 root_windows
[0]->MoveCursorTo(gfx::Point(-150, 250));
1361 EXPECT_EQ("-150,250", env
->last_mouse_location().ToString());
1363 // A mouse pointer will stay in 2nd display.
1364 UpdateDisplay("300x300,200x300");
1365 EXPECT_EQ("-50,150", env
->last_mouse_location().ToString());
1367 // A mouse pointer will be outside of displays and move to the
1368 // center of 2nd display.
1369 UpdateDisplay("300x300,200x100");
1370 EXPECT_EQ("-100,50", env
->last_mouse_location().ToString());
1372 // 2nd display was disconnected. Mouse pointer should move to
1374 UpdateDisplay("300x300");
1375 EXPECT_EQ("150,150", env
->last_mouse_location().ToString());
1378 // Test that the cursor swaps displays and that its scale factor and rotation
1379 // are updated when the primary display is swapped.
1380 TEST_F(WindowTreeHostManagerTest
,
1381 UpdateMouseLocationAfterDisplayChange_SwapPrimary
) {
1382 if (!SupportsMultipleDisplays())
1385 UpdateDisplay("200x200,200x200*2/r");
1387 aura::Env
* env
= aura::Env::GetInstance();
1388 Shell
* shell
= Shell::GetInstance();
1389 WindowTreeHostManager
* window_tree_host_manager
=
1390 shell
->window_tree_host_manager();
1391 test::CursorManagerTestApi
test_api(shell
->cursor_manager());
1393 window_tree_host_manager
->GetPrimaryRootWindow()->MoveCursorTo(
1394 gfx::Point(20, 50));
1396 EXPECT_EQ("20,50", env
->last_mouse_location().ToString());
1397 EXPECT_EQ(1.0f
, test_api
.GetCurrentCursor().device_scale_factor());
1398 EXPECT_EQ(gfx::Display::ROTATE_0
, test_api
.GetCurrentCursorRotation());
1400 window_tree_host_manager
->SwapPrimaryDisplay();
1402 EXPECT_EQ("20,50", env
->last_mouse_location().ToString());
1403 EXPECT_EQ(2.0f
, test_api
.GetCurrentCursor().device_scale_factor());
1404 EXPECT_EQ(gfx::Display::ROTATE_90
, test_api
.GetCurrentCursorRotation());
1407 // Test that the cursor moves to the other display and that its scale factor
1408 // and rotation are updated when the primary display is disconnected.
1409 TEST_F(WindowTreeHostManagerTest
,
1410 UpdateMouseLocationAfterDisplayChange_PrimaryDisconnected
) {
1411 if (!SupportsMultipleDisplays())
1414 aura::Env
* env
= aura::Env::GetInstance();
1415 Shell
* shell
= Shell::GetInstance();
1416 WindowTreeHostManager
* window_tree_host_manager
=
1417 shell
->window_tree_host_manager();
1418 test::CursorManagerTestApi
test_api(shell
->cursor_manager());
1420 UpdateDisplay("300x300*2/r,200x200");
1421 // Swap the primary display to make it possible to remove the primary display
1422 // via UpdateDisplay().
1423 window_tree_host_manager
->SwapPrimaryDisplay();
1424 int primary_display_id
= window_tree_host_manager
->GetPrimaryDisplayId();
1426 window_tree_host_manager
->GetPrimaryRootWindow()->MoveCursorTo(
1427 gfx::Point(20, 50));
1429 EXPECT_EQ("20,50", env
->last_mouse_location().ToString());
1430 EXPECT_EQ(1.0f
, test_api
.GetCurrentCursor().device_scale_factor());
1431 EXPECT_EQ(gfx::Display::ROTATE_0
, test_api
.GetCurrentCursorRotation());
1433 UpdateDisplay("300x300*2/r");
1434 ASSERT_NE(primary_display_id
,
1435 window_tree_host_manager
->GetPrimaryDisplayId());
1437 // Cursor should be centered on the remaining display.
1438 EXPECT_EQ("75,75", env
->last_mouse_location().ToString());
1439 EXPECT_EQ(2.0f
, test_api
.GetCurrentCursor().device_scale_factor());
1440 EXPECT_EQ(gfx::Display::ROTATE_90
, test_api
.GetCurrentCursorRotation());
1443 // GetRootWindowForDisplayId() for removed gfx::Display during
1444 // OnDisplayRemoved() should not cause crash. See http://crbug.com/415222
1445 TEST_F(WindowTreeHostManagerTest
,
1446 GetRootWindowForDisplayIdDuringDisplayDisconnection
) {
1447 if (!SupportsMultipleDisplays())
1450 UpdateDisplay("300x300,200x200");
1451 aura::Window
* root2
=
1452 Shell::GetInstance()
1453 ->window_tree_host_manager()
1454 ->GetRootWindowForDisplayId(ScreenUtil::GetSecondaryDisplay().id());
1455 views::Widget
* widget
= views::Widget::CreateWindowWithContextAndBounds(
1456 nullptr, root2
, gfx::Rect(350, 0, 100, 100));
1457 views::View
* view
= new views::View();
1458 widget
->GetContentsView()->AddChildView(view
);
1459 view
->SetBounds(0, 0, 100, 100);
1462 TestMouseWatcherListener listener
;
1463 views::MouseWatcher
watcher(
1464 new views::MouseWatcherViewHost(view
, gfx::Insets()), &listener
);
1467 ui::test::EventGenerator
event_generator(
1468 widget
->GetNativeWindow()->GetRootWindow());
1469 event_generator
.MoveMouseToCenterOf(widget
->GetNativeWindow());
1471 UpdateDisplay("300x300");