1 // Copyright 2014 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.
5 #include "athena/wm/public/window_manager.h"
7 #include "athena/screen/public/screen_manager.h"
8 #include "athena/test/athena_test_base.h"
9 #include "athena/wm/public/window_list_provider.h"
10 #include "athena/wm/split_view_controller.h"
11 #include "athena/wm/test/window_manager_impl_test_api.h"
12 #include "athena/wm/window_manager_impl.h"
13 #include "ui/aura/client/window_tree_client.h"
14 #include "ui/aura/test/test_window_delegate.h"
15 #include "ui/aura/window.h"
16 #include "ui/base/hit_test.h"
17 #include "ui/events/test/event_generator.h"
18 #include "ui/gfx/display.h"
19 #include "ui/gfx/screen.h"
20 #include "ui/wm/core/window_util.h"
24 class WindowManagerTest : public test::AthenaTestBase {
26 WindowManagerTest() {}
27 virtual ~WindowManagerTest() {}
29 scoped_ptr<aura::Window> CreateAndActivateWindow(
30 aura::WindowDelegate* delegate) {
31 scoped_ptr<aura::Window> window(CreateTestWindow(delegate, gfx::Rect()));
33 wm::ActivateWindow(window.get());
38 DISALLOW_COPY_AND_ASSIGN(WindowManagerTest);
41 TEST_F(WindowManagerTest, OverviewModeBasics) {
42 aura::test::TestWindowDelegate delegate;
43 scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate));
44 scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate));
46 test::WindowManagerImplTestApi wm_api;
47 wm::ActivateWindow(second.get());
49 ASSERT_FALSE(WindowManager::Get()->IsOverviewModeActive());
50 EXPECT_EQ(first->bounds().ToString(), second->bounds().ToString());
51 EXPECT_EQ(gfx::Screen::GetNativeScreen()
56 first->bounds().size().ToString());
57 EXPECT_FALSE(WindowManager::Get()->IsOverviewModeActive());
59 // Tests that going into overview mode does not change the window bounds.
60 WindowManager::Get()->ToggleOverview();
61 ASSERT_TRUE(WindowManager::Get()->IsOverviewModeActive());
62 EXPECT_EQ(first->bounds().ToString(), second->bounds().ToString());
63 EXPECT_EQ(gfx::Screen::GetNativeScreen()
68 first->bounds().size().ToString());
69 EXPECT_TRUE(first->IsVisible());
70 EXPECT_TRUE(second->IsVisible());
72 // Terminate overview mode. |first| should be hidden, since it's not visible
73 // to the user anymore.
74 WindowManager::Get()->ToggleOverview();
75 ASSERT_FALSE(WindowManager::Get()->IsOverviewModeActive());
76 EXPECT_FALSE(first->IsVisible());
77 EXPECT_TRUE(second->IsVisible());
80 TEST_F(WindowManagerTest, OverviewToSplitViewMode) {
81 test::WindowManagerImplTestApi wm_api;
83 aura::test::TestWindowDelegate delegate;
84 scoped_ptr<aura::Window> w1(CreateAndActivateWindow(&delegate));
85 scoped_ptr<aura::Window> w2(CreateAndActivateWindow(&delegate));
86 scoped_ptr<aura::Window> w3(CreateAndActivateWindow(&delegate));
87 wm::ActivateWindow(w3.get());
89 WindowManager::Get()->ToggleOverview();
90 EXPECT_TRUE(w1->IsVisible());
91 EXPECT_TRUE(w2->IsVisible());
92 EXPECT_TRUE(w3->IsVisible());
94 // Go into split-view mode.
95 WindowOverviewModeDelegate* overview_delegate = wm_api.wm();
96 overview_delegate->OnSelectSplitViewWindow(w3.get(), NULL, w3.get());
97 EXPECT_TRUE(w3->IsVisible());
98 EXPECT_TRUE(w2->IsVisible());
99 EXPECT_FALSE(w1->IsVisible());
102 TEST_F(WindowManagerTest, NewWindowFromOverview) {
103 aura::test::TestWindowDelegate delegate;
104 scoped_ptr<aura::Window> w1(CreateAndActivateWindow(&delegate));
105 scoped_ptr<aura::Window> w2(CreateAndActivateWindow(&delegate));
107 WindowManager::Get()->ToggleOverview();
108 EXPECT_TRUE(w1->IsVisible());
109 EXPECT_TRUE(w2->IsVisible());
111 // Test that opening a new window exits overview mode. The new window could
112 // have been opened by JavaScript or by the home card.
113 scoped_ptr<aura::Window> w3(CreateAndActivateWindow(&delegate));
115 ASSERT_FALSE(WindowManager::Get()->IsOverviewModeActive());
116 EXPECT_TRUE(w3->IsVisible());
117 EXPECT_TRUE(wm::IsActiveWindow(w3.get()));
118 EXPECT_FALSE(w1->IsVisible());
119 EXPECT_FALSE(w2->IsVisible());
122 TEST_F(WindowManagerTest, BezelGestureToSplitViewMode) {
123 aura::test::TestWindowDelegate delegate;
124 scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate));
125 scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate));
126 scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate));
128 test::WindowManagerImplTestApi wm_api;
130 // Test that going into split-view mode with two-finger gesture selects the
131 // correct windows on left and right splits.
132 ui::test::EventGenerator generator(root_window());
133 const gfx::Point start_points[2] = {
134 gfx::Point(2, 10), gfx::Point(4, 20),
136 const int kEventTimeSepration = 16;
137 int x_middle = root_window()->bounds().width() / 2;
138 generator.GestureMultiFingerScroll(
139 2, start_points, kEventTimeSepration, 1, x_middle, 0);
140 ASSERT_TRUE(wm_api.GetSplitViewController()->IsSplitViewModeActive());
141 EXPECT_EQ(second.get(), wm_api.GetSplitViewController()->left_window());
142 EXPECT_EQ(third.get(), wm_api.GetSplitViewController()->right_window());
143 EXPECT_EQ(second->bounds().size().ToString(),
144 third->bounds().size().ToString());
147 TEST_F(WindowManagerTest, BezelGestureToSwitchBetweenWindows) {
148 aura::test::TestWindowDelegate delegate;
149 scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate));
150 scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate));
151 scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate));
155 test::WindowManagerImplTestApi wm_api;
157 EXPECT_EQ(third.get(),
158 wm_api.GetWindowListProvider()->GetWindowList().back());
160 // Do a two-finger swipe from the left bezel.
161 ui::test::EventGenerator generator(root_window());
162 const gfx::Point left_bezel_points[2] = {
163 gfx::Point(2, 10), gfx::Point(4, 20),
165 const int kEventTimeSeparation = 16;
166 int width = root_window()->bounds().width();
167 generator.GestureMultiFingerScroll(
168 2, left_bezel_points, kEventTimeSeparation, 1, width, 0);
169 EXPECT_TRUE(wm::IsActiveWindow(second.get()));
170 EXPECT_EQ(second.get(),
171 wm_api.GetWindowListProvider()->GetWindowList().back());
173 // Do a two-finger swipe from the right bezel.
174 const gfx::Point right_bezel_points[2] = {
175 gfx::Point(width - 5, 10),
176 gfx::Point(width - 10, 20)
178 generator.GestureMultiFingerScroll(
179 2, right_bezel_points, kEventTimeSeparation, 1, -width, 0);
180 EXPECT_TRUE(wm::IsActiveWindow(third.get()));
181 EXPECT_EQ(third.get(),
182 wm_api.GetWindowListProvider()->GetWindowList().back());
185 TEST_F(WindowManagerTest, TitleDragSwitchBetweenWindows) {
186 aura::test::TestWindowDelegate delegate;
187 delegate.set_window_component(HTCAPTION);
188 scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate));
189 scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate));
190 scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate));
192 test::WindowManagerImplTestApi wm_api;
194 EXPECT_EQ(third.get(),
195 wm_api.GetWindowListProvider()->GetWindowList().back());
197 // Do a title-swipe from the top to switch to the previous window.
198 ui::test::EventGenerator generator(root_window());
199 generator.GestureScrollSequence(gfx::Point(20, 10),
201 base::TimeDelta::FromMilliseconds(20),
203 EXPECT_TRUE(wm::IsActiveWindow(second.get()));
204 EXPECT_EQ(second.get(),
205 wm_api.GetWindowListProvider()->GetWindowList().back());
206 EXPECT_TRUE(second->IsVisible());
207 EXPECT_FALSE(third->IsVisible());
209 // Performing the same gesture again will switch back to |third|.
210 generator.GestureScrollSequence(gfx::Point(20, 10),
212 base::TimeDelta::FromMilliseconds(20),
214 EXPECT_TRUE(wm::IsActiveWindow(third.get()));
215 EXPECT_EQ(third.get(),
216 wm_api.GetWindowListProvider()->GetWindowList().back());
217 EXPECT_FALSE(second->IsVisible());
218 EXPECT_TRUE(third->IsVisible());
220 // Perform a swipe that doesn't go enough to perform the window switch.
221 generator.GestureScrollSequence(gfx::Point(20, 10),
223 base::TimeDelta::FromMilliseconds(20),
225 EXPECT_TRUE(wm::IsActiveWindow(third.get()));
226 EXPECT_EQ(third.get(),
227 wm_api.GetWindowListProvider()->GetWindowList().back());
228 EXPECT_FALSE(second->IsVisible());
229 EXPECT_TRUE(third->IsVisible());
232 TEST_F(WindowManagerTest, TitleDragSwitchBetweenWindowsInSplitViewMode) {
233 aura::test::TestWindowDelegate delegate;
234 delegate.set_window_component(HTCAPTION);
235 scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate));
236 scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate));
237 scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate));
238 scoped_ptr<aura::Window> fourth(CreateAndActivateWindow(&delegate));
240 test::WindowManagerImplTestApi wm_api;
242 // Test that going into split-view mode with two-finger gesture selects the
243 // correct windows on left and right splits.
244 ui::test::EventGenerator generator(root_window());
245 const gfx::Point start_points[2] = {
246 gfx::Point(2, 10), gfx::Point(4, 20),
248 const int kEventTimeSepration = 16;
249 int x_middle = root_window()->bounds().width() / 2;
250 generator.GestureMultiFingerScroll(
251 2, start_points, kEventTimeSepration, 1, x_middle, 0);
252 ASSERT_TRUE(wm_api.GetSplitViewController()->IsSplitViewModeActive());
253 EXPECT_EQ(third.get(), wm_api.GetSplitViewController()->left_window());
254 EXPECT_EQ(fourth.get(), wm_api.GetSplitViewController()->right_window());
256 // Swipe the title of the left window. It should switch to |second|.
257 generator.GestureScrollSequence(gfx::Point(20, 10),
259 base::TimeDelta::FromMilliseconds(20),
261 EXPECT_EQ(second.get(), wm_api.GetSplitViewController()->left_window());
262 EXPECT_EQ(fourth.get(), wm_api.GetSplitViewController()->right_window());
263 aura::Window::Windows windows =
264 wm_api.GetWindowListProvider()->GetWindowList();
265 ASSERT_EQ(4u, windows.size());
266 EXPECT_EQ(second.get(), windows[3]);
267 EXPECT_EQ(fourth.get(), windows[2]);
269 // Swipe the title of the right window now. It should switch to |third|.
270 generator.GestureScrollSequence(gfx::Point(x_middle + 20, 10),
271 gfx::Point(x_middle + 20, 400),
272 base::TimeDelta::FromMilliseconds(20),
274 EXPECT_EQ(second.get(), wm_api.GetSplitViewController()->left_window());
275 EXPECT_EQ(third.get(), wm_api.GetSplitViewController()->right_window());
276 windows = wm_api.GetWindowListProvider()->GetWindowList();
277 ASSERT_EQ(4u, windows.size());
278 EXPECT_EQ(third.get(), windows[3]);
279 EXPECT_EQ(second.get(), windows[2]);
282 TEST_F(WindowManagerTest, NewWindowBounds) {
283 aura::test::TestWindowDelegate delegate;
284 scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate));
286 test::WindowManagerImplTestApi wm_api;
287 // The window should have the same size as the container.
288 const gfx::Size work_area =
289 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area().size();
290 EXPECT_EQ(work_area.ToString(),
291 first->bounds().size().ToString());
292 EXPECT_TRUE(first->bounds().origin().IsOrigin());
294 // A second window should have the same bounds as the first one.
295 scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate));
296 EXPECT_EQ(first->bounds().ToString(), second->bounds().ToString());
298 // Get into split view.
299 wm_api.GetSplitViewController()->ActivateSplitMode(NULL, NULL, NULL);
300 const gfx::Rect left_bounds =
301 wm_api.GetSplitViewController()->left_window()->bounds();
302 EXPECT_NE(work_area.ToString(),
303 left_bounds.size().ToString());
305 // A new window should replace the left window when in split view.
306 scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate));
307 EXPECT_EQ(wm_api.GetSplitViewController()->left_window(), third.get());
308 EXPECT_EQ(left_bounds.ToString(), third->bounds().ToString());
311 TEST_F(WindowManagerTest, SplitModeActivationByShortcut) {
312 test::WindowManagerImplTestApi wm_api;
314 aura::test::TestWindowDelegate delegate;
315 scoped_ptr<aura::Window> w1(CreateAndActivateWindow(&delegate));
317 // Splitview mode needs at least two windows.
318 wm_api.wm()->ToggleSplitView();
319 EXPECT_FALSE(wm_api.GetSplitViewController()->IsSplitViewModeActive());
321 scoped_ptr<aura::Window> w2(CreateAndActivateWindow(&delegate));
324 wm_api.wm()->ToggleSplitView();
325 EXPECT_TRUE(wm_api.GetSplitViewController()->IsSplitViewModeActive());
327 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area().width();
329 EXPECT_EQ(w1->bounds().width(), w2->bounds().width());
330 EXPECT_GE(width / 2, w1->bounds().width());
332 // Toggle back to normal mode.
333 wm_api.wm()->ToggleSplitView();
334 EXPECT_FALSE(wm_api.GetSplitViewController()->IsSplitViewModeActive());
336 EXPECT_EQ(width, w1->bounds().width());
337 EXPECT_EQ(width, w2->bounds().width());
340 TEST_F(WindowManagerTest, OverviewModeFromSplitMode) {
341 test::WindowManagerImplTestApi wm_api;
343 aura::test::TestWindowDelegate delegate;
344 scoped_ptr<aura::Window> w1(CreateAndActivateWindow(&delegate));
345 scoped_ptr<aura::Window> w2(CreateAndActivateWindow(&delegate));
346 scoped_ptr<aura::Window> w3(CreateAndActivateWindow(&delegate));
348 // Get into split-view mode, and then turn on overview mode.
349 wm_api.GetSplitViewController()->ActivateSplitMode(NULL, NULL, NULL);
350 WindowManager::Get()->ToggleOverview();
351 EXPECT_TRUE(wm_api.GetSplitViewController()->IsSplitViewModeActive());
352 EXPECT_EQ(w3.get(), wm_api.GetSplitViewController()->left_window());
353 EXPECT_EQ(w2.get(), wm_api.GetSplitViewController()->right_window());
355 WindowOverviewModeDelegate* overview_delegate = wm_api.wm();
356 overview_delegate->OnSelectWindow(w1.get());
357 EXPECT_FALSE(wm_api.GetSplitViewController()->IsSplitViewModeActive());
358 EXPECT_TRUE(w1->IsVisible());
359 // Make sure the windows that were in split-view mode are hidden.
360 EXPECT_FALSE(w2->IsVisible());
361 EXPECT_FALSE(w3->IsVisible());
364 } // namespace athena