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