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