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.
4
5#include "ash/display/display_manager.h"
6
7#include "ash/display/display_controller.h"
8#include "ash/display/display_layout_store.h"
9#include "ash/screen_ash.h"
10#include "ash/shell.h"
11#include "ash/test/ash_test_base.h"
12#include "ash/test/display_manager_test_api.h"
13#include "ash/test/mirror_window_test_api.h"
14#include "base/format_macros.h"
15#include "base/strings/string_number_conversions.h"
16#include "base/strings/stringprintf.h"
17#include "ui/aura/env.h"
18#include "ui/aura/root_window.h"
19#include "ui/aura/test/event_generator.h"
20#include "ui/aura/window_observer.h"
21#include "ui/gfx/display_observer.h"
22#include "ui/gfx/display.h"
23
24namespace ash {
25namespace internal {
26
27using std::vector;
28using std::string;
29
30using base::StringPrintf;
31
32namespace {
33
34std::string ToDisplayName(int64 id) {
35  return "x-" + base::Int64ToString(id);
36}
37
38}  // namespace
39
40class DisplayManagerTest : public test::AshTestBase,
41                           public gfx::DisplayObserver,
42                           public aura::WindowObserver {
43 public:
44  DisplayManagerTest()
45      : removed_count_(0U),
46        root_window_destroyed_(false) {
47  }
48  virtual ~DisplayManagerTest() {}
49
50  virtual void SetUp() OVERRIDE {
51    AshTestBase::SetUp();
52    Shell::GetScreen()->AddObserver(this);
53    Shell::GetPrimaryRootWindow()->AddObserver(this);
54  }
55  virtual void TearDown() OVERRIDE {
56    Shell::GetPrimaryRootWindow()->RemoveObserver(this);
57    Shell::GetScreen()->RemoveObserver(this);
58    AshTestBase::TearDown();
59  }
60
61  DisplayManager* display_manager() {
62    return Shell::GetInstance()->display_manager();
63  }
64  const vector<gfx::Display>& changed() const { return changed_; }
65  const vector<gfx::Display>& added() const { return added_; }
66
67  string GetCountSummary() const {
68    return StringPrintf("%" PRIuS " %" PRIuS " %" PRIuS,
69                        changed_.size(), added_.size(), removed_count_);
70  }
71
72  void reset() {
73    changed_.clear();
74    added_.clear();
75    removed_count_ = 0U;
76    root_window_destroyed_ = false;
77  }
78
79  bool root_window_destroyed() const {
80    return root_window_destroyed_;
81  }
82
83  const DisplayInfo& GetDisplayInfo(const gfx::Display& display) {
84    return display_manager()->GetDisplayInfo(display.id());
85  }
86
87  const DisplayInfo& GetDisplayInfoAt(int index) {
88    return GetDisplayInfo(display_manager()->GetDisplayAt(index));
89  }
90
91  const gfx::Display& GetDisplayForId(int64 id) {
92    return display_manager()->GetDisplayForId(id);
93  }
94
95  const DisplayInfo& GetDisplayInfoForId(int64 id) {
96    return GetDisplayInfo(display_manager()->GetDisplayForId(id));
97  }
98
99  const gfx::Display GetMirroredDisplay() {
100    return Shell::GetInstance()->display_manager()->mirrored_display();
101  }
102
103  // aura::DisplayObserver overrides:
104  virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE {
105    changed_.push_back(display);
106  }
107  virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE {
108    added_.push_back(new_display);
109  }
110  virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE {
111    ++removed_count_;
112  }
113
114  // aura::WindowObserver overrides:
115  virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
116    ASSERT_EQ(Shell::GetPrimaryRootWindow(), window);
117    root_window_destroyed_ = true;
118  }
119
120 private:
121  vector<gfx::Display> changed_;
122  vector<gfx::Display> added_;
123  size_t removed_count_;
124  bool root_window_destroyed_;
125
126  DISALLOW_COPY_AND_ASSIGN(DisplayManagerTest);
127};
128
129TEST_F(DisplayManagerTest, UpdateDisplayTest) {
130  if (!SupportsMultipleDisplays())
131    return;
132
133  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
134
135  // Update primary and add seconary.
136  UpdateDisplay("100+0-500x500,0+501-400x400");
137  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
138  EXPECT_EQ("0,0 500x500",
139            display_manager()->GetDisplayAt(0).bounds().ToString());
140
141  EXPECT_EQ("1 1 0", GetCountSummary());
142  EXPECT_EQ(display_manager()->GetDisplayAt(0).id(), changed()[0].id());
143  EXPECT_EQ(display_manager()->GetDisplayAt(1).id(), added()[0].id());
144  EXPECT_EQ("0,0 500x500", changed()[0].bounds().ToString());
145  // Secondary display is on right.
146  EXPECT_EQ("500,0 400x400", added()[0].bounds().ToString());
147  EXPECT_EQ("0,501 400x400",
148            GetDisplayInfo(added()[0]).bounds_in_pixel().ToString());
149  reset();
150
151  // Delete secondary.
152  UpdateDisplay("100+0-500x500");
153  EXPECT_EQ("0 0 1", GetCountSummary());
154  reset();
155
156  // Change primary.
157  UpdateDisplay("1+1-1000x600");
158  EXPECT_EQ("1 0 0", GetCountSummary());
159  EXPECT_EQ(display_manager()->GetDisplayAt(0).id(), changed()[0].id());
160  EXPECT_EQ("0,0 1000x600", changed()[0].bounds().ToString());
161  reset();
162
163  // Add secondary.
164  UpdateDisplay("1+1-1000x600,1002+0-600x400");
165  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
166  EXPECT_EQ("0 1 0", GetCountSummary());
167  EXPECT_EQ(display_manager()->GetDisplayAt(1).id(), added()[0].id());
168  // Secondary display is on right.
169  EXPECT_EQ("1000,0 600x400", added()[0].bounds().ToString());
170  EXPECT_EQ("1002,0 600x400",
171            GetDisplayInfo(added()[0]).bounds_in_pixel().ToString());
172  reset();
173
174  // Secondary removed, primary changed.
175  UpdateDisplay("1+1-800x300");
176  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
177  EXPECT_EQ("1 0 1", GetCountSummary());
178  EXPECT_EQ(display_manager()->GetDisplayAt(0).id(), changed()[0].id());
179  EXPECT_EQ("0,0 800x300", changed()[0].bounds().ToString());
180  reset();
181
182  // # of display can go to zero when screen is off.
183  const vector<DisplayInfo> empty;
184  display_manager()->OnNativeDisplaysChanged(empty);
185  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
186  EXPECT_EQ("0 0 0", GetCountSummary());
187  EXPECT_FALSE(root_window_destroyed());
188  // Display configuration stays the same
189  EXPECT_EQ("0,0 800x300",
190            display_manager()->GetDisplayAt(0).bounds().ToString());
191  reset();
192
193  // Connect to display again
194  UpdateDisplay("100+100-500x400");
195  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
196  EXPECT_EQ("1 0 0", GetCountSummary());
197  EXPECT_FALSE(root_window_destroyed());
198  EXPECT_EQ("0,0 500x400", changed()[0].bounds().ToString());
199  EXPECT_EQ("100,100 500x400",
200            GetDisplayInfo(changed()[0]).bounds_in_pixel().ToString());
201  reset();
202
203  // Go back to zero and wake up with multiple displays.
204  display_manager()->OnNativeDisplaysChanged(empty);
205  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
206  EXPECT_FALSE(root_window_destroyed());
207  reset();
208
209  // Add secondary.
210  UpdateDisplay("0+0-1000x600,1000+1000-600x400");
211  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
212  EXPECT_EQ("0,0 1000x600",
213            display_manager()->GetDisplayAt(0).bounds().ToString());
214  // Secondary display is on right.
215  EXPECT_EQ("1000,0 600x400",
216            display_manager()->GetDisplayAt(1).bounds().ToString());
217  EXPECT_EQ("1000,1000 600x400",
218            GetDisplayInfoAt(1).bounds_in_pixel().ToString());
219  reset();
220
221  // Changing primary will update secondary as well.
222  UpdateDisplay("0+0-800x600,1000+1000-600x400");
223  EXPECT_EQ("2 0 0", GetCountSummary());
224  reset();
225  EXPECT_EQ("0,0 800x600",
226            display_manager()->GetDisplayAt(0).bounds().ToString());
227  EXPECT_EQ("800,0 600x400",
228            display_manager()->GetDisplayAt(1).bounds().ToString());
229}
230
231// Test in emulation mode (use_fullscreen_host_window=false)
232TEST_F(DisplayManagerTest, EmulatorTest) {
233  if (!SupportsMultipleDisplays())
234    return;
235
236  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
237
238  display_manager()->AddRemoveDisplay();
239  // Update primary and add seconary.
240  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
241  EXPECT_EQ("0 1 0", GetCountSummary());
242  reset();
243
244  display_manager()->AddRemoveDisplay();
245  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
246  EXPECT_EQ("0 0 1", GetCountSummary());
247  reset();
248
249  display_manager()->AddRemoveDisplay();
250  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
251  EXPECT_EQ("0 1 0", GetCountSummary());
252  reset();
253}
254
255TEST_F(DisplayManagerTest, OverscanInsetsTest) {
256  if (!SupportsMultipleDisplays())
257    return;
258
259  UpdateDisplay("0+0-500x500,0+501-400x400");
260  reset();
261  ASSERT_EQ(2u, display_manager()->GetNumDisplays());
262  const DisplayInfo& display_info1 = GetDisplayInfoAt(0);
263  const DisplayInfo& display_info2 = GetDisplayInfoAt(1);
264  display_manager()->SetOverscanInsets(
265      display_info2.id(), gfx::Insets(13, 12, 11, 10));
266
267  std::vector<gfx::Display> changed_displays = changed();
268  EXPECT_EQ(1u, changed_displays.size());
269  EXPECT_EQ(display_info2.id(), changed_displays[0].id());
270  EXPECT_EQ("0,0 500x500",
271            GetDisplayInfoAt(0).bounds_in_pixel().ToString());
272  DisplayInfo updated_display_info2 = GetDisplayInfoAt(1);
273  EXPECT_EQ("0,501 400x400",
274            updated_display_info2.bounds_in_pixel().ToString());
275  EXPECT_EQ("378x376",
276            updated_display_info2.size_in_pixel().ToString());
277  EXPECT_EQ("13,12,11,10",
278            updated_display_info2.overscan_insets_in_dip().ToString());
279  EXPECT_EQ("500,0 378x376",
280            ScreenAsh::GetSecondaryDisplay().bounds().ToString());
281
282  // Make sure that SetOverscanInsets() is idempotent.
283  display_manager()->SetOverscanInsets(display_info1.id(), gfx::Insets());
284  display_manager()->SetOverscanInsets(
285      display_info2.id(), gfx::Insets(13, 12, 11, 10));
286  EXPECT_EQ("0,0 500x500",
287            GetDisplayInfoAt(0).bounds_in_pixel().ToString());
288  updated_display_info2 = GetDisplayInfoAt(1);
289  EXPECT_EQ("0,501 400x400",
290            updated_display_info2.bounds_in_pixel().ToString());
291  EXPECT_EQ("378x376",
292            updated_display_info2.size_in_pixel().ToString());
293  EXPECT_EQ("13,12,11,10",
294            updated_display_info2.overscan_insets_in_dip().ToString());
295
296  display_manager()->SetOverscanInsets(
297      display_info2.id(), gfx::Insets(10, 11, 12, 13));
298  EXPECT_EQ("0,0 500x500",
299            GetDisplayInfoAt(0).bounds_in_pixel().ToString());
300  EXPECT_EQ("376x378",
301            GetDisplayInfoAt(1).size_in_pixel().ToString());
302  EXPECT_EQ("10,11,12,13",
303            GetDisplayInfoAt(1).overscan_insets_in_dip().ToString());
304
305  // Recreate a new 2nd display. It won't apply the overscan inset because the
306  // new display has a different ID.
307  UpdateDisplay("0+0-500x500");
308  UpdateDisplay("0+0-500x500,0+501-400x400");
309  EXPECT_EQ("0,0 500x500",
310            GetDisplayInfoAt(0).bounds_in_pixel().ToString());
311  EXPECT_EQ("0,501 400x400",
312            GetDisplayInfoAt(1).bounds_in_pixel().ToString());
313
314  // Recreate the displays with the same ID.  It should apply the overscan
315  // inset.
316  UpdateDisplay("0+0-500x500");
317  std::vector<DisplayInfo> display_info_list;
318  display_info_list.push_back(display_info1);
319  display_info_list.push_back(display_info2);
320  display_manager()->OnNativeDisplaysChanged(display_info_list);
321  EXPECT_EQ("1,1 500x500",
322            GetDisplayInfoAt(0).bounds_in_pixel().ToString());
323  updated_display_info2 = GetDisplayInfoAt(1);
324  EXPECT_EQ("376x378",
325            updated_display_info2.size_in_pixel().ToString());
326  EXPECT_EQ("10,11,12,13",
327            updated_display_info2.overscan_insets_in_dip().ToString());
328
329  // HiDPI but overscan display. The specified insets size should be doubled.
330  UpdateDisplay("0+0-500x500,0+501-400x400*2");
331  display_manager()->SetOverscanInsets(
332      display_manager()->GetDisplayAt(1).id(), gfx::Insets(4, 5, 6, 7));
333  EXPECT_EQ("0,0 500x500",
334            GetDisplayInfoAt(0).bounds_in_pixel().ToString());
335  updated_display_info2 = GetDisplayInfoAt(1);
336  EXPECT_EQ("0,501 400x400",
337            updated_display_info2.bounds_in_pixel().ToString());
338  EXPECT_EQ("376x380",
339            updated_display_info2.size_in_pixel().ToString());
340  EXPECT_EQ("4,5,6,7",
341            updated_display_info2.overscan_insets_in_dip().ToString());
342  EXPECT_EQ("8,10,12,14",
343            updated_display_info2.GetOverscanInsetsInPixel().ToString());
344
345  // Make sure switching primary display applies the overscan offset only once.
346  ash::Shell::GetInstance()->display_controller()->SetPrimaryDisplay(
347      ScreenAsh::GetSecondaryDisplay());
348  EXPECT_EQ("-500,0 500x500",
349            ScreenAsh::GetSecondaryDisplay().bounds().ToString());
350  EXPECT_EQ("0,0 500x500",
351            GetDisplayInfo(ScreenAsh::GetSecondaryDisplay()).
352            bounds_in_pixel().ToString());
353  EXPECT_EQ("0,501 400x400",
354            GetDisplayInfo(Shell::GetScreen()->GetPrimaryDisplay()).
355            bounds_in_pixel().ToString());
356  EXPECT_EQ("0,0 188x190",
357            Shell::GetScreen()->GetPrimaryDisplay().bounds().ToString());
358}
359
360TEST_F(DisplayManagerTest, ZeroOverscanInsets) {
361  if (!SupportsMultipleDisplays())
362    return;
363
364  // Make sure the display change events is emitted for overscan inset changes.
365  UpdateDisplay("0+0-500x500,0+501-400x400");
366  ASSERT_EQ(2u, display_manager()->GetNumDisplays());
367  int64 display2_id = display_manager()->GetDisplayAt(1).id();
368
369  reset();
370  display_manager()->SetOverscanInsets(display2_id, gfx::Insets(0, 0, 0, 0));
371  EXPECT_EQ(0u, changed().size());
372
373  reset();
374  display_manager()->SetOverscanInsets(display2_id, gfx::Insets(1, 0, 0, 0));
375  EXPECT_EQ(1u, changed().size());
376  EXPECT_EQ(display2_id, changed()[0].id());
377
378  reset();
379  display_manager()->SetOverscanInsets(display2_id, gfx::Insets(0, 0, 0, 0));
380  EXPECT_EQ(1u, changed().size());
381  EXPECT_EQ(display2_id, changed()[0].id());
382}
383
384TEST_F(DisplayManagerTest, TestDeviceScaleOnlyChange) {
385  if (!SupportsHostWindowResize())
386    return;
387
388  UpdateDisplay("1000x600");
389  EXPECT_EQ(1,
390            Shell::GetPrimaryRootWindow()->compositor()->device_scale_factor());
391  EXPECT_EQ("1000x600",
392            Shell::GetPrimaryRootWindow()->bounds().size().ToString());
393  UpdateDisplay("1000x600*2");
394  EXPECT_EQ(2,
395            Shell::GetPrimaryRootWindow()->compositor()->device_scale_factor());
396  EXPECT_EQ("500x300",
397            Shell::GetPrimaryRootWindow()->bounds().size().ToString());
398}
399
400DisplayInfo CreateDisplayInfo(int64 id, const gfx::Rect& bounds) {
401  DisplayInfo info(id, ToDisplayName(id), false);
402  info.SetBounds(bounds);
403  return info;
404}
405
406TEST_F(DisplayManagerTest, TestNativeDisplaysChanged) {
407  const int64 internal_display_id =
408      test::DisplayManagerTestApi(display_manager()).
409      SetFirstDisplayAsInternalDisplay();
410  const int external_id = 10;
411  const int mirror_id = 11;
412  const int64 invalid_id = gfx::Display::kInvalidDisplayID;
413  const DisplayInfo internal_display_info =
414      CreateDisplayInfo(internal_display_id, gfx::Rect(0, 0, 500, 500));
415  const DisplayInfo external_display_info =
416      CreateDisplayInfo(external_id, gfx::Rect(1, 1, 100, 100));
417  const DisplayInfo mirrored_display_info =
418      CreateDisplayInfo(mirror_id, gfx::Rect(0, 0, 500, 500));
419
420  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
421  EXPECT_EQ(1U, display_manager()->num_connected_displays());
422  std::string default_bounds =
423      display_manager()->GetDisplayAt(0).bounds().ToString();
424
425  std::vector<DisplayInfo> display_info_list;
426  // Primary disconnected.
427  display_manager()->OnNativeDisplaysChanged(display_info_list);
428  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
429  EXPECT_EQ(default_bounds,
430            display_manager()->GetDisplayAt(0).bounds().ToString());
431  EXPECT_EQ(1U, display_manager()->num_connected_displays());
432  EXPECT_FALSE(display_manager()->mirrored_display().is_valid());
433
434  if (!SupportsMultipleDisplays())
435    return;
436
437  // External connected while primary was disconnected.
438  display_info_list.push_back(external_display_info);
439  display_manager()->OnNativeDisplaysChanged(display_info_list);
440  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
441
442  EXPECT_EQ(invalid_id, GetDisplayForId(internal_display_id).id());
443  EXPECT_EQ("1,1 100x100",
444            GetDisplayInfoForId(external_id).bounds_in_pixel().ToString());
445  EXPECT_EQ(1U, display_manager()->num_connected_displays());
446  EXPECT_FALSE(display_manager()->mirrored_display().is_valid());
447  EXPECT_EQ(external_id, Shell::GetScreen()->GetPrimaryDisplay().id());
448
449  EXPECT_EQ(internal_display_id, gfx::Display::InternalDisplayId());
450
451  // Primary connected, with different bounds.
452  display_info_list.clear();
453  display_info_list.push_back(internal_display_info);
454  display_info_list.push_back(external_display_info);
455  display_manager()->OnNativeDisplaysChanged(display_info_list);
456  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
457  EXPECT_EQ(internal_display_id, Shell::GetScreen()->GetPrimaryDisplay().id());
458
459  // This combinatino is new, so internal display becomes primary.
460  EXPECT_EQ("0,0 500x500",
461            GetDisplayForId(internal_display_id).bounds().ToString());
462  EXPECT_EQ("1,1 100x100",
463            GetDisplayInfoForId(10).bounds_in_pixel().ToString());
464  EXPECT_EQ(2U, display_manager()->num_connected_displays());
465  EXPECT_FALSE(display_manager()->mirrored_display().is_valid());
466  EXPECT_EQ(ToDisplayName(internal_display_id),
467            display_manager()->GetDisplayNameForId(internal_display_id));
468
469  // Emulate suspend.
470  display_info_list.clear();
471  display_manager()->OnNativeDisplaysChanged(display_info_list);
472  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
473  EXPECT_EQ("0,0 500x500",
474            GetDisplayForId(internal_display_id).bounds().ToString());
475  EXPECT_EQ("1,1 100x100",
476            GetDisplayInfoForId(10).bounds_in_pixel().ToString());
477  EXPECT_EQ(2U, display_manager()->num_connected_displays());
478  EXPECT_FALSE(display_manager()->mirrored_display().is_valid());
479  EXPECT_EQ(ToDisplayName(internal_display_id),
480            display_manager()->GetDisplayNameForId(internal_display_id));
481
482  // External display has disconnected then resumed.
483  display_info_list.push_back(internal_display_info);
484  display_manager()->OnNativeDisplaysChanged(display_info_list);
485  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
486  EXPECT_EQ("0,0 500x500",
487            GetDisplayForId(internal_display_id).bounds().ToString());
488  EXPECT_EQ(1U, display_manager()->num_connected_displays());
489  EXPECT_FALSE(display_manager()->mirrored_display().is_valid());
490
491  // External display was changed during suspend.
492  display_info_list.push_back(external_display_info);
493  display_manager()->OnNativeDisplaysChanged(display_info_list);
494  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
495  EXPECT_EQ(2U, display_manager()->num_connected_displays());
496  EXPECT_FALSE(display_manager()->mirrored_display().is_valid());
497
498  // suspend...
499  display_info_list.clear();
500  display_manager()->OnNativeDisplaysChanged(display_info_list);
501  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
502  EXPECT_EQ(2U, display_manager()->num_connected_displays());
503  EXPECT_FALSE(display_manager()->mirrored_display().is_valid());
504
505  // and resume with different external display.
506  display_info_list.push_back(internal_display_info);
507  display_info_list.push_back(CreateDisplayInfo(12, gfx::Rect(1, 1, 100, 100)));
508  display_manager()->OnNativeDisplaysChanged(display_info_list);
509  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
510  EXPECT_EQ(2U, display_manager()->num_connected_displays());
511  EXPECT_FALSE(display_manager()->mirrored_display().is_valid());
512  EXPECT_FALSE(display_manager()->IsMirrored());
513
514  // mirrored...
515  display_info_list.clear();
516  display_info_list.push_back(internal_display_info);
517  display_info_list.push_back(mirrored_display_info);
518  display_manager()->OnNativeDisplaysChanged(display_info_list);
519  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
520  EXPECT_EQ("0,0 500x500",
521            GetDisplayForId(internal_display_id).bounds().ToString());
522  EXPECT_EQ(2U, display_manager()->num_connected_displays());
523  EXPECT_EQ(11U, display_manager()->mirrored_display().id());
524  EXPECT_TRUE(display_manager()->IsMirrored());
525
526  // Test display name.
527  EXPECT_EQ(ToDisplayName(internal_display_id),
528            display_manager()->GetDisplayNameForId(internal_display_id));
529  EXPECT_EQ("x-10", display_manager()->GetDisplayNameForId(10));
530  EXPECT_EQ("x-11", display_manager()->GetDisplayNameForId(11));
531  EXPECT_EQ("x-12", display_manager()->GetDisplayNameForId(12));
532  // Default name for the id that doesn't exist.
533  EXPECT_EQ("Display 100", display_manager()->GetDisplayNameForId(100));
534
535  // and exit mirroring.
536  display_info_list.clear();
537  display_info_list.push_back(internal_display_info);
538  display_info_list.push_back(external_display_info);
539  display_manager()->OnNativeDisplaysChanged(display_info_list);
540  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
541  EXPECT_EQ(2U, display_manager()->num_connected_displays());
542  EXPECT_FALSE(display_manager()->IsMirrored());
543  EXPECT_EQ("0,0 500x500",
544            GetDisplayForId(internal_display_id).bounds().ToString());
545  EXPECT_EQ("500,0 100x100",
546            GetDisplayForId(10).bounds().ToString());
547
548  // Turn off internal
549  display_info_list.clear();
550  display_info_list.push_back(external_display_info);
551  display_manager()->OnNativeDisplaysChanged(display_info_list);
552  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
553  EXPECT_EQ(invalid_id, GetDisplayForId(internal_display_id).id());
554  EXPECT_EQ("1,1 100x100",
555            GetDisplayInfoForId(external_id).bounds_in_pixel().ToString());
556  EXPECT_EQ(1U, display_manager()->num_connected_displays());
557  EXPECT_FALSE(display_manager()->mirrored_display().is_valid());
558
559  // Switched to another display
560  display_info_list.clear();
561  display_info_list.push_back(internal_display_info);
562  display_manager()->OnNativeDisplaysChanged(display_info_list);
563  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
564  EXPECT_EQ(
565      "0,0 500x500",
566      GetDisplayInfoForId(internal_display_id).bounds_in_pixel().ToString());
567  EXPECT_EQ(1U, display_manager()->num_connected_displays());
568  EXPECT_FALSE(display_manager()->mirrored_display().is_valid());
569}
570
571#if defined(OS_WIN)
572// TODO(scottmg): RootWindow doesn't get resized on Windows
573// Ash. http://crbug.com/247916.
574#define MAYBE_TestNativeDisplaysChangedNoInternal \
575        DISABLED_TestNativeDisplaysChangedNoInternal
576#else
577#define MAYBE_TestNativeDisplaysChangedNoInternal \
578        TestNativeDisplaysChangedNoInternal
579#endif
580
581TEST_F(DisplayManagerTest, MAYBE_TestNativeDisplaysChangedNoInternal) {
582  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
583
584  // Don't change the display info if all displays are disconnected.
585  std::vector<DisplayInfo> display_info_list;
586  display_manager()->OnNativeDisplaysChanged(display_info_list);
587  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
588
589  // Connect another display which will become primary.
590  const DisplayInfo external_display_info =
591      CreateDisplayInfo(10, gfx::Rect(1, 1, 100, 100));
592  display_info_list.push_back(external_display_info);
593  display_manager()->OnNativeDisplaysChanged(display_info_list);
594  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
595  EXPECT_EQ("1,1 100x100",
596            GetDisplayInfoForId(10).bounds_in_pixel().ToString());
597  EXPECT_EQ("100x100",
598            ash::Shell::GetPrimaryRootWindow()->GetHostSize().ToString());
599}
600
601#if defined(OS_WIN)
602// Tests that rely on the actual host size/location does not work on windows.
603#define MAYBE_EnsurePointerInDisplays DISABLED_EnsurePointerInDisplays
604#define MAYBE_EnsurePointerInDisplays_2ndOnLeft DISABLED_EnsurePointerInDisplays_2ndOnLeft
605#else
606#define MAYBE_EnsurePointerInDisplays EnsurePointerInDisplays
607#define MAYBE_EnsurePointerInDisplays_2ndOnLeft EnsurePointerInDisplays_2ndOnLeft
608#endif
609
610TEST_F(DisplayManagerTest, MAYBE_EnsurePointerInDisplays) {
611  UpdateDisplay("200x200,300x300");
612  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
613
614  aura::Env* env = aura::Env::GetInstance();
615
616  aura::test::EventGenerator generator(root_windows[0]);
617
618  // Set the initial position.
619  generator.MoveMouseToInHost(350, 150);
620  EXPECT_EQ("350,150", env->last_mouse_location().ToString());
621
622  // A mouse pointer will stay in the 2nd display.
623  UpdateDisplay("300x300,200x200");
624  EXPECT_EQ("450,50", env->last_mouse_location().ToString());
625
626  // A mouse pointer will be outside of displays and move to the
627  // center of 2nd display.
628  UpdateDisplay("300x300,100x100");
629  EXPECT_EQ("350,50", env->last_mouse_location().ToString());
630
631  // 2nd display was disconnected, and the cursor is
632  // now in the 1st display.
633  UpdateDisplay("400x400");
634  EXPECT_EQ("50,350", env->last_mouse_location().ToString());
635
636  // 1st display's resolution has changed, and the mouse pointer is
637  // now outside. Move the mouse pointer to the center of 1st display.
638  UpdateDisplay("300x300");
639  EXPECT_EQ("150,150", env->last_mouse_location().ToString());
640
641  // Move the mouse pointer to the bottom of 1st display.
642  generator.MoveMouseToInHost(150, 290);
643  EXPECT_EQ("150,290", env->last_mouse_location().ToString());
644
645  // The mouse pointer is now on 2nd display.
646  UpdateDisplay("300x280,200x200");
647  EXPECT_EQ("450,10", env->last_mouse_location().ToString());
648}
649
650TEST_F(DisplayManagerTest, MAYBE_EnsurePointerInDisplays_2ndOnLeft) {
651  // Set the 2nd display on the left.
652  DisplayLayoutStore* layout_store =
653      Shell::GetInstance()->display_manager()->layout_store();
654  DisplayLayout layout = layout_store->default_display_layout();
655  layout.position = DisplayLayout::LEFT;
656  layout_store->SetDefaultDisplayLayout(layout);
657
658  UpdateDisplay("200x200,300x300");
659  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
660
661  EXPECT_EQ("-300,0 300x300",
662            ScreenAsh::GetSecondaryDisplay().bounds().ToString());
663
664  aura::Env* env = aura::Env::GetInstance();
665
666  // Set the initial position.
667  root_windows[0]->MoveCursorTo(gfx::Point(-150, 250));
668  EXPECT_EQ("-150,250", env->last_mouse_location().ToString());
669
670  // A mouse pointer will stay in 2nd display.
671  UpdateDisplay("300x300,200x300");
672  EXPECT_EQ("-50,150", env->last_mouse_location().ToString());
673
674  // A mouse pointer will be outside of displays and move to the
675  // center of 2nd display.
676  UpdateDisplay("300x300,200x100");
677  EXPECT_EQ("-100,50", env->last_mouse_location().ToString());
678
679  // 2nd display was disconnected. Mouse pointer should move to
680  // 1st display.
681  UpdateDisplay("300x300");
682  EXPECT_EQ("150,150", env->last_mouse_location().ToString());
683}
684
685TEST_F(DisplayManagerTest, NativeDisplaysChangedAfterPrimaryChange) {
686  if (!SupportsMultipleDisplays())
687    return;
688
689  const int64 internal_display_id =
690      test::DisplayManagerTestApi(display_manager()).
691      SetFirstDisplayAsInternalDisplay();
692  const DisplayInfo native_display_info =
693      CreateDisplayInfo(internal_display_id, gfx::Rect(0, 0, 500, 500));
694  const DisplayInfo secondary_display_info =
695      CreateDisplayInfo(10, gfx::Rect(1, 1, 100, 100));
696
697  std::vector<DisplayInfo> display_info_list;
698  display_info_list.push_back(native_display_info);
699  display_info_list.push_back(secondary_display_info);
700  display_manager()->OnNativeDisplaysChanged(display_info_list);
701  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
702  EXPECT_EQ("0,0 500x500",
703            GetDisplayForId(internal_display_id).bounds().ToString());
704  EXPECT_EQ("500,0 100x100", GetDisplayForId(10).bounds().ToString());
705
706  ash::Shell::GetInstance()->display_controller()->SetPrimaryDisplay(
707      GetDisplayForId(secondary_display_info.id()));
708  EXPECT_EQ("-500,0 500x500",
709            GetDisplayForId(internal_display_id).bounds().ToString());
710  EXPECT_EQ("0,0 100x100", GetDisplayForId(10).bounds().ToString());
711
712  // OnNativeDisplaysChanged may change the display bounds.  Here makes sure
713  // nothing changed if the exactly same displays are specified.
714  display_manager()->OnNativeDisplaysChanged(display_info_list);
715  EXPECT_EQ("-500,0 500x500",
716            GetDisplayForId(internal_display_id).bounds().ToString());
717  EXPECT_EQ("0,0 100x100", GetDisplayForId(10).bounds().ToString());
718}
719
720TEST_F(DisplayManagerTest, Rotate) {
721  if (!SupportsMultipleDisplays())
722    return;
723
724  UpdateDisplay("100x200/r,300x400/l");
725  EXPECT_EQ("1,1 100x200",
726            GetDisplayInfoAt(0).bounds_in_pixel().ToString());
727  EXPECT_EQ("200x100",
728            GetDisplayInfoAt(0).size_in_pixel().ToString());
729
730  EXPECT_EQ("1,201 300x400",
731            GetDisplayInfoAt(1).bounds_in_pixel().ToString());
732  EXPECT_EQ("400x300",
733            GetDisplayInfoAt(1).size_in_pixel().ToString());
734  reset();
735  UpdateDisplay("100x200/b,300x400");
736  EXPECT_EQ("2 0 0", GetCountSummary());
737  reset();
738
739  EXPECT_EQ("1,1 100x200",
740            GetDisplayInfoAt(0).bounds_in_pixel().ToString());
741  EXPECT_EQ("100x200",
742            GetDisplayInfoAt(0).size_in_pixel().ToString());
743
744  EXPECT_EQ("1,201 300x400",
745            GetDisplayInfoAt(1).bounds_in_pixel().ToString());
746  EXPECT_EQ("300x400",
747            GetDisplayInfoAt(1).size_in_pixel().ToString());
748
749  // Just Rotating display will change the bounds on both display.
750  UpdateDisplay("100x200/l,300x400");
751  EXPECT_EQ("2 0 0", GetCountSummary());
752  reset();
753
754  // Updating tothe same configuration should report no changes.
755  UpdateDisplay("100x200/l,300x400");
756  EXPECT_EQ("0 0 0", GetCountSummary());
757  reset();
758
759  UpdateDisplay("100x200/l,300x400");
760  EXPECT_EQ("0 0 0", GetCountSummary());
761  reset();
762
763  UpdateDisplay("200x200");
764  EXPECT_EQ("1 0 1", GetCountSummary());
765  reset();
766
767  UpdateDisplay("200x200/l");
768  EXPECT_EQ("1 0 0", GetCountSummary());
769}
770
771TEST_F(DisplayManagerTest, UIScale) {
772  UpdateDisplay("1280x800");
773  int64 display_id = Shell::GetScreen()->GetPrimaryDisplay().id();
774  display_manager()->SetDisplayUIScale(display_id, 1.125f);
775  EXPECT_EQ(1.0, GetDisplayInfoAt(0).ui_scale());
776  display_manager()->SetDisplayUIScale(display_id, 0.8f);
777  EXPECT_EQ(1.0f, GetDisplayInfoAt(0).ui_scale());
778  display_manager()->SetDisplayUIScale(display_id, 0.75f);
779  EXPECT_EQ(1.0f, GetDisplayInfoAt(0).ui_scale());
780  display_manager()->SetDisplayUIScale(display_id, 0.625f);
781  EXPECT_EQ(1.0f, GetDisplayInfoAt(0).ui_scale());
782
783  gfx::Display::SetInternalDisplayId(display_id);
784
785  display_manager()->SetDisplayUIScale(display_id, 1.5f);
786  EXPECT_EQ(1.0f, GetDisplayInfoAt(0).ui_scale());
787  display_manager()->SetDisplayUIScale(display_id, 1.25f);
788  EXPECT_EQ(1.0f, GetDisplayInfoAt(0).ui_scale());
789  display_manager()->SetDisplayUIScale(display_id, 1.125f);
790  EXPECT_EQ(1.125f, GetDisplayInfoAt(0).ui_scale());
791  display_manager()->SetDisplayUIScale(display_id, 0.8f);
792  EXPECT_EQ(0.8f, GetDisplayInfoAt(0).ui_scale());
793  display_manager()->SetDisplayUIScale(display_id, 0.75f);
794  EXPECT_EQ(0.8f, GetDisplayInfoAt(0).ui_scale());
795  display_manager()->SetDisplayUIScale(display_id, 0.625f);
796  EXPECT_EQ(0.625f, GetDisplayInfoAt(0).ui_scale());
797  display_manager()->SetDisplayUIScale(display_id, 0.6f);
798  EXPECT_EQ(0.625f, GetDisplayInfoAt(0).ui_scale());
799  display_manager()->SetDisplayUIScale(display_id, 0.5f);
800  EXPECT_EQ(0.5f, GetDisplayInfoAt(0).ui_scale());
801
802  UpdateDisplay("1366x768");
803  display_manager()->SetDisplayUIScale(display_id, 1.5f);
804  EXPECT_EQ(1.0f, GetDisplayInfoAt(0).ui_scale());
805  display_manager()->SetDisplayUIScale(display_id, 1.25f);
806  EXPECT_EQ(1.0f, GetDisplayInfoAt(0).ui_scale());
807  display_manager()->SetDisplayUIScale(display_id, 1.125f);
808  EXPECT_EQ(1.125f, GetDisplayInfoAt(0).ui_scale());
809  display_manager()->SetDisplayUIScale(display_id, 0.8f);
810  EXPECT_EQ(1.125f, GetDisplayInfoAt(0).ui_scale());
811  display_manager()->SetDisplayUIScale(display_id, 0.75f);
812  EXPECT_EQ(0.75f, GetDisplayInfoAt(0).ui_scale());
813  display_manager()->SetDisplayUIScale(display_id, 0.6f);
814  EXPECT_EQ(0.6f, GetDisplayInfoAt(0).ui_scale());
815  display_manager()->SetDisplayUIScale(display_id, 0.625f);
816  EXPECT_EQ(0.6f, GetDisplayInfoAt(0).ui_scale());
817  display_manager()->SetDisplayUIScale(display_id, 0.5f);
818  EXPECT_EQ(0.5f, GetDisplayInfoAt(0).ui_scale());
819
820  UpdateDisplay("1280x850*2");
821  EXPECT_EQ(1.0f, GetDisplayInfoAt(0).ui_scale());
822  display_manager()->SetDisplayUIScale(display_id, 1.5f);
823  EXPECT_EQ(1.5f, GetDisplayInfoAt(0).ui_scale());
824  display_manager()->SetDisplayUIScale(display_id, 1.25f);
825  EXPECT_EQ(1.25f, GetDisplayInfoAt(0).ui_scale());
826  display_manager()->SetDisplayUIScale(display_id, 1.125f);
827  EXPECT_EQ(1.125f, GetDisplayInfoAt(0).ui_scale());
828  display_manager()->SetDisplayUIScale(display_id, 0.8f);
829  EXPECT_EQ(0.8f, GetDisplayInfoAt(0).ui_scale());
830  display_manager()->SetDisplayUIScale(display_id, 0.75f);
831  EXPECT_EQ(0.8f, GetDisplayInfoAt(0).ui_scale());
832  display_manager()->SetDisplayUIScale(display_id, 0.625f);
833  EXPECT_EQ(0.625f, GetDisplayInfoAt(0).ui_scale());
834  display_manager()->SetDisplayUIScale(display_id, 0.6f);
835  EXPECT_EQ(0.625f, GetDisplayInfoAt(0).ui_scale());
836  display_manager()->SetDisplayUIScale(display_id, 0.5f);
837  EXPECT_EQ(0.5f, GetDisplayInfoAt(0).ui_scale());
838}
839
840
841#if defined(OS_WIN)
842// TODO(scottmg): RootWindow doesn't get resized on Windows
843// Ash. http://crbug.com/247916.
844#define MAYBE_UpdateMouseCursorAfterRotateZoom DISABLED_UpdateMouseCursorAfterRotateZoom
845#else
846#define MAYBE_UpdateMouseCursorAfterRotateZoom UpdateMouseCursorAfterRotateZoom
847#endif
848
849TEST_F(DisplayManagerTest, MAYBE_UpdateMouseCursorAfterRotateZoom) {
850  // Make sure just rotating will not change native location.
851  UpdateDisplay("300x200,200x150");
852  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
853  aura::Env* env = aura::Env::GetInstance();
854
855  aura::test::EventGenerator generator1(root_windows[0]);
856  aura::test::EventGenerator generator2(root_windows[1]);
857
858  // Test on 1st display.
859  generator1.MoveMouseToInHost(150, 50);
860  EXPECT_EQ("150,50", env->last_mouse_location().ToString());
861  UpdateDisplay("300x200/r,200x150");
862  EXPECT_EQ("50,149", env->last_mouse_location().ToString());
863
864  // Test on 2nd display.
865  generator2.MoveMouseToInHost(50, 100);
866  EXPECT_EQ("250,100", env->last_mouse_location().ToString());
867  UpdateDisplay("300x200/r,200x150/l");
868  EXPECT_EQ("249,50", env->last_mouse_location().ToString());
869
870  // The native location is now outside, so move to the center
871  // of closest display.
872  UpdateDisplay("300x200/r,100x50/l");
873  EXPECT_EQ("225,50", env->last_mouse_location().ToString());
874
875  // Make sure just zooming will not change native location.
876  UpdateDisplay("600x400*2,400x300");
877
878  // Test on 1st display.
879  generator1.MoveMouseToInHost(200, 300);
880  EXPECT_EQ("100,150", env->last_mouse_location().ToString());
881  UpdateDisplay("600x400*2@1.5,400x300");
882  EXPECT_EQ("150,225", env->last_mouse_location().ToString());
883
884  // Test on 2nd display.
885  UpdateDisplay("600x400,400x300*2");
886  generator2.MoveMouseToInHost(200, 250);
887  EXPECT_EQ("700,125", env->last_mouse_location().ToString());
888  UpdateDisplay("600x400,400x300*2@1.5");
889  EXPECT_EQ("750,187", env->last_mouse_location().ToString());
890
891  // The native location is now outside, so move to the
892  // center of closest display.
893  UpdateDisplay("600x400,400x200*2@1.5");
894  EXPECT_EQ("750,75", env->last_mouse_location().ToString());
895}
896
897class TestDisplayObserver : public gfx::DisplayObserver {
898 public:
899  TestDisplayObserver() : changed_(false) {}
900  virtual ~TestDisplayObserver() {}
901
902  // gfx::DisplayObserver overrides:
903  virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE {
904  }
905  virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE {
906    // Mirror window should already be delete before restoring
907    // the external dispay.
908    EXPECT_FALSE(test_api.GetRootWindow());
909    changed_ = true;
910  }
911  virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE {
912    // Mirror window should not be created until the external display
913    // is removed.
914    EXPECT_FALSE(test_api.GetRootWindow());
915    changed_ = true;
916  }
917
918  bool changed_and_reset() {
919    bool changed = changed_;
920    changed_ = false;
921    return changed;
922  }
923
924 private:
925  test::MirrorWindowTestApi test_api;
926  bool changed_;
927
928  DISALLOW_COPY_AND_ASSIGN(TestDisplayObserver);
929};
930
931TEST_F(DisplayManagerTest, SoftwareMirroring) {
932  if (!SupportsMultipleDisplays())
933    return;
934
935  UpdateDisplay("300x400,400x500");
936
937  test::MirrorWindowTestApi test_api;
938  EXPECT_EQ(NULL, test_api.GetRootWindow());
939
940  TestDisplayObserver display_observer;
941  Shell::GetScreen()->AddObserver(&display_observer);
942
943  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
944  display_manager->SetSoftwareMirroring(true);
945  display_manager->UpdateDisplays();
946  EXPECT_TRUE(display_observer.changed_and_reset());
947  EXPECT_EQ(1U, display_manager->GetNumDisplays());
948  EXPECT_EQ("0,0 300x400",
949            Shell::GetScreen()->GetPrimaryDisplay().bounds().ToString());
950  EXPECT_EQ("400x500", test_api.GetRootWindow()->GetHostSize().ToString());
951  EXPECT_EQ("300x400", test_api.GetRootWindow()->bounds().size().ToString());
952  EXPECT_TRUE(display_manager->IsMirrored());
953
954  display_manager->SetMirrorMode(false);
955  EXPECT_TRUE(display_observer.changed_and_reset());
956  EXPECT_EQ(NULL, test_api.GetRootWindow());
957  EXPECT_EQ(2U, display_manager->GetNumDisplays());
958  EXPECT_FALSE(display_manager->IsMirrored());
959
960  // Make sure the mirror window has the pixel size of the
961  // source display.
962  display_manager->SetMirrorMode(true);
963  EXPECT_TRUE(display_observer.changed_and_reset());
964
965  UpdateDisplay("300x400@0.5,400x500");
966  EXPECT_FALSE(display_observer.changed_and_reset());
967  EXPECT_EQ("300x400", test_api.GetRootWindow()->bounds().size().ToString());
968  EXPECT_EQ("400x500", GetMirroredDisplay().size().ToString());
969
970  UpdateDisplay("310x410*2,400x500");
971  EXPECT_FALSE(display_observer.changed_and_reset());
972  EXPECT_EQ("310x410", test_api.GetRootWindow()->bounds().size().ToString());
973  EXPECT_EQ("400x500", GetMirroredDisplay().size().ToString());
974
975  UpdateDisplay("320x420/r,400x500");
976  EXPECT_FALSE(display_observer.changed_and_reset());
977  EXPECT_EQ("320x420", test_api.GetRootWindow()->bounds().size().ToString());
978  EXPECT_EQ("400x500", GetMirroredDisplay().size().ToString());
979
980  UpdateDisplay("330x440/r,400x500");
981  EXPECT_FALSE(display_observer.changed_and_reset());
982  EXPECT_EQ("330x440", test_api.GetRootWindow()->bounds().size().ToString());
983  EXPECT_EQ("400x500", GetMirroredDisplay().size().ToString());
984
985  // Overscan insets are ignored.
986  UpdateDisplay("400x600/o,600x800/o");
987  EXPECT_FALSE(display_observer.changed_and_reset());
988  EXPECT_EQ("400x600", test_api.GetRootWindow()->bounds().size().ToString());
989  EXPECT_EQ("600x800", GetMirroredDisplay().size().ToString());
990
991  Shell::GetScreen()->RemoveObserver(&display_observer);
992}
993
994}  // namespace internal
995}  // namespace ash
996