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.
5 #include "ash/root_window_controller.h"
6 #include "ash/screen_util.h"
7 #include "ash/shelf/shelf.h"
8 #include "ash/shelf/shelf_widget.h"
10 #include "ash/test/ash_test_base.h"
11 #include "ash/test/shelf_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 #include "ui/views/corewm/window_util.h"
43 class NonActivatableActivationDelegate
44 : public aura::client::ActivationDelegate {
46 virtual bool ShouldActivate() const OVERRIDE {
51 bool IsWindowAbove(aura::Window* w1, aura::Window* w2) {
52 aura::Window* parent = w1->parent();
53 DCHECK_EQ(parent, w2->parent());
54 for (aura::Window::Windows::const_iterator iter = parent->children().begin();
55 iter != parent->children().end(); ++iter) {
65 aura::Window* GetWindowByName(aura::Window* container,
66 const std::string& name) {
67 aura::Window* window = NULL;
68 for (aura::Window::Windows::const_iterator iter =
69 container->children().begin(); iter != container->children().end();
71 if ((*iter)->name() == name) {
72 // The name should be unique.
80 // Returns the copy of |window| created for overview. It is found using the
81 // window name which should be the same as the source window's name with a
82 // special suffix, and in the same container as the source window.
83 aura::Window* GetCopyWindow(aura::Window* window) {
84 aura::Window* copy_window = NULL;
85 std::string copy_name = window->name() + " (Copy)";
86 std::vector<aura::Window*> containers(
87 Shell::GetContainersFromAllRootWindows(window->parent()->id(), NULL));
88 for (std::vector<aura::Window*>::iterator iter = containers.begin();
89 iter != containers.end(); ++iter) {
90 aura::Window* found = GetWindowByName(*iter, copy_name);
92 // There should only be one copy window.
102 class WindowSelectorTest : public test::AshTestBase {
104 WindowSelectorTest() {}
105 virtual ~WindowSelectorTest() {}
107 virtual void SetUp() OVERRIDE {
108 test::AshTestBase::SetUp();
109 ASSERT_TRUE(test::TestShelfDelegate::instance());
111 shelf_view_test_.reset(new test::ShelfViewTestAPI(
112 test::ShelfTestAPI(Shelf::ForPrimaryDisplay()).shelf_view()));
113 shelf_view_test_->SetAnimationDuration(1);
116 aura::Window* CreateWindow(const gfx::Rect& bounds) {
117 return CreateTestWindowInShellWithDelegate(&delegate_, -1, bounds);
120 aura::Window* CreateNonActivatableWindow(const gfx::Rect& bounds) {
121 aura::Window* window = CreateWindow(bounds);
122 aura::client::SetActivationDelegate(window,
123 &non_activatable_activation_delegate_);
124 EXPECT_FALSE(ash::wm::CanActivateWindow(window));
128 aura::Window* CreatePanelWindow(const gfx::Rect& bounds) {
129 aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
130 NULL, ui::wm::WINDOW_TYPE_PANEL, 0, bounds);
131 test::TestShelfDelegate::instance()->AddLauncherItem(window);
132 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
136 bool WindowsOverlapping(aura::Window* window1, aura::Window* window2) {
137 gfx::RectF window1_bounds = GetTransformedTargetBounds(window1);
138 gfx::RectF window2_bounds = GetTransformedTargetBounds(window2);
139 return window1_bounds.Intersects(window2_bounds);
142 void ToggleOverview() {
143 ash::Shell::GetInstance()->window_selector_controller()->ToggleOverview();
146 void Cycle(WindowSelector::Direction direction) {
147 ash::Shell::GetInstance()->window_selector_controller()->
148 HandleCycleWindow(direction);
152 ash::Shell::GetInstance()->window_selector_controller()->window_selector_->
156 void FireOverviewStartTimer() {
157 // Calls the method to start overview mode which is normally called by the
158 // timer. The timer will still fire and call this method triggering the
159 // DCHECK that overview mode was not already started, except that we call
160 // StopCycling before the timer has a chance to fire.
161 ash::Shell::GetInstance()->window_selector_controller()->window_selector_->
165 gfx::Transform GetTransformRelativeTo(gfx::PointF origin,
166 const gfx::Transform& transform) {
168 t.Translate(origin.x(), origin.y());
169 t.PreconcatTransform(transform);
170 t.Translate(-origin.x(), -origin.y());
174 gfx::RectF GetTransformedBounds(aura::Window* window) {
175 gfx::RectF bounds(ScreenUtil::ConvertRectToScreen(
176 window->parent(), window->layer()->bounds()));
177 gfx::Transform transform(GetTransformRelativeTo(bounds.origin(),
178 window->layer()->transform()));
179 transform.TransformRect(&bounds);
183 gfx::RectF GetTransformedTargetBounds(aura::Window* window) {
184 gfx::RectF bounds(ScreenUtil::ConvertRectToScreen(
185 window->parent(), window->layer()->GetTargetBounds()));
186 gfx::Transform transform(GetTransformRelativeTo(bounds.origin(),
187 window->layer()->GetTargetTransform()));
188 transform.TransformRect(&bounds);
192 void ClickWindow(aura::Window* window) {
193 aura::test::EventGenerator event_generator(window->GetRootWindow(), window);
194 gfx::RectF target = GetTransformedBounds(window);
195 event_generator.ClickLeftButton();
199 return ash::Shell::GetInstance()->window_selector_controller()->
203 aura::Window* GetFocusedWindow() {
204 return aura::client::GetFocusClient(
205 Shell::GetPrimaryRootWindow())->GetFocusedWindow();
208 test::ShelfViewTestAPI* shelf_view_test() {
209 return shelf_view_test_.get();
213 aura::test::TestWindowDelegate delegate_;
214 NonActivatableActivationDelegate non_activatable_activation_delegate_;
215 scoped_ptr<test::ShelfViewTestAPI> shelf_view_test_;
217 DISALLOW_COPY_AND_ASSIGN(WindowSelectorTest);
220 // Tests entering overview mode with two windows and selecting one.
221 TEST_F(WindowSelectorTest, Basic) {
222 gfx::Rect bounds(0, 0, 400, 400);
223 aura::Window* root_window = Shell::GetPrimaryRootWindow();
224 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
225 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
226 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
227 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
228 EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get()));
229 EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
230 wm::ActivateWindow(window2.get());
231 EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
232 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
233 EXPECT_EQ(window2.get(), GetFocusedWindow());
234 // Hide the cursor before entering overview to test that it will be shown.
235 aura::client::GetCursorClient(root_window)->HideCursor();
237 // In overview mode the windows should no longer overlap and focus should
238 // be removed from the window.
240 EXPECT_EQ(NULL, GetFocusedWindow());
241 EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get()));
242 EXPECT_FALSE(WindowsOverlapping(window1.get(), panel1.get()));
243 // Panels 1 and 2 should still be overlapping being in a single selector
245 EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
247 // The cursor should be visible and locked as a pointer
248 EXPECT_EQ(ui::kCursorPointer,
249 root_window->GetDispatcher()->last_cursor().native_type());
250 EXPECT_TRUE(aura::client::GetCursorClient(root_window)->IsCursorLocked());
251 EXPECT_TRUE(aura::client::GetCursorClient(root_window)->IsCursorVisible());
253 // Clicking window 1 should activate it.
254 ClickWindow(window1.get());
255 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
256 EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
257 EXPECT_EQ(window1.get(), GetFocusedWindow());
259 // Cursor should have been unlocked.
260 EXPECT_FALSE(aura::client::GetCursorClient(root_window)->IsCursorLocked());
263 // Tests entering overview mode with two windows and selecting one.
264 TEST_F(WindowSelectorTest, FullscreenWindow) {
265 gfx::Rect bounds(0, 0, 400, 400);
266 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
267 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
268 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
269 wm::ActivateWindow(window1.get());
271 wm::GetWindowState(window1.get())->ToggleFullscreen();
272 // The panel is hidden in fullscreen mode.
273 EXPECT_FALSE(panel1->IsVisible());
274 EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen());
276 // Enter overview and select the fullscreen window.
279 // The panel becomes temporarily visible for the overview.
280 EXPECT_TRUE(panel1->IsVisible());
281 ClickWindow(window1.get());
283 // The window is still fullscreen as it was selected. The panel should again
285 EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen());
286 EXPECT_FALSE(panel1->IsVisible());
288 // Entering overview and selecting another window, the previous window remains
290 // TODO(flackr): Currently the panel remains hidden, but should become visible
293 ClickWindow(window2.get());
294 EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen());
297 // Tests that the shelf dimming state is removed while in overview and restored
298 // on exiting overview.
299 TEST_F(WindowSelectorTest, OverviewUndimsShelf) {
300 gfx::Rect bounds(0, 0, 400, 400);
301 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
302 wm::WindowState* window_state = wm::GetWindowState(window1.get());
303 window_state->Maximize();
304 ash::ShelfWidget* shelf = Shell::GetPrimaryRootWindowController()->shelf();
305 EXPECT_TRUE(shelf->GetDimsShelf());
307 EXPECT_FALSE(shelf->GetDimsShelf());
309 EXPECT_TRUE(shelf->GetDimsShelf());
312 // Tests that beginning window selection hides the app list.
313 TEST_F(WindowSelectorTest, SelectingHidesAppList) {
314 gfx::Rect bounds(0, 0, 400, 400);
315 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
316 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
317 Shell::GetInstance()->ToggleAppList(NULL);
318 EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility());
320 EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility());
323 // The app list uses an animation to fade out. If it is toggled on immediately
324 // after being removed the old widget is re-used and it does not gain focus.
325 // When running under normal circumstances this shouldn't be possible, but
326 // it is in a test without letting the message loop run.
327 RunAllPendingInMessageLoop();
329 Shell::GetInstance()->ToggleAppList(NULL);
330 EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility());
331 Cycle(WindowSelector::FORWARD);
332 EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility());
336 // Tests that a minimized window's visibility and layer visibility is correctly
337 // changed when entering overview and restored when leaving overview mode.
338 TEST_F(WindowSelectorTest, MinimizedWindowVisibility) {
339 gfx::Rect bounds(0, 0, 400, 400);
340 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
341 wm::WindowState* window_state = wm::GetWindowState(window1.get());
342 window_state->Minimize();
343 EXPECT_FALSE(window1->IsVisible());
344 EXPECT_FALSE(window1->layer()->GetTargetVisibility());
346 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
347 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
349 EXPECT_TRUE(window1->IsVisible());
350 EXPECT_TRUE(window1->layer()->GetTargetVisibility());
353 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
354 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
356 EXPECT_FALSE(window1->IsVisible());
357 EXPECT_FALSE(window1->layer()->GetTargetVisibility());
361 // Tests that a bounds change during overview is corrected for.
362 TEST_F(WindowSelectorTest, BoundsChangeDuringOverview) {
363 scoped_ptr<aura::Window> window(CreateWindow(gfx::Rect(0, 0, 400, 400)));
365 gfx::Rect overview_bounds =
366 ToEnclosingRect(GetTransformedTargetBounds(window.get()));
367 window->SetBounds(gfx::Rect(200, 0, 200, 200));
368 gfx::Rect new_overview_bounds =
369 ToEnclosingRect(GetTransformedTargetBounds(window.get()));
370 EXPECT_EQ(overview_bounds.x(), new_overview_bounds.x());
371 EXPECT_EQ(overview_bounds.y(), new_overview_bounds.y());
372 EXPECT_EQ(overview_bounds.width(), new_overview_bounds.width());
373 EXPECT_EQ(overview_bounds.height(), new_overview_bounds.height());
377 // Tests entering overview mode with three windows and cycling through them.
378 TEST_F(WindowSelectorTest, BasicCycle) {
379 gfx::Rect bounds(0, 0, 400, 400);
380 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
381 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
382 scoped_ptr<aura::Window> window3(CreateWindow(bounds));
383 wm::ActivateWindow(window3.get());
384 wm::ActivateWindow(window2.get());
385 wm::ActivateWindow(window1.get());
386 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
387 EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
388 EXPECT_FALSE(wm::IsActiveWindow(window3.get()));
390 Cycle(WindowSelector::FORWARD);
391 EXPECT_TRUE(IsSelecting());
392 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
394 Cycle(WindowSelector::FORWARD);
395 EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
398 EXPECT_FALSE(IsSelecting());
399 EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
400 EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
401 EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
404 // Tests that cycling through windows preserves the window stacking order.
405 TEST_F(WindowSelectorTest, CyclePreservesStackingOrder) {
406 gfx::Rect bounds(0, 0, 400, 400);
407 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
408 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
409 scoped_ptr<aura::Window> window3(CreateWindow(bounds));
410 wm::ActivateWindow(window3.get());
411 wm::ActivateWindow(window2.get());
412 wm::ActivateWindow(window1.get());
413 // Window order from top to bottom is 1, 2, 3.
414 EXPECT_TRUE(IsWindowAbove(window1.get(), window2.get()));
415 EXPECT_TRUE(IsWindowAbove(window2.get(), window3.get()));
418 Cycle(WindowSelector::FORWARD);
419 EXPECT_TRUE(IsWindowAbove(window2.get(), window1.get()));
420 EXPECT_TRUE(IsWindowAbove(window1.get(), window3.get()));
423 Cycle(WindowSelector::FORWARD);
424 EXPECT_TRUE(IsWindowAbove(window3.get(), window1.get()));
425 EXPECT_TRUE(IsWindowAbove(window1.get(), window2.get()));
428 Cycle(WindowSelector::FORWARD);
429 EXPECT_TRUE(IsWindowAbove(window1.get(), window2.get()));
430 EXPECT_TRUE(IsWindowAbove(window2.get(), window3.get()));
434 // Tests that cycling through windows shows and minimizes windows as they
436 TEST_F(WindowSelectorTest, CyclePreservesMinimization) {
437 gfx::Rect bounds(0, 0, 400, 400);
438 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
439 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
440 wm::ActivateWindow(window2.get());
441 wm::GetWindowState(window2.get())->Minimize();
442 wm::ActivateWindow(window1.get());
443 EXPECT_TRUE(wm::IsWindowMinimized(window2.get()));
446 Cycle(WindowSelector::FORWARD);
447 EXPECT_FALSE(wm::IsWindowMinimized(window2.get()));
450 Cycle(WindowSelector::FORWARD);
451 EXPECT_TRUE(wm::IsWindowMinimized(window2.get()));
454 EXPECT_TRUE(wm::IsWindowMinimized(window2.get()));
457 // Tests beginning cycling while in overview mode.
458 TEST_F(WindowSelectorTest, OverviewTransitionToCycle) {
459 gfx::Rect bounds(0, 0, 400, 400);
460 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
461 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
462 wm::ActivateWindow(window2.get());
463 wm::ActivateWindow(window1.get());
466 Cycle(WindowSelector::FORWARD);
469 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
470 EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
471 EXPECT_EQ(window2.get(), GetFocusedWindow());
474 // Tests cycles between panel and normal windows.
475 TEST_F(WindowSelectorTest, CyclePanels) {
476 gfx::Rect bounds(0, 0, 400, 400);
477 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
478 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
479 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
480 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
481 wm::ActivateWindow(window2.get());
482 wm::ActivateWindow(window1.get());
483 wm::ActivateWindow(panel2.get());
484 wm::ActivateWindow(panel1.get());
485 EXPECT_TRUE(wm::IsActiveWindow(panel1.get()));
487 // Cycling once should select window1 since the panels are grouped into a
488 // single selectable item.
489 Cycle(WindowSelector::FORWARD);
491 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
493 // Cycling again should select the most recently used panel.
494 Cycle(WindowSelector::FORWARD);
496 EXPECT_TRUE(wm::IsActiveWindow(panel1.get()));
499 // Tests the visibility of panel windows during cycling.
500 TEST_F(WindowSelectorTest, CyclePanelVisibility) {
501 gfx::Rect bounds(0, 0, 400, 400);
502 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
503 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
504 wm::ActivateWindow(panel1.get());
505 wm::ActivateWindow(window1.get());
507 Cycle(WindowSelector::FORWARD);
508 FireOverviewStartTimer();
509 EXPECT_EQ(1.0f, panel1->layer()->GetTargetOpacity());
513 // Tests cycles between panel and normal windows.
514 TEST_F(WindowSelectorTest, CyclePanelsDestroyed) {
515 gfx::Rect bounds(0, 0, 400, 400);
516 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
517 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
518 scoped_ptr<aura::Window> window3(CreateWindow(bounds));
519 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
520 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
521 wm::ActivateWindow(window3.get());
522 wm::ActivateWindow(panel2.get());
523 wm::ActivateWindow(panel1.get());
524 wm::ActivateWindow(window2.get());
525 wm::ActivateWindow(window1.get());
526 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
528 // Cycling once highlights window2.
529 Cycle(WindowSelector::FORWARD);
530 // All panels are destroyed.
533 // Cycling again should now select window3.
534 Cycle(WindowSelector::FORWARD);
536 EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
539 // Tests cycles between panel and normal windows.
540 TEST_F(WindowSelectorTest, CycleMruPanelDestroyed) {
541 gfx::Rect bounds(0, 0, 400, 400);
542 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
543 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
544 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
545 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
546 wm::ActivateWindow(panel2.get());
547 wm::ActivateWindow(panel1.get());
548 wm::ActivateWindow(window2.get());
549 wm::ActivateWindow(window1.get());
550 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
552 // Cycling once highlights window2.
553 Cycle(WindowSelector::FORWARD);
554 // Panel 1 is the next item as the MRU panel, removing it should make panel 2
555 // the next window to be selected.
557 // Cycling again should now select window3.
558 Cycle(WindowSelector::FORWARD);
560 EXPECT_TRUE(wm::IsActiveWindow(panel2.get()));
563 // Tests that a newly created window aborts overview.
564 TEST_F(WindowSelectorTest, NewWindowCancelsOveriew) {
565 gfx::Rect bounds(0, 0, 400, 400);
566 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
567 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
569 EXPECT_TRUE(IsSelecting());
571 // A window being created should exit overview mode.
572 scoped_ptr<aura::Window> window3(CreateWindow(bounds));
573 EXPECT_FALSE(IsSelecting());
576 // Tests that a window activation exits overview mode.
577 TEST_F(WindowSelectorTest, ActivationCancelsOveriew) {
578 gfx::Rect bounds(0, 0, 400, 400);
579 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
580 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
583 EXPECT_TRUE(IsSelecting());
585 // A window being activated should exit overview mode.
587 EXPECT_FALSE(IsSelecting());
589 // window1 should be focused after exiting even though window2 was focused on
590 // entering overview because we exited due to an activation.
591 EXPECT_EQ(window1.get(), GetFocusedWindow());
594 // Verifies that overview mode only begins after a delay when cycling.
595 TEST_F(WindowSelectorTest, CycleOverviewDelay) {
596 gfx::Rect bounds(0, 0, 400, 400);
597 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
598 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
599 EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get()));
601 // When cycling first starts, the windows will still be overlapping.
602 Cycle(WindowSelector::FORWARD);
603 EXPECT_TRUE(IsSelecting());
604 EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get()));
606 // Once the overview timer fires, the windows should no longer overlap.
607 FireOverviewStartTimer();
608 EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get()));
612 // Tests that exiting overview mode without selecting a window restores focus
613 // to the previously focused window.
614 TEST_F(WindowSelectorTest, CancelRestoresFocus) {
615 gfx::Rect bounds(0, 0, 400, 400);
616 scoped_ptr<aura::Window> window(CreateWindow(bounds));
617 wm::ActivateWindow(window.get());
618 EXPECT_EQ(window.get(), GetFocusedWindow());
620 // In overview mode, focus should be removed.
622 EXPECT_EQ(NULL, GetFocusedWindow());
624 // If canceling overview mode, focus should be restored.
626 EXPECT_EQ(window.get(), GetFocusedWindow());
629 // Tests that overview mode is exited if the last remaining window is destroyed.
630 TEST_F(WindowSelectorTest, LastWindowDestroyed) {
631 gfx::Rect bounds(0, 0, 400, 400);
632 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
633 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
638 EXPECT_FALSE(IsSelecting());
641 // Tests that entering overview mode restores a window to its original
643 TEST_F(WindowSelectorTest, QuickReentryRestoresInitialTransform) {
644 gfx::Rect bounds(0, 0, 400, 400);
645 scoped_ptr<aura::Window> window(CreateWindow(bounds));
646 gfx::Rect initial_bounds = ToEnclosingRect(
647 GetTransformedBounds(window.get()));
649 // Quickly exit and reenter overview mode. The window should still be
650 // animating when we reenter. We cannot short circuit animations for this but
651 // we also don't have to wait for them to complete.
653 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
654 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
658 EXPECT_NE(initial_bounds, ToEnclosingRect(
659 GetTransformedTargetBounds(window.get())));
661 EXPECT_FALSE(IsSelecting());
662 EXPECT_EQ(initial_bounds, ToEnclosingRect(
663 GetTransformedTargetBounds(window.get())));
666 // Tests that non-activatable windows are hidden when entering overview mode.
667 TEST_F(WindowSelectorTest, NonActivatableWindowsHidden) {
668 gfx::Rect bounds(0, 0, 400, 400);
669 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
670 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
671 scoped_ptr<aura::Window> non_activatable_window(
672 CreateNonActivatableWindow(Shell::GetPrimaryRootWindow()->bounds()));
673 EXPECT_TRUE(non_activatable_window->IsVisible());
675 EXPECT_FALSE(non_activatable_window->IsVisible());
677 EXPECT_TRUE(non_activatable_window->IsVisible());
679 // Test that a window behind the fullscreen non-activatable window can be
681 non_activatable_window->parent()->StackChildAtTop(
682 non_activatable_window.get());
684 ClickWindow(window1.get());
685 EXPECT_FALSE(IsSelecting());
686 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
689 // Tests that windows with modal child windows are transformed with the modal
690 // child even though not activatable themselves.
691 TEST_F(WindowSelectorTest, ModalChild) {
692 gfx::Rect bounds(0, 0, 400, 400);
693 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
694 scoped_ptr<aura::Window> child1(CreateWindow(bounds));
695 child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
696 views::corewm::AddTransientChild(window1.get(), child1.get());
697 EXPECT_EQ(window1->parent(), child1->parent());
699 EXPECT_TRUE(window1->IsVisible());
700 EXPECT_TRUE(child1->IsVisible());
701 EXPECT_EQ(ToEnclosingRect(GetTransformedTargetBounds(child1.get())),
702 ToEnclosingRect(GetTransformedTargetBounds(window1.get())));
706 // Tests that clicking a modal window's parent activates the modal window in
708 TEST_F(WindowSelectorTest, ClickModalWindowParent) {
709 scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 180, 180)));
710 scoped_ptr<aura::Window> child1(CreateWindow(gfx::Rect(200, 0, 180, 180)));
711 child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
712 views::corewm::AddTransientChild(window1.get(), child1.get());
713 EXPECT_FALSE(WindowsOverlapping(window1.get(), child1.get()));
714 EXPECT_EQ(window1->parent(), child1->parent());
716 // Given that their relative positions are preserved, the windows should still
718 EXPECT_FALSE(WindowsOverlapping(window1.get(), child1.get()));
719 ClickWindow(window1.get());
720 EXPECT_FALSE(IsSelecting());
722 // Clicking on window1 should activate child1.
723 EXPECT_TRUE(wm::IsActiveWindow(child1.get()));
726 // Tests that windows remain on the display they are currently on in overview
728 TEST_F(WindowSelectorTest, MultipleDisplays) {
729 if (!SupportsMultipleDisplays())
732 UpdateDisplay("600x400,600x400");
733 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
734 gfx::Rect bounds1(0, 0, 400, 400);
735 gfx::Rect bounds2(650, 0, 400, 400);
737 scoped_ptr<aura::Window> window1(CreateWindow(bounds1));
738 scoped_ptr<aura::Window> window2(CreateWindow(bounds1));
739 scoped_ptr<aura::Window> window3(CreateWindow(bounds2));
740 scoped_ptr<aura::Window> window4(CreateWindow(bounds2));
741 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds1));
742 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds1));
743 scoped_ptr<aura::Window> panel3(CreatePanelWindow(bounds2));
744 scoped_ptr<aura::Window> panel4(CreatePanelWindow(bounds2));
745 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
746 EXPECT_EQ(root_windows[0], window2->GetRootWindow());
747 EXPECT_EQ(root_windows[1], window3->GetRootWindow());
748 EXPECT_EQ(root_windows[1], window4->GetRootWindow());
750 EXPECT_EQ(root_windows[0], panel1->GetRootWindow());
751 EXPECT_EQ(root_windows[0], panel2->GetRootWindow());
752 EXPECT_EQ(root_windows[1], panel3->GetRootWindow());
753 EXPECT_EQ(root_windows[1], panel4->GetRootWindow());
755 // In overview mode, each window remains in the same root window.
757 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
758 EXPECT_EQ(root_windows[0], window2->GetRootWindow());
759 EXPECT_EQ(root_windows[1], window3->GetRootWindow());
760 EXPECT_EQ(root_windows[1], window4->GetRootWindow());
761 EXPECT_EQ(root_windows[0], panel1->GetRootWindow());
762 EXPECT_EQ(root_windows[0], panel2->GetRootWindow());
763 EXPECT_EQ(root_windows[1], panel3->GetRootWindow());
764 EXPECT_EQ(root_windows[1], panel4->GetRootWindow());
766 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
767 ToEnclosingRect(GetTransformedTargetBounds(window1.get()))));
768 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
769 ToEnclosingRect(GetTransformedTargetBounds(window2.get()))));
770 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
771 ToEnclosingRect(GetTransformedTargetBounds(window3.get()))));
772 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
773 ToEnclosingRect(GetTransformedTargetBounds(window4.get()))));
775 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
776 ToEnclosingRect(GetTransformedTargetBounds(panel1.get()))));
777 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
778 ToEnclosingRect(GetTransformedTargetBounds(panel2.get()))));
779 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
780 ToEnclosingRect(GetTransformedTargetBounds(panel3.get()))));
781 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
782 ToEnclosingRect(GetTransformedTargetBounds(panel4.get()))));
783 EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
784 EXPECT_TRUE(WindowsOverlapping(panel3.get(), panel4.get()));
785 EXPECT_FALSE(WindowsOverlapping(panel1.get(), panel3.get()));
788 // Verifies that the single display overview used during alt tab cycling uses
789 // the display of the selected window by default.
790 TEST_F(WindowSelectorTest, CycleOverviewUsesCurrentDisplay) {
791 if (!SupportsMultipleDisplays())
794 UpdateDisplay("400x400,400x400");
795 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
797 scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 100, 100)));
798 scoped_ptr<aura::Window> window2(CreateWindow(gfx::Rect(450, 0, 100, 100)));
799 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
800 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
801 wm::ActivateWindow(window2.get());
802 wm::ActivateWindow(window1.get());
803 EXPECT_EQ(root_windows[0], Shell::GetTargetRootWindow());
805 Cycle(WindowSelector::FORWARD);
806 FireOverviewStartTimer();
808 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
809 ToEnclosingRect(GetTransformedTargetBounds(window1.get()))));
810 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
811 ToEnclosingRect(GetTransformedTargetBounds(window2.get()))));
815 // Verifies that the windows being shown on another display are copied.
816 TEST_F(WindowSelectorTest, CycleMultipleDisplaysCopiesWindows) {
817 if (!SupportsMultipleDisplays())
820 UpdateDisplay("400x400,400x400");
821 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
823 gfx::Rect root1_rect(0, 0, 100, 100);
824 gfx::Rect root2_rect(450, 0, 100, 100);
825 scoped_ptr<aura::Window> unmoved1(CreateWindow(root2_rect));
826 scoped_ptr<aura::Window> unmoved2(CreateWindow(root2_rect));
827 scoped_ptr<aura::Window> moved1_trans_parent(CreateWindow(root1_rect));
828 scoped_ptr<aura::Window> moved1(CreateWindow(root1_rect));
829 unmoved1->SetName("unmoved1");
830 unmoved2->SetName("unmoved2");
831 moved1->SetName("moved1");
832 moved1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
833 views::corewm::AddTransientChild(moved1_trans_parent.get(), moved1.get());
834 moved1_trans_parent->SetName("moved1_trans_parent");
836 EXPECT_EQ(root_windows[0], moved1->GetRootWindow());
837 EXPECT_EQ(root_windows[0], moved1_trans_parent->GetRootWindow());
838 EXPECT_EQ(root_windows[1], unmoved1->GetRootWindow());
839 EXPECT_EQ(root_windows[1], unmoved2->GetRootWindow());
840 wm::ActivateWindow(unmoved2.get());
841 wm::ActivateWindow(unmoved1.get());
843 Cycle(WindowSelector::FORWARD);
844 FireOverviewStartTimer();
846 // All windows are moved to second root window.
847 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
848 ToEnclosingRect(GetTransformedTargetBounds(unmoved1.get()))));
849 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
850 ToEnclosingRect(GetTransformedTargetBounds(unmoved2.get()))));
851 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
852 ToEnclosingRect(GetTransformedTargetBounds(moved1.get()))));
853 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
854 ToEnclosingRect(GetTransformedTargetBounds(moved1_trans_parent.get()))));
856 // unmoved1 and unmoved2 were already on the correct display and should not
858 EXPECT_TRUE(!GetCopyWindow(unmoved1.get()));
859 EXPECT_TRUE(!GetCopyWindow(unmoved2.get()));
861 // moved1 and its transient parent moved1_trans_parent should have also been
862 // copied for displaying on root_windows[1].
863 aura::Window* copy1 = GetCopyWindow(moved1.get());
864 aura::Window* copy1_trans_parent = GetCopyWindow(moved1_trans_parent.get());
865 ASSERT_FALSE(!copy1);
866 ASSERT_FALSE(!copy1_trans_parent);
868 // Verify that the bounds and transform of the copy match the original window
869 // but that it is on the other root window.
870 EXPECT_EQ(root_windows[1], copy1->GetRootWindow());
871 EXPECT_EQ(moved1->GetBoundsInScreen().ToString(),
872 copy1->GetBoundsInScreen().ToString());
873 EXPECT_EQ(moved1->layer()->GetTargetTransform().ToString(),
874 copy1->layer()->GetTargetTransform().ToString());
877 // After cycling the copy windows should have been destroyed.
878 RunAllPendingInMessageLoop();
879 EXPECT_TRUE(!GetCopyWindow(moved1.get()));
880 EXPECT_TRUE(!GetCopyWindow(moved1_trans_parent.get()));
883 // Tests that beginning to cycle from overview mode moves windows to the
885 TEST_F(WindowSelectorTest, MultipleDisplaysOverviewTransitionToCycle) {
886 if (!SupportsMultipleDisplays())
889 UpdateDisplay("400x400,400x400");
890 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
892 scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 100, 100)));
893 scoped_ptr<aura::Window> window2(CreateWindow(gfx::Rect(450, 0, 100, 100)));
894 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
895 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
896 wm::ActivateWindow(window2.get());
897 wm::ActivateWindow(window1.get());
900 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
901 ToEnclosingRect(GetTransformedTargetBounds(window1.get()))));
902 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
903 ToEnclosingRect(GetTransformedTargetBounds(window2.get()))));
905 Cycle(WindowSelector::FORWARD);
906 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
907 ToEnclosingRect(GetTransformedTargetBounds(window1.get()))));
908 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
909 ToEnclosingRect(GetTransformedTargetBounds(window2.get()))));
913 // Tests that a bounds change during overview is corrected for.
914 TEST_F(WindowSelectorTest, BoundsChangeDuringCycleOnOtherDisplay) {
915 if (!SupportsMultipleDisplays())
918 UpdateDisplay("400x400,400x400");
919 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
921 scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 100, 100)));
922 scoped_ptr<aura::Window> window2(CreateWindow(gfx::Rect(450, 0, 100, 100)));
923 scoped_ptr<aura::Window> window3(CreateWindow(gfx::Rect(450, 0, 100, 100)));
924 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
925 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
926 EXPECT_EQ(root_windows[1], window3->GetRootWindow());
927 wm::ActivateWindow(window1.get());
928 wm::ActivateWindow(window2.get());
929 wm::ActivateWindow(window3.get());
931 Cycle(WindowSelector::FORWARD);
932 FireOverviewStartTimer();
934 gfx::Rect overview_bounds(
935 ToEnclosingRect(GetTransformedTargetBounds(window1.get())));
936 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(overview_bounds));
938 // Change the position and size of window1 (being displayed on the second
939 // root window) and it should remain within the same bounds.
940 window1->SetBounds(gfx::Rect(100, 0, 200, 200));
941 gfx::Rect new_overview_bounds =
942 ToEnclosingRect(GetTransformedTargetBounds(window1.get()));
943 EXPECT_EQ(overview_bounds.x(), new_overview_bounds.x());
944 EXPECT_EQ(overview_bounds.y(), new_overview_bounds.y());
945 EXPECT_EQ(overview_bounds.width(), new_overview_bounds.width());
946 EXPECT_EQ(overview_bounds.height(), new_overview_bounds.height());
950 // Tests shutting down during overview.
951 TEST_F(WindowSelectorTest, Shutdown) {
952 gfx::Rect bounds(0, 0, 400, 400);
953 // These windows will be deleted when the test exits and the Shell instance
955 aura::Window* window1(CreateWindow(bounds));
956 aura::Window* window2(CreateWindow(bounds));
957 aura::Window* window3(CreatePanelWindow(bounds));
958 aura::Window* window4(CreatePanelWindow(bounds));
960 wm::ActivateWindow(window4);
961 wm::ActivateWindow(window3);
962 wm::ActivateWindow(window2);
963 wm::ActivateWindow(window1);
968 // Tests removing a display during overview.
969 TEST_F(WindowSelectorTest, RemoveDisplay) {
970 if (!SupportsMultipleDisplays())
973 UpdateDisplay("400x400,400x400");
974 gfx::Rect bounds1(0, 0, 100, 100);
975 gfx::Rect bounds2(450, 0, 100, 100);
976 scoped_ptr<aura::Window> window1(CreateWindow(bounds1));
977 scoped_ptr<aura::Window> window2(CreateWindow(bounds2));
978 scoped_ptr<aura::Window> window3(CreatePanelWindow(bounds1));
979 scoped_ptr<aura::Window> window4(CreatePanelWindow(bounds2));
981 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
982 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
983 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
984 EXPECT_EQ(root_windows[0], window3->GetRootWindow());
985 EXPECT_EQ(root_windows[1], window4->GetRootWindow());
987 wm::ActivateWindow(window4.get());
988 wm::ActivateWindow(window3.get());
989 wm::ActivateWindow(window2.get());
990 wm::ActivateWindow(window1.get());
993 EXPECT_TRUE(IsSelecting());
994 UpdateDisplay("400x400");
995 EXPECT_FALSE(IsSelecting());
998 } // namespace internal