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