1 // Copyright 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 "ash/launcher/launcher.h"
6 #include "ash/root_window_controller.h"
7 #include "ash/screen_ash.h"
8 #include "ash/shelf/shelf_widget.h"
9 #include "ash/shell.h"
10 #include "ash/test/ash_test_base.h"
11 #include "ash/test/launcher_test_api.h"
12 #include "ash/test/shelf_view_test_api.h"
13 #include "ash/test/shell_test_api.h"
14 #include "ash/test/test_shelf_delegate.h"
15 #include "ash/wm/mru_window_tracker.h"
16 #include "ash/wm/overview/window_selector.h"
17 #include "ash/wm/overview/window_selector_controller.h"
18 #include "ash/wm/window_state.h"
19 #include "ash/wm/window_util.h"
20 #include "base/basictypes.h"
21 #include "base/compiler_specific.h"
22 #include "base/memory/scoped_vector.h"
23 #include "base/run_loop.h"
24 #include "ui/aura/client/activation_delegate.h"
25 #include "ui/aura/client/aura_constants.h"
26 #include "ui/aura/client/cursor_client.h"
27 #include "ui/aura/client/focus_client.h"
28 #include "ui/aura/root_window.h"
29 #include "ui/aura/test/event_generator.h"
30 #include "ui/aura/test/test_window_delegate.h"
31 #include "ui/aura/test/test_windows.h"
32 #include "ui/aura/window.h"
33 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
34 #include "ui/gfx/rect_conversions.h"
35 #include "ui/gfx/transform.h"
36
37 namespace ash {
38 namespace internal {
39
40 namespace {
41
42 class NonActivatableActivationDelegate
43 : public aura::client::ActivationDelegate {
44 public:
ShouldActivate() const45 virtual bool ShouldActivate() const OVERRIDE {
46 return false;
47 }
48 };
49
IsWindowAbove(aura::Window * w1,aura::Window * w2)50 bool IsWindowAbove(aura::Window* w1, aura::Window* w2) {
51 aura::Window* parent = w1->parent();
52 DCHECK_EQ(parent, w2->parent());
53 for (aura::Window::Windows::const_iterator iter = parent->children().begin();
54 iter != parent->children().end(); ++iter) {
55 if (*iter == w1)
56 return false;
57 if (*iter == w2)
58 return true;
59 }
60 NOTREACHED();
61 return false;
62 }
63
GetWindowByName(aura::Window * container,const std::string & name)64 aura::Window* GetWindowByName(aura::Window* container,
65 const std::string& name) {
66 aura::Window* window = NULL;
67 for (aura::Window::Windows::const_iterator iter =
68 container->children().begin(); iter != container->children().end();
69 ++iter) {
70 if ((*iter)->name() == name) {
71 // The name should be unique.
72 DCHECK(!window);
73 window = *iter;
74 }
75 }
76 return window;
77 }
78
79 // Returns the copy of |window| created for overview. It is found using the
80 // window name which should be the same as the source window's name with a
81 // special suffix, and in the same container as the source window.
GetCopyWindow(aura::Window * window)82 aura::Window* GetCopyWindow(aura::Window* window) {
83 aura::Window* copy_window = NULL;
84 std::string copy_name = window->name() + " (Copy)";
85 std::vector<aura::Window*> containers(
86 Shell::GetContainersFromAllRootWindows(window->parent()->id(), NULL));
87 for (std::vector<aura::Window*>::iterator iter = containers.begin();
88 iter != containers.end(); ++iter) {
89 aura::Window* found = GetWindowByName(*iter, copy_name);
90 if (found) {
91 // There should only be one copy window.
92 DCHECK(!copy_window);
93 copy_window = found;
94 }
95 }
96 return copy_window;
97 }
98
99 } // namespace
100
101 class WindowSelectorTest : public test::AshTestBase {
102 public:
WindowSelectorTest()103 WindowSelectorTest() {}
~WindowSelectorTest()104 virtual ~WindowSelectorTest() {}
105
SetUp()106 virtual void SetUp() OVERRIDE {
107 test::AshTestBase::SetUp();
108 ASSERT_TRUE(test::TestShelfDelegate::instance());
109
110 shelf_view_test_.reset(new test::ShelfViewTestAPI(
111 test::LauncherTestAPI(Launcher::ForPrimaryDisplay()).shelf_view()));
112 shelf_view_test_->SetAnimationDuration(1);
113 }
114
CreateWindow(const gfx::Rect & bounds)115 aura::Window* CreateWindow(const gfx::Rect& bounds) {
116 return CreateTestWindowInShellWithDelegate(&delegate_, -1, bounds);
117 }
118
CreateNonActivatableWindow(const gfx::Rect & bounds)119 aura::Window* CreateNonActivatableWindow(const gfx::Rect& bounds) {
120 aura::Window* window = CreateWindow(bounds);
121 aura::client::SetActivationDelegate(window,
122 &non_activatable_activation_delegate_);
123 EXPECT_FALSE(ash::wm::CanActivateWindow(window));
124 return window;
125 }
126
CreatePanelWindow(const gfx::Rect & bounds)127 aura::Window* CreatePanelWindow(const gfx::Rect& bounds) {
128 aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
129 NULL, aura::client::WINDOW_TYPE_PANEL, 0, bounds);
130 test::TestShelfDelegate::instance()->AddLauncherItem(window);
131 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
132 return window;
133 }
134
WindowsOverlapping(aura::Window * window1,aura::Window * window2)135 bool WindowsOverlapping(aura::Window* window1, aura::Window* window2) {
136 gfx::RectF window1_bounds = GetTransformedTargetBounds(window1);
137 gfx::RectF window2_bounds = GetTransformedTargetBounds(window2);
138 return window1_bounds.Intersects(window2_bounds);
139 }
140
ToggleOverview()141 void ToggleOverview() {
142 ash::Shell::GetInstance()->window_selector_controller()->ToggleOverview();
143 }
144
Cycle(WindowSelector::Direction direction)145 void Cycle(WindowSelector::Direction direction) {
146 ash::Shell::GetInstance()->window_selector_controller()->
147 HandleCycleWindow(direction);
148 }
149
StopCycling()150 void StopCycling() {
151 ash::Shell::GetInstance()->window_selector_controller()->window_selector_->
152 SelectWindow();
153 }
154
FireOverviewStartTimer()155 void FireOverviewStartTimer() {
156 // Calls the method to start overview mode which is normally called by the
157 // timer. The timer will still fire and call this method triggering the
158 // DCHECK that overview mode was not already started, except that we call
159 // StopCycling before the timer has a chance to fire.
160 ash::Shell::GetInstance()->window_selector_controller()->window_selector_->
161 StartOverview();
162 }
163
GetTransformRelativeTo(gfx::PointF origin,const gfx::Transform & transform)164 gfx::Transform GetTransformRelativeTo(gfx::PointF origin,
165 const gfx::Transform& transform) {
166 gfx::Transform t;
167 t.Translate(origin.x(), origin.y());
168 t.PreconcatTransform(transform);
169 t.Translate(-origin.x(), -origin.y());
170 return t;
171 }
172
GetTransformedBounds(aura::Window * window)173 gfx::RectF GetTransformedBounds(aura::Window* window) {
174 gfx::RectF bounds(ash::ScreenAsh::ConvertRectToScreen(
175 window->parent(), window->layer()->bounds()));
176 gfx::Transform transform(GetTransformRelativeTo(bounds.origin(),
177 window->layer()->transform()));
178 transform.TransformRect(&bounds);
179 return bounds;
180 }
181
GetTransformedTargetBounds(aura::Window * window)182 gfx::RectF GetTransformedTargetBounds(aura::Window* window) {
183 gfx::RectF bounds(ash::ScreenAsh::ConvertRectToScreen(
184 window->parent(), window->layer()->GetTargetBounds()));
185 gfx::Transform transform(GetTransformRelativeTo(bounds.origin(),
186 window->layer()->GetTargetTransform()));
187 transform.TransformRect(&bounds);
188 return bounds;
189 }
190
ClickWindow(aura::Window * window)191 void ClickWindow(aura::Window* window) {
192 aura::test::EventGenerator event_generator(window->GetRootWindow(), window);
193 gfx::RectF target = GetTransformedBounds(window);
194 event_generator.ClickLeftButton();
195 }
196
IsSelecting()197 bool IsSelecting() {
198 return ash::Shell::GetInstance()->window_selector_controller()->
199 IsSelecting();
200 }
201
GetFocusedWindow()202 aura::Window* GetFocusedWindow() {
203 return aura::client::GetFocusClient(
204 Shell::GetPrimaryRootWindow())->GetFocusedWindow();
205 }
206
shelf_view_test()207 test::ShelfViewTestAPI* shelf_view_test() {
208 return shelf_view_test_.get();
209 }
210
211 private:
212 aura::test::TestWindowDelegate delegate_;
213 NonActivatableActivationDelegate non_activatable_activation_delegate_;
214 scoped_ptr<test::ShelfViewTestAPI> shelf_view_test_;
215
216 DISALLOW_COPY_AND_ASSIGN(WindowSelectorTest);
217 };
218
219 // Tests entering overview mode with two windows and selecting one.
TEST_F(WindowSelectorTest,Basic)220 TEST_F(WindowSelectorTest, Basic) {
221 gfx::Rect bounds(0, 0, 400, 400);
222 aura::Window* root_window = Shell::GetPrimaryRootWindow();
223 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
224 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
225 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
226 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
227 EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get()));
228 EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
229 wm::ActivateWindow(window2.get());
230 EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
231 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
232 EXPECT_EQ(window2.get(), GetFocusedWindow());
233 // Hide the cursor before entering overview to test that it will be shown.
234 aura::client::GetCursorClient(root_window)->HideCursor();
235
236 // In overview mode the windows should no longer overlap and focus should
237 // be removed from the window.
238 ToggleOverview();
239 EXPECT_EQ(NULL, GetFocusedWindow());
240 EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get()));
241 EXPECT_FALSE(WindowsOverlapping(window1.get(), panel1.get()));
242 // Panels 1 and 2 should still be overlapping being in a single selector
243 // item.
244 EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
245
246 // The cursor should be visible and locked as a pointer
247 EXPECT_EQ(ui::kCursorPointer,
248 root_window->GetDispatcher()->last_cursor().native_type());
249 EXPECT_TRUE(aura::client::GetCursorClient(root_window)->IsCursorLocked());
250 EXPECT_TRUE(aura::client::GetCursorClient(root_window)->IsCursorVisible());
251
252 // Clicking window 1 should activate it.
253 ClickWindow(window1.get());
254 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
255 EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
256 EXPECT_EQ(window1.get(), GetFocusedWindow());
257
258 // Cursor should have been unlocked.
259 EXPECT_FALSE(aura::client::GetCursorClient(root_window)->IsCursorLocked());
260 }
261
262 // Tests entering overview mode with two windows and selecting one.
TEST_F(WindowSelectorTest,FullscreenWindow)263 TEST_F(WindowSelectorTest, FullscreenWindow) {
264 gfx::Rect bounds(0, 0, 400, 400);
265 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
266 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
267 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
268 wm::ActivateWindow(window1.get());
269
270 wm::GetWindowState(window1.get())->ToggleFullscreen();
271 // The panel is hidden in fullscreen mode.
272 EXPECT_FALSE(panel1->IsVisible());
273 EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen());
274
275 // Enter overview and select the fullscreen window.
276 ToggleOverview();
277
278 // The panel becomes temporarily visible for the overview.
279 EXPECT_TRUE(panel1->IsVisible());
280 ClickWindow(window1.get());
281
282 // The window is still fullscreen as it was selected. The panel should again
283 // be hidden.
284 EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen());
285 EXPECT_FALSE(panel1->IsVisible());
286
287 // Entering overview and selecting another window, the previous window remains
288 // fullscreen.
289 // TODO(flackr): Currently the panel remains hidden, but should become visible
290 // again.
291 ToggleOverview();
292 ClickWindow(window2.get());
293 EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen());
294 }
295
296 // Tests that the shelf dimming state is removed while in overview and restored
297 // on exiting overview.
TEST_F(WindowSelectorTest,OverviewUndimsShelf)298 TEST_F(WindowSelectorTest, OverviewUndimsShelf) {
299 gfx::Rect bounds(0, 0, 400, 400);
300 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
301 wm::WindowState* window_state = wm::GetWindowState(window1.get());
302 window_state->Maximize();
303 ash::ShelfWidget* shelf = Shell::GetPrimaryRootWindowController()->shelf();
304 EXPECT_TRUE(shelf->GetDimsShelf());
305 ToggleOverview();
306 EXPECT_FALSE(shelf->GetDimsShelf());
307 ToggleOverview();
308 EXPECT_TRUE(shelf->GetDimsShelf());
309 }
310
311 // Tests that beginning window selection hides the app list.
TEST_F(WindowSelectorTest,SelectingHidesAppList)312 TEST_F(WindowSelectorTest, SelectingHidesAppList) {
313 gfx::Rect bounds(0, 0, 400, 400);
314 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
315 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
316 Shell::GetInstance()->ToggleAppList(NULL);
317 EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility());
318 ToggleOverview();
319 EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility());
320 ToggleOverview();
321
322 // The app list uses an animation to fade out. If it is toggled on immediately
323 // after being removed the old widget is re-used and it does not gain focus.
324 // When running under normal circumstances this shouldn't be possible, but
325 // it is in a test without letting the message loop run.
326 RunAllPendingInMessageLoop();
327
328 Shell::GetInstance()->ToggleAppList(NULL);
329 EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility());
330 Cycle(WindowSelector::FORWARD);
331 EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility());
332 StopCycling();
333 }
334
335 // Tests that a minimized window's visibility and layer visibility is correctly
336 // changed when entering overview and restored when leaving overview mode.
TEST_F(WindowSelectorTest,MinimizedWindowVisibility)337 TEST_F(WindowSelectorTest, MinimizedWindowVisibility) {
338 gfx::Rect bounds(0, 0, 400, 400);
339 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
340 wm::WindowState* window_state = wm::GetWindowState(window1.get());
341 window_state->Minimize();
342 EXPECT_FALSE(window1->IsVisible());
343 EXPECT_FALSE(window1->layer()->GetTargetVisibility());
344 {
345 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
346 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
347 ToggleOverview();
348 EXPECT_TRUE(window1->IsVisible());
349 EXPECT_TRUE(window1->layer()->GetTargetVisibility());
350 }
351 {
352 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
353 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
354 ToggleOverview();
355 EXPECT_FALSE(window1->IsVisible());
356 EXPECT_FALSE(window1->layer()->GetTargetVisibility());
357 }
358 }
359
360 // Tests that a bounds change during overview is corrected for.
TEST_F(WindowSelectorTest,BoundsChangeDuringOverview)361 TEST_F(WindowSelectorTest, BoundsChangeDuringOverview) {
362 scoped_ptr<aura::Window> window(CreateWindow(gfx::Rect(0, 0, 400, 400)));
363 ToggleOverview();
364 gfx::Rect overview_bounds =
365 ToEnclosingRect(GetTransformedTargetBounds(window.get()));
366 window->SetBounds(gfx::Rect(200, 0, 200, 200));
367 gfx::Rect new_overview_bounds =
368 ToEnclosingRect(GetTransformedTargetBounds(window.get()));
369 EXPECT_EQ(overview_bounds.x(), new_overview_bounds.x());
370 EXPECT_EQ(overview_bounds.y(), new_overview_bounds.y());
371 EXPECT_EQ(overview_bounds.width(), new_overview_bounds.width());
372 EXPECT_EQ(overview_bounds.height(), new_overview_bounds.height());
373 ToggleOverview();
374 }
375
376 // Tests entering overview mode with three windows and cycling through them.
TEST_F(WindowSelectorTest,BasicCycle)377 TEST_F(WindowSelectorTest, BasicCycle) {
378 gfx::Rect bounds(0, 0, 400, 400);
379 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
380 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
381 scoped_ptr<aura::Window> window3(CreateWindow(bounds));
382 wm::ActivateWindow(window3.get());
383 wm::ActivateWindow(window2.get());
384 wm::ActivateWindow(window1.get());
385 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
386 EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
387 EXPECT_FALSE(wm::IsActiveWindow(window3.get()));
388
389 Cycle(WindowSelector::FORWARD);
390 EXPECT_TRUE(IsSelecting());
391 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
392
393 Cycle(WindowSelector::FORWARD);
394 EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
395
396 StopCycling();
397 EXPECT_FALSE(IsSelecting());
398 EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
399 EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
400 EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
401 }
402
403 // Tests that cycling through windows preserves the window stacking order.
TEST_F(WindowSelectorTest,CyclePreservesStackingOrder)404 TEST_F(WindowSelectorTest, CyclePreservesStackingOrder) {
405 gfx::Rect bounds(0, 0, 400, 400);
406 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
407 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
408 scoped_ptr<aura::Window> window3(CreateWindow(bounds));
409 wm::ActivateWindow(window3.get());
410 wm::ActivateWindow(window2.get());
411 wm::ActivateWindow(window1.get());
412 // Window order from top to bottom is 1, 2, 3.
413 EXPECT_TRUE(IsWindowAbove(window1.get(), window2.get()));
414 EXPECT_TRUE(IsWindowAbove(window2.get(), window3.get()));
415
416 // On window 2.
417 Cycle(WindowSelector::FORWARD);
418 EXPECT_TRUE(IsWindowAbove(window2.get(), window1.get()));
419 EXPECT_TRUE(IsWindowAbove(window1.get(), window3.get()));
420
421 // On window 3.
422 Cycle(WindowSelector::FORWARD);
423 EXPECT_TRUE(IsWindowAbove(window3.get(), window1.get()));
424 EXPECT_TRUE(IsWindowAbove(window1.get(), window2.get()));
425
426 // Back on window 1.
427 Cycle(WindowSelector::FORWARD);
428 EXPECT_TRUE(IsWindowAbove(window1.get(), window2.get()));
429 EXPECT_TRUE(IsWindowAbove(window2.get(), window3.get()));
430 StopCycling();
431 }
432
433 // Tests that cycling through windows shows and minimizes windows as they
434 // are passed.
TEST_F(WindowSelectorTest,CyclePreservesMinimization)435 TEST_F(WindowSelectorTest, CyclePreservesMinimization) {
436 gfx::Rect bounds(0, 0, 400, 400);
437 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
438 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
439 wm::ActivateWindow(window2.get());
440 wm::GetWindowState(window2.get())->Minimize();
441 wm::ActivateWindow(window1.get());
442 EXPECT_TRUE(wm::IsWindowMinimized(window2.get()));
443
444 // On window 2.
445 Cycle(WindowSelector::FORWARD);
446 EXPECT_FALSE(wm::IsWindowMinimized(window2.get()));
447
448 // Back on window 1.
449 Cycle(WindowSelector::FORWARD);
450 EXPECT_TRUE(wm::IsWindowMinimized(window2.get()));
451
452 StopCycling();
453 EXPECT_TRUE(wm::IsWindowMinimized(window2.get()));
454 }
455
456 // Tests beginning cycling while in overview mode.
TEST_F(WindowSelectorTest,OverviewTransitionToCycle)457 TEST_F(WindowSelectorTest, OverviewTransitionToCycle) {
458 gfx::Rect bounds(0, 0, 400, 400);
459 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
460 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
461 wm::ActivateWindow(window2.get());
462 wm::ActivateWindow(window1.get());
463
464 ToggleOverview();
465 Cycle(WindowSelector::FORWARD);
466 StopCycling();
467
468 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
469 EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
470 EXPECT_EQ(window2.get(), GetFocusedWindow());
471 }
472
473 // Tests cycles between panel and normal windows.
TEST_F(WindowSelectorTest,CyclePanels)474 TEST_F(WindowSelectorTest, CyclePanels) {
475 gfx::Rect bounds(0, 0, 400, 400);
476 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
477 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
478 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
479 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
480 wm::ActivateWindow(window2.get());
481 wm::ActivateWindow(window1.get());
482 wm::ActivateWindow(panel2.get());
483 wm::ActivateWindow(panel1.get());
484 EXPECT_TRUE(wm::IsActiveWindow(panel1.get()));
485
486 // Cycling once should select window1 since the panels are grouped into a
487 // single selectable item.
488 Cycle(WindowSelector::FORWARD);
489 StopCycling();
490 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
491
492 // Cycling again should select the most recently used panel.
493 Cycle(WindowSelector::FORWARD);
494 StopCycling();
495 EXPECT_TRUE(wm::IsActiveWindow(panel1.get()));
496 }
497
498 // Tests the visibility of panel windows during cycling.
TEST_F(WindowSelectorTest,CyclePanelVisibility)499 TEST_F(WindowSelectorTest, CyclePanelVisibility) {
500 gfx::Rect bounds(0, 0, 400, 400);
501 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
502 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
503 wm::ActivateWindow(panel1.get());
504 wm::ActivateWindow(window1.get());
505
506 Cycle(WindowSelector::FORWARD);
507 FireOverviewStartTimer();
508 EXPECT_EQ(1.0f, panel1->layer()->GetTargetOpacity());
509 StopCycling();
510 }
511
512 // Tests cycles between panel and normal windows.
TEST_F(WindowSelectorTest,CyclePanelsDestroyed)513 TEST_F(WindowSelectorTest, CyclePanelsDestroyed) {
514 gfx::Rect bounds(0, 0, 400, 400);
515 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
516 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
517 scoped_ptr<aura::Window> window3(CreateWindow(bounds));
518 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
519 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
520 wm::ActivateWindow(window3.get());
521 wm::ActivateWindow(panel2.get());
522 wm::ActivateWindow(panel1.get());
523 wm::ActivateWindow(window2.get());
524 wm::ActivateWindow(window1.get());
525 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
526
527 // Cycling once highlights window2.
528 Cycle(WindowSelector::FORWARD);
529 // All panels are destroyed.
530 panel1.reset();
531 panel2.reset();
532 // Cycling again should now select window3.
533 Cycle(WindowSelector::FORWARD);
534 StopCycling();
535 EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
536 }
537
538 // Tests cycles between panel and normal windows.
TEST_F(WindowSelectorTest,CycleMruPanelDestroyed)539 TEST_F(WindowSelectorTest, CycleMruPanelDestroyed) {
540 gfx::Rect bounds(0, 0, 400, 400);
541 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
542 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
543 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
544 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
545 wm::ActivateWindow(panel2.get());
546 wm::ActivateWindow(panel1.get());
547 wm::ActivateWindow(window2.get());
548 wm::ActivateWindow(window1.get());
549 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
550
551 // Cycling once highlights window2.
552 Cycle(WindowSelector::FORWARD);
553 // Panel 1 is the next item as the MRU panel, removing it should make panel 2
554 // the next window to be selected.
555 panel1.reset();
556 // Cycling again should now select window3.
557 Cycle(WindowSelector::FORWARD);
558 StopCycling();
559 EXPECT_TRUE(wm::IsActiveWindow(panel2.get()));
560 }
561
562 // Tests that a newly created window aborts overview.
TEST_F(WindowSelectorTest,NewWindowCancelsOveriew)563 TEST_F(WindowSelectorTest, NewWindowCancelsOveriew) {
564 gfx::Rect bounds(0, 0, 400, 400);
565 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
566 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
567 ToggleOverview();
568 EXPECT_TRUE(IsSelecting());
569
570 // A window being created should exit overview mode.
571 scoped_ptr<aura::Window> window3(CreateWindow(bounds));
572 EXPECT_FALSE(IsSelecting());
573 }
574
575 // Tests that a window activation exits overview mode.
TEST_F(WindowSelectorTest,ActivationCancelsOveriew)576 TEST_F(WindowSelectorTest, ActivationCancelsOveriew) {
577 gfx::Rect bounds(0, 0, 400, 400);
578 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
579 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
580 window2->Focus();
581 ToggleOverview();
582 EXPECT_TRUE(IsSelecting());
583
584 // A window being activated should exit overview mode.
585 window1->Focus();
586 EXPECT_FALSE(IsSelecting());
587
588 // window1 should be focused after exiting even though window2 was focused on
589 // entering overview because we exited due to an activation.
590 EXPECT_EQ(window1.get(), GetFocusedWindow());
591 }
592
593 // Verifies that overview mode only begins after a delay when cycling.
TEST_F(WindowSelectorTest,CycleOverviewDelay)594 TEST_F(WindowSelectorTest, CycleOverviewDelay) {
595 gfx::Rect bounds(0, 0, 400, 400);
596 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
597 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
598 EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get()));
599
600 // When cycling first starts, the windows will still be overlapping.
601 Cycle(WindowSelector::FORWARD);
602 EXPECT_TRUE(IsSelecting());
603 EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get()));
604
605 // Once the overview timer fires, the windows should no longer overlap.
606 FireOverviewStartTimer();
607 EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get()));
608 StopCycling();
609 }
610
611 // Tests that exiting overview mode without selecting a window restores focus
612 // to the previously focused window.
TEST_F(WindowSelectorTest,CancelRestoresFocus)613 TEST_F(WindowSelectorTest, CancelRestoresFocus) {
614 gfx::Rect bounds(0, 0, 400, 400);
615 scoped_ptr<aura::Window> window(CreateWindow(bounds));
616 wm::ActivateWindow(window.get());
617 EXPECT_EQ(window.get(), GetFocusedWindow());
618
619 // In overview mode, focus should be removed.
620 ToggleOverview();
621 EXPECT_EQ(NULL, GetFocusedWindow());
622
623 // If canceling overview mode, focus should be restored.
624 ToggleOverview();
625 EXPECT_EQ(window.get(), GetFocusedWindow());
626 }
627
628 // Tests that overview mode is exited if the last remaining window is destroyed.
TEST_F(WindowSelectorTest,LastWindowDestroyed)629 TEST_F(WindowSelectorTest, LastWindowDestroyed) {
630 gfx::Rect bounds(0, 0, 400, 400);
631 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
632 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
633 ToggleOverview();
634
635 window1.reset();
636 window2.reset();
637 EXPECT_FALSE(IsSelecting());
638 }
639
640 // Tests that entering overview mode restores a window to its original
641 // target location.
TEST_F(WindowSelectorTest,QuickReentryRestoresInitialTransform)642 TEST_F(WindowSelectorTest, QuickReentryRestoresInitialTransform) {
643 gfx::Rect bounds(0, 0, 400, 400);
644 scoped_ptr<aura::Window> window(CreateWindow(bounds));
645 gfx::Rect initial_bounds = ToEnclosingRect(
646 GetTransformedBounds(window.get()));
647 ToggleOverview();
648 // Quickly exit and reenter overview mode. The window should still be
649 // animating when we reenter. We cannot short circuit animations for this but
650 // we also don't have to wait for them to complete.
651 {
652 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
653 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
654 ToggleOverview();
655 ToggleOverview();
656 }
657 EXPECT_NE(initial_bounds, ToEnclosingRect(
658 GetTransformedTargetBounds(window.get())));
659 ToggleOverview();
660 EXPECT_FALSE(IsSelecting());
661 EXPECT_EQ(initial_bounds, ToEnclosingRect(
662 GetTransformedTargetBounds(window.get())));
663 }
664
665 // Tests that non-activatable windows are hidden when entering overview mode.
TEST_F(WindowSelectorTest,NonActivatableWindowsHidden)666 TEST_F(WindowSelectorTest, NonActivatableWindowsHidden) {
667 gfx::Rect bounds(0, 0, 400, 400);
668 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
669 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
670 scoped_ptr<aura::Window> non_activatable_window(
671 CreateNonActivatableWindow(Shell::GetPrimaryRootWindow()->bounds()));
672 EXPECT_TRUE(non_activatable_window->IsVisible());
673 ToggleOverview();
674 EXPECT_FALSE(non_activatable_window->IsVisible());
675 ToggleOverview();
676 EXPECT_TRUE(non_activatable_window->IsVisible());
677
678 // Test that a window behind the fullscreen non-activatable window can be
679 // clicked.
680 non_activatable_window->parent()->StackChildAtTop(
681 non_activatable_window.get());
682 ToggleOverview();
683 ClickWindow(window1.get());
684 EXPECT_FALSE(IsSelecting());
685 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
686 }
687
688 // Tests that windows with modal child windows are transformed with the modal
689 // child even though not activatable themselves.
TEST_F(WindowSelectorTest,ModalChild)690 TEST_F(WindowSelectorTest, ModalChild) {
691 gfx::Rect bounds(0, 0, 400, 400);
692 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
693 scoped_ptr<aura::Window> child1(CreateWindow(bounds));
694 child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
695 window1->AddTransientChild(child1.get());
696 EXPECT_EQ(window1->parent(), child1->parent());
697 ToggleOverview();
698 EXPECT_TRUE(window1->IsVisible());
699 EXPECT_TRUE(child1->IsVisible());
700 EXPECT_EQ(ToEnclosingRect(GetTransformedTargetBounds(child1.get())),
701 ToEnclosingRect(GetTransformedTargetBounds(window1.get())));
702 ToggleOverview();
703 }
704
705 // Tests that clicking a modal window's parent activates the modal window in
706 // overview.
TEST_F(WindowSelectorTest,ClickModalWindowParent)707 TEST_F(WindowSelectorTest, ClickModalWindowParent) {
708 scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 180, 180)));
709 scoped_ptr<aura::Window> child1(CreateWindow(gfx::Rect(200, 0, 180, 180)));
710 child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
711 window1->AddTransientChild(child1.get());
712 EXPECT_FALSE(WindowsOverlapping(window1.get(), child1.get()));
713 EXPECT_EQ(window1->parent(), child1->parent());
714 ToggleOverview();
715 // Given that their relative positions are preserved, the windows should still
716 // not overlap.
717 EXPECT_FALSE(WindowsOverlapping(window1.get(), child1.get()));
718 ClickWindow(window1.get());
719 EXPECT_FALSE(IsSelecting());
720
721 // Clicking on window1 should activate child1.
722 EXPECT_TRUE(wm::IsActiveWindow(child1.get()));
723 }
724
725 // Tests that windows remain on the display they are currently on in overview
726 // mode.
TEST_F(WindowSelectorTest,MultipleDisplays)727 TEST_F(WindowSelectorTest, MultipleDisplays) {
728 if (!SupportsMultipleDisplays())
729 return;
730
731 UpdateDisplay("600x400,600x400");
732 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
733 gfx::Rect bounds1(0, 0, 400, 400);
734 gfx::Rect bounds2(650, 0, 400, 400);
735
736 scoped_ptr<aura::Window> window1(CreateWindow(bounds1));
737 scoped_ptr<aura::Window> window2(CreateWindow(bounds1));
738 scoped_ptr<aura::Window> window3(CreateWindow(bounds2));
739 scoped_ptr<aura::Window> window4(CreateWindow(bounds2));
740 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds1));
741 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds1));
742 scoped_ptr<aura::Window> panel3(CreatePanelWindow(bounds2));
743 scoped_ptr<aura::Window> panel4(CreatePanelWindow(bounds2));
744 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
745 EXPECT_EQ(root_windows[0], window2->GetRootWindow());
746 EXPECT_EQ(root_windows[1], window3->GetRootWindow());
747 EXPECT_EQ(root_windows[1], window4->GetRootWindow());
748
749 EXPECT_EQ(root_windows[0], panel1->GetRootWindow());
750 EXPECT_EQ(root_windows[0], panel2->GetRootWindow());
751 EXPECT_EQ(root_windows[1], panel3->GetRootWindow());
752 EXPECT_EQ(root_windows[1], panel4->GetRootWindow());
753
754 // In overview mode, each window remains in the same root window.
755 ToggleOverview();
756 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
757 EXPECT_EQ(root_windows[0], window2->GetRootWindow());
758 EXPECT_EQ(root_windows[1], window3->GetRootWindow());
759 EXPECT_EQ(root_windows[1], window4->GetRootWindow());
760 EXPECT_EQ(root_windows[0], panel1->GetRootWindow());
761 EXPECT_EQ(root_windows[0], panel2->GetRootWindow());
762 EXPECT_EQ(root_windows[1], panel3->GetRootWindow());
763 EXPECT_EQ(root_windows[1], panel4->GetRootWindow());
764
765 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
766 ToEnclosingRect(GetTransformedTargetBounds(window1.get()))));
767 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
768 ToEnclosingRect(GetTransformedTargetBounds(window2.get()))));
769 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
770 ToEnclosingRect(GetTransformedTargetBounds(window3.get()))));
771 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
772 ToEnclosingRect(GetTransformedTargetBounds(window4.get()))));
773
774 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
775 ToEnclosingRect(GetTransformedTargetBounds(panel1.get()))));
776 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
777 ToEnclosingRect(GetTransformedTargetBounds(panel2.get()))));
778 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
779 ToEnclosingRect(GetTransformedTargetBounds(panel3.get()))));
780 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
781 ToEnclosingRect(GetTransformedTargetBounds(panel4.get()))));
782 EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
783 EXPECT_TRUE(WindowsOverlapping(panel3.get(), panel4.get()));
784 EXPECT_FALSE(WindowsOverlapping(panel1.get(), panel3.get()));
785 }
786
787 // Verifies that the single display overview used during alt tab cycling uses
788 // the display of the selected window by default.
TEST_F(WindowSelectorTest,CycleOverviewUsesCurrentDisplay)789 TEST_F(WindowSelectorTest, CycleOverviewUsesCurrentDisplay) {
790 if (!SupportsMultipleDisplays())
791 return;
792
793 UpdateDisplay("400x400,400x400");
794 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
795
796 scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 100, 100)));
797 scoped_ptr<aura::Window> window2(CreateWindow(gfx::Rect(450, 0, 100, 100)));
798 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
799 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
800 wm::ActivateWindow(window2.get());
801 wm::ActivateWindow(window1.get());
802 EXPECT_EQ(root_windows[0], Shell::GetTargetRootWindow());
803
804 Cycle(WindowSelector::FORWARD);
805 FireOverviewStartTimer();
806
807 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
808 ToEnclosingRect(GetTransformedTargetBounds(window1.get()))));
809 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
810 ToEnclosingRect(GetTransformedTargetBounds(window2.get()))));
811 StopCycling();
812 }
813
814 // Verifies that the windows being shown on another display are copied.
TEST_F(WindowSelectorTest,CycleMultipleDisplaysCopiesWindows)815 TEST_F(WindowSelectorTest, CycleMultipleDisplaysCopiesWindows) {
816 if (!SupportsMultipleDisplays())
817 return;
818
819 UpdateDisplay("400x400,400x400");
820 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
821
822 gfx::Rect root1_rect(0, 0, 100, 100);
823 gfx::Rect root2_rect(450, 0, 100, 100);
824 scoped_ptr<aura::Window> unmoved1(CreateWindow(root2_rect));
825 scoped_ptr<aura::Window> unmoved2(CreateWindow(root2_rect));
826 scoped_ptr<aura::Window> moved1_trans_parent(CreateWindow(root1_rect));
827 scoped_ptr<aura::Window> moved1(CreateWindow(root1_rect));
828 unmoved1->SetName("unmoved1");
829 unmoved2->SetName("unmoved2");
830 moved1->SetName("moved1");
831 moved1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
832 moved1_trans_parent->AddTransientChild(moved1.get());
833 moved1_trans_parent->SetName("moved1_trans_parent");
834
835 EXPECT_EQ(root_windows[0], moved1->GetRootWindow());
836 EXPECT_EQ(root_windows[0], moved1_trans_parent->GetRootWindow());
837 EXPECT_EQ(root_windows[1], unmoved1->GetRootWindow());
838 EXPECT_EQ(root_windows[1], unmoved2->GetRootWindow());
839 wm::ActivateWindow(unmoved2.get());
840 wm::ActivateWindow(unmoved1.get());
841
842 Cycle(WindowSelector::FORWARD);
843 FireOverviewStartTimer();
844
845 // All windows are moved to second root window.
846 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
847 ToEnclosingRect(GetTransformedTargetBounds(unmoved1.get()))));
848 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
849 ToEnclosingRect(GetTransformedTargetBounds(unmoved2.get()))));
850 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
851 ToEnclosingRect(GetTransformedTargetBounds(moved1.get()))));
852 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
853 ToEnclosingRect(GetTransformedTargetBounds(moved1_trans_parent.get()))));
854
855 // unmoved1 and unmoved2 were already on the correct display and should not
856 // have been copied.
857 EXPECT_TRUE(!GetCopyWindow(unmoved1.get()));
858 EXPECT_TRUE(!GetCopyWindow(unmoved2.get()));
859
860 // moved1 and its transient parent moved1_trans_parent should have also been
861 // copied for displaying on root_windows[1].
862 aura::Window* copy1 = GetCopyWindow(moved1.get());
863 aura::Window* copy1_trans_parent = GetCopyWindow(moved1_trans_parent.get());
864 ASSERT_FALSE(!copy1);
865 ASSERT_FALSE(!copy1_trans_parent);
866
867 // Verify that the bounds and transform of the copy match the original window
868 // but that it is on the other root window.
869 EXPECT_EQ(root_windows[1], copy1->GetRootWindow());
870 EXPECT_EQ(moved1->GetBoundsInScreen().ToString(),
871 copy1->GetBoundsInScreen().ToString());
872 EXPECT_EQ(moved1->layer()->GetTargetTransform().ToString(),
873 copy1->layer()->GetTargetTransform().ToString());
874 StopCycling();
875
876 // After cycling the copy windows should have been destroyed.
877 RunAllPendingInMessageLoop();
878 EXPECT_TRUE(!GetCopyWindow(moved1.get()));
879 EXPECT_TRUE(!GetCopyWindow(moved1_trans_parent.get()));
880 }
881
882 // Tests that beginning to cycle from overview mode moves windows to the
883 // active display.
TEST_F(WindowSelectorTest,MultipleDisplaysOverviewTransitionToCycle)884 TEST_F(WindowSelectorTest, MultipleDisplaysOverviewTransitionToCycle) {
885 if (!SupportsMultipleDisplays())
886 return;
887
888 UpdateDisplay("400x400,400x400");
889 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
890
891 scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 100, 100)));
892 scoped_ptr<aura::Window> window2(CreateWindow(gfx::Rect(450, 0, 100, 100)));
893 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
894 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
895 wm::ActivateWindow(window2.get());
896 wm::ActivateWindow(window1.get());
897
898 ToggleOverview();
899 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
900 ToEnclosingRect(GetTransformedTargetBounds(window1.get()))));
901 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
902 ToEnclosingRect(GetTransformedTargetBounds(window2.get()))));
903
904 Cycle(WindowSelector::FORWARD);
905 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
906 ToEnclosingRect(GetTransformedTargetBounds(window1.get()))));
907 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
908 ToEnclosingRect(GetTransformedTargetBounds(window2.get()))));
909 StopCycling();
910 }
911
912 // Tests that a bounds change during overview is corrected for.
TEST_F(WindowSelectorTest,BoundsChangeDuringCycleOnOtherDisplay)913 TEST_F(WindowSelectorTest, BoundsChangeDuringCycleOnOtherDisplay) {
914 if (!SupportsMultipleDisplays())
915 return;
916
917 UpdateDisplay("400x400,400x400");
918 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
919
920 scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 100, 100)));
921 scoped_ptr<aura::Window> window2(CreateWindow(gfx::Rect(450, 0, 100, 100)));
922 scoped_ptr<aura::Window> window3(CreateWindow(gfx::Rect(450, 0, 100, 100)));
923 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
924 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
925 EXPECT_EQ(root_windows[1], window3->GetRootWindow());
926 wm::ActivateWindow(window1.get());
927 wm::ActivateWindow(window2.get());
928 wm::ActivateWindow(window3.get());
929
930 Cycle(WindowSelector::FORWARD);
931 FireOverviewStartTimer();
932
933 gfx::Rect overview_bounds(
934 ToEnclosingRect(GetTransformedTargetBounds(window1.get())));
935 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(overview_bounds));
936
937 // Change the position and size of window1 (being displayed on the second
938 // root window) and it should remain within the same bounds.
939 window1->SetBounds(gfx::Rect(100, 0, 200, 200));
940 gfx::Rect new_overview_bounds =
941 ToEnclosingRect(GetTransformedTargetBounds(window1.get()));
942 EXPECT_EQ(overview_bounds.x(), new_overview_bounds.x());
943 EXPECT_EQ(overview_bounds.y(), new_overview_bounds.y());
944 EXPECT_EQ(overview_bounds.width(), new_overview_bounds.width());
945 EXPECT_EQ(overview_bounds.height(), new_overview_bounds.height());
946 StopCycling();
947 }
948
949 // Tests shutting down during overview.
TEST_F(WindowSelectorTest,Shutdown)950 TEST_F(WindowSelectorTest, Shutdown) {
951 gfx::Rect bounds(0, 0, 400, 400);
952 // These windows will be deleted when the test exits and the Shell instance
953 // is shut down.
954 aura::Window* window1(CreateWindow(bounds));
955 aura::Window* window2(CreateWindow(bounds));
956 aura::Window* window3(CreatePanelWindow(bounds));
957 aura::Window* window4(CreatePanelWindow(bounds));
958
959 wm::ActivateWindow(window4);
960 wm::ActivateWindow(window3);
961 wm::ActivateWindow(window2);
962 wm::ActivateWindow(window1);
963
964 ToggleOverview();
965 }
966
967 // Tests removing a display during overview.
TEST_F(WindowSelectorTest,RemoveDisplay)968 TEST_F(WindowSelectorTest, RemoveDisplay) {
969 if (!SupportsMultipleDisplays())
970 return;
971
972 UpdateDisplay("400x400,400x400");
973 gfx::Rect bounds1(0, 0, 100, 100);
974 gfx::Rect bounds2(450, 0, 100, 100);
975 scoped_ptr<aura::Window> window1(CreateWindow(bounds1));
976 scoped_ptr<aura::Window> window2(CreateWindow(bounds2));
977 scoped_ptr<aura::Window> window3(CreatePanelWindow(bounds1));
978 scoped_ptr<aura::Window> window4(CreatePanelWindow(bounds2));
979
980 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
981 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
982 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
983 EXPECT_EQ(root_windows[0], window3->GetRootWindow());
984 EXPECT_EQ(root_windows[1], window4->GetRootWindow());
985
986 wm::ActivateWindow(window4.get());
987 wm::ActivateWindow(window3.get());
988 wm::ActivateWindow(window2.get());
989 wm::ActivateWindow(window1.get());
990
991 ToggleOverview();
992 EXPECT_TRUE(IsSelecting());
993 UpdateDisplay("400x400");
994 EXPECT_FALSE(IsSelecting());
995 }
996
997 } // namespace internal
998 } // namespace ash
999