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