desktop_screen_x11_unittest.cc revision f2477e01787aa58f445919b809d89e252beef54f
1// Copyright (c) 2013 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 "ui/views/widget/desktop_aura/desktop_screen_x11.h"
6
7#include "base/message_loop/message_loop.h"
8#include "testing/gtest/include/gtest/gtest.h"
9#include "ui/gfx/display_observer.h"
10#include "ui/views/test/views_test_base.h"
11#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
12#include "ui/views/widget/desktop_aura/desktop_root_window_host_x11.h"
13
14namespace views {
15
16const int64 kFirstDisplay = 5321829;
17const int64 kSecondDisplay = 928310;
18
19class DesktopScreenX11Test : public views::ViewsTestBase,
20                             public gfx::DisplayObserver {
21 public:
22  DesktopScreenX11Test() {}
23  virtual ~DesktopScreenX11Test() {}
24
25  // Overridden from testing::Test:
26  virtual void SetUp() OVERRIDE {
27    ViewsTestBase::SetUp();
28    // Initialize the world to the single monitor case.
29    std::vector<gfx::Display> displays;
30    displays.push_back(gfx::Display(kFirstDisplay, gfx::Rect(0, 0, 640, 480)));
31    screen_.reset(new DesktopScreenX11(displays));
32    screen_->AddObserver(this);
33  }
34
35  virtual void TearDown() OVERRIDE {
36    screen_.reset();
37    ViewsTestBase::TearDown();
38  }
39
40 protected:
41  std::vector<gfx::Display> changed_display_;
42  std::vector<gfx::Display> added_display_;
43  std::vector<gfx::Display> removed_display_;
44
45  DesktopScreenX11* screen() { return screen_.get(); }
46
47  void ResetDisplayChanges() {
48    changed_display_.clear();
49    added_display_.clear();
50    removed_display_.clear();
51  }
52
53  Widget* BuildTopLevelDesktopWidget(const gfx::Rect& bounds) {
54    Widget* toplevel = new Widget;
55    Widget::InitParams toplevel_params =
56        CreateParams(Widget::InitParams::TYPE_WINDOW);
57    toplevel_params.native_widget =
58        new views::DesktopNativeWidgetAura(toplevel);
59    toplevel_params.bounds = bounds;
60    toplevel->Init(toplevel_params);
61    return toplevel;
62  }
63
64 private:
65  // Overridden from gfx::DisplayObserver:
66  virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE {
67    changed_display_.push_back(display);
68  }
69
70  virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE {
71    added_display_.push_back(new_display);
72  }
73
74  virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE {
75    removed_display_.push_back(old_display);
76  }
77
78  scoped_ptr<DesktopScreenX11> screen_;
79
80  DISALLOW_COPY_AND_ASSIGN(DesktopScreenX11Test);
81};
82
83TEST_F(DesktopScreenX11Test, BoundsChangeSingleMonitor) {
84  std::vector<gfx::Display> displays;
85  displays.push_back(gfx::Display(kFirstDisplay, gfx::Rect(0, 0, 1024, 768)));
86  screen()->ProcessDisplayChange(displays);
87
88  EXPECT_EQ(1u, changed_display_.size());
89  EXPECT_EQ(0u, added_display_.size());
90  EXPECT_EQ(0u, removed_display_.size());
91}
92
93TEST_F(DesktopScreenX11Test, AddMonitorToTheRight) {
94  std::vector<gfx::Display> displays;
95  displays.push_back(gfx::Display(kFirstDisplay, gfx::Rect(0, 0, 640, 480)));
96  displays.push_back(gfx::Display(kSecondDisplay,
97                                  gfx::Rect(640, 0, 1024, 768)));
98  screen()->ProcessDisplayChange(displays);
99
100  EXPECT_EQ(0u, changed_display_.size());
101  EXPECT_EQ(1u, added_display_.size());
102  EXPECT_EQ(0u, removed_display_.size());
103}
104
105TEST_F(DesktopScreenX11Test, AddMonitorToTheLeft) {
106  std::vector<gfx::Display> displays;
107  displays.push_back(gfx::Display(kSecondDisplay, gfx::Rect(0, 0, 1024, 768)));
108  displays.push_back(gfx::Display(kFirstDisplay, gfx::Rect(1024, 0, 640, 480)));
109  screen()->ProcessDisplayChange(displays);
110
111  EXPECT_EQ(1u, changed_display_.size());
112  EXPECT_EQ(1u, added_display_.size());
113  EXPECT_EQ(0u, removed_display_.size());
114}
115
116TEST_F(DesktopScreenX11Test, RemoveMonitorOnRight) {
117  std::vector<gfx::Display> displays;
118  displays.push_back(gfx::Display(kFirstDisplay, gfx::Rect(0, 0, 640, 480)));
119  displays.push_back(gfx::Display(kSecondDisplay,
120                                  gfx::Rect(640, 0, 1024, 768)));
121  screen()->ProcessDisplayChange(displays);
122
123  ResetDisplayChanges();
124
125  displays.clear();
126  displays.push_back(gfx::Display(kFirstDisplay, gfx::Rect(0, 0, 640, 480)));
127  screen()->ProcessDisplayChange(displays);
128
129  EXPECT_EQ(0u, changed_display_.size());
130  EXPECT_EQ(0u, added_display_.size());
131  EXPECT_EQ(1u, removed_display_.size());
132}
133
134TEST_F(DesktopScreenX11Test, RemoveMonitorOnLeft) {
135  std::vector<gfx::Display> displays;
136  displays.push_back(gfx::Display(kFirstDisplay, gfx::Rect(0, 0, 640, 480)));
137  displays.push_back(gfx::Display(kSecondDisplay,
138                                  gfx::Rect(640, 0, 1024, 768)));
139  screen()->ProcessDisplayChange(displays);
140
141  ResetDisplayChanges();
142
143  displays.clear();
144  displays.push_back(gfx::Display(kSecondDisplay, gfx::Rect(0, 0, 1024, 768)));
145  screen()->ProcessDisplayChange(displays);
146
147  EXPECT_EQ(1u, changed_display_.size());
148  EXPECT_EQ(0u, added_display_.size());
149  EXPECT_EQ(1u, removed_display_.size());
150}
151
152TEST_F(DesktopScreenX11Test, GetDisplayNearestPoint) {
153  std::vector<gfx::Display> displays;
154  displays.push_back(gfx::Display(kFirstDisplay, gfx::Rect(0, 0, 640, 480)));
155  displays.push_back(gfx::Display(kSecondDisplay,
156                                  gfx::Rect(640, 0, 1024, 768)));
157  screen()->ProcessDisplayChange(displays);
158
159  EXPECT_EQ(kSecondDisplay,
160            screen()->GetDisplayNearestPoint(gfx::Point(650, 10)).id());
161  EXPECT_EQ(kFirstDisplay,
162            screen()->GetDisplayNearestPoint(gfx::Point(10, 10)).id());
163  EXPECT_EQ(kFirstDisplay,
164            screen()->GetDisplayNearestPoint(gfx::Point(10000, 10000)).id());
165}
166
167TEST_F(DesktopScreenX11Test, GetDisplayMatchingBasic) {
168  std::vector<gfx::Display> displays;
169  displays.push_back(gfx::Display(kFirstDisplay, gfx::Rect(0, 0, 640, 480)));
170  displays.push_back(gfx::Display(kSecondDisplay,
171                                  gfx::Rect(640, 0, 1024, 768)));
172  screen()->ProcessDisplayChange(displays);
173
174  EXPECT_EQ(kSecondDisplay,
175            screen()->GetDisplayMatching(gfx::Rect(700, 20, 100, 100)).id());
176}
177
178TEST_F(DesktopScreenX11Test, GetDisplayMatchingOverlap) {
179  std::vector<gfx::Display> displays;
180  displays.push_back(gfx::Display(kFirstDisplay, gfx::Rect(0, 0, 640, 480)));
181  displays.push_back(gfx::Display(kSecondDisplay,
182                                  gfx::Rect(640, 0, 1024, 768)));
183  screen()->ProcessDisplayChange(displays);
184
185  EXPECT_EQ(kSecondDisplay,
186            screen()->GetDisplayMatching(gfx::Rect(630, 20, 100, 100)).id());
187}
188
189TEST_F(DesktopScreenX11Test, GetPrimaryDisplay) {
190  std::vector<gfx::Display> displays;
191  displays.push_back(gfx::Display(kFirstDisplay,
192                                  gfx::Rect(640, 0, 1024, 768)));
193  displays.push_back(gfx::Display(kSecondDisplay, gfx::Rect(0, 0, 640, 480)));
194  screen()->ProcessDisplayChange(displays);
195
196  // The first display in the list is always the primary, even if other
197  // displays are to the left in screen layout.
198  EXPECT_EQ(kFirstDisplay, screen()->GetPrimaryDisplay().id());
199}
200
201TEST_F(DesktopScreenX11Test, GetWindowAtScreenPoint) {
202  Widget* window_one = BuildTopLevelDesktopWidget(gfx::Rect(10, 10, 10, 10));
203  Widget* window_two = BuildTopLevelDesktopWidget(gfx::Rect(50, 50, 10, 10));
204  Widget* window_three = BuildTopLevelDesktopWidget(gfx::Rect(15, 15, 20, 20));
205
206  // Make sure the internal state of DesktopRootWindowHostX11 is set up
207  // correctly.
208  ASSERT_EQ(3u, DesktopRootWindowHostX11::GetAllOpenWindows().size());
209
210  EXPECT_EQ(window_one->GetNativeWindow(),
211            screen()->GetWindowAtScreenPoint(gfx::Point(15, 15)));
212  EXPECT_EQ(window_two->GetNativeWindow(),
213            screen()->GetWindowAtScreenPoint(gfx::Point(55, 55)));
214  EXPECT_EQ(NULL,
215            screen()->GetWindowAtScreenPoint(gfx::Point(100, 100)));
216
217  // Bring the third window in front. It overlaps with the first window.
218  // Hit-testing on the intersecting region should give the third window.
219  window_three->Activate();
220  EXPECT_EQ(window_three->GetNativeWindow(),
221            screen()->GetWindowAtScreenPoint(gfx::Point(15, 15)));
222
223  window_one->CloseNow();
224  window_two->CloseNow();
225}
226
227TEST_F(DesktopScreenX11Test, GetDisplayNearestWindow) {
228  // Set up a two monitor situation.
229  std::vector<gfx::Display> displays;
230  displays.push_back(gfx::Display(kFirstDisplay, gfx::Rect(0, 0, 640, 480)));
231  displays.push_back(gfx::Display(kSecondDisplay,
232                                  gfx::Rect(640, 0, 1024, 768)));
233  screen()->ProcessDisplayChange(displays);
234
235  Widget* window_one = BuildTopLevelDesktopWidget(gfx::Rect(10, 10, 10, 10));
236  Widget* window_two = BuildTopLevelDesktopWidget(gfx::Rect(650, 50, 10, 10));
237
238  EXPECT_EQ(
239      kFirstDisplay,
240      screen()->GetDisplayNearestWindow(window_one->GetNativeWindow()).id());
241  EXPECT_EQ(
242      kSecondDisplay,
243      screen()->GetDisplayNearestWindow(window_two->GetNativeWindow()).id());
244
245  window_one->CloseNow();
246  window_two->CloseNow();
247}
248
249}  // namespace views
250