Windows should animate when they are about to get docked at screen edges.
[chromium-blink-merge.git] / ash / wm / window_cycle_controller_unittest.cc
blob8e745434254a36eeb6aa11eb879f00505b9c5b33
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.
5 #include "ash/wm/window_cycle_controller.h"
7 #include <algorithm>
9 #include "ash/session_state_delegate.h"
10 #include "ash/shell.h"
11 #include "ash/shell_window_ids.h"
12 #include "ash/test/ash_test_base.h"
13 #include "ash/test/test_shell_delegate.h"
14 #include "ash/wm/window_cycle_list.h"
15 #include "ash/wm/window_util.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "ui/aura/client/aura_constants.h"
18 #include "ui/aura/client/screen_position_client.h"
19 #include "ui/aura/env.h"
20 #include "ui/aura/test/test_windows.h"
21 #include "ui/aura/window.h"
22 #include "ui/gfx/rect.h"
23 #include "ui/gfx/screen.h"
25 namespace ash {
27 namespace {
29 using aura::test::CreateTestWindowWithId;
30 using aura::test::TestWindowDelegate;
31 using aura::Window;
33 typedef test::AshTestBase WindowCycleControllerTest;
35 TEST_F(WindowCycleControllerTest, HandleCycleWindowBaseCases) {
36 WindowCycleController* controller =
37 Shell::GetInstance()->window_cycle_controller();
39 // Cycling doesn't crash if there are no windows.
40 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
42 // Create a single test window.
43 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
44 wm::ActivateWindow(window0.get());
45 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
47 // Cycling works for a single window, even though nothing changes.
48 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
49 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
52 // Verifies if there is only one window and it isn't active that cycling
53 // activates it.
54 TEST_F(WindowCycleControllerTest, SingleWindowNotActive) {
55 WindowCycleController* controller =
56 Shell::GetInstance()->window_cycle_controller();
58 // Create a single test window.
59 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
60 wm::ActivateWindow(window0.get());
61 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
63 // Rotate focus, this should move focus to another window that isn't part of
64 // the default container.
65 Shell::GetInstance()->RotateFocus(Shell::FORWARD);
66 EXPECT_FALSE(wm::IsActiveWindow(window0.get()));
68 // Cycling should activate the window.
69 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
70 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
73 TEST_F(WindowCycleControllerTest, HandleCycleWindow) {
74 WindowCycleController* controller =
75 Shell::GetInstance()->window_cycle_controller();
77 // Set up several windows to use to test cycling. Create them in reverse
78 // order so they are stacked 0 over 1 over 2.
79 scoped_ptr<Window> window2(CreateTestWindowInShellWithId(2));
80 scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1));
81 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
82 wm::ActivateWindow(window0.get());
84 // Simulate pressing and releasing Alt-tab.
85 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
86 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
88 // Window lists should return the topmost window in front.
89 ASSERT_TRUE(controller->windows());
90 ASSERT_EQ(3u, controller->windows()->windows().size());
91 ASSERT_EQ(window0.get(), controller->windows()->windows()[0]);
92 ASSERT_EQ(window1.get(), controller->windows()->windows()[1]);
93 ASSERT_EQ(window2.get(), controller->windows()->windows()[2]);
95 controller->AltKeyReleased();
96 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
98 // Pressing and releasing Alt-tab again should cycle back to the most-
99 // recently-used window in the current child order.
100 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
101 controller->AltKeyReleased();
102 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
104 // Pressing Alt-tab multiple times without releasing Alt should cycle through
105 // all the windows and wrap around.
106 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
107 EXPECT_TRUE(controller->IsCycling());
108 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
110 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
111 EXPECT_TRUE(controller->IsCycling());
112 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
114 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
115 EXPECT_TRUE(controller->IsCycling());
116 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
118 controller->AltKeyReleased();
119 EXPECT_FALSE(controller->IsCycling());
120 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
122 // Reset our stacking order.
123 wm::ActivateWindow(window2.get());
124 wm::ActivateWindow(window1.get());
125 wm::ActivateWindow(window0.get());
127 // Likewise we can cycle backwards through all the windows.
128 controller->HandleCycleWindow(WindowCycleController::BACKWARD, true);
129 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
130 controller->HandleCycleWindow(WindowCycleController::BACKWARD, true);
131 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
132 controller->HandleCycleWindow(WindowCycleController::BACKWARD, true);
133 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
134 controller->AltKeyReleased();
135 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
137 // Passing false for is_alt_down does not start a cycle gesture.
138 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
139 EXPECT_FALSE(controller->IsCycling());
140 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
142 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
143 EXPECT_FALSE(controller->IsCycling());
144 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
146 // When the screen is locked, cycling window does not take effect.
147 Shell::GetInstance()->session_state_delegate()->LockScreen();
148 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
149 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
150 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
151 controller->HandleCycleWindow(WindowCycleController::BACKWARD, false);
152 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
154 Shell::GetInstance()->session_state_delegate()->UnlockScreen();
155 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
156 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
157 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
158 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
159 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
161 // When a modal window is active, cycling window does not take effect.
162 aura::Window* modal_container =
163 ash::Shell::GetContainer(
164 Shell::GetPrimaryRootWindow(),
165 internal::kShellWindowId_SystemModalContainer);
166 scoped_ptr<Window> modal_window(
167 CreateTestWindowWithId(-2, modal_container));
168 modal_window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM);
169 wm::ActivateWindow(modal_window.get());
170 EXPECT_TRUE(wm::IsActiveWindow(modal_window.get()));
171 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
172 EXPECT_TRUE(wm::IsActiveWindow(modal_window.get()));
173 EXPECT_FALSE(wm::IsActiveWindow(window0.get()));
174 EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
175 EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
176 controller->HandleCycleWindow(WindowCycleController::BACKWARD, false);
177 EXPECT_TRUE(wm::IsActiveWindow(modal_window.get()));
178 EXPECT_FALSE(wm::IsActiveWindow(window0.get()));
179 EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
180 EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
183 // Cycles between a maximized and normal window.
184 TEST_F(WindowCycleControllerTest, MaximizedWindow) {
185 // Create a couple of test windows.
186 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
187 scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1));
189 wm::MaximizeWindow(window1.get());
190 wm::ActivateWindow(window1.get());
191 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
193 // Rotate focus, this should move focus to window0.
194 WindowCycleController* controller =
195 Shell::GetInstance()->window_cycle_controller();
196 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
197 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
199 // One more time.
200 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
201 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
204 // Cycles to a minimized window.
205 TEST_F(WindowCycleControllerTest, Minimized) {
206 // Create a couple of test windows.
207 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
208 scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1));
210 wm::MinimizeWindow(window1.get());
211 wm::ActivateWindow(window0.get());
212 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
214 // Rotate focus, this should move focus to window1 and unminimize it.
215 WindowCycleController* controller =
216 Shell::GetInstance()->window_cycle_controller();
217 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
218 EXPECT_FALSE(wm::IsWindowMinimized(window1.get()));
219 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
221 // One more time back to w0.
222 controller->HandleCycleWindow(WindowCycleController::FORWARD, false);
223 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
226 TEST_F(WindowCycleControllerTest, AlwaysOnTopWindow) {
227 WindowCycleController* controller =
228 Shell::GetInstance()->window_cycle_controller();
230 // Set up several windows to use to test cycling.
231 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
232 scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1));
234 Window* top_container =
235 Shell::GetContainer(
236 Shell::GetPrimaryRootWindow(),
237 internal::kShellWindowId_AlwaysOnTopContainer);
238 scoped_ptr<Window> window2(CreateTestWindowWithId(2, top_container));
239 wm::ActivateWindow(window0.get());
241 // Simulate pressing and releasing Alt-tab.
242 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
243 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
245 // Window lists should return the topmost window in front.
246 ASSERT_TRUE(controller->windows());
247 ASSERT_EQ(3u, controller->windows()->windows().size());
248 EXPECT_EQ(window0.get(), controller->windows()->windows()[0]);
249 EXPECT_EQ(window2.get(), controller->windows()->windows()[1]);
250 EXPECT_EQ(window1.get(), controller->windows()->windows()[2]);
252 controller->AltKeyReleased();
253 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
255 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
256 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
258 controller->AltKeyReleased();
260 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
261 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
263 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
264 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
266 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
267 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
270 TEST_F(WindowCycleControllerTest, AlwaysOnTopMultiWindow) {
271 WindowCycleController* controller =
272 Shell::GetInstance()->window_cycle_controller();
274 // Set up several windows to use to test cycling.
275 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
276 scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1));
278 Window* top_container =
279 Shell::GetContainer(
280 Shell::GetPrimaryRootWindow(),
281 internal::kShellWindowId_AlwaysOnTopContainer);
282 scoped_ptr<Window> window2(CreateTestWindowWithId(2, top_container));
283 scoped_ptr<Window> window3(CreateTestWindowWithId(3, top_container));
284 wm::ActivateWindow(window0.get());
286 // Simulate pressing and releasing Alt-tab.
287 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
288 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
290 // Window lists should return the topmost window in front.
291 ASSERT_TRUE(controller->windows());
292 ASSERT_EQ(4u, controller->windows()->windows().size());
293 EXPECT_EQ(window0.get(), controller->windows()->windows()[0]);
294 EXPECT_EQ(window3.get(), controller->windows()->windows()[1]);
295 EXPECT_EQ(window2.get(), controller->windows()->windows()[2]);
296 EXPECT_EQ(window1.get(), controller->windows()->windows()[3]);
298 controller->AltKeyReleased();
299 EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
301 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
302 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
304 controller->AltKeyReleased();
306 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
307 EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
309 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
310 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
312 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
313 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
315 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
316 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
319 TEST_F(WindowCycleControllerTest, AlwaysOnTopMultipleRootWindows) {
320 if (!SupportsMultipleDisplays())
321 return;
323 // Set up a second root window
324 UpdateDisplay("1000x600,600x400");
325 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
326 ASSERT_EQ(2U, root_windows.size());
328 WindowCycleController* controller =
329 Shell::GetInstance()->window_cycle_controller();
331 Shell::GetInstance()->set_active_root_window(root_windows[0]);
333 // Create two windows in the primary root.
334 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
335 EXPECT_EQ(root_windows[0], window0->GetRootWindow());
336 Window* top_container0 =
337 Shell::GetContainer(
338 root_windows[0],
339 internal::kShellWindowId_AlwaysOnTopContainer);
340 scoped_ptr<Window> window1(CreateTestWindowWithId(1, top_container0));
341 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
343 // And two on the secondary root.
344 Shell::GetInstance()->set_active_root_window(root_windows[1]);
345 scoped_ptr<Window> window2(CreateTestWindowInShellWithId(2));
346 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
348 Window* top_container1 =
349 Shell::GetContainer(
350 root_windows[1],
351 internal::kShellWindowId_AlwaysOnTopContainer);
352 scoped_ptr<Window> window3(CreateTestWindowWithId(3, top_container1));
353 EXPECT_EQ(root_windows[1], window3->GetRootWindow());
355 // Move the active root window to the secondary.
356 Shell::GetInstance()->set_active_root_window(root_windows[1]);
358 wm::ActivateWindow(window2.get());
360 EXPECT_EQ(root_windows[0], window0->GetRootWindow());
361 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
362 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
363 EXPECT_EQ(root_windows[1], window3->GetRootWindow());
365 // Simulate pressing and releasing Alt-tab.
366 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
367 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
369 // Window lists should return the topmost window in front.
370 ASSERT_TRUE(controller->windows());
371 ASSERT_EQ(4u, controller->windows()->windows().size());
372 EXPECT_EQ(window2.get(), controller->windows()->windows()[0]);
373 EXPECT_EQ(window3.get(), controller->windows()->windows()[1]);
374 EXPECT_EQ(window1.get(), controller->windows()->windows()[2]);
375 EXPECT_EQ(window0.get(), controller->windows()->windows()[3]);
377 controller->AltKeyReleased();
378 EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
380 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
381 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
383 controller->AltKeyReleased();
385 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
386 EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
388 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
389 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
391 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
392 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
394 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
395 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
398 TEST_F(WindowCycleControllerTest, MostRecentlyUsed) {
399 WindowCycleController* controller =
400 Shell::GetInstance()->window_cycle_controller();
402 // Set up several windows to use to test cycling.
403 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
404 scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1));
405 scoped_ptr<Window> window2(CreateTestWindowInShellWithId(2));
407 wm::ActivateWindow(window0.get());
409 // Simulate pressing and releasing Alt-tab.
410 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
411 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
413 // Window lists should return the topmost window in front.
414 ASSERT_TRUE(controller->windows());
415 ASSERT_EQ(3u, controller->windows()->windows().size());
416 EXPECT_EQ(window0.get(), controller->windows()->windows()[0]);
417 EXPECT_EQ(window2.get(), controller->windows()->windows()[1]);
418 EXPECT_EQ(window1.get(), controller->windows()->windows()[2]);
420 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
421 controller->AltKeyReleased();
422 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
425 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
426 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
428 controller->AltKeyReleased();
430 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
431 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
433 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
434 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
436 controller->HandleCycleWindow(WindowCycleController::FORWARD, true);
437 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
440 } // namespace
442 } // namespace ash