display_controller_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_controller.h"
6
7#include "ash/display/display_info.h"
8#include "ash/display/display_manager.h"
9#include "ash/launcher/launcher.h"
10#include "ash/screen_ash.h"
11#include "ash/shelf/shelf_widget.h"
12#include "ash/shell.h"
13#include "ash/test/ash_test_base.h"
14#include "ash/test/cursor_manager_test_api.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_tracker.h"
19#include "ui/base/events/event_handler.h"
20#include "ui/gfx/display.h"
21#include "ui/gfx/screen.h"
22#include "ui/views/widget/widget.h"
23
24namespace ash {
25namespace test {
26namespace {
27
28const char kDesktopBackgroundView[] = "DesktopBackgroundView";
29
30class TestObserver : public DisplayController::Observer {
31 public:
32  TestObserver() : changing_count_(0), changed_count_(0) {
33    Shell::GetInstance()->display_controller()->AddObserver(this);
34  }
35
36  virtual ~TestObserver() {
37    Shell::GetInstance()->display_controller()->RemoveObserver(this);
38  }
39
40  virtual void OnDisplayConfigurationChanging() OVERRIDE {
41    ++changing_count_;
42  }
43
44  virtual void OnDisplayConfigurationChanged() OVERRIDE {
45    ++changed_count_;
46  }
47
48  int CountAndReset() {
49    EXPECT_EQ(changing_count_, changed_count_);
50    int c = changing_count_;
51    changing_count_ = changed_count_ = 0;
52    return c;
53  }
54
55 private:
56  int changing_count_;
57  int changed_count_;
58
59  DISALLOW_COPY_AND_ASSIGN(TestObserver);
60};
61
62gfx::Display GetPrimaryDisplay() {
63  return Shell::GetScreen()->GetDisplayNearestWindow(
64      Shell::GetAllRootWindows()[0]);
65}
66
67gfx::Display GetSecondaryDisplay() {
68  return Shell::GetScreen()->GetDisplayNearestWindow(
69      Shell::GetAllRootWindows()[1]);
70}
71
72void SetSecondaryDisplayLayoutAndOffset(DisplayLayout::Position position,
73                                        int offset) {
74  DisplayController* display_controller =
75      Shell::GetInstance()->display_controller();
76  DisplayLayout layout(position, offset);
77  ASSERT_GT(Shell::GetScreen()->GetNumDisplays(), 1);
78  display_controller->SetLayoutForCurrentDisplays(layout);
79}
80
81void SetSecondaryDisplayLayout(DisplayLayout::Position position) {
82  SetSecondaryDisplayLayoutAndOffset(position, 0);
83}
84
85void SetDefaultDisplayLayout(DisplayLayout::Position position) {
86  Shell::GetInstance()->display_controller()->
87      SetDefaultDisplayLayout(DisplayLayout(position, 0));
88}
89
90class DisplayControllerShutdownTest : public test::AshTestBase {
91 public:
92  virtual void TearDown() OVERRIDE {
93    test::AshTestBase::TearDown();
94    if (!SupportsMultipleDisplays())
95      return;
96
97    // Make sure that primary display is accessible after shutdown.
98    gfx::Display primary = Shell::GetScreen()->GetPrimaryDisplay();
99    EXPECT_EQ("0,0 444x333", primary.bounds().ToString());
100    EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
101  }
102};
103
104class TestEventHandler : public ui::EventHandler {
105 public:
106  TestEventHandler() : target_root_(NULL),
107                       touch_radius_x_(0.0),
108                       touch_radius_y_(0.0),
109                       scroll_x_offset_(0.0),
110                       scroll_y_offset_(0.0),
111                       scroll_x_offset_ordinal_(0.0),
112                       scroll_y_offset_ordinal_(0.0) {}
113  virtual ~TestEventHandler() {}
114
115  virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
116    if (event->flags() & ui::EF_IS_SYNTHESIZED)
117      return;
118    aura::Window* target = static_cast<aura::Window*>(event->target());
119    mouse_location_ = event->root_location();
120    target_root_ = target->GetRootWindow();
121    event->StopPropagation();
122  }
123
124  virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
125    aura::Window* target = static_cast<aura::Window*>(event->target());
126    // Only record when the target is the background which covers
127    // entire root window.
128    if (target->name() != kDesktopBackgroundView)
129      return;
130    touch_radius_x_ = event->radius_x();
131    touch_radius_y_ = event->radius_y();
132    event->StopPropagation();
133  }
134
135  virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
136    aura::Window* target = static_cast<aura::Window*>(event->target());
137    // Only record when the target is the background which covers
138    // entire root window.
139    if (target->name() != kDesktopBackgroundView)
140      return;
141
142    if (event->type() == ui::ET_SCROLL) {
143      scroll_x_offset_ = event->x_offset();
144      scroll_y_offset_ = event->y_offset();
145      scroll_x_offset_ordinal_ = event->x_offset_ordinal();
146      scroll_y_offset_ordinal_ = event->y_offset_ordinal();
147    }
148    event->StopPropagation();
149  }
150
151  std::string GetLocationAndReset() {
152    std::string result = mouse_location_.ToString();
153    mouse_location_.SetPoint(0, 0);
154    target_root_ = NULL;
155    return result;
156  }
157
158  float touch_radius_x() { return touch_radius_x_; }
159  float touch_radius_y() { return touch_radius_y_; }
160  float scroll_x_offset() { return scroll_x_offset_; }
161  float scroll_y_offset() { return scroll_y_offset_; }
162  float scroll_x_offset_ordinal() { return scroll_x_offset_ordinal_; }
163  float scroll_y_offset_ordinal() { return scroll_y_offset_ordinal_; }
164
165 private:
166  gfx::Point mouse_location_;
167  aura::RootWindow* target_root_;
168
169  float touch_radius_x_;
170  float touch_radius_y_;
171  float scroll_x_offset_;
172  float scroll_y_offset_;
173  float scroll_x_offset_ordinal_;
174  float scroll_y_offset_ordinal_;
175
176  DISALLOW_COPY_AND_ASSIGN(TestEventHandler);
177};
178
179gfx::Display::Rotation GetStoredRotation(int64 id) {
180  return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).rotation();
181}
182
183float GetStoredUIScale(int64 id) {
184  return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).ui_scale();
185}
186
187}  // namespace
188
189typedef test::AshTestBase DisplayControllerTest;
190
191TEST_F(DisplayControllerShutdownTest, Shutdown) {
192  if (!SupportsMultipleDisplays())
193    return;
194
195  UpdateDisplay("444x333, 200x200");
196}
197
198TEST_F(DisplayControllerTest, SecondaryDisplayLayout) {
199  if (!SupportsMultipleDisplays())
200    return;
201
202  TestObserver observer;
203  UpdateDisplay("500x500,400x400");
204  EXPECT_EQ(1, observer.CountAndReset());  // resize and add
205  gfx::Display* secondary_display =
206      Shell::GetInstance()->display_manager()->GetDisplayAt(1);
207  gfx::Insets insets(5, 5, 5, 5);
208  secondary_display->UpdateWorkAreaFromInsets(insets);
209
210  // Default layout is RIGHT.
211  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
212  EXPECT_EQ("500,0 400x400", GetSecondaryDisplay().bounds().ToString());
213  EXPECT_EQ("505,5 390x390", GetSecondaryDisplay().work_area().ToString());
214
215  // Layout the secondary display to the bottom of the primary.
216  SetSecondaryDisplayLayout(DisplayLayout::BOTTOM);
217  EXPECT_EQ(1, observer.CountAndReset());
218  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
219  EXPECT_EQ("0,500 400x400", GetSecondaryDisplay().bounds().ToString());
220  EXPECT_EQ("5,505 390x390", GetSecondaryDisplay().work_area().ToString());
221
222  // Layout the secondary display to the left of the primary.
223  SetSecondaryDisplayLayout(DisplayLayout::LEFT);
224  EXPECT_EQ(1, observer.CountAndReset());
225  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
226  EXPECT_EQ("-400,0 400x400", GetSecondaryDisplay().bounds().ToString());
227  EXPECT_EQ("-395,5 390x390", GetSecondaryDisplay().work_area().ToString());
228
229  // Layout the secondary display to the top of the primary.
230  SetSecondaryDisplayLayout(DisplayLayout::TOP);
231  EXPECT_EQ(1, observer.CountAndReset());
232  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
233  EXPECT_EQ("0,-400 400x400", GetSecondaryDisplay().bounds().ToString());
234  EXPECT_EQ("5,-395 390x390", GetSecondaryDisplay().work_area().ToString());
235
236  // Layout to the right with an offset.
237  SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, 300);
238  EXPECT_EQ(1, observer.CountAndReset());  // resize and add
239  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
240  EXPECT_EQ("500,300 400x400", GetSecondaryDisplay().bounds().ToString());
241
242  // Keep the minimum 100.
243  SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, 490);
244  EXPECT_EQ(1, observer.CountAndReset());  // resize and add
245  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
246  EXPECT_EQ("500,400 400x400", GetSecondaryDisplay().bounds().ToString());
247
248  SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, -400);
249  EXPECT_EQ(1, observer.CountAndReset());  // resize and add
250  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
251  EXPECT_EQ("500,-300 400x400", GetSecondaryDisplay().bounds().ToString());
252
253  //  Layout to the bottom with an offset.
254  SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -200);
255  EXPECT_EQ(1, observer.CountAndReset());  // resize and add
256  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
257  EXPECT_EQ("-200,500 400x400", GetSecondaryDisplay().bounds().ToString());
258
259  // Keep the minimum 100.
260  SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, 490);
261  EXPECT_EQ(1, observer.CountAndReset());  // resize and add
262  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
263  EXPECT_EQ("400,500 400x400", GetSecondaryDisplay().bounds().ToString());
264
265  SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -400);
266  EXPECT_EQ(1, observer.CountAndReset());  // resize and add
267  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
268  EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString());
269}
270
271TEST_F(DisplayControllerTest, BoundsUpdated) {
272  if (!SupportsMultipleDisplays())
273    return;
274
275  TestObserver observer;
276  SetDefaultDisplayLayout(DisplayLayout::BOTTOM);
277  UpdateDisplay("200x200,300x300");  // layout, resize and add.
278  EXPECT_EQ(1, observer.CountAndReset());
279
280  internal::DisplayManager* display_manager =
281      Shell::GetInstance()->display_manager();
282  gfx::Display* secondary_display = display_manager->GetDisplayAt(1);
283  gfx::Insets insets(5, 5, 5, 5);
284  secondary_display->UpdateWorkAreaFromInsets(insets);
285
286  EXPECT_EQ("0,0 200x200", GetPrimaryDisplay().bounds().ToString());
287  EXPECT_EQ("0,200 300x300", GetSecondaryDisplay().bounds().ToString());
288  EXPECT_EQ("5,205 290x290", GetSecondaryDisplay().work_area().ToString());
289
290  UpdateDisplay("400x400,200x200");
291  EXPECT_EQ(1, observer.CountAndReset());  // two resizes
292  EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
293  EXPECT_EQ("0,400 200x200", GetSecondaryDisplay().bounds().ToString());
294
295  UpdateDisplay("400x400,300x300");
296  EXPECT_EQ(1, observer.CountAndReset());
297  EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
298  EXPECT_EQ("0,400 300x300", GetSecondaryDisplay().bounds().ToString());
299
300  UpdateDisplay("400x400");
301  EXPECT_EQ(1, observer.CountAndReset());
302  EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
303  EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
304
305  UpdateDisplay("400x500*2,300x300");
306  EXPECT_EQ(1, observer.CountAndReset());
307  ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());
308  EXPECT_EQ("0,0 200x250", GetPrimaryDisplay().bounds().ToString());
309  EXPECT_EQ("0,250 300x300", GetSecondaryDisplay().bounds().ToString());
310
311  // No change
312  UpdateDisplay("400x500*2,300x300");
313  EXPECT_EQ(0, observer.CountAndReset());
314
315  // Rotation
316  int64 primary_id = GetPrimaryDisplay().id();
317  display_manager->SetDisplayRotation(primary_id, gfx::Display::ROTATE_90);
318  EXPECT_EQ(1, observer.CountAndReset());
319  display_manager->SetDisplayRotation(primary_id, gfx::Display::ROTATE_90);
320  EXPECT_EQ(0, observer.CountAndReset());
321
322  // UI scale is eanbled only on internal display.
323  int64 secondary_id = GetSecondaryDisplay().id();
324  gfx::Display::SetInternalDisplayId(secondary_id);
325  display_manager->SetDisplayUIScale(secondary_id, 1.125f);
326  EXPECT_EQ(1, observer.CountAndReset());
327  display_manager->SetDisplayUIScale(secondary_id, 1.125f);
328  EXPECT_EQ(0, observer.CountAndReset());
329  display_manager->SetDisplayUIScale(primary_id, 1.125f);
330  EXPECT_EQ(0, observer.CountAndReset());
331  display_manager->SetDisplayUIScale(primary_id, 1.125f);
332  EXPECT_EQ(0, observer.CountAndReset());
333}
334
335TEST_F(DisplayControllerTest, MirroredLayout) {
336  if (!SupportsMultipleDisplays())
337    return;
338
339  DisplayController* display_controller =
340      Shell::GetInstance()->display_controller();
341  UpdateDisplay("500x500,400x400");
342  EXPECT_FALSE(display_controller->GetCurrentDisplayLayout().mirrored);
343  EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
344  EXPECT_EQ(
345      2U, Shell::GetInstance()->display_manager()->num_connected_displays());
346
347  UpdateDisplay("500x500,1+0-500x500");
348  EXPECT_TRUE(display_controller->GetCurrentDisplayLayout().mirrored);
349  EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
350  EXPECT_EQ(
351      2U, Shell::GetInstance()->display_manager()->num_connected_displays());
352
353  UpdateDisplay("500x500,500x500");
354  EXPECT_FALSE(display_controller->GetCurrentDisplayLayout().mirrored);
355  EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
356  EXPECT_EQ(
357      2U, Shell::GetInstance()->display_manager()->num_connected_displays());
358}
359
360TEST_F(DisplayControllerTest, InvertLayout) {
361  EXPECT_EQ("left, 0",
362            DisplayLayout(DisplayLayout::RIGHT, 0).Invert().ToString());
363  EXPECT_EQ("left, -100",
364            DisplayLayout(DisplayLayout::RIGHT, 100).Invert().ToString());
365  EXPECT_EQ("left, 50",
366            DisplayLayout(DisplayLayout::RIGHT, -50).Invert().ToString());
367
368  EXPECT_EQ("right, 0",
369            DisplayLayout(DisplayLayout::LEFT, 0).Invert().ToString());
370  EXPECT_EQ("right, -90",
371            DisplayLayout(DisplayLayout::LEFT, 90).Invert().ToString());
372  EXPECT_EQ("right, 60",
373            DisplayLayout(DisplayLayout::LEFT, -60).Invert().ToString());
374
375  EXPECT_EQ("bottom, 0",
376            DisplayLayout(DisplayLayout::TOP, 0).Invert().ToString());
377  EXPECT_EQ("bottom, -80",
378            DisplayLayout(DisplayLayout::TOP, 80).Invert().ToString());
379  EXPECT_EQ("bottom, 70",
380            DisplayLayout(DisplayLayout::TOP, -70).Invert().ToString());
381
382  EXPECT_EQ("top, 0",
383            DisplayLayout(DisplayLayout::BOTTOM, 0).Invert().ToString());
384  EXPECT_EQ("top, -70",
385            DisplayLayout(DisplayLayout::BOTTOM, 70).Invert().ToString());
386  EXPECT_EQ("top, 80",
387            DisplayLayout(DisplayLayout::BOTTOM, -80).Invert().ToString());
388}
389
390TEST_F(DisplayControllerTest, SwapPrimary) {
391  if (!SupportsMultipleDisplays())
392    return;
393
394  DisplayController* display_controller =
395      Shell::GetInstance()->display_controller();
396
397  UpdateDisplay("200x200,300x300");
398  gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay();
399  gfx::Display secondary_display = ScreenAsh::GetSecondaryDisplay();
400
401  DisplayLayout display_layout(DisplayLayout::RIGHT, 50);
402  display_controller->SetLayoutForCurrentDisplays(display_layout);
403
404  EXPECT_NE(primary_display.id(), secondary_display.id());
405  aura::RootWindow* primary_root =
406      display_controller->GetRootWindowForDisplayId(primary_display.id());
407  aura::RootWindow* secondary_root =
408      display_controller->GetRootWindowForDisplayId(secondary_display.id());
409  EXPECT_NE(primary_root, secondary_root);
410  aura::Window* launcher_window =
411      Launcher::ForPrimaryDisplay()->shelf_widget()->GetNativeView();
412  EXPECT_TRUE(primary_root->Contains(launcher_window));
413  EXPECT_FALSE(secondary_root->Contains(launcher_window));
414  EXPECT_EQ(primary_display.id(),
415            Shell::GetScreen()->GetDisplayNearestPoint(
416                gfx::Point(-100, -100)).id());
417  EXPECT_EQ(primary_display.id(),
418            Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
419
420  EXPECT_EQ("0,0 200x200", primary_display.bounds().ToString());
421  EXPECT_EQ("0,0 200x152", primary_display.work_area().ToString());
422  EXPECT_EQ("200,0 300x300", secondary_display.bounds().ToString());
423  EXPECT_EQ("200,0 300x252", secondary_display.work_area().ToString());
424  EXPECT_EQ("right, 50",
425            display_controller->GetCurrentDisplayLayout().ToString());
426
427  // Switch primary and secondary
428  display_controller->SetPrimaryDisplay(secondary_display);
429  const DisplayLayout& inverted_layout =
430      display_controller->GetCurrentDisplayLayout();
431  EXPECT_EQ("left, -50", inverted_layout.ToString());
432
433  EXPECT_EQ(secondary_display.id(),
434            Shell::GetScreen()->GetPrimaryDisplay().id());
435  EXPECT_EQ(primary_display.id(), ScreenAsh::GetSecondaryDisplay().id());
436  EXPECT_EQ(secondary_display.id(),
437            Shell::GetScreen()->GetDisplayNearestPoint(
438                gfx::Point(-100, -100)).id());
439  EXPECT_EQ(secondary_display.id(),
440            Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
441
442  EXPECT_EQ(
443      primary_root,
444      display_controller->GetRootWindowForDisplayId(secondary_display.id()));
445  EXPECT_EQ(
446      secondary_root,
447      display_controller->GetRootWindowForDisplayId(primary_display.id()));
448  EXPECT_TRUE(primary_root->Contains(launcher_window));
449  EXPECT_FALSE(secondary_root->Contains(launcher_window));
450
451  // Test if the bounds are correctly swapped.
452  gfx::Display swapped_primary = Shell::GetScreen()->GetPrimaryDisplay();
453  gfx::Display swapped_secondary = ScreenAsh::GetSecondaryDisplay();
454  EXPECT_EQ("0,0 300x300", swapped_primary.bounds().ToString());
455  EXPECT_EQ("0,0 300x252", swapped_primary.work_area().ToString());
456  EXPECT_EQ("-200,-50 200x200", swapped_secondary.bounds().ToString());
457
458  EXPECT_EQ("-200,-50 200x152", swapped_secondary.work_area().ToString());
459
460  aura::WindowTracker tracker;
461  tracker.Add(primary_root);
462  tracker.Add(secondary_root);
463
464  // Deleting 2nd display should move the primary to original primary display.
465  UpdateDisplay("200x200");
466  RunAllPendingInMessageLoop();  // RootWindow is deleted in a posted task.
467  EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
468  EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetPrimaryDisplay().id());
469  EXPECT_EQ(primary_display.id(),
470            Shell::GetScreen()->GetDisplayNearestPoint(
471                gfx::Point(-100, -100)).id());
472  EXPECT_EQ(primary_display.id(),
473            Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
474  EXPECT_TRUE(tracker.Contains(primary_root));
475  EXPECT_FALSE(tracker.Contains(secondary_root));
476  EXPECT_TRUE(primary_root->Contains(launcher_window));
477}
478
479TEST_F(DisplayControllerTest, SwapPrimaryById) {
480  if (!SupportsMultipleDisplays())
481    return;
482
483  DisplayController* display_controller =
484      Shell::GetInstance()->display_controller();
485
486  UpdateDisplay("200x200,300x300");
487  gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay();
488  gfx::Display secondary_display = ScreenAsh::GetSecondaryDisplay();
489
490  DisplayLayout display_layout(DisplayLayout::RIGHT, 50);
491  display_controller->SetLayoutForCurrentDisplays(display_layout);
492
493  EXPECT_NE(primary_display.id(), secondary_display.id());
494  aura::RootWindow* primary_root =
495      display_controller->GetRootWindowForDisplayId(primary_display.id());
496  aura::RootWindow* secondary_root =
497      display_controller->GetRootWindowForDisplayId(secondary_display.id());
498  aura::Window* launcher_window =
499      Launcher::ForPrimaryDisplay()->shelf_widget()->GetNativeView();
500  EXPECT_TRUE(primary_root->Contains(launcher_window));
501  EXPECT_FALSE(secondary_root->Contains(launcher_window));
502  EXPECT_NE(primary_root, secondary_root);
503  EXPECT_EQ(primary_display.id(),
504            Shell::GetScreen()->GetDisplayNearestPoint(
505                gfx::Point(-100, -100)).id());
506  EXPECT_EQ(primary_display.id(),
507            Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
508
509  // Switch primary and secondary by display ID.
510  TestObserver observer;
511  display_controller->SetPrimaryDisplayId(secondary_display.id());
512  EXPECT_EQ(secondary_display.id(),
513            Shell::GetScreen()->GetPrimaryDisplay().id());
514  EXPECT_EQ(primary_display.id(), ScreenAsh::GetSecondaryDisplay().id());
515  EXPECT_LT(0, observer.CountAndReset());
516
517  EXPECT_EQ(
518      primary_root,
519      display_controller->GetRootWindowForDisplayId(secondary_display.id()));
520  EXPECT_EQ(
521      secondary_root,
522      display_controller->GetRootWindowForDisplayId(primary_display.id()));
523  EXPECT_TRUE(primary_root->Contains(launcher_window));
524  EXPECT_FALSE(secondary_root->Contains(launcher_window));
525
526  const DisplayLayout& inverted_layout =
527      display_controller->GetCurrentDisplayLayout();
528
529  EXPECT_EQ("left, -50", inverted_layout.ToString());
530
531  // Calling the same ID don't do anything.
532  display_controller->SetPrimaryDisplayId(secondary_display.id());
533  EXPECT_EQ(0, observer.CountAndReset());
534
535  aura::WindowTracker tracker;
536  tracker.Add(primary_root);
537  tracker.Add(secondary_root);
538
539  // Deleting 2nd display should move the primary to original primary display.
540  UpdateDisplay("200x200");
541  RunAllPendingInMessageLoop();  // RootWindow is deleted in a posted task.
542  EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
543  EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetPrimaryDisplay().id());
544  EXPECT_EQ(primary_display.id(),
545            Shell::GetScreen()->GetDisplayNearestPoint(
546                gfx::Point(-100, -100)).id());
547  EXPECT_EQ(primary_display.id(),
548            Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
549  EXPECT_TRUE(tracker.Contains(primary_root));
550  EXPECT_FALSE(tracker.Contains(secondary_root));
551  EXPECT_TRUE(primary_root->Contains(launcher_window));
552
553  internal::DisplayManager* display_manager =
554      Shell::GetInstance()->display_manager();
555  // Adding 2nd display with the same ID.  The 2nd display should become primary
556  // since secondary id is still stored as desirable_primary_id.
557  std::vector<internal::DisplayInfo> display_info_list;
558  display_info_list.push_back(
559      display_manager->GetDisplayInfo(primary_display.id()));
560  display_info_list.push_back(
561      display_manager->GetDisplayInfo(secondary_display.id()));
562  display_manager->OnNativeDisplaysChanged(display_info_list);
563
564  EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
565  EXPECT_EQ(secondary_display.id(),
566            Shell::GetScreen()->GetPrimaryDisplay().id());
567  EXPECT_EQ(primary_display.id(), ScreenAsh::GetSecondaryDisplay().id());
568  EXPECT_EQ(
569      primary_root,
570      display_controller->GetRootWindowForDisplayId(secondary_display.id()));
571  EXPECT_NE(
572      primary_root,
573      display_controller->GetRootWindowForDisplayId(primary_display.id()));
574  EXPECT_TRUE(primary_root->Contains(launcher_window));
575
576  // Deleting 2nd display and adding 2nd display with a different ID.  The 2nd
577  // display shouldn't become primary.
578  UpdateDisplay("200x200");
579  internal::DisplayInfo third_display_info(
580      secondary_display.id() + 1, std::string(), false);
581  third_display_info.SetBounds(secondary_display.bounds());
582  ASSERT_NE(primary_display.id(), third_display_info.id());
583
584  const internal::DisplayInfo& primary_display_info =
585      display_manager->GetDisplayInfo(primary_display.id());
586  std::vector<internal::DisplayInfo> display_info_list2;
587  display_info_list2.push_back(primary_display_info);
588  display_info_list2.push_back(third_display_info);
589  display_manager->OnNativeDisplaysChanged(display_info_list2);
590  EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
591  EXPECT_EQ(primary_display.id(),
592            Shell::GetScreen()->GetPrimaryDisplay().id());
593  EXPECT_EQ(third_display_info.id(), ScreenAsh::GetSecondaryDisplay().id());
594  EXPECT_EQ(
595      primary_root,
596      display_controller->GetRootWindowForDisplayId(primary_display.id()));
597  EXPECT_NE(
598      primary_root,
599      display_controller->GetRootWindowForDisplayId(third_display_info.id()));
600  EXPECT_TRUE(primary_root->Contains(launcher_window));
601}
602
603TEST_F(DisplayControllerTest, CursorDeviceScaleFactorSwapPrimary) {
604  if (!SupportsMultipleDisplays())
605    return;
606
607  DisplayController* display_controller =
608      Shell::GetInstance()->display_controller();
609
610  UpdateDisplay("200x200,200x200*2");
611  gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay();
612  gfx::Display secondary_display = ScreenAsh::GetSecondaryDisplay();
613
614  aura::RootWindow* primary_root =
615      display_controller->GetRootWindowForDisplayId(primary_display.id());
616  aura::RootWindow* secondary_root =
617      display_controller->GetRootWindowForDisplayId(secondary_display.id());
618  EXPECT_NE(primary_root, secondary_root);
619
620  test::CursorManagerTestApi test_api(Shell::GetInstance()->cursor_manager());
621
622  EXPECT_EQ(1.0f,
623            primary_root->AsRootWindowHostDelegate()->GetDeviceScaleFactor());
624  primary_root->MoveCursorTo(gfx::Point(50, 50));
625  EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor());
626  EXPECT_EQ(2.0f,
627            secondary_root->AsRootWindowHostDelegate()->GetDeviceScaleFactor());
628  secondary_root->MoveCursorTo(gfx::Point(50, 50));
629  EXPECT_EQ(2.0f, test_api.GetDisplay().device_scale_factor());
630
631  // Switch primary and secondary
632  display_controller->SetPrimaryDisplay(secondary_display);
633
634  // Cursor's device scale factor should be updated accroding to the swap of
635  // primary and secondary.
636  EXPECT_EQ(1.0f,
637            secondary_root->AsRootWindowHostDelegate()->GetDeviceScaleFactor());
638  secondary_root->MoveCursorTo(gfx::Point(50, 50));
639  EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor());
640  primary_root->MoveCursorTo(gfx::Point(50, 50));
641  EXPECT_EQ(2.0f,
642            primary_root->AsRootWindowHostDelegate()->GetDeviceScaleFactor());
643  EXPECT_EQ(2.0f, test_api.GetDisplay().device_scale_factor());
644
645  // Deleting 2nd display.
646  UpdateDisplay("200x200");
647  RunAllPendingInMessageLoop();  // RootWindow is deleted in a posted task.
648
649  // Cursor's device scale factor should be updated even without moving cursor.
650  EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor());
651
652  primary_root->MoveCursorTo(gfx::Point(50, 50));
653  EXPECT_EQ(1.0f,
654            primary_root->AsRootWindowHostDelegate()->GetDeviceScaleFactor());
655  EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor());
656}
657
658#if defined(OS_WIN)
659// TODO(scottmg): RootWindow doesn't get resized on Windows
660// Ash. http://crbug.com/247916.
661#define MAYBE_UpdateDisplayWithHostOrigin DISABLED_UpdateDisplayWithHostOrigin
662#else
663#define MAYBE_UpdateDisplayWithHostOrigin UpdateDisplayWithHostOrigin
664#endif
665
666TEST_F(DisplayControllerTest, MAYBE_UpdateDisplayWithHostOrigin) {
667  UpdateDisplay("100x200,300x400");
668  ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());
669  Shell::RootWindowList root_windows =
670      Shell::GetInstance()->GetAllRootWindows();
671  ASSERT_EQ(2U, root_windows.size());
672  EXPECT_EQ("1,1", root_windows[0]->GetHostOrigin().ToString());
673  EXPECT_EQ("100x200", root_windows[0]->GetHostSize().ToString());
674  // UpdateDisplay set the origin if it's not set.
675  EXPECT_NE("1,1", root_windows[1]->GetHostOrigin().ToString());
676  EXPECT_EQ("300x400", root_windows[1]->GetHostSize().ToString());
677
678  UpdateDisplay("100x200,200+300-300x400");
679  ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());
680  EXPECT_EQ("0,0", root_windows[0]->GetHostOrigin().ToString());
681  EXPECT_EQ("100x200", root_windows[0]->GetHostSize().ToString());
682  EXPECT_EQ("200,300", root_windows[1]->GetHostOrigin().ToString());
683  EXPECT_EQ("300x400", root_windows[1]->GetHostSize().ToString());
684
685  UpdateDisplay("400+500-200x300,300x400");
686  ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());
687  EXPECT_EQ("400,500", root_windows[0]->GetHostOrigin().ToString());
688  EXPECT_EQ("200x300", root_windows[0]->GetHostSize().ToString());
689  EXPECT_EQ("0,0", root_windows[1]->GetHostOrigin().ToString());
690  EXPECT_EQ("300x400", root_windows[1]->GetHostSize().ToString());
691
692  UpdateDisplay("100+200-100x200,300+500-200x300");
693  ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());
694  EXPECT_EQ("100,200", root_windows[0]->GetHostOrigin().ToString());
695  EXPECT_EQ("100x200", root_windows[0]->GetHostSize().ToString());
696  EXPECT_EQ("300,500", root_windows[1]->GetHostOrigin().ToString());
697  EXPECT_EQ("200x300", root_windows[1]->GetHostSize().ToString());
698}
699
700TEST_F(DisplayControllerTest, OverscanInsets) {
701  if (!SupportsMultipleDisplays())
702    return;
703
704  DisplayController* display_controller =
705      Shell::GetInstance()->display_controller();
706  TestEventHandler event_handler;
707  Shell::GetInstance()->AddPreTargetHandler(&event_handler);
708
709  UpdateDisplay("120x200,300x400*2");
710  gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
711  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
712
713  display_controller->SetOverscanInsets(display1.id(),
714                                        gfx::Insets(10, 15, 20, 25));
715  EXPECT_EQ("0,0 80x170", root_windows[0]->bounds().ToString());
716  EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
717  EXPECT_EQ("80,0 150x200",
718            ScreenAsh::GetSecondaryDisplay().bounds().ToString());
719
720  aura::test::EventGenerator generator(root_windows[0]);
721  generator.MoveMouseToInHost(20, 25);
722  EXPECT_EQ("5,15", event_handler.GetLocationAndReset());
723
724  display_controller->ClearCustomOverscanInsets(display1.id());
725  EXPECT_EQ("0,0 120x200", root_windows[0]->bounds().ToString());
726  EXPECT_EQ("120,0 150x200",
727            ScreenAsh::GetSecondaryDisplay().bounds().ToString());
728
729  generator.MoveMouseToInHost(30, 20);
730  EXPECT_EQ("30,20", event_handler.GetLocationAndReset());
731
732  Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
733}
734
735TEST_F(DisplayControllerTest, Rotate) {
736  if (!SupportsMultipleDisplays())
737    return;
738
739  DisplayController* display_controller =
740      Shell::GetInstance()->display_controller();
741  internal::DisplayManager* display_manager =
742      Shell::GetInstance()->display_manager();
743  TestEventHandler event_handler;
744  Shell::GetInstance()->AddPreTargetHandler(&event_handler);
745
746  UpdateDisplay("120x200,300x400*2");
747  gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
748  int64 display2_id = ScreenAsh::GetSecondaryDisplay().id();
749  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
750  aura::test::EventGenerator generator1(root_windows[0]);
751
752  EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString());
753  EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
754  EXPECT_EQ("120,0 150x200",
755            ScreenAsh::GetSecondaryDisplay().bounds().ToString());
756  generator1.MoveMouseToInHost(50, 40);
757  EXPECT_EQ("50,40", event_handler.GetLocationAndReset());
758  EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display1.id()));
759  EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id));
760
761  display_manager->SetDisplayRotation(display1.id(),
762                                      gfx::Display::ROTATE_90);
763  EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString());
764  EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
765  EXPECT_EQ("200,0 150x200",
766            ScreenAsh::GetSecondaryDisplay().bounds().ToString());
767  generator1.MoveMouseToInHost(50, 40);
768  EXPECT_EQ("40,69", event_handler.GetLocationAndReset());
769  EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id()));
770  EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id));
771
772  DisplayLayout display_layout(DisplayLayout::BOTTOM, 50);
773  display_controller->SetLayoutForCurrentDisplays(display_layout);
774  EXPECT_EQ("50,120 150x200",
775            ScreenAsh::GetSecondaryDisplay().bounds().ToString());
776
777  display_manager->SetDisplayRotation(display2_id,
778                                      gfx::Display::ROTATE_270);
779  EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString());
780  EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString());
781  EXPECT_EQ("50,120 200x150",
782            ScreenAsh::GetSecondaryDisplay().bounds().ToString());
783  EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id()));
784  EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id));
785
786  aura::test::EventGenerator generator2(root_windows[1]);
787  generator2.MoveMouseToInHost(50, 40);
788  EXPECT_EQ("179,25", event_handler.GetLocationAndReset());
789  display_manager->SetDisplayRotation(display1.id(),
790                                      gfx::Display::ROTATE_180);
791
792  EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString());
793  EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString());
794  // Dislay must share at least 100, so the x's offset becomes 20.
795  EXPECT_EQ("20,200 200x150",
796            ScreenAsh::GetSecondaryDisplay().bounds().ToString());
797  EXPECT_EQ(gfx::Display::ROTATE_180, GetStoredRotation(display1.id()));
798  EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id));
799
800  generator1.MoveMouseToInHost(50, 40);
801  EXPECT_EQ("69,159", event_handler.GetLocationAndReset());
802
803  Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
804}
805
806TEST_F(DisplayControllerTest, ScaleRootWindow) {
807  if (!SupportsMultipleDisplays())
808    return;
809
810  TestEventHandler event_handler;
811  Shell::GetInstance()->AddPreTargetHandler(&event_handler);
812
813  UpdateDisplay("600x400*2@1.5,500x300");
814
815  gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
816  gfx::Display::SetInternalDisplayId(display1.id());
817
818  gfx::Display display2 = ScreenAsh::GetSecondaryDisplay();
819  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
820  EXPECT_EQ("0,0 450x300", display1.bounds().ToString());
821  EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString());
822  EXPECT_EQ("450,0 500x300", display2.bounds().ToString());
823  EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
824  EXPECT_EQ(1.0f, GetStoredUIScale(display2.id()));
825
826  aura::test::EventGenerator generator(root_windows[0]);
827  generator.MoveMouseToInHost(599, 200);
828  EXPECT_EQ("449,150", event_handler.GetLocationAndReset());
829
830  internal::DisplayManager* display_manager =
831      Shell::GetInstance()->display_manager();
832  display_manager->SetDisplayUIScale(display1.id(), 1.25f);
833  display1 = Shell::GetScreen()->GetPrimaryDisplay();
834  display2 = ScreenAsh::GetSecondaryDisplay();
835  EXPECT_EQ("0,0 375x250", display1.bounds().ToString());
836  EXPECT_EQ("0,0 375x250", root_windows[0]->bounds().ToString());
837  EXPECT_EQ("375,0 500x300", display2.bounds().ToString());
838  EXPECT_EQ(1.25f, GetStoredUIScale(display1.id()));
839  EXPECT_EQ(1.0f, GetStoredUIScale(display2.id()));
840
841  Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
842}
843
844TEST_F(DisplayControllerTest, TouchScale) {
845  if (!SupportsMultipleDisplays())
846    return;
847
848  TestEventHandler event_handler;
849  Shell::GetInstance()->AddPreTargetHandler(&event_handler);
850
851  UpdateDisplay("200x200*2");
852  gfx::Display display = Shell::GetScreen()->GetPrimaryDisplay();
853  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
854  aura::RootWindow* root_window = root_windows[0];
855  aura::test::EventGenerator generator(root_window);
856
857  generator.PressMoveAndReleaseTouchTo(50, 50);
858  // Default test touches have radius_x/y = 1.0, with device scale
859  // factor = 2, the scaled radius_x/y should be 0.5.
860  EXPECT_EQ(0.5, event_handler.touch_radius_x());
861  EXPECT_EQ(0.5, event_handler.touch_radius_y());
862
863  generator.ScrollSequence(gfx::Point(0,0),
864                           base::TimeDelta::FromMilliseconds(100),
865                           10.0, 1.0, 5, 1);
866
867  // With device scale factor = 2, ordinal_offset * 2 = offset.
868  EXPECT_EQ(event_handler.scroll_x_offset(),
869            event_handler.scroll_x_offset_ordinal() * 2);
870  EXPECT_EQ(event_handler.scroll_y_offset(),
871            event_handler.scroll_y_offset_ordinal() * 2);
872
873  Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
874}
875
876TEST_F(DisplayControllerTest, ConvertHostToRootCoords) {
877  if (!SupportsMultipleDisplays())
878    return;
879
880  TestEventHandler event_handler;
881  Shell::GetInstance()->AddPreTargetHandler(&event_handler);
882
883  UpdateDisplay("600x400*2/r@1.5");
884
885  gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
886  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
887  EXPECT_EQ("0,0 300x450", display1.bounds().ToString());
888  EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString());
889  EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
890
891  aura::test::EventGenerator generator(root_windows[0]);
892  generator.MoveMouseToInHost(0, 0);
893  EXPECT_EQ("0,449", event_handler.GetLocationAndReset());
894  generator.MoveMouseToInHost(599, 0);
895  EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
896  generator.MoveMouseToInHost(599, 399);
897  EXPECT_EQ("299,0", event_handler.GetLocationAndReset());
898  generator.MoveMouseToInHost(0, 399);
899  EXPECT_EQ("299,449", event_handler.GetLocationAndReset());
900
901  UpdateDisplay("600x400*2/u@1.5");
902  display1 = Shell::GetScreen()->GetPrimaryDisplay();
903  root_windows = Shell::GetAllRootWindows();
904  EXPECT_EQ("0,0 450x300", display1.bounds().ToString());
905  EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString());
906  EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
907
908  generator.MoveMouseToInHost(0, 0);
909  EXPECT_EQ("449,299", event_handler.GetLocationAndReset());
910  generator.MoveMouseToInHost(599, 0);
911  EXPECT_EQ("0,299", event_handler.GetLocationAndReset());
912  generator.MoveMouseToInHost(599, 399);
913  EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
914  generator.MoveMouseToInHost(0, 399);
915  EXPECT_EQ("449,0", event_handler.GetLocationAndReset());
916
917  UpdateDisplay("600x400*2/l@1.5");
918  display1 = Shell::GetScreen()->GetPrimaryDisplay();
919  root_windows = Shell::GetAllRootWindows();
920  EXPECT_EQ("0,0 300x450", display1.bounds().ToString());
921  EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString());
922  EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
923
924  generator.MoveMouseToInHost(0, 0);
925  EXPECT_EQ("299,0", event_handler.GetLocationAndReset());
926  generator.MoveMouseToInHost(599, 0);
927  EXPECT_EQ("299,449", event_handler.GetLocationAndReset());
928  generator.MoveMouseToInHost(599, 399);
929  EXPECT_EQ("0,449", event_handler.GetLocationAndReset());
930  generator.MoveMouseToInHost(0, 399);
931  EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
932
933  Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
934}
935
936}  // namespace test
937}  // namespace ash
938