blob: 8469eb5fb148f6d0cea9a19a5b1c4433b1c85539 [file] [log] [blame]
[email protected]c39be8f2012-06-15 22:58:361// 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/monitor/monitor_controller.h"
[email protected]a5e71c92012-06-22 22:09:086#include "ash/monitor/multi_monitor_manager.h"
[email protected]c39be8f2012-06-15 22:58:367#include "ash/shell.h"
8#include "ash/test/ash_test_base.h"
[email protected]0f81f442012-06-22 06:20:279#include "ash/wm/window_cycle_controller.h"
[email protected]c39be8f2012-06-15 22:58:3610#include "ash/wm/window_util.h"
11#include "ui/aura/client/activation_client.h"
12#include "ui/aura/client/capture_client.h"
[email protected]a5e71c92012-06-22 22:09:0813#include "ui/aura/env.h"
[email protected]c39be8f2012-06-15 22:58:3614#include "ui/aura/focus_manager.h"
15#include "ui/aura/root_window.h"
16#include "ui/aura/test/event_generator.h"
[email protected]a5e71c92012-06-22 22:09:0817#include "ui/aura/test/test_windows.h"
[email protected]c39be8f2012-06-15 22:58:3618#include "ui/aura/window.h"
19#include "ui/base/cursor/cursor.h"
[email protected]a5e71c92012-06-22 22:09:0820#include "ui/gfx/display.h"
[email protected]c39be8f2012-06-15 22:58:3621#include "ui/views/widget/widget.h"
22#include "ui/views/widget/widget_delegate.h"
23
24namespace ash {
25namespace {
26
27views::Widget* CreateTestWidget(const gfx::Rect& bounds) {
28 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
29 params.bounds = bounds;
30 views::Widget* widget = new views::Widget;
31 widget->Init(params);
[email protected]0f81f442012-06-22 06:20:2732 widget->Show();
[email protected]c39be8f2012-06-15 22:58:3633 return widget;
34}
35
36class ModalWidgetDelegate : public views::WidgetDelegateView {
37 public:
38 ModalWidgetDelegate() {}
39 virtual ~ModalWidgetDelegate() {}
40
41 // Overridden from views::WidgetDelegate:
42 virtual views::View* GetContentsView() OVERRIDE {
43 return this;
44 }
45 virtual ui::ModalType GetModalType() const OVERRIDE {
46 return ui::MODAL_TYPE_SYSTEM;
47 }
48
49 private:
50 DISALLOW_COPY_AND_ASSIGN(ModalWidgetDelegate);
51};
52
53} // namespace
54
55class ExtendedDesktopTest : public test::AshTestBase {
56 public:
57 ExtendedDesktopTest() {}
58 virtual ~ExtendedDesktopTest() {}
59
60 virtual void SetUp() OVERRIDE {
61 internal::MonitorController::SetExtendedDesktopEnabled(true);
62 AshTestBase::SetUp();
63 }
64
65 virtual void TearDown() OVERRIDE {
66 AshTestBase::TearDown();
67 internal::MonitorController::SetExtendedDesktopEnabled(false);
68 }
69
[email protected]a5e71c92012-06-22 22:09:0870 protected:
71 internal::MultiMonitorManager* monitor_manager() {
72 return static_cast<internal::MultiMonitorManager*>(
73 aura::Env::GetInstance()->monitor_manager());
74 }
75
[email protected]c39be8f2012-06-15 22:58:3676 private:
77 DISALLOW_COPY_AND_ASSIGN(ExtendedDesktopTest);
78};
79
80// Test conditions that root windows in extended desktop mode
81// must satisfy.
82TEST_F(ExtendedDesktopTest, Basic) {
83 UpdateMonitor("0+0-1000x600,1001+0-600x400");
84 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
85
86 // All root windows must have the root window controller.
87 ASSERT_EQ(2U, root_windows.size());
88 for (Shell::RootWindowList::const_iterator iter = root_windows.begin();
89 iter != root_windows.end(); ++iter) {
90 EXPECT_TRUE(wm::GetRootWindowController(*iter) != NULL);
91 }
92 // Make sure root windows share the same controllers.
93 EXPECT_EQ(root_windows[0]->GetFocusManager(),
94 root_windows[1]->GetFocusManager());
95 EXPECT_EQ(aura::client::GetActivationClient(root_windows[0]),
96 aura::client::GetActivationClient(root_windows[1]));
97 EXPECT_EQ(aura::client::GetCaptureClient(root_windows[0]),
98 aura::client::GetCaptureClient(root_windows[1]));
99}
100
101TEST_F(ExtendedDesktopTest, Activation) {
102 UpdateMonitor("0+0-1000x600,1001+0-600x400");
103 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
104
105 // Move the active root window to the secondary.
106 Shell::GetInstance()->set_active_root_window(root_windows[1]);
107
108 views::Widget* widget_on_2nd = CreateTestWidget(gfx::Rect(10, 10, 100, 100));
109 EXPECT_EQ(root_windows[1], widget_on_2nd->GetNativeView()->GetRootWindow());
[email protected]c39be8f2012-06-15 22:58:36110
111 // Move the active root window back to the primary.
112 Shell::GetInstance()->set_active_root_window(root_windows[0]);
113
114 views::Widget* widget_on_1st = CreateTestWidget(gfx::Rect(10, 10, 100, 100));
115 EXPECT_EQ(root_windows[0], widget_on_1st->GetNativeView()->GetRootWindow());
[email protected]c39be8f2012-06-15 22:58:36116
117 aura::test::EventGenerator generator_1st(root_windows[0]);
118 aura::test::EventGenerator generator_2nd(root_windows[1]);
119
120 // Clicking a window changes the active window and active root window.
121 generator_2nd.MoveMouseToCenterOf(widget_on_2nd->GetNativeView());
122 generator_2nd.ClickLeftButton();
123
124 EXPECT_EQ(widget_on_2nd->GetNativeView(),
125 root_windows[0]->GetFocusManager()->GetFocusedWindow());
126 EXPECT_TRUE(wm::IsActiveWindow(widget_on_2nd->GetNativeView()));
127
128 generator_1st.MoveMouseToCenterOf(widget_on_1st->GetNativeView());
129 generator_1st.ClickLeftButton();
130
131 EXPECT_EQ(widget_on_1st->GetNativeView(),
132 root_windows[0]->GetFocusManager()->GetFocusedWindow());
133 EXPECT_TRUE(wm::IsActiveWindow(widget_on_1st->GetNativeView()));
134}
135
136TEST_F(ExtendedDesktopTest, SystemModal) {
137 UpdateMonitor("0+0-1000x600,1001+0-600x400");
138 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
139 Shell::GetInstance()->set_active_root_window(root_windows[0]);
140
141 views::Widget* widget_on_1st = CreateTestWidget(gfx::Rect(10, 10, 100, 100));
[email protected]c39be8f2012-06-15 22:58:36142 EXPECT_TRUE(wm::IsActiveWindow(widget_on_1st->GetNativeView()));
143 EXPECT_EQ(root_windows[0], Shell::GetActiveRootWindow());
144
145 // Change the active root window to 2nd.
146 Shell::GetInstance()->set_active_root_window(root_windows[1]);
147
148 // Open system modal. Make sure it's on 2nd root window and active.
149 views::Widget* modal_widget = views::Widget::CreateWindowWithParent(
150 new ModalWidgetDelegate(), NULL);
151 modal_widget->Show();
152 EXPECT_TRUE(wm::IsActiveWindow(modal_widget->GetNativeView()));
153 EXPECT_EQ(root_windows[1], modal_widget->GetNativeView()->GetRootWindow());
154 EXPECT_EQ(root_windows[1], Shell::GetActiveRootWindow());
155
156 // Clicking a widget on widget_on_1st monitor should not change activation.
157 aura::test::EventGenerator generator_1st(root_windows[0]);
158 generator_1st.MoveMouseToCenterOf(widget_on_1st->GetNativeView());
159 generator_1st.ClickLeftButton();
160 EXPECT_TRUE(wm::IsActiveWindow(modal_widget->GetNativeView()));
161 EXPECT_EQ(root_windows[1], Shell::GetActiveRootWindow());
162
163 // Close system modal and so clicking a widget should work now.
164 modal_widget->Close();
165 generator_1st.MoveMouseToCenterOf(widget_on_1st->GetNativeView());
166 generator_1st.ClickLeftButton();
167 EXPECT_TRUE(wm::IsActiveWindow(widget_on_1st->GetNativeView()));
168 EXPECT_EQ(root_windows[0], Shell::GetActiveRootWindow());
169}
170
171TEST_F(ExtendedDesktopTest, TestCursor) {
172 UpdateMonitor("0+0-1000x600,1001+0-600x400");
173 Shell::GetInstance()->ShowCursor(false);
174 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
175 EXPECT_FALSE(root_windows[0]->cursor_shown());
176 EXPECT_FALSE(root_windows[1]->cursor_shown());
177 Shell::GetInstance()->ShowCursor(true);
178 EXPECT_TRUE(root_windows[0]->cursor_shown());
179 EXPECT_TRUE(root_windows[1]->cursor_shown());
180
181 EXPECT_EQ(ui::kCursorPointer, root_windows[0]->last_cursor().native_type());
182 EXPECT_EQ(ui::kCursorPointer, root_windows[1]->last_cursor().native_type());
183 Shell::GetInstance()->SetCursor(ui::kCursorCopy);
184 EXPECT_EQ(ui::kCursorCopy, root_windows[0]->last_cursor().native_type());
185 EXPECT_EQ(ui::kCursorCopy, root_windows[1]->last_cursor().native_type());
186}
187
[email protected]0f81f442012-06-22 06:20:27188TEST_F(ExtendedDesktopTest, CycleWindows) {
[email protected]20c59762012-06-23 01:10:24189 internal::MonitorController::SetVirtualScreenCoordinatesEnabled(true);
190 UpdateMonitor("0+0-700x500,0+0-500x500");
[email protected]0f81f442012-06-22 06:20:27191 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
[email protected]20c59762012-06-23 01:10:24192 // Emulate virtual screen coordinate system.
193 root_windows[0]->SetBounds(gfx::Rect(0, 0, 700, 500));
194 root_windows[1]->SetBounds(gfx::Rect(700, 0, 500, 500));
195
[email protected]0f81f442012-06-22 06:20:27196 WindowCycleController* controller =
197 Shell::GetInstance()->window_cycle_controller();
198
[email protected]0f81f442012-06-22 06:20:27199 views::Widget* d1_w1 = CreateTestWidget(gfx::Rect(10, 10, 100, 100));
200 EXPECT_EQ(root_windows[0], d1_w1->GetNativeView()->GetRootWindow());
[email protected]20c59762012-06-23 01:10:24201 views::Widget* d2_w1 = CreateTestWidget(gfx::Rect(800, 10, 100, 100));
[email protected]0f81f442012-06-22 06:20:27202 EXPECT_EQ(root_windows[1], d2_w1->GetNativeView()->GetRootWindow());
203 EXPECT_TRUE(wm::IsActiveWindow(d2_w1->GetNativeView()));
204
205 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
206 EXPECT_TRUE(wm::IsActiveWindow(d1_w1->GetNativeView()));
207 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
208 EXPECT_TRUE(wm::IsActiveWindow(d2_w1->GetNativeView()));
209 controller->HandleCycleWindow(WindowCycleController::BACKWARD, false);
210 EXPECT_TRUE(wm::IsActiveWindow(d1_w1->GetNativeView()));
211 controller->HandleCycleWindow(WindowCycleController::BACKWARD, false);
212 EXPECT_TRUE(wm::IsActiveWindow(d2_w1->GetNativeView()));
213
214 // Cycle through all windows across root windows.
[email protected]20c59762012-06-23 01:10:24215 views::Widget* d1_w2 = CreateTestWidget(gfx::Rect(10, 200, 100, 100));
[email protected]0f81f442012-06-22 06:20:27216 EXPECT_EQ(root_windows[0], d1_w2->GetNativeView()->GetRootWindow());
[email protected]20c59762012-06-23 01:10:24217 views::Widget* d2_w2 = CreateTestWidget(gfx::Rect(800, 200, 100, 100));
[email protected]0f81f442012-06-22 06:20:27218 EXPECT_EQ(root_windows[1], d2_w2->GetNativeView()->GetRootWindow());
219
220 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
221 EXPECT_TRUE(wm::IsActiveWindow(d2_w1->GetNativeView()));
222 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
223 EXPECT_TRUE(wm::IsActiveWindow(d1_w2->GetNativeView()));
224 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
225 EXPECT_TRUE(wm::IsActiveWindow(d1_w1->GetNativeView()));
226 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
227 EXPECT_TRUE(wm::IsActiveWindow(d2_w2->GetNativeView()));
228
229 // Backwards
230 controller->HandleCycleWindow(WindowCycleController::BACKWARD, true);
231 EXPECT_TRUE(wm::IsActiveWindow(d1_w1->GetNativeView()));
232 controller->HandleCycleWindow(WindowCycleController::BACKWARD, true);
233 EXPECT_TRUE(wm::IsActiveWindow(d1_w2->GetNativeView()));
234 controller->HandleCycleWindow(WindowCycleController::BACKWARD, true);
235 EXPECT_TRUE(wm::IsActiveWindow(d2_w1->GetNativeView()));
236 controller->HandleCycleWindow(WindowCycleController::BACKWARD, true);
237 EXPECT_TRUE(wm::IsActiveWindow(d2_w2->GetNativeView()));
[email protected]20c59762012-06-23 01:10:24238 internal::MonitorController::SetVirtualScreenCoordinatesEnabled(false);
239}
240
241TEST_F(ExtendedDesktopTest, GetRootWindowAt) {
242 internal::MonitorController::SetVirtualScreenCoordinatesEnabled(true);
243 UpdateMonitor("0+0-700x500,0+0-500x500");
244 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
245 // Emulate virtual screen coordinate system.
246 root_windows[0]->SetBounds(gfx::Rect(500, 0, 700, 500));
247 root_windows[1]->SetBounds(gfx::Rect(0, 0, 500, 500));
248
249 EXPECT_EQ(root_windows[1], Shell::GetRootWindowAt(gfx::Point(100, 100)));
250 EXPECT_EQ(root_windows[1], Shell::GetRootWindowAt(gfx::Point(499, 100)));
251 EXPECT_EQ(root_windows[0], Shell::GetRootWindowAt(gfx::Point(500, 300)));
252 EXPECT_EQ(root_windows[0], Shell::GetRootWindowAt(gfx::Point(1200,300)));
253
254 // Zero origin.
255 EXPECT_EQ(root_windows[1], Shell::GetRootWindowAt(gfx::Point(0, 0)));
256
257 // Out of range point should return the primary root window
258 EXPECT_EQ(root_windows[0], Shell::GetRootWindowAt(gfx::Point(-100, 0)));
259 EXPECT_EQ(root_windows[0], Shell::GetRootWindowAt(gfx::Point(1201, 100)));
260 internal::MonitorController::SetVirtualScreenCoordinatesEnabled(false);
261}
262
263TEST_F(ExtendedDesktopTest, GetRootWindowMatching) {
264 internal::MonitorController::SetVirtualScreenCoordinatesEnabled(true);
265 UpdateMonitor("0+0-700x500,0+0-500x500");
266 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
267 // Emulate virtual screen coordinate system.
268 root_windows[0]->SetBounds(gfx::Rect(500, 0, 700, 500));
269 root_windows[1]->SetBounds(gfx::Rect(0, 0, 500, 500));
270
271 // Containing rect.
272 EXPECT_EQ(root_windows[1],
273 Shell::GetRootWindowMatching(gfx::Rect(200, 10, 50, 50)));
274 EXPECT_EQ(root_windows[0],
275 Shell::GetRootWindowMatching(gfx::Rect(600, 10, 50, 50)));
276
277 // Intersecting rect.
278 EXPECT_EQ(root_windows[1],
279 Shell::GetRootWindowMatching(gfx::Rect(300, 0, 300, 300)));
280 EXPECT_EQ(root_windows[0],
281 Shell::GetRootWindowMatching(gfx::Rect(400, 0, 300, 300)));
282
283 // Zero origin.
284 EXPECT_EQ(root_windows[1],
285 Shell::GetRootWindowMatching(gfx::Rect(0, 0, 0, 0)));
286 EXPECT_EQ(root_windows[1],
287 Shell::GetRootWindowMatching(gfx::Rect(0, 0, 1, 1)));
288
289 // Empty rect.
290 EXPECT_EQ(root_windows[1],
291 Shell::GetRootWindowMatching(gfx::Rect(100, 100, 0, 0)));
292 EXPECT_EQ(root_windows[0],
293 Shell::GetRootWindowMatching(gfx::Rect(600, 100, 0, 0)));
294
295 // Out of range rect should return the primary root window.
296 EXPECT_EQ(root_windows[0],
297 Shell::GetRootWindowMatching(gfx::Rect(-100, -300, 50, 50)));
298 EXPECT_EQ(root_windows[0],
299 Shell::GetRootWindowMatching(gfx::Rect(0, 2000, 50, 50)));
300 internal::MonitorController::SetVirtualScreenCoordinatesEnabled(false);
[email protected]0f81f442012-06-22 06:20:27301}
302
[email protected]a5e71c92012-06-22 22:09:08303TEST_F(ExtendedDesktopTest, Capture) {
304 UpdateMonitor("0+0-1000x600,1001+0-600x400");
305 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
306
307 aura::test::EventCountDelegate r1_d1;
308 aura::test::EventCountDelegate r1_d2;
309 aura::test::EventCountDelegate r2_d1;
310
311 scoped_ptr<aura::Window> r1_w1(aura::test::CreateTestWindowWithDelegate(
312 &r1_d1, 0, gfx::Rect(10, 10, 100, 100), root_windows[0]));
313 scoped_ptr<aura::Window> r1_w2(aura::test::CreateTestWindowWithDelegate(
314 &r1_d2, 0, gfx::Rect(10, 100, 100, 100), root_windows[0]));
315 scoped_ptr<aura::Window> r2_w1(aura::test::CreateTestWindowWithDelegate(
316 &r2_d1, 0, gfx::Rect(10, 10, 100, 100), root_windows[1]));
317 r1_w1->SetCapture();
318
319 EXPECT_EQ(r1_w1.get(),
320 aura::client::GetCaptureWindow(r2_w1->GetRootWindow()));
321 aura::test::EventGenerator generator2(root_windows[1]);
322 generator2.MoveMouseToCenterOf(r2_w1.get());
323 generator2.ClickLeftButton();
324 EXPECT_EQ("0 0 0", r2_d1.GetMouseMotionCountsAndReset());
325 EXPECT_EQ("0 0", r2_d1.GetMouseButtonCountsAndReset());
326 EXPECT_EQ("1 1 0", r1_d1.GetMouseMotionCountsAndReset());
327 EXPECT_EQ("1 1", r1_d1.GetMouseButtonCountsAndReset());
328
329 r1_w2->SetCapture();
330 EXPECT_EQ(r1_w2.get(),
331 aura::client::GetCaptureWindow(r2_w1->GetRootWindow()));
332 generator2.MoveMouseBy(10, 10);
333 generator2.ClickLeftButton();
334 EXPECT_EQ("0 0 0", r2_d1.GetMouseMotionCountsAndReset());
335 EXPECT_EQ("0 0", r2_d1.GetMouseButtonCountsAndReset());
336 // mouse is already entered.
337 EXPECT_EQ("0 1 0", r1_d2.GetMouseMotionCountsAndReset());
338 EXPECT_EQ("1 1", r1_d2.GetMouseButtonCountsAndReset());
339
340 r1_w2->ReleaseCapture();
341 EXPECT_EQ(NULL,
342 aura::client::GetCaptureWindow(r2_w1->GetRootWindow()));
343 generator2.MoveMouseBy(-10, -10);
344 generator2.ClickLeftButton();
345 EXPECT_EQ("1 1 0", r2_d1.GetMouseMotionCountsAndReset());
346 EXPECT_EQ("1 1", r2_d1.GetMouseButtonCountsAndReset());
347 // Make sure the mouse_moved_handler_ is properly reset.
348 EXPECT_EQ("0 0 0", r1_d2.GetMouseMotionCountsAndReset());
349 EXPECT_EQ("0 0", r1_d2.GetMouseButtonCountsAndReset());
350}
351
352namespace internal {
353// Test if the Window::ConvertPointToWindow works across root windows.
354// TODO(oshima): Move multiple display suport and this test to aura.
355TEST_F(ExtendedDesktopTest, ConvertPoint) {
356 UpdateMonitor("0+0-1000x600,1001+0-600x400");
357 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
358 gfx::Display& display_1 =
359 monitor_manager()->FindDisplayForRootWindow(root_windows[0]);
360 EXPECT_EQ("0,0", display_1.bounds().origin().ToString());
361 gfx::Display& display_2 =
362 monitor_manager()->FindDisplayForRootWindow(root_windows[1]);
363 Shell::GetInstance()->set_active_root_window(root_windows[0]);
364 aura::Window* d1 =
365 CreateTestWidget(gfx::Rect(10, 10, 100, 100))->GetNativeView();
366 Shell::GetInstance()->set_active_root_window(root_windows[1]);
367 aura::Window* d2 =
368 CreateTestWidget(gfx::Rect(20, 20, 100, 100))->GetNativeView();
369
370 // TODO(oshima):
371 // This is a hack to emulate virtual screen coordinates. Cleanup this
372 // when the virtual screen coordinates is implemented.a
373 gfx::Rect bounds = display_2.bounds();
374 bounds.set_origin(gfx::Point(500, 500));
375 display_2.set_bounds(bounds);
376 // Convert point in the Root2's window to the Root1's window Coord.
377 gfx::Point p(0, 0);
378 aura::Window::ConvertPointToWindow(root_windows[1], root_windows[0], &p);
379 EXPECT_EQ("500,500", p.ToString());
380 p.SetPoint(0, 0);
381 aura::Window::ConvertPointToWindow(d2, d1, &p);
382 EXPECT_EQ("510,510", p.ToString());
383
384 // Convert point in the Root1's window to the Root2's window Coord.
385 p.SetPoint(0, 0);
386 aura::Window::ConvertPointToWindow(root_windows[0], root_windows[1], &p);
387 EXPECT_EQ("-500,-500", p.ToString());
388 p.SetPoint(0, 0);
389 aura::Window::ConvertPointToWindow(d1, d2, &p);
390 EXPECT_EQ("-510,-510", p.ToString());
391}
392} // namespace internal
[email protected]c39be8f2012-06-15 22:58:36393} // namespace ash