OLD | NEW |
| (Empty) |
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/wm/window_cycle_controller.h" | |
6 | |
7 #include <algorithm> | |
8 | |
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_state.h" | |
16 #include "ash/wm/window_util.h" | |
17 #include "base/memory/scoped_ptr.h" | |
18 #include "ui/aura/client/aura_constants.h" | |
19 #include "ui/aura/client/screen_position_client.h" | |
20 #include "ui/aura/env.h" | |
21 #include "ui/aura/test/test_windows.h" | |
22 #include "ui/aura/window.h" | |
23 #include "ui/aura/window_event_dispatcher.h" | |
24 #include "ui/gfx/rect.h" | |
25 #include "ui/gfx/screen.h" | |
26 | |
27 namespace ash { | |
28 | |
29 namespace { | |
30 | |
31 using aura::test::CreateTestWindowWithId; | |
32 using aura::test::TestWindowDelegate; | |
33 using aura::Window; | |
34 | |
35 typedef test::AshTestBase WindowCycleControllerTest; | |
36 | |
37 TEST_F(WindowCycleControllerTest, HandleCycleWindowBaseCases) { | |
38 WindowCycleController* controller = | |
39 Shell::GetInstance()->window_cycle_controller(); | |
40 | |
41 // Cycling doesn't crash if there are no windows. | |
42 controller->HandleCycleWindow(WindowCycleController::FORWARD, false); | |
43 | |
44 // Create a single test window. | |
45 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); | |
46 wm::ActivateWindow(window0.get()); | |
47 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
48 | |
49 // Cycling works for a single window, even though nothing changes. | |
50 controller->HandleCycleWindow(WindowCycleController::FORWARD, false); | |
51 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
52 } | |
53 | |
54 // Verifies if there is only one window and it isn't active that cycling | |
55 // activates it. | |
56 TEST_F(WindowCycleControllerTest, SingleWindowNotActive) { | |
57 WindowCycleController* controller = | |
58 Shell::GetInstance()->window_cycle_controller(); | |
59 | |
60 // Create a single test window. | |
61 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); | |
62 wm::ActivateWindow(window0.get()); | |
63 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
64 | |
65 // Rotate focus, this should move focus to another window that isn't part of | |
66 // the default container. | |
67 Shell::GetInstance()->RotateFocus(Shell::FORWARD); | |
68 EXPECT_FALSE(wm::IsActiveWindow(window0.get())); | |
69 | |
70 // Cycling should activate the window. | |
71 controller->HandleCycleWindow(WindowCycleController::FORWARD, false); | |
72 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
73 } | |
74 | |
75 TEST_F(WindowCycleControllerTest, HandleCycleWindow) { | |
76 WindowCycleController* controller = | |
77 Shell::GetInstance()->window_cycle_controller(); | |
78 | |
79 // Set up several windows to use to test cycling. Create them in reverse | |
80 // order so they are stacked 0 over 1 over 2. | |
81 scoped_ptr<Window> window2(CreateTestWindowInShellWithId(2)); | |
82 scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1)); | |
83 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); | |
84 wm::ActivateWindow(window0.get()); | |
85 | |
86 // Simulate pressing and releasing Alt-tab. | |
87 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
88 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
89 | |
90 // Window lists should return the topmost window in front. | |
91 ASSERT_TRUE(controller->windows()); | |
92 ASSERT_EQ(3u, controller->windows()->windows().size()); | |
93 ASSERT_EQ(window0.get(), controller->windows()->windows()[0]); | |
94 ASSERT_EQ(window1.get(), controller->windows()->windows()[1]); | |
95 ASSERT_EQ(window2.get(), controller->windows()->windows()[2]); | |
96 | |
97 controller->AltKeyReleased(); | |
98 EXPECT_TRUE(wm::IsActiveWindow(window1.get())); | |
99 | |
100 // Pressing and releasing Alt-tab again should cycle back to the most- | |
101 // recently-used window in the current child order. | |
102 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
103 controller->AltKeyReleased(); | |
104 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
105 | |
106 // Pressing Alt-tab multiple times without releasing Alt should cycle through | |
107 // all the windows and wrap around. | |
108 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
109 EXPECT_TRUE(controller->IsCycling()); | |
110 EXPECT_TRUE(wm::IsActiveWindow(window1.get())); | |
111 | |
112 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
113 EXPECT_TRUE(controller->IsCycling()); | |
114 EXPECT_TRUE(wm::IsActiveWindow(window2.get())); | |
115 | |
116 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
117 EXPECT_TRUE(controller->IsCycling()); | |
118 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
119 | |
120 controller->AltKeyReleased(); | |
121 EXPECT_FALSE(controller->IsCycling()); | |
122 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
123 | |
124 // Reset our stacking order. | |
125 wm::ActivateWindow(window2.get()); | |
126 wm::ActivateWindow(window1.get()); | |
127 wm::ActivateWindow(window0.get()); | |
128 | |
129 // Likewise we can cycle backwards through all the windows. | |
130 controller->HandleCycleWindow(WindowCycleController::BACKWARD, true); | |
131 EXPECT_TRUE(wm::IsActiveWindow(window2.get())); | |
132 controller->HandleCycleWindow(WindowCycleController::BACKWARD, true); | |
133 EXPECT_TRUE(wm::IsActiveWindow(window1.get())); | |
134 controller->HandleCycleWindow(WindowCycleController::BACKWARD, true); | |
135 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
136 controller->AltKeyReleased(); | |
137 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
138 | |
139 // Passing false for is_alt_down does not start a cycle gesture. | |
140 controller->HandleCycleWindow(WindowCycleController::FORWARD, false); | |
141 EXPECT_FALSE(controller->IsCycling()); | |
142 EXPECT_TRUE(wm::IsActiveWindow(window1.get())); | |
143 | |
144 controller->HandleCycleWindow(WindowCycleController::FORWARD, false); | |
145 EXPECT_FALSE(controller->IsCycling()); | |
146 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
147 | |
148 // When the screen is locked, cycling window does not take effect. | |
149 Shell::GetInstance()->session_state_delegate()->LockScreen(); | |
150 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
151 controller->HandleCycleWindow(WindowCycleController::FORWARD, false); | |
152 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
153 controller->HandleCycleWindow(WindowCycleController::BACKWARD, false); | |
154 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
155 | |
156 Shell::GetInstance()->session_state_delegate()->UnlockScreen(); | |
157 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
158 controller->HandleCycleWindow(WindowCycleController::FORWARD, false); | |
159 EXPECT_TRUE(wm::IsActiveWindow(window1.get())); | |
160 controller->HandleCycleWindow(WindowCycleController::FORWARD, false); | |
161 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
162 | |
163 // When a modal window is active, cycling window does not take effect. | |
164 aura::Window* modal_container = | |
165 ash::Shell::GetContainer( | |
166 Shell::GetPrimaryRootWindow(), | |
167 internal::kShellWindowId_SystemModalContainer); | |
168 scoped_ptr<Window> modal_window( | |
169 CreateTestWindowWithId(-2, modal_container)); | |
170 modal_window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM); | |
171 wm::ActivateWindow(modal_window.get()); | |
172 EXPECT_TRUE(wm::IsActiveWindow(modal_window.get())); | |
173 controller->HandleCycleWindow(WindowCycleController::FORWARD, false); | |
174 EXPECT_TRUE(wm::IsActiveWindow(modal_window.get())); | |
175 EXPECT_FALSE(wm::IsActiveWindow(window0.get())); | |
176 EXPECT_FALSE(wm::IsActiveWindow(window1.get())); | |
177 EXPECT_FALSE(wm::IsActiveWindow(window2.get())); | |
178 controller->HandleCycleWindow(WindowCycleController::BACKWARD, false); | |
179 EXPECT_TRUE(wm::IsActiveWindow(modal_window.get())); | |
180 EXPECT_FALSE(wm::IsActiveWindow(window0.get())); | |
181 EXPECT_FALSE(wm::IsActiveWindow(window1.get())); | |
182 EXPECT_FALSE(wm::IsActiveWindow(window2.get())); | |
183 } | |
184 | |
185 // Cycles between a maximized and normal window. | |
186 TEST_F(WindowCycleControllerTest, MaximizedWindow) { | |
187 // Create a couple of test windows. | |
188 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); | |
189 scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1)); | |
190 wm::WindowState* window1_state = wm::GetWindowState(window1.get()); | |
191 window1_state->Maximize(); | |
192 window1_state->Activate(); | |
193 EXPECT_TRUE(window1_state->IsActive()); | |
194 | |
195 // Rotate focus, this should move focus to window0. | |
196 WindowCycleController* controller = | |
197 Shell::GetInstance()->window_cycle_controller(); | |
198 controller->HandleCycleWindow(WindowCycleController::FORWARD, false); | |
199 EXPECT_TRUE(wm::GetWindowState(window0.get())->IsActive()); | |
200 | |
201 // One more time. | |
202 controller->HandleCycleWindow(WindowCycleController::FORWARD, false); | |
203 EXPECT_TRUE(window1_state->IsActive()); | |
204 } | |
205 | |
206 // Cycles to a minimized window. | |
207 TEST_F(WindowCycleControllerTest, Minimized) { | |
208 // Create a couple of test windows. | |
209 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); | |
210 scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1)); | |
211 wm::WindowState* window0_state = wm::GetWindowState(window0.get()); | |
212 wm::WindowState* window1_state = wm::GetWindowState(window1.get()); | |
213 | |
214 window1_state->Minimize(); | |
215 window0_state->Activate(); | |
216 EXPECT_TRUE(window0_state->IsActive()); | |
217 | |
218 // Rotate focus, this should move focus to window1 and unminimize it. | |
219 WindowCycleController* controller = | |
220 Shell::GetInstance()->window_cycle_controller(); | |
221 controller->HandleCycleWindow(WindowCycleController::FORWARD, false); | |
222 EXPECT_FALSE(window1_state->IsMinimized()); | |
223 EXPECT_TRUE(window1_state->IsActive()); | |
224 | |
225 // One more time back to w0. | |
226 controller->HandleCycleWindow(WindowCycleController::FORWARD, false); | |
227 EXPECT_TRUE(window0_state->IsActive()); | |
228 } | |
229 | |
230 TEST_F(WindowCycleControllerTest, AlwaysOnTopWindow) { | |
231 WindowCycleController* controller = | |
232 Shell::GetInstance()->window_cycle_controller(); | |
233 | |
234 // Set up several windows to use to test cycling. | |
235 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); | |
236 scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1)); | |
237 | |
238 Window* top_container = | |
239 Shell::GetContainer( | |
240 Shell::GetPrimaryRootWindow(), | |
241 internal::kShellWindowId_AlwaysOnTopContainer); | |
242 scoped_ptr<Window> window2(CreateTestWindowWithId(2, top_container)); | |
243 wm::ActivateWindow(window0.get()); | |
244 | |
245 // Simulate pressing and releasing Alt-tab. | |
246 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
247 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
248 | |
249 // Window lists should return the topmost window in front. | |
250 ASSERT_TRUE(controller->windows()); | |
251 ASSERT_EQ(3u, controller->windows()->windows().size()); | |
252 EXPECT_EQ(window0.get(), controller->windows()->windows()[0]); | |
253 EXPECT_EQ(window2.get(), controller->windows()->windows()[1]); | |
254 EXPECT_EQ(window1.get(), controller->windows()->windows()[2]); | |
255 | |
256 controller->AltKeyReleased(); | |
257 EXPECT_TRUE(wm::IsActiveWindow(window2.get())); | |
258 | |
259 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
260 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
261 | |
262 controller->AltKeyReleased(); | |
263 | |
264 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
265 EXPECT_TRUE(wm::IsActiveWindow(window2.get())); | |
266 | |
267 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
268 EXPECT_TRUE(wm::IsActiveWindow(window1.get())); | |
269 | |
270 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
271 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
272 } | |
273 | |
274 TEST_F(WindowCycleControllerTest, AlwaysOnTopMultiWindow) { | |
275 WindowCycleController* controller = | |
276 Shell::GetInstance()->window_cycle_controller(); | |
277 | |
278 // Set up several windows to use to test cycling. | |
279 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); | |
280 scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1)); | |
281 | |
282 Window* top_container = | |
283 Shell::GetContainer( | |
284 Shell::GetPrimaryRootWindow(), | |
285 internal::kShellWindowId_AlwaysOnTopContainer); | |
286 scoped_ptr<Window> window2(CreateTestWindowWithId(2, top_container)); | |
287 scoped_ptr<Window> window3(CreateTestWindowWithId(3, top_container)); | |
288 wm::ActivateWindow(window0.get()); | |
289 | |
290 // Simulate pressing and releasing Alt-tab. | |
291 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
292 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
293 | |
294 // Window lists should return the topmost window in front. | |
295 ASSERT_TRUE(controller->windows()); | |
296 ASSERT_EQ(4u, controller->windows()->windows().size()); | |
297 EXPECT_EQ(window0.get(), controller->windows()->windows()[0]); | |
298 EXPECT_EQ(window3.get(), controller->windows()->windows()[1]); | |
299 EXPECT_EQ(window2.get(), controller->windows()->windows()[2]); | |
300 EXPECT_EQ(window1.get(), controller->windows()->windows()[3]); | |
301 | |
302 controller->AltKeyReleased(); | |
303 EXPECT_TRUE(wm::IsActiveWindow(window3.get())); | |
304 | |
305 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
306 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
307 | |
308 controller->AltKeyReleased(); | |
309 | |
310 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
311 EXPECT_TRUE(wm::IsActiveWindow(window3.get())); | |
312 | |
313 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
314 EXPECT_TRUE(wm::IsActiveWindow(window2.get())); | |
315 | |
316 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
317 EXPECT_TRUE(wm::IsActiveWindow(window1.get())); | |
318 | |
319 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
320 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
321 } | |
322 | |
323 TEST_F(WindowCycleControllerTest, AlwaysOnTopMultipleRootWindows) { | |
324 if (!SupportsMultipleDisplays()) | |
325 return; | |
326 | |
327 // Set up a second root window | |
328 UpdateDisplay("1000x600,600x400"); | |
329 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | |
330 ASSERT_EQ(2U, root_windows.size()); | |
331 | |
332 WindowCycleController* controller = | |
333 Shell::GetInstance()->window_cycle_controller(); | |
334 | |
335 Shell::GetInstance()->set_target_root_window(root_windows[0]); | |
336 | |
337 // Create two windows in the primary root. | |
338 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); | |
339 EXPECT_EQ(root_windows[0], window0->GetRootWindow()); | |
340 Window* top_container0 = | |
341 Shell::GetContainer( | |
342 root_windows[0], | |
343 internal::kShellWindowId_AlwaysOnTopContainer); | |
344 scoped_ptr<Window> window1(CreateTestWindowWithId(1, top_container0)); | |
345 EXPECT_EQ(root_windows[0], window1->GetRootWindow()); | |
346 | |
347 // And two on the secondary root. | |
348 Shell::GetInstance()->set_target_root_window(root_windows[1]); | |
349 scoped_ptr<Window> window2(CreateTestWindowInShellWithId(2)); | |
350 EXPECT_EQ(root_windows[1], window2->GetRootWindow()); | |
351 | |
352 Window* top_container1 = | |
353 Shell::GetContainer( | |
354 root_windows[1], | |
355 internal::kShellWindowId_AlwaysOnTopContainer); | |
356 scoped_ptr<Window> window3(CreateTestWindowWithId(3, top_container1)); | |
357 EXPECT_EQ(root_windows[1], window3->GetRootWindow()); | |
358 | |
359 // Move the active root window to the secondary. | |
360 Shell::GetInstance()->set_target_root_window(root_windows[1]); | |
361 | |
362 wm::ActivateWindow(window2.get()); | |
363 | |
364 EXPECT_EQ(root_windows[0], window0->GetRootWindow()); | |
365 EXPECT_EQ(root_windows[0], window1->GetRootWindow()); | |
366 EXPECT_EQ(root_windows[1], window2->GetRootWindow()); | |
367 EXPECT_EQ(root_windows[1], window3->GetRootWindow()); | |
368 | |
369 // Simulate pressing and releasing Alt-tab. | |
370 EXPECT_TRUE(wm::IsActiveWindow(window2.get())); | |
371 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
372 | |
373 // Window lists should return the topmost window in front. | |
374 ASSERT_TRUE(controller->windows()); | |
375 ASSERT_EQ(4u, controller->windows()->windows().size()); | |
376 EXPECT_EQ(window2.get(), controller->windows()->windows()[0]); | |
377 EXPECT_EQ(window3.get(), controller->windows()->windows()[1]); | |
378 EXPECT_EQ(window1.get(), controller->windows()->windows()[2]); | |
379 EXPECT_EQ(window0.get(), controller->windows()->windows()[3]); | |
380 | |
381 controller->AltKeyReleased(); | |
382 EXPECT_TRUE(wm::IsActiveWindow(window3.get())); | |
383 | |
384 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
385 EXPECT_TRUE(wm::IsActiveWindow(window2.get())); | |
386 | |
387 controller->AltKeyReleased(); | |
388 | |
389 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
390 EXPECT_TRUE(wm::IsActiveWindow(window3.get())); | |
391 | |
392 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
393 EXPECT_TRUE(wm::IsActiveWindow(window1.get())); | |
394 | |
395 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
396 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
397 | |
398 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
399 EXPECT_TRUE(wm::IsActiveWindow(window2.get())); | |
400 } | |
401 | |
402 TEST_F(WindowCycleControllerTest, MostRecentlyUsed) { | |
403 WindowCycleController* controller = | |
404 Shell::GetInstance()->window_cycle_controller(); | |
405 | |
406 // Set up several windows to use to test cycling. | |
407 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0)); | |
408 scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1)); | |
409 scoped_ptr<Window> window2(CreateTestWindowInShellWithId(2)); | |
410 | |
411 wm::ActivateWindow(window0.get()); | |
412 | |
413 // Simulate pressing and releasing Alt-tab. | |
414 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
415 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
416 | |
417 // Window lists should return the topmost window in front. | |
418 ASSERT_TRUE(controller->windows()); | |
419 ASSERT_EQ(3u, controller->windows()->windows().size()); | |
420 EXPECT_EQ(window0.get(), controller->windows()->windows()[0]); | |
421 EXPECT_EQ(window2.get(), controller->windows()->windows()[1]); | |
422 EXPECT_EQ(window1.get(), controller->windows()->windows()[2]); | |
423 | |
424 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
425 controller->AltKeyReleased(); | |
426 EXPECT_TRUE(wm::IsActiveWindow(window1.get())); | |
427 | |
428 | |
429 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
430 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
431 | |
432 controller->AltKeyReleased(); | |
433 | |
434 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
435 EXPECT_TRUE(wm::IsActiveWindow(window1.get())); | |
436 | |
437 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
438 EXPECT_TRUE(wm::IsActiveWindow(window2.get())); | |
439 | |
440 controller->HandleCycleWindow(WindowCycleController::FORWARD, true); | |
441 EXPECT_TRUE(wm::IsActiveWindow(window0.get())); | |
442 } | |
443 | |
444 } // namespace | |
445 | |
446 } // namespace ash | |
OLD | NEW |