display_controller_unittest.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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/ash_switches.h"
8#include "ash/display/display_info.h"
9#include "ash/display/display_layout_store.h"
10#include "ash/display/display_manager.h"
11#include "ash/screen_util.h"
12#include "ash/shelf/shelf.h"
13#include "ash/shelf/shelf_widget.h"
14#include "ash/shell.h"
15#include "ash/test/ash_test_base.h"
16#include "ash/test/ash_test_helper.h"
17#include "ash/test/cursor_manager_test_api.h"
18#include "ash/test/display_manager_test_api.h"
19#include "ash/test/test_shell_delegate.h"
20#include "ash/wm/window_state.h"
21#include "ash/wm/wm_event.h"
22#include "base/command_line.h"
23#include "ui/aura/client/focus_change_observer.h"
24#include "ui/aura/client/focus_client.h"
25#include "ui/aura/env.h"
26#include "ui/aura/window_tracker.h"
27#include "ui/aura/window_tree_host.h"
28#include "ui/events/event_handler.h"
29#include "ui/events/test/event_generator.h"
30#include "ui/gfx/display.h"
31#include "ui/gfx/screen.h"
32#include "ui/views/widget/widget.h"
33#include "ui/wm/public/activation_change_observer.h"
34#include "ui/wm/public/activation_client.h"
35
36#if defined(USE_X11)
37#include <X11/Xlib.h>
38#include "ui/gfx/x/x11_types.h"
39#undef RootWindow
40#endif
41
42namespace ash {
43namespace {
44
45const char kDesktopBackgroundView[] = "DesktopBackgroundView";
46
47template<typename T>
48class Resetter {
49 public:
50  explicit Resetter(T* value) : value_(*value) {
51    *value = 0;
52  }
53  ~Resetter() { }
54  T value() { return value_; }
55
56 private:
57  T value_;
58  DISALLOW_COPY_AND_ASSIGN(Resetter);
59};
60
61class TestObserver : public DisplayController::Observer,
62                     public gfx::DisplayObserver,
63                     public aura::client::FocusChangeObserver,
64                     public aura::client::ActivationChangeObserver {
65 public:
66  TestObserver()
67      : changing_count_(0),
68        changed_count_(0),
69        bounds_changed_count_(0),
70        rotation_changed_count_(0),
71        workarea_changed_count_(0),
72        changed_display_id_(0),
73        focus_changed_count_(0),
74        activation_changed_count_(0) {
75    Shell::GetInstance()->display_controller()->AddObserver(this);
76    Shell::GetScreen()->AddObserver(this);
77    aura::client::GetFocusClient(Shell::GetPrimaryRootWindow())->
78        AddObserver(this);
79    aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
80        AddObserver(this);
81  }
82
83  virtual ~TestObserver() {
84    Shell::GetInstance()->display_controller()->RemoveObserver(this);
85    Shell::GetScreen()->RemoveObserver(this);
86    aura::client::GetFocusClient(Shell::GetPrimaryRootWindow())->
87        RemoveObserver(this);
88    aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
89        RemoveObserver(this);
90  }
91
92  // Overridden from DisplayController::Observer
93  virtual void OnDisplayConfigurationChanging() OVERRIDE {
94    ++changing_count_;
95  }
96  virtual void OnDisplayConfigurationChanged() OVERRIDE {
97    ++changed_count_;
98  }
99
100  // Overrideen from gfx::DisplayObserver
101  virtual void OnDisplayMetricsChanged(const gfx::Display& display,
102                                       uint32_t metrics) OVERRIDE {
103    changed_display_id_ = display.id();
104    if (metrics & DISPLAY_METRIC_BOUNDS)
105      ++bounds_changed_count_;
106    if (metrics & DISPLAY_METRIC_ROTATION)
107      ++rotation_changed_count_;
108    if (metrics & DISPLAY_METRIC_WORK_AREA)
109      ++workarea_changed_count_;
110  }
111  virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE {
112  }
113  virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE {
114  }
115
116  // Overridden from aura::client::FocusChangeObserver
117  virtual void OnWindowFocused(aura::Window* gained_focus,
118                               aura::Window* lost_focus) OVERRIDE {
119    focus_changed_count_++;
120  }
121
122  // Overridden from aura::client::ActivationChangeObserver
123  virtual void OnWindowActivated(aura::Window* gained_active,
124                                 aura::Window* lost_active) OVERRIDE {
125    activation_changed_count_++;
126  }
127  virtual void OnAttemptToReactivateWindow(
128      aura::Window* request_active,
129      aura::Window* actual_active) OVERRIDE {
130  }
131
132  int CountAndReset() {
133    EXPECT_EQ(changing_count_, changed_count_);
134    changed_count_ = 0;
135    return Resetter<int>(&changing_count_).value();
136  }
137
138  int64 GetBoundsChangedCountAndReset() {
139    return Resetter<int>(&bounds_changed_count_).value();
140  }
141
142  int64 GetRotationChangedCountAndReset() {
143    return Resetter<int>(&rotation_changed_count_).value();
144  }
145
146  int64 GetWorkareaChangedCountAndReset() {
147    return Resetter<int>(&workarea_changed_count_).value();
148  }
149
150  int64 GetChangedDisplayIdAndReset() {
151    return Resetter<int64>(&changed_display_id_).value();
152  }
153
154  int GetFocusChangedCountAndReset() {
155    return Resetter<int>(&focus_changed_count_).value();
156  }
157
158  int GetActivationChangedCountAndReset() {
159    return Resetter<int>(&activation_changed_count_).value();
160  }
161
162 private:
163  int changing_count_;
164  int changed_count_;
165
166  int bounds_changed_count_;
167  int rotation_changed_count_;
168  int workarea_changed_count_;
169  int64 changed_display_id_;
170
171  int focus_changed_count_;
172  int activation_changed_count_;
173
174  DISALLOW_COPY_AND_ASSIGN(TestObserver);
175};
176
177gfx::Display GetPrimaryDisplay() {
178  return Shell::GetScreen()->GetDisplayNearestWindow(
179      Shell::GetAllRootWindows()[0]);
180}
181
182gfx::Display GetSecondaryDisplay() {
183  return Shell::GetScreen()->GetDisplayNearestWindow(
184      Shell::GetAllRootWindows()[1]);
185}
186
187void SetSecondaryDisplayLayoutAndOffset(DisplayLayout::Position position,
188                                        int offset) {
189  DisplayLayout layout(position, offset);
190  ASSERT_GT(Shell::GetScreen()->GetNumDisplays(), 1);
191  Shell::GetInstance()->display_manager()->
192      SetLayoutForCurrentDisplays(layout);
193}
194
195void SetSecondaryDisplayLayout(DisplayLayout::Position position) {
196  SetSecondaryDisplayLayoutAndOffset(position, 0);
197}
198
199void SetDefaultDisplayLayout(DisplayLayout::Position position) {
200  Shell::GetInstance()->display_manager()->layout_store()->
201      SetDefaultDisplayLayout(DisplayLayout(position, 0));
202}
203
204class DisplayControllerShutdownTest : public test::AshTestBase {
205 public:
206  DisplayControllerShutdownTest() {}
207  virtual ~DisplayControllerShutdownTest() {}
208
209  virtual void TearDown() OVERRIDE {
210    test::AshTestBase::TearDown();
211    if (!SupportsMultipleDisplays())
212      return;
213
214    // Make sure that primary display is accessible after shutdown.
215    gfx::Display primary = Shell::GetScreen()->GetPrimaryDisplay();
216    EXPECT_EQ("0,0 444x333", primary.bounds().ToString());
217    EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
218  }
219
220 private:
221  DISALLOW_COPY_AND_ASSIGN(DisplayControllerShutdownTest);
222};
223
224class StartupHelper : public test::TestShellDelegate,
225                      public DisplayController::Observer {
226 public:
227  StartupHelper() : displays_initialized_(false) {}
228  virtual ~StartupHelper() {}
229
230  // ash::ShellSelegate:
231  virtual void PreInit() OVERRIDE {
232    Shell::GetInstance()->display_controller()->AddObserver(this);
233  }
234
235  // ash::DisplayController::Observer:
236  virtual void OnDisplaysInitialized() OVERRIDE {
237    DCHECK(!displays_initialized_);
238    displays_initialized_ = true;
239  }
240
241  bool displays_initialized() const {
242    return displays_initialized_;
243  }
244
245 private:
246  bool displays_initialized_;
247
248  DISALLOW_COPY_AND_ASSIGN(StartupHelper);
249};
250
251class DisplayControllerStartupTest : public test::AshTestBase {
252 public:
253  DisplayControllerStartupTest() : startup_helper_(new StartupHelper) {}
254  virtual ~DisplayControllerStartupTest() {}
255
256  // ash::test::AshTestBase:
257  virtual void SetUp() OVERRIDE {
258    ash_test_helper()->set_test_shell_delegate(startup_helper_);
259    test::AshTestBase::SetUp();
260  }
261  virtual void TearDown() OVERRIDE {
262    Shell::GetInstance()->display_controller()->RemoveObserver(startup_helper_);
263    test::AshTestBase::TearDown();
264  }
265
266  const StartupHelper* startup_helper() const { return startup_helper_; }
267
268 private:
269  StartupHelper* startup_helper_;  // Owned by ash::Shell.
270
271  DISALLOW_COPY_AND_ASSIGN(DisplayControllerStartupTest);
272};
273
274class TestEventHandler : public ui::EventHandler {
275 public:
276  TestEventHandler() : target_root_(NULL),
277                       touch_radius_x_(0.0),
278                       touch_radius_y_(0.0),
279                       scroll_x_offset_(0.0),
280                       scroll_y_offset_(0.0),
281                       scroll_x_offset_ordinal_(0.0),
282                       scroll_y_offset_ordinal_(0.0) {}
283  virtual ~TestEventHandler() {}
284
285  virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
286    if (event->flags() & ui::EF_IS_SYNTHESIZED &&
287        event->type() != ui::ET_MOUSE_EXITED &&
288        event->type() != ui::ET_MOUSE_ENTERED) {
289      return;
290    }
291    aura::Window* target = static_cast<aura::Window*>(event->target());
292    mouse_location_ = event->root_location();
293    target_root_ = target->GetRootWindow();
294    event->StopPropagation();
295  }
296
297  virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
298    aura::Window* target = static_cast<aura::Window*>(event->target());
299    // Only record when the target is the background which covers
300    // entire root window.
301    if (target->name() != kDesktopBackgroundView)
302      return;
303    touch_radius_x_ = event->radius_x();
304    touch_radius_y_ = event->radius_y();
305    event->StopPropagation();
306  }
307
308  virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
309    aura::Window* target = static_cast<aura::Window*>(event->target());
310    // Only record when the target is the background which covers
311    // entire root window.
312    if (target->name() != kDesktopBackgroundView)
313      return;
314
315    if (event->type() == ui::ET_SCROLL) {
316      scroll_x_offset_ = event->x_offset();
317      scroll_y_offset_ = event->y_offset();
318      scroll_x_offset_ordinal_ = event->x_offset_ordinal();
319      scroll_y_offset_ordinal_ = event->y_offset_ordinal();
320    }
321    event->StopPropagation();
322  }
323
324  std::string GetLocationAndReset() {
325    std::string result = mouse_location_.ToString();
326    mouse_location_.SetPoint(0, 0);
327    target_root_ = NULL;
328    return result;
329  }
330
331  float touch_radius_x() { return touch_radius_x_; }
332  float touch_radius_y() { return touch_radius_y_; }
333  float scroll_x_offset() { return scroll_x_offset_; }
334  float scroll_y_offset() { return scroll_y_offset_; }
335  float scroll_x_offset_ordinal() { return scroll_x_offset_ordinal_; }
336  float scroll_y_offset_ordinal() { return scroll_y_offset_ordinal_; }
337
338 private:
339  gfx::Point mouse_location_;
340  aura::Window* target_root_;
341
342  float touch_radius_x_;
343  float touch_radius_y_;
344  float scroll_x_offset_;
345  float scroll_y_offset_;
346  float scroll_x_offset_ordinal_;
347  float scroll_y_offset_ordinal_;
348
349  DISALLOW_COPY_AND_ASSIGN(TestEventHandler);
350};
351
352gfx::Display::Rotation GetStoredRotation(int64 id) {
353  return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).rotation();
354}
355
356float GetStoredUIScale(int64 id) {
357  return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).
358      GetEffectiveUIScale();
359}
360
361#if defined(USE_X11)
362void GetPrimaryAndSeconary(aura::Window** primary,
363                           aura::Window** secondary) {
364  *primary = Shell::GetPrimaryRootWindow();
365  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
366  *secondary = root_windows[0] == *primary ? root_windows[1] : root_windows[0];
367}
368
369std::string GetXWindowName(aura::WindowTreeHost* host) {
370  char* name = NULL;
371  XFetchName(gfx::GetXDisplay(), host->GetAcceleratedWidget(), &name);
372  std::string ret(name);
373  XFree(name);
374  return ret;
375}
376#endif
377
378}  // namespace
379
380typedef test::AshTestBase DisplayControllerTest;
381
382TEST_F(DisplayControllerShutdownTest, Shutdown) {
383  if (!SupportsMultipleDisplays())
384    return;
385
386  UpdateDisplay("444x333, 200x200");
387}
388
389TEST_F(DisplayControllerStartupTest, Startup) {
390  if (!SupportsMultipleDisplays())
391    return;
392
393  EXPECT_TRUE(startup_helper()->displays_initialized());
394}
395
396TEST_F(DisplayControllerTest, SecondaryDisplayLayout) {
397  if (!SupportsMultipleDisplays())
398    return;
399
400  // Creates windows to catch activation change event.
401  scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
402  w1->Focus();
403
404  TestObserver observer;
405  UpdateDisplay("500x500,400x400");
406  EXPECT_EQ(1, observer.CountAndReset());  // resize and add
407  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
408  EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
409  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
410  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
411  gfx::Insets insets(5, 5, 5, 5);
412  int64 secondary_display_id = ScreenUtil::GetSecondaryDisplay().id();
413  Shell::GetInstance()->display_manager()->UpdateWorkAreaOfDisplay(
414      secondary_display_id, insets);
415
416  // Default layout is RIGHT.
417  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
418  EXPECT_EQ("500,0 400x400", GetSecondaryDisplay().bounds().ToString());
419  EXPECT_EQ("505,5 390x390", GetSecondaryDisplay().work_area().ToString());
420  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
421  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
422
423  // Layout the secondary display to the bottom of the primary.
424  SetSecondaryDisplayLayout(DisplayLayout::BOTTOM);
425  EXPECT_EQ(1, observer.CountAndReset());
426  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
427  EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
428  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
429  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
430  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
431  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
432  EXPECT_EQ("0,500 400x400", GetSecondaryDisplay().bounds().ToString());
433  EXPECT_EQ("5,505 390x390", GetSecondaryDisplay().work_area().ToString());
434
435  // Layout the secondary display to the left of the primary.
436  SetSecondaryDisplayLayout(DisplayLayout::LEFT);
437  EXPECT_EQ(1, observer.CountAndReset());
438  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
439  EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
440  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
441  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
442  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
443  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
444  EXPECT_EQ("-400,0 400x400", GetSecondaryDisplay().bounds().ToString());
445  EXPECT_EQ("-395,5 390x390", GetSecondaryDisplay().work_area().ToString());
446
447  // Layout the secondary display to the top of the primary.
448  SetSecondaryDisplayLayout(DisplayLayout::TOP);
449  EXPECT_EQ(1, observer.CountAndReset());
450  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
451  EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
452  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
453  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
454  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
455  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
456  EXPECT_EQ("0,-400 400x400", GetSecondaryDisplay().bounds().ToString());
457  EXPECT_EQ("5,-395 390x390", GetSecondaryDisplay().work_area().ToString());
458
459  // Layout to the right with an offset.
460  SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, 300);
461  EXPECT_EQ(1, observer.CountAndReset());  // resize and add
462  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
463  EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
464  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
465  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
466  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
467  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
468  EXPECT_EQ("500,300 400x400", GetSecondaryDisplay().bounds().ToString());
469
470  // Keep the minimum 100.
471  SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, 490);
472  EXPECT_EQ(1, observer.CountAndReset());  // resize and add
473  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
474  EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
475  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
476  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
477  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
478  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
479  EXPECT_EQ("500,400 400x400", GetSecondaryDisplay().bounds().ToString());
480
481  SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, -400);
482  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
483  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
484  EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
485  EXPECT_EQ(1, observer.CountAndReset());  // resize and add
486  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
487  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
488  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
489  EXPECT_EQ("500,-300 400x400", GetSecondaryDisplay().bounds().ToString());
490
491  //  Layout to the bottom with an offset.
492  SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -200);
493  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
494  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
495  EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
496  EXPECT_EQ(1, observer.CountAndReset());  // resize and add
497  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
498  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
499  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
500  EXPECT_EQ("-200,500 400x400", GetSecondaryDisplay().bounds().ToString());
501
502  // Keep the minimum 100.
503  SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, 490);
504  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
505  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
506  EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
507  EXPECT_EQ(1, observer.CountAndReset());  // resize and add
508  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
509  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
510  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
511  EXPECT_EQ("400,500 400x400", GetSecondaryDisplay().bounds().ToString());
512
513  SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -400);
514  EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
515  EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
516  EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
517  EXPECT_EQ(1, observer.CountAndReset());  // resize and add
518  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
519  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
520  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
521  EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString());
522
523  // Setting the same layout shouldn't invoke observers.
524  SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -400);
525  EXPECT_EQ(0, observer.GetChangedDisplayIdAndReset());
526  EXPECT_EQ(0, observer.GetBoundsChangedCountAndReset());
527  EXPECT_EQ(0, observer.GetWorkareaChangedCountAndReset());
528  EXPECT_EQ(0, observer.CountAndReset());  // resize and add
529  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
530  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
531  EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
532  EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString());
533
534  UpdateDisplay("500x500");
535  EXPECT_LE(1, observer.GetFocusChangedCountAndReset());
536  EXPECT_LE(1, observer.GetActivationChangedCountAndReset());
537}
538
539namespace {
540
541DisplayInfo CreateDisplayInfo(int64 id,
542                              const gfx::Rect& bounds,
543                              float device_scale_factor) {
544  DisplayInfo info(id, "", false);
545  info.SetBounds(bounds);
546  info.set_device_scale_factor(device_scale_factor);
547  return info;
548}
549
550}  // namespace
551
552TEST_F(DisplayControllerTest, MirrorToDockedWithFullscreen) {
553  if (!SupportsMultipleDisplays())
554    return;
555
556  // Creates windows to catch activation change event.
557  scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
558  w1->Focus();
559
560  // Docked mode.
561  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
562
563  const DisplayInfo internal_display_info =
564      CreateDisplayInfo(1, gfx::Rect(0, 0, 500, 500), 2.0f);
565  const DisplayInfo external_display_info =
566      CreateDisplayInfo(2, gfx::Rect(0, 0, 500, 500), 1.0f);
567
568  std::vector<DisplayInfo> display_info_list;
569  // Mirror.
570  display_info_list.push_back(internal_display_info);
571  display_info_list.push_back(external_display_info);
572  display_manager->OnNativeDisplaysChanged(display_info_list);
573  const int64 internal_display_id =
574      test::DisplayManagerTestApi(display_manager).
575      SetFirstDisplayAsInternalDisplay();
576  EXPECT_EQ(1, internal_display_id);
577  EXPECT_EQ(2U, display_manager->num_connected_displays());
578  EXPECT_EQ(1U, display_manager->GetNumDisplays());
579
580  wm::WindowState* window_state = wm::GetWindowState(w1.get());
581  const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
582  window_state->OnWMEvent(&toggle_fullscreen_event);
583  EXPECT_TRUE(window_state->IsFullscreen());
584  EXPECT_EQ("0,0 250x250", w1->bounds().ToString());
585  // Dock mode.
586  TestObserver observer;
587  display_info_list.clear();
588  display_info_list.push_back(external_display_info);
589  display_manager->OnNativeDisplaysChanged(display_info_list);
590  EXPECT_EQ(1U, display_manager->GetNumDisplays());
591  EXPECT_EQ(1U, display_manager->num_connected_displays());
592  EXPECT_EQ(0, observer.GetChangedDisplayIdAndReset());
593  EXPECT_EQ(0, observer.GetBoundsChangedCountAndReset());
594  EXPECT_EQ(0, observer.GetWorkareaChangedCountAndReset());
595  EXPECT_EQ(1, observer.CountAndReset());
596  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
597  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
598
599  EXPECT_TRUE(window_state->IsFullscreen());
600  EXPECT_EQ("0,0 500x500", w1->bounds().ToString());
601}
602
603TEST_F(DisplayControllerTest, BoundsUpdated) {
604  if (!SupportsMultipleDisplays())
605    return;
606
607  // Creates windows to catch activation change event.
608  scoped_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
609  w1->Focus();
610
611  TestObserver observer;
612  SetDefaultDisplayLayout(DisplayLayout::BOTTOM);
613  UpdateDisplay("200x200,300x300");  // layout, resize and add.
614  EXPECT_EQ(1, observer.CountAndReset());
615  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
616  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
617
618  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
619  gfx::Insets insets(5, 5, 5, 5);
620  display_manager->UpdateWorkAreaOfDisplay(
621      ScreenUtil::GetSecondaryDisplay().id(), insets);
622
623  EXPECT_EQ("0,0 200x200", GetPrimaryDisplay().bounds().ToString());
624  EXPECT_EQ("0,200 300x300", GetSecondaryDisplay().bounds().ToString());
625  EXPECT_EQ("5,205 290x290", GetSecondaryDisplay().work_area().ToString());
626
627  UpdateDisplay("400x400,200x200");
628  EXPECT_EQ(1, observer.CountAndReset());  // two resizes
629  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
630  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
631  EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
632  EXPECT_EQ("0,400 200x200", GetSecondaryDisplay().bounds().ToString());
633
634  UpdateDisplay("400x400,300x300");
635  EXPECT_EQ(1, observer.CountAndReset());
636  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
637  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
638  EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
639  EXPECT_EQ("0,400 300x300", GetSecondaryDisplay().bounds().ToString());
640
641  UpdateDisplay("400x400");
642  EXPECT_EQ(1, observer.CountAndReset());
643  EXPECT_LE(1, observer.GetFocusChangedCountAndReset());
644  EXPECT_LE(1, observer.GetActivationChangedCountAndReset());
645  EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
646  EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
647
648  UpdateDisplay("400x500*2,300x300");
649  EXPECT_EQ(1, observer.CountAndReset());
650  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
651  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
652  ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());
653  EXPECT_EQ("0,0 200x250", GetPrimaryDisplay().bounds().ToString());
654  EXPECT_EQ("0,250 300x300", GetSecondaryDisplay().bounds().ToString());
655
656  // No change
657  UpdateDisplay("400x500*2,300x300");
658  // We still call into Pre/PostDisplayConfigurationChange().
659  EXPECT_EQ(1, observer.CountAndReset());
660  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
661  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
662
663  // Rotation
664  observer.GetRotationChangedCountAndReset();  // we only want to reset.
665  int64 primary_id = GetPrimaryDisplay().id();
666  display_manager->SetDisplayRotation(primary_id, gfx::Display::ROTATE_90);
667  EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
668  EXPECT_EQ(1, observer.CountAndReset());
669  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
670  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
671  display_manager->SetDisplayRotation(primary_id, gfx::Display::ROTATE_90);
672  EXPECT_EQ(0, observer.GetRotationChangedCountAndReset());
673  EXPECT_EQ(0, observer.CountAndReset());
674  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
675  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
676
677  // UI scale is eanbled only on internal display.
678  int64 secondary_id = GetSecondaryDisplay().id();
679  gfx::Display::SetInternalDisplayId(secondary_id);
680  display_manager->SetDisplayUIScale(secondary_id, 1.125f);
681  EXPECT_EQ(1, observer.CountAndReset());
682  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
683  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
684  display_manager->SetDisplayUIScale(secondary_id, 1.125f);
685  EXPECT_EQ(0, observer.CountAndReset());
686  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
687  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
688  display_manager->SetDisplayUIScale(primary_id, 1.125f);
689  EXPECT_EQ(0, observer.CountAndReset());
690  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
691  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
692  display_manager->SetDisplayUIScale(primary_id, 1.125f);
693  EXPECT_EQ(0, observer.CountAndReset());
694  EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
695  EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
696}
697
698TEST_F(DisplayControllerTest, SwapPrimary) {
699  if (!SupportsMultipleDisplays())
700    return;
701
702  DisplayController* display_controller =
703      Shell::GetInstance()->display_controller();
704  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
705
706  UpdateDisplay("200x200,300x300");
707  gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay();
708  gfx::Display secondary_display = ScreenUtil::GetSecondaryDisplay();
709
710  DisplayLayout display_layout(DisplayLayout::RIGHT, 50);
711  display_manager->SetLayoutForCurrentDisplays(display_layout);
712
713  EXPECT_NE(primary_display.id(), secondary_display.id());
714  aura::Window* primary_root =
715      display_controller->GetRootWindowForDisplayId(primary_display.id());
716  aura::Window* secondary_root =
717      display_controller->GetRootWindowForDisplayId(secondary_display.id());
718  EXPECT_NE(primary_root, secondary_root);
719  aura::Window* shelf_window =
720      Shelf::ForPrimaryDisplay()->shelf_widget()->GetNativeView();
721  EXPECT_TRUE(primary_root->Contains(shelf_window));
722  EXPECT_FALSE(secondary_root->Contains(shelf_window));
723  EXPECT_EQ(primary_display.id(),
724            Shell::GetScreen()->GetDisplayNearestPoint(
725                gfx::Point(-100, -100)).id());
726  EXPECT_EQ(primary_display.id(),
727            Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
728
729  EXPECT_EQ("0,0 200x200", primary_display.bounds().ToString());
730  EXPECT_EQ("0,0 200x153", primary_display.work_area().ToString());
731  EXPECT_EQ("200,0 300x300", secondary_display.bounds().ToString());
732  EXPECT_EQ("200,0 300x253", secondary_display.work_area().ToString());
733  EXPECT_EQ("right, 50",
734            display_manager->GetCurrentDisplayLayout().ToString());
735
736  // Switch primary and secondary
737  display_controller->SetPrimaryDisplay(secondary_display);
738  const DisplayLayout& inverted_layout =
739      display_manager->GetCurrentDisplayLayout();
740  EXPECT_EQ("left, -50", inverted_layout.ToString());
741
742  EXPECT_EQ(secondary_display.id(),
743            Shell::GetScreen()->GetPrimaryDisplay().id());
744  EXPECT_EQ(primary_display.id(), ScreenUtil::GetSecondaryDisplay().id());
745  EXPECT_EQ(primary_display.id(),
746            Shell::GetScreen()->GetDisplayNearestPoint(
747                gfx::Point(-100, -100)).id());
748  EXPECT_EQ(secondary_display.id(),
749            Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
750
751  EXPECT_EQ(
752      primary_root,
753      display_controller->GetRootWindowForDisplayId(secondary_display.id()));
754  EXPECT_EQ(
755      secondary_root,
756      display_controller->GetRootWindowForDisplayId(primary_display.id()));
757  EXPECT_TRUE(primary_root->Contains(shelf_window));
758  EXPECT_FALSE(secondary_root->Contains(shelf_window));
759
760  // Test if the bounds are correctly swapped.
761  gfx::Display swapped_primary = Shell::GetScreen()->GetPrimaryDisplay();
762  gfx::Display swapped_secondary = ScreenUtil::GetSecondaryDisplay();
763  EXPECT_EQ("0,0 300x300", swapped_primary.bounds().ToString());
764  EXPECT_EQ("0,0 300x253", swapped_primary.work_area().ToString());
765  EXPECT_EQ("-200,-50 200x200", swapped_secondary.bounds().ToString());
766
767  EXPECT_EQ("-200,-50 200x153", swapped_secondary.work_area().ToString());
768
769  aura::WindowTracker tracker;
770  tracker.Add(primary_root);
771  tracker.Add(secondary_root);
772
773  // Deleting 2nd display should move the primary to original primary display.
774  UpdateDisplay("200x200");
775  RunAllPendingInMessageLoop();  // RootWindow is deleted in a posted task.
776  EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
777  EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetPrimaryDisplay().id());
778  EXPECT_EQ(primary_display.id(),
779            Shell::GetScreen()->GetDisplayNearestPoint(
780                gfx::Point(-100, -100)).id());
781  EXPECT_EQ(primary_display.id(),
782            Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
783  EXPECT_TRUE(tracker.Contains(primary_root));
784  EXPECT_FALSE(tracker.Contains(secondary_root));
785  EXPECT_TRUE(primary_root->Contains(shelf_window));
786}
787
788TEST_F(DisplayControllerTest, FindNearestDisplay) {
789  if (!SupportsMultipleDisplays())
790    return;
791
792  DisplayController* display_controller =
793      Shell::GetInstance()->display_controller();
794  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
795
796  UpdateDisplay("200x200,300x300");
797  DisplayLayout display_layout(DisplayLayout::RIGHT, 50);
798  display_manager->SetLayoutForCurrentDisplays(display_layout);
799
800  gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay();
801  gfx::Display secondary_display = ScreenUtil::GetSecondaryDisplay();
802  EXPECT_NE(primary_display.id(), secondary_display.id());
803  aura::Window* primary_root =
804      display_controller->GetRootWindowForDisplayId(primary_display.id());
805  aura::Window* secondary_root =
806      display_controller->GetRootWindowForDisplayId(secondary_display.id());
807  EXPECT_NE(primary_root, secondary_root);
808
809  // Test that points outside of any display return the nearest display.
810  EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
811      gfx::Point(-100, 0)).id());
812  EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
813      gfx::Point(0, -100)).id());
814  EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
815      gfx::Point(100, 100)).id());
816  EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
817      gfx::Point(224, 25)).id());
818  EXPECT_EQ(secondary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
819      gfx::Point(226, 25)).id());
820  EXPECT_EQ(secondary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
821      gfx::Point(600, 100)).id());
822  EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
823      gfx::Point(174, 225)).id());
824  EXPECT_EQ(secondary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
825      gfx::Point(176, 225)).id());
826  EXPECT_EQ(secondary_display.id(), Shell::GetScreen()->GetDisplayNearestPoint(
827      gfx::Point(300, 400)).id());
828}
829
830TEST_F(DisplayControllerTest, SwapPrimaryById) {
831  if (!SupportsMultipleDisplays())
832    return;
833
834  DisplayController* display_controller =
835      Shell::GetInstance()->display_controller();
836  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
837
838  UpdateDisplay("200x200,300x300");
839  gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay();
840  gfx::Display secondary_display = ScreenUtil::GetSecondaryDisplay();
841
842  DisplayLayout display_layout(DisplayLayout::RIGHT, 50);
843  display_manager->SetLayoutForCurrentDisplays(display_layout);
844
845  EXPECT_NE(primary_display.id(), secondary_display.id());
846  aura::Window* primary_root =
847      display_controller->GetRootWindowForDisplayId(primary_display.id());
848  aura::Window* secondary_root =
849      display_controller->GetRootWindowForDisplayId(secondary_display.id());
850  aura::Window* shelf_window =
851      Shelf::ForPrimaryDisplay()->shelf_widget()->GetNativeView();
852  EXPECT_TRUE(primary_root->Contains(shelf_window));
853  EXPECT_FALSE(secondary_root->Contains(shelf_window));
854  EXPECT_NE(primary_root, secondary_root);
855  EXPECT_EQ(primary_display.id(),
856            Shell::GetScreen()->GetDisplayNearestPoint(
857                gfx::Point(-100, -100)).id());
858  EXPECT_EQ(primary_display.id(),
859            Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
860
861  // Switch primary and secondary by display ID.
862  TestObserver observer;
863  display_controller->SetPrimaryDisplayId(secondary_display.id());
864  EXPECT_EQ(secondary_display.id(),
865            Shell::GetScreen()->GetPrimaryDisplay().id());
866  EXPECT_EQ(primary_display.id(), ScreenUtil::GetSecondaryDisplay().id());
867  EXPECT_LT(0, observer.CountAndReset());
868
869  EXPECT_EQ(
870      primary_root,
871      display_controller->GetRootWindowForDisplayId(secondary_display.id()));
872  EXPECT_EQ(
873      secondary_root,
874      display_controller->GetRootWindowForDisplayId(primary_display.id()));
875  EXPECT_TRUE(primary_root->Contains(shelf_window));
876  EXPECT_FALSE(secondary_root->Contains(shelf_window));
877
878  const DisplayLayout& inverted_layout =
879      display_manager->GetCurrentDisplayLayout();
880
881  EXPECT_EQ("left, -50", inverted_layout.ToString());
882
883  // Calling the same ID don't do anything.
884  display_controller->SetPrimaryDisplayId(secondary_display.id());
885  EXPECT_EQ(0, observer.CountAndReset());
886
887  aura::WindowTracker tracker;
888  tracker.Add(primary_root);
889  tracker.Add(secondary_root);
890
891  // Deleting 2nd display should move the primary to original primary display.
892  UpdateDisplay("200x200");
893  RunAllPendingInMessageLoop();  // RootWindow is deleted in a posted task.
894  EXPECT_EQ(1, Shell::GetScreen()->GetNumDisplays());
895  EXPECT_EQ(primary_display.id(), Shell::GetScreen()->GetPrimaryDisplay().id());
896  EXPECT_EQ(primary_display.id(),
897            Shell::GetScreen()->GetDisplayNearestPoint(
898                gfx::Point(-100, -100)).id());
899  EXPECT_EQ(primary_display.id(),
900            Shell::GetScreen()->GetDisplayNearestWindow(NULL).id());
901  EXPECT_TRUE(tracker.Contains(primary_root));
902  EXPECT_FALSE(tracker.Contains(secondary_root));
903  EXPECT_TRUE(primary_root->Contains(shelf_window));
904
905  // Adding 2nd display with the same ID.  The 2nd display should become primary
906  // since secondary id is still stored as desirable_primary_id.
907  std::vector<DisplayInfo> display_info_list;
908  display_info_list.push_back(
909      display_manager->GetDisplayInfo(primary_display.id()));
910  display_info_list.push_back(
911      display_manager->GetDisplayInfo(secondary_display.id()));
912  display_manager->OnNativeDisplaysChanged(display_info_list);
913
914  EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
915  EXPECT_EQ(secondary_display.id(),
916            Shell::GetScreen()->GetPrimaryDisplay().id());
917  EXPECT_EQ(primary_display.id(), ScreenUtil::GetSecondaryDisplay().id());
918  EXPECT_EQ(
919      primary_root,
920      display_controller->GetRootWindowForDisplayId(secondary_display.id()));
921  EXPECT_NE(
922      primary_root,
923      display_controller->GetRootWindowForDisplayId(primary_display.id()));
924  EXPECT_TRUE(primary_root->Contains(shelf_window));
925
926  // Deleting 2nd display and adding 2nd display with a different ID.  The 2nd
927  // display shouldn't become primary.
928  UpdateDisplay("200x200");
929  DisplayInfo third_display_info(
930      secondary_display.id() + 1, std::string(), false);
931  third_display_info.SetBounds(secondary_display.bounds());
932  ASSERT_NE(primary_display.id(), third_display_info.id());
933
934  const DisplayInfo& primary_display_info =
935      display_manager->GetDisplayInfo(primary_display.id());
936  std::vector<DisplayInfo> display_info_list2;
937  display_info_list2.push_back(primary_display_info);
938  display_info_list2.push_back(third_display_info);
939  display_manager->OnNativeDisplaysChanged(display_info_list2);
940  EXPECT_EQ(2, Shell::GetScreen()->GetNumDisplays());
941  EXPECT_EQ(primary_display.id(),
942            Shell::GetScreen()->GetPrimaryDisplay().id());
943  EXPECT_EQ(third_display_info.id(), ScreenUtil::GetSecondaryDisplay().id());
944  EXPECT_EQ(
945      primary_root,
946      display_controller->GetRootWindowForDisplayId(primary_display.id()));
947  EXPECT_NE(
948      primary_root,
949      display_controller->GetRootWindowForDisplayId(third_display_info.id()));
950  EXPECT_TRUE(primary_root->Contains(shelf_window));
951}
952
953TEST_F(DisplayControllerTest, CursorDeviceScaleFactorSwapPrimary) {
954  if (!SupportsMultipleDisplays())
955    return;
956
957  DisplayController* display_controller =
958      Shell::GetInstance()->display_controller();
959
960  UpdateDisplay("200x200,200x200*2");
961  gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay();
962  gfx::Display secondary_display = ScreenUtil::GetSecondaryDisplay();
963
964  aura::Window* primary_root =
965      display_controller->GetRootWindowForDisplayId(primary_display.id());
966  aura::Window* secondary_root =
967      display_controller->GetRootWindowForDisplayId(secondary_display.id());
968  EXPECT_NE(primary_root, secondary_root);
969
970  test::CursorManagerTestApi test_api(Shell::GetInstance()->cursor_manager());
971
972  EXPECT_EQ(1.0f, primary_root->GetHost()->compositor()->
973      device_scale_factor());
974  primary_root->MoveCursorTo(gfx::Point(50, 50));
975  EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
976  EXPECT_EQ(2.0f, secondary_root->GetHost()->compositor()->
977      device_scale_factor());
978  secondary_root->MoveCursorTo(gfx::Point(50, 50));
979  EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor());
980
981  // Switch primary and secondary
982  display_controller->SetPrimaryDisplay(secondary_display);
983
984  // Cursor's device scale factor should be updated accroding to the swap of
985  // primary and secondary.
986  EXPECT_EQ(1.0f, secondary_root->GetHost()->compositor()->
987      device_scale_factor());
988  secondary_root->MoveCursorTo(gfx::Point(50, 50));
989  EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
990  primary_root->MoveCursorTo(gfx::Point(50, 50));
991  EXPECT_EQ(2.0f, primary_root->GetHost()->compositor()->
992      device_scale_factor());
993  EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor());
994
995  // Deleting 2nd display.
996  UpdateDisplay("200x200");
997  RunAllPendingInMessageLoop();  // RootWindow is deleted in a posted task.
998
999  // Cursor's device scale factor should be updated even without moving cursor.
1000  EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
1001
1002  primary_root->MoveCursorTo(gfx::Point(50, 50));
1003  EXPECT_EQ(1.0f, primary_root->GetHost()->compositor()->
1004      device_scale_factor());
1005  EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
1006}
1007
1008TEST_F(DisplayControllerTest, OverscanInsets) {
1009  if (!SupportsMultipleDisplays())
1010    return;
1011
1012  DisplayController* display_controller =
1013      Shell::GetInstance()->display_controller();
1014  TestEventHandler event_handler;
1015  Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1016
1017  UpdateDisplay("120x200,300x400*2");
1018  gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
1019  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1020
1021  display_controller->SetOverscanInsets(display1.id(),
1022                                        gfx::Insets(10, 15, 20, 25));
1023  EXPECT_EQ("0,0 80x170", root_windows[0]->bounds().ToString());
1024  EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
1025  EXPECT_EQ("80,0 150x200",
1026            ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1027
1028  ui::test::EventGenerator generator(root_windows[0]);
1029  generator.MoveMouseToInHost(20, 25);
1030  EXPECT_EQ("5,15", event_handler.GetLocationAndReset());
1031
1032  display_controller->SetOverscanInsets(display1.id(), gfx::Insets());
1033  EXPECT_EQ("0,0 120x200", root_windows[0]->bounds().ToString());
1034  EXPECT_EQ("120,0 150x200",
1035            ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1036
1037  generator.MoveMouseToInHost(30, 20);
1038  EXPECT_EQ("30,20", event_handler.GetLocationAndReset());
1039
1040  // Make sure the root window transformer uses correct scale
1041  // factor when swapping display. Test crbug.com/253690.
1042  UpdateDisplay("400x300*2,600x400/o");
1043  root_windows = Shell::GetAllRootWindows();
1044  gfx::Point point;
1045  Shell::GetAllRootWindows()[1]->GetHost()->
1046      GetRootTransform().TransformPoint(&point);
1047  EXPECT_EQ("15,10", point.ToString());
1048
1049  display_controller->SwapPrimaryDisplay();
1050  point.SetPoint(0, 0);
1051  Shell::GetAllRootWindows()[1]->GetHost()->
1052      GetRootTransform().TransformPoint(&point);
1053  EXPECT_EQ("15,10", point.ToString());
1054
1055  Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1056}
1057
1058TEST_F(DisplayControllerTest, Rotate) {
1059  if (!SupportsMultipleDisplays())
1060    return;
1061
1062  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1063  TestEventHandler event_handler;
1064  Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1065
1066  UpdateDisplay("120x200,300x400*2");
1067  gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
1068  int64 display2_id = ScreenUtil::GetSecondaryDisplay().id();
1069  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1070  ui::test::EventGenerator generator1(root_windows[0]);
1071
1072  TestObserver observer;
1073  EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString());
1074  EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
1075  EXPECT_EQ("120,0 150x200",
1076            ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1077  generator1.MoveMouseToInHost(50, 40);
1078  EXPECT_EQ("50,40", event_handler.GetLocationAndReset());
1079  EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display1.id()));
1080  EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id));
1081  EXPECT_EQ(0, observer.GetRotationChangedCountAndReset());
1082
1083  display_manager->SetDisplayRotation(display1.id(),
1084                                      gfx::Display::ROTATE_90);
1085  EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString());
1086  EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
1087  EXPECT_EQ("200,0 150x200",
1088            ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1089  generator1.MoveMouseToInHost(50, 40);
1090  EXPECT_EQ("40,69", event_handler.GetLocationAndReset());
1091  EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id()));
1092  EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id));
1093  EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
1094
1095  DisplayLayout display_layout(DisplayLayout::BOTTOM, 50);
1096  display_manager->SetLayoutForCurrentDisplays(display_layout);
1097  EXPECT_EQ("50,120 150x200",
1098            ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1099
1100  display_manager->SetDisplayRotation(display2_id,
1101                                      gfx::Display::ROTATE_270);
1102  EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString());
1103  EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString());
1104  EXPECT_EQ("50,120 200x150",
1105            ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1106  EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id()));
1107  EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id));
1108  EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
1109
1110#if !defined(OS_WIN)
1111  ui::test::EventGenerator generator2(root_windows[1]);
1112  generator2.MoveMouseToInHost(50, 40);
1113  EXPECT_EQ("179,25", event_handler.GetLocationAndReset());
1114  display_manager->SetDisplayRotation(display1.id(),
1115                                      gfx::Display::ROTATE_180);
1116
1117  EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString());
1118  EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString());
1119  // Dislay must share at least 100, so the x's offset becomes 20.
1120  EXPECT_EQ("20,200 200x150",
1121            ScreenUtil::GetSecondaryDisplay().bounds().ToString());
1122  EXPECT_EQ(gfx::Display::ROTATE_180, GetStoredRotation(display1.id()));
1123  EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id));
1124  EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
1125
1126  generator1.MoveMouseToInHost(50, 40);
1127  EXPECT_EQ("69,159", event_handler.GetLocationAndReset());
1128#endif
1129
1130  Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1131}
1132
1133TEST_F(DisplayControllerTest, ScaleRootWindow) {
1134  if (!SupportsMultipleDisplays())
1135    return;
1136
1137  TestEventHandler event_handler;
1138  Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1139
1140  UpdateDisplay("600x400*2@1.5,500x300");
1141
1142  gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
1143  gfx::Display::SetInternalDisplayId(display1.id());
1144
1145  gfx::Display display2 = ScreenUtil::GetSecondaryDisplay();
1146  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1147  EXPECT_EQ("0,0 450x300", display1.bounds().ToString());
1148  EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString());
1149  EXPECT_EQ("450,0 500x300", display2.bounds().ToString());
1150  EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1151  EXPECT_EQ(1.0f, GetStoredUIScale(display2.id()));
1152
1153  ui::test::EventGenerator generator(root_windows[0]);
1154  generator.MoveMouseToInHost(599, 200);
1155  EXPECT_EQ("449,150", event_handler.GetLocationAndReset());
1156
1157  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1158  display_manager->SetDisplayUIScale(display1.id(), 1.25f);
1159  display1 = Shell::GetScreen()->GetPrimaryDisplay();
1160  display2 = ScreenUtil::GetSecondaryDisplay();
1161  EXPECT_EQ("0,0 375x250", display1.bounds().ToString());
1162  EXPECT_EQ("0,0 375x250", root_windows[0]->bounds().ToString());
1163  EXPECT_EQ("375,0 500x300", display2.bounds().ToString());
1164  EXPECT_EQ(1.25f, GetStoredUIScale(display1.id()));
1165  EXPECT_EQ(1.0f, GetStoredUIScale(display2.id()));
1166
1167  Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1168}
1169
1170TEST_F(DisplayControllerTest, TouchScale) {
1171  if (!SupportsMultipleDisplays())
1172    return;
1173
1174  TestEventHandler event_handler;
1175  Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1176
1177  UpdateDisplay("200x200*2");
1178  gfx::Display display = Shell::GetScreen()->GetPrimaryDisplay();
1179  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1180  aura::Window* root_window = root_windows[0];
1181  ui::test::EventGenerator generator(root_window);
1182
1183  generator.PressMoveAndReleaseTouchTo(50, 50);
1184  // Default test touches have radius_x/y = 1.0, with device scale
1185  // factor = 2, the scaled radius_x/y should be 0.5.
1186  EXPECT_EQ(0.5, event_handler.touch_radius_x());
1187  EXPECT_EQ(0.5, event_handler.touch_radius_y());
1188
1189  generator.ScrollSequence(gfx::Point(0,0),
1190                           base::TimeDelta::FromMilliseconds(100),
1191                           10.0, 1.0, 5, 1);
1192
1193  // ordinal_offset is invariant to the device scale factor.
1194  EXPECT_EQ(event_handler.scroll_x_offset(),
1195            event_handler.scroll_x_offset_ordinal());
1196  EXPECT_EQ(event_handler.scroll_y_offset(),
1197            event_handler.scroll_y_offset_ordinal());
1198
1199  Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1200}
1201
1202TEST_F(DisplayControllerTest, ConvertHostToRootCoords) {
1203  if (!SupportsMultipleDisplays())
1204    return;
1205
1206  TestEventHandler event_handler;
1207  Shell::GetInstance()->AddPreTargetHandler(&event_handler);
1208
1209  UpdateDisplay("600x400*2/r@1.5");
1210
1211  gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
1212  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1213  EXPECT_EQ("0,0 300x450", display1.bounds().ToString());
1214  EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString());
1215  EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1216
1217  ui::test::EventGenerator generator(root_windows[0]);
1218  generator.MoveMouseToInHost(0, 0);
1219  EXPECT_EQ("0,449", event_handler.GetLocationAndReset());
1220  generator.MoveMouseToInHost(599, 0);
1221  EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
1222  generator.MoveMouseToInHost(599, 399);
1223  EXPECT_EQ("299,0", event_handler.GetLocationAndReset());
1224  generator.MoveMouseToInHost(0, 399);
1225  EXPECT_EQ("299,449", event_handler.GetLocationAndReset());
1226
1227  UpdateDisplay("600x400*2/u@1.5");
1228  display1 = Shell::GetScreen()->GetPrimaryDisplay();
1229  root_windows = Shell::GetAllRootWindows();
1230  EXPECT_EQ("0,0 450x300", display1.bounds().ToString());
1231  EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString());
1232  EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1233
1234  generator.MoveMouseToInHost(0, 0);
1235  EXPECT_EQ("449,299", event_handler.GetLocationAndReset());
1236  generator.MoveMouseToInHost(599, 0);
1237  EXPECT_EQ("0,299", event_handler.GetLocationAndReset());
1238  generator.MoveMouseToInHost(599, 399);
1239  EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
1240  generator.MoveMouseToInHost(0, 399);
1241  EXPECT_EQ("449,0", event_handler.GetLocationAndReset());
1242
1243  UpdateDisplay("600x400*2/l@1.5");
1244  display1 = Shell::GetScreen()->GetPrimaryDisplay();
1245  root_windows = Shell::GetAllRootWindows();
1246  EXPECT_EQ("0,0 300x450", display1.bounds().ToString());
1247  EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString());
1248  EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
1249
1250  generator.MoveMouseToInHost(0, 0);
1251  EXPECT_EQ("299,0", event_handler.GetLocationAndReset());
1252  generator.MoveMouseToInHost(599, 0);
1253  EXPECT_EQ("299,449", event_handler.GetLocationAndReset());
1254  generator.MoveMouseToInHost(599, 399);
1255  EXPECT_EQ("0,449", event_handler.GetLocationAndReset());
1256  generator.MoveMouseToInHost(0, 399);
1257  EXPECT_EQ("0,0", event_handler.GetLocationAndReset());
1258
1259  Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
1260}
1261
1262namespace {
1263
1264DisplayInfo CreateDisplayInfo(int64 id,
1265                              int y,
1266                              gfx::Display::Rotation rotation) {
1267  DisplayInfo info(id, "", false);
1268  info.SetBounds(gfx::Rect(0, y, 500, 500));
1269  info.set_rotation(rotation);
1270  return info;
1271}
1272
1273}  // namespace
1274
1275// Make sure that the compositor based mirroring can switch
1276// from/to dock mode.
1277TEST_F(DisplayControllerTest, DockToSingle) {
1278  if (!SupportsMultipleDisplays())
1279    return;
1280
1281  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1282
1283  const int64 internal_id = 1;
1284
1285  const DisplayInfo internal_display_info =
1286      CreateDisplayInfo(internal_id, 0, gfx::Display::ROTATE_0);
1287  const DisplayInfo external_display_info =
1288      CreateDisplayInfo(2, 1, gfx::Display::ROTATE_90);
1289
1290  std::vector<DisplayInfo> display_info_list;
1291  // Extended
1292  display_info_list.push_back(internal_display_info);
1293  display_info_list.push_back(external_display_info);
1294  display_manager->OnNativeDisplaysChanged(display_info_list);
1295  const int64 internal_display_id =
1296      test::DisplayManagerTestApi(display_manager).
1297      SetFirstDisplayAsInternalDisplay();
1298  EXPECT_EQ(internal_id, internal_display_id);
1299  EXPECT_EQ(2U, display_manager->GetNumDisplays());
1300
1301  // Dock mode.
1302  display_info_list.clear();
1303  display_info_list.push_back(external_display_info);
1304  display_manager->OnNativeDisplaysChanged(display_info_list);
1305  EXPECT_EQ(1U, display_manager->GetNumDisplays());
1306  EXPECT_FALSE(Shell::GetPrimaryRootWindow()->GetHost()->
1307               GetRootTransform().IsIdentityOrIntegerTranslation());
1308
1309  // Switch to single mode and make sure the transform is the one
1310  // for the internal display.
1311  display_info_list.clear();
1312  display_info_list.push_back(internal_display_info);
1313  display_manager->OnNativeDisplaysChanged(display_info_list);
1314  EXPECT_TRUE(Shell::GetPrimaryRootWindow()->GetHost()->
1315              GetRootTransform().IsIdentityOrIntegerTranslation());
1316}
1317
1318#if defined(USE_X11)
1319TEST_F(DisplayControllerTest, XWidowNameForRootWindow) {
1320  EXPECT_EQ("aura_root_0", GetXWindowName(
1321      Shell::GetPrimaryRootWindow()->GetHost()));
1322
1323  // Multiple display.
1324  UpdateDisplay("200x200,300x300");
1325  aura::Window* primary, *secondary;
1326  GetPrimaryAndSeconary(&primary, &secondary);
1327  EXPECT_EQ("aura_root_0", GetXWindowName(primary->GetHost()));
1328  EXPECT_EQ("aura_root_x", GetXWindowName(secondary->GetHost()));
1329
1330  // Swap primary.
1331  primary = secondary = NULL;
1332  Shell::GetInstance()->display_controller()->SwapPrimaryDisplay();
1333  GetPrimaryAndSeconary(&primary, &secondary);
1334  EXPECT_EQ("aura_root_0", GetXWindowName(primary->GetHost()));
1335  EXPECT_EQ("aura_root_x", GetXWindowName(secondary->GetHost()));
1336
1337  // Switching back to single display.
1338  UpdateDisplay("300x400");
1339  EXPECT_EQ("aura_root_0", GetXWindowName(
1340      Shell::GetPrimaryRootWindow()->GetHost()));
1341}
1342#endif
1343
1344}  // namespace ash
1345