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/drag_drop/drag_drop_controller.h"
6 #include "ash/root_window_controller.h"
7 #include "ash/screen_util.h"
8 #include "ash/shelf/shelf.h"
9 #include "ash/shelf/shelf_widget.h"
10 #include "ash/shell.h"
11 #include "ash/test/ash_test_base.h"
12 #include "ash/test/shelf_test_api.h"
13 #include "ash/test/shelf_view_test_api.h"
14 #include "ash/test/shell_test_api.h"
15 #include "ash/test/test_shelf_delegate.h"
16 #include "ash/wm/mru_window_tracker.h"
17 #include "ash/wm/overview/window_selector.h"
18 #include "ash/wm/overview/window_selector_controller.h"
19 #include "ash/wm/window_state.h"
20 #include "ash/wm/window_util.h"
21 #include "base/basictypes.h"
22 #include "base/compiler_specific.h"
23 #include "base/memory/scoped_vector.h"
24 #include "base/run_loop.h"
25 #include "base/strings/utf_string_conversions.h"
26 #include "ui/aura/client/activation_delegate.h"
27 #include "ui/aura/client/aura_constants.h"
28 #include "ui/aura/client/cursor_client.h"
29 #include "ui/aura/client/focus_client.h"
30 #include "ui/aura/root_window.h"
31 #include "ui/aura/test/event_generator.h"
32 #include "ui/aura/test/test_window_delegate.h"
33 #include "ui/aura/test/test_windows.h"
34 #include "ui/aura/window.h"
35 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
36 #include "ui/gfx/rect_conversions.h"
37 #include "ui/gfx/transform.h"
38 #include "ui/views/corewm/window_util.h"
45 class NonActivatableActivationDelegate
46 : public aura::client::ActivationDelegate {
48 virtual bool ShouldActivate() const OVERRIDE {
53 bool IsWindowAbove(aura::Window* w1, aura::Window* w2) {
54 aura::Window* parent = w1->parent();
55 DCHECK_EQ(parent, w2->parent());
56 for (aura::Window::Windows::const_iterator iter = parent->children().begin();
57 iter != parent->children().end(); ++iter) {
67 aura::Window* GetWindowByName(aura::Window* container,
68 const std::string& name) {
69 aura::Window* window = NULL;
70 for (aura::Window::Windows::const_iterator iter =
71 container->children().begin(); iter != container->children().end();
73 if ((*iter)->name() == name) {
74 // The name should be unique.
82 // Returns the copy of |window| created for overview. It is found using the
83 // window name which should be the same as the source window's name with a
84 // special suffix, and in the same container as the source window.
85 aura::Window* GetCopyWindow(aura::Window* window) {
86 aura::Window* copy_window = NULL;
87 std::string copy_name = window->name() + " (Copy)";
88 std::vector<aura::Window*> containers(
89 Shell::GetContainersFromAllRootWindows(window->parent()->id(), NULL));
90 for (std::vector<aura::Window*>::iterator iter = containers.begin();
91 iter != containers.end(); ++iter) {
92 aura::Window* found = GetWindowByName(*iter, copy_name);
94 // There should only be one copy window.
102 void CancelDrag(DragDropController* controller, bool* canceled) {
103 if (controller->IsDragDropInProgress()) {
105 controller->DragCancel();
111 class WindowSelectorTest : public test::AshTestBase {
113 WindowSelectorTest() {}
114 virtual ~WindowSelectorTest() {}
116 virtual void SetUp() OVERRIDE {
117 test::AshTestBase::SetUp();
118 ASSERT_TRUE(test::TestShelfDelegate::instance());
120 shelf_view_test_.reset(new test::ShelfViewTestAPI(
121 test::ShelfTestAPI(Shelf::ForPrimaryDisplay()).shelf_view()));
122 shelf_view_test_->SetAnimationDuration(1);
125 aura::Window* CreateWindow(const gfx::Rect& bounds) {
126 return CreateTestWindowInShellWithDelegate(&delegate_, -1, bounds);
129 aura::Window* CreateNonActivatableWindow(const gfx::Rect& bounds) {
130 aura::Window* window = CreateWindow(bounds);
131 aura::client::SetActivationDelegate(window,
132 &non_activatable_activation_delegate_);
133 EXPECT_FALSE(ash::wm::CanActivateWindow(window));
137 aura::Window* CreatePanelWindow(const gfx::Rect& bounds) {
138 aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
139 NULL, ui::wm::WINDOW_TYPE_PANEL, 0, bounds);
140 test::TestShelfDelegate::instance()->AddShelfItem(window);
141 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
145 bool WindowsOverlapping(aura::Window* window1, aura::Window* window2) {
146 gfx::RectF window1_bounds = GetTransformedTargetBounds(window1);
147 gfx::RectF window2_bounds = GetTransformedTargetBounds(window2);
148 return window1_bounds.Intersects(window2_bounds);
151 void ToggleOverview() {
152 ash::Shell::GetInstance()->window_selector_controller()->ToggleOverview();
155 void Cycle(WindowSelector::Direction direction) {
156 ash::Shell::GetInstance()->window_selector_controller()->
157 HandleCycleWindow(direction);
161 ash::Shell::GetInstance()->window_selector_controller()->window_selector_->
165 void FireOverviewStartTimer() {
166 // Calls the method to start overview mode which is normally called by the
167 // timer. The timer will still fire and call this method triggering the
168 // DCHECK that overview mode was not already started, except that we call
169 // StopCycling before the timer has a chance to fire.
170 ash::Shell::GetInstance()->window_selector_controller()->window_selector_->
174 gfx::Transform GetTransformRelativeTo(gfx::PointF origin,
175 const gfx::Transform& transform) {
177 t.Translate(origin.x(), origin.y());
178 t.PreconcatTransform(transform);
179 t.Translate(-origin.x(), -origin.y());
183 gfx::RectF GetTransformedBounds(aura::Window* window) {
184 gfx::RectF bounds(ScreenUtil::ConvertRectToScreen(
185 window->parent(), window->layer()->bounds()));
186 gfx::Transform transform(GetTransformRelativeTo(bounds.origin(),
187 window->layer()->transform()));
188 transform.TransformRect(&bounds);
192 gfx::RectF GetTransformedTargetBounds(aura::Window* window) {
193 gfx::RectF bounds(ScreenUtil::ConvertRectToScreen(
194 window->parent(), window->layer()->GetTargetBounds()));
195 gfx::Transform transform(GetTransformRelativeTo(bounds.origin(),
196 window->layer()->GetTargetTransform()));
197 transform.TransformRect(&bounds);
201 gfx::RectF GetTransformedBoundsInRootWindow(aura::Window* window) {
202 gfx::RectF bounds = gfx::Rect(window->bounds().size());
203 aura::Window* root = window->GetRootWindow();
204 CHECK(window->layer());
205 CHECK(root->layer());
206 gfx::Transform transform;
207 if (!window->layer()->GetTargetTransformRelativeTo(root->layer(),
211 transform.TransformRect(&bounds);
215 void ClickWindow(aura::Window* window) {
216 aura::test::EventGenerator event_generator(window->GetRootWindow(), window);
217 gfx::RectF target = GetTransformedBounds(window);
218 event_generator.ClickLeftButton();
222 return ash::Shell::GetInstance()->window_selector_controller()->
226 aura::Window* GetFocusedWindow() {
227 return aura::client::GetFocusClient(
228 Shell::GetPrimaryRootWindow())->GetFocusedWindow();
231 test::ShelfViewTestAPI* shelf_view_test() {
232 return shelf_view_test_.get();
236 aura::test::TestWindowDelegate delegate_;
237 NonActivatableActivationDelegate non_activatable_activation_delegate_;
238 scoped_ptr<test::ShelfViewTestAPI> shelf_view_test_;
240 DISALLOW_COPY_AND_ASSIGN(WindowSelectorTest);
243 // Tests entering overview mode with two windows and selecting one.
244 TEST_F(WindowSelectorTest, Basic) {
245 gfx::Rect bounds(0, 0, 400, 400);
246 aura::Window* root_window = Shell::GetPrimaryRootWindow();
247 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
248 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
249 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
250 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
251 EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get()));
252 EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
253 wm::ActivateWindow(window2.get());
254 EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
255 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
256 EXPECT_EQ(window2.get(), GetFocusedWindow());
257 // Hide the cursor before entering overview to test that it will be shown.
258 aura::client::GetCursorClient(root_window)->HideCursor();
260 // In overview mode the windows should no longer overlap and focus should
261 // be removed from the window.
263 EXPECT_EQ(NULL, GetFocusedWindow());
264 EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get()));
265 EXPECT_FALSE(WindowsOverlapping(window1.get(), panel1.get()));
266 // Panels 1 and 2 should still be overlapping being in a single selector
268 EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
270 // The cursor should be visible and locked as a pointer
271 EXPECT_EQ(ui::kCursorPointer,
272 root_window->GetDispatcher()->host()->last_cursor().native_type());
273 EXPECT_TRUE(aura::client::GetCursorClient(root_window)->IsCursorLocked());
274 EXPECT_TRUE(aura::client::GetCursorClient(root_window)->IsCursorVisible());
276 // Clicking window 1 should activate it.
277 ClickWindow(window1.get());
278 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
279 EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
280 EXPECT_EQ(window1.get(), GetFocusedWindow());
282 // Cursor should have been unlocked.
283 EXPECT_FALSE(aura::client::GetCursorClient(root_window)->IsCursorLocked());
286 // Tests entering overview mode with two windows and selecting one.
287 TEST_F(WindowSelectorTest, FullscreenWindow) {
288 gfx::Rect bounds(0, 0, 400, 400);
289 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
290 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
291 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
292 wm::ActivateWindow(window1.get());
294 wm::GetWindowState(window1.get())->ToggleFullscreen();
295 // The panel is hidden in fullscreen mode.
296 EXPECT_FALSE(panel1->IsVisible());
297 EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen());
299 // Enter overview and select the fullscreen window.
302 // The panel becomes temporarily visible for the overview.
303 EXPECT_TRUE(panel1->IsVisible());
304 ClickWindow(window1.get());
306 // The window is still fullscreen as it was selected. The panel should again
308 EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen());
309 EXPECT_FALSE(panel1->IsVisible());
311 // Entering overview and selecting another window, the previous window remains
313 // TODO(flackr): Currently the panel remains hidden, but should become visible
316 ClickWindow(window2.get());
317 EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen());
320 // Tests that the shelf dimming state is removed while in overview and restored
321 // on exiting overview.
322 TEST_F(WindowSelectorTest, OverviewUndimsShelf) {
323 gfx::Rect bounds(0, 0, 400, 400);
324 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
325 wm::WindowState* window_state = wm::GetWindowState(window1.get());
326 window_state->Maximize();
327 ash::ShelfWidget* shelf = Shell::GetPrimaryRootWindowController()->shelf();
328 EXPECT_TRUE(shelf->GetDimsShelf());
330 EXPECT_FALSE(shelf->GetDimsShelf());
332 EXPECT_TRUE(shelf->GetDimsShelf());
335 // Tests that beginning window selection hides the app list.
336 TEST_F(WindowSelectorTest, SelectingHidesAppList) {
337 gfx::Rect bounds(0, 0, 400, 400);
338 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
339 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
340 Shell::GetInstance()->ToggleAppList(NULL);
341 EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility());
343 EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility());
346 // The app list uses an animation to fade out. If it is toggled on immediately
347 // after being removed the old widget is re-used and it does not gain focus.
348 // When running under normal circumstances this shouldn't be possible, but
349 // it is in a test without letting the message loop run.
350 RunAllPendingInMessageLoop();
352 Shell::GetInstance()->ToggleAppList(NULL);
353 EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility());
354 Cycle(WindowSelector::FORWARD);
355 EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility());
359 // Tests that a minimized window's visibility and layer visibility is correctly
360 // changed when entering overview and restored when leaving overview mode.
361 TEST_F(WindowSelectorTest, MinimizedWindowVisibility) {
362 gfx::Rect bounds(0, 0, 400, 400);
363 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
364 wm::WindowState* window_state = wm::GetWindowState(window1.get());
365 window_state->Minimize();
366 EXPECT_FALSE(window1->IsVisible());
367 EXPECT_FALSE(window1->layer()->GetTargetVisibility());
369 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
370 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
372 EXPECT_TRUE(window1->IsVisible());
373 EXPECT_TRUE(window1->layer()->GetTargetVisibility());
376 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
377 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
379 EXPECT_FALSE(window1->IsVisible());
380 EXPECT_FALSE(window1->layer()->GetTargetVisibility());
384 // Tests that a bounds change during overview is corrected for.
385 TEST_F(WindowSelectorTest, BoundsChangeDuringOverview) {
386 scoped_ptr<aura::Window> window(CreateWindow(gfx::Rect(0, 0, 400, 400)));
388 gfx::Rect overview_bounds =
389 ToEnclosingRect(GetTransformedTargetBounds(window.get()));
390 window->SetBounds(gfx::Rect(200, 0, 200, 200));
391 gfx::Rect new_overview_bounds =
392 ToEnclosingRect(GetTransformedTargetBounds(window.get()));
393 EXPECT_EQ(overview_bounds.x(), new_overview_bounds.x());
394 EXPECT_EQ(overview_bounds.y(), new_overview_bounds.y());
395 EXPECT_EQ(overview_bounds.width(), new_overview_bounds.width());
396 EXPECT_EQ(overview_bounds.height(), new_overview_bounds.height());
400 // Tests entering overview mode with three windows and cycling through them.
401 TEST_F(WindowSelectorTest, BasicCycle) {
402 gfx::Rect bounds(0, 0, 400, 400);
403 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
404 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
405 scoped_ptr<aura::Window> window3(CreateWindow(bounds));
406 wm::ActivateWindow(window3.get());
407 wm::ActivateWindow(window2.get());
408 wm::ActivateWindow(window1.get());
409 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
410 EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
411 EXPECT_FALSE(wm::IsActiveWindow(window3.get()));
413 Cycle(WindowSelector::FORWARD);
414 EXPECT_TRUE(IsSelecting());
415 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
417 Cycle(WindowSelector::FORWARD);
418 EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
421 EXPECT_FALSE(IsSelecting());
422 EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
423 EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
424 EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
427 // Tests that cycling through windows preserves the window stacking order.
428 TEST_F(WindowSelectorTest, CyclePreservesStackingOrder) {
429 gfx::Rect bounds(0, 0, 400, 400);
430 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
431 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
432 scoped_ptr<aura::Window> window3(CreateWindow(bounds));
433 wm::ActivateWindow(window3.get());
434 wm::ActivateWindow(window2.get());
435 wm::ActivateWindow(window1.get());
436 // Window order from top to bottom is 1, 2, 3.
437 EXPECT_TRUE(IsWindowAbove(window1.get(), window2.get()));
438 EXPECT_TRUE(IsWindowAbove(window2.get(), window3.get()));
441 Cycle(WindowSelector::FORWARD);
442 EXPECT_TRUE(IsWindowAbove(window2.get(), window1.get()));
443 EXPECT_TRUE(IsWindowAbove(window1.get(), window3.get()));
446 Cycle(WindowSelector::FORWARD);
447 EXPECT_TRUE(IsWindowAbove(window3.get(), window1.get()));
448 EXPECT_TRUE(IsWindowAbove(window1.get(), window2.get()));
451 Cycle(WindowSelector::FORWARD);
452 EXPECT_TRUE(IsWindowAbove(window1.get(), window2.get()));
453 EXPECT_TRUE(IsWindowAbove(window2.get(), window3.get()));
457 // Tests that cycling through windows shows and minimizes windows as they
459 TEST_F(WindowSelectorTest, CyclePreservesMinimization) {
460 gfx::Rect bounds(0, 0, 400, 400);
461 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
462 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
463 wm::ActivateWindow(window2.get());
464 wm::GetWindowState(window2.get())->Minimize();
465 wm::ActivateWindow(window1.get());
466 EXPECT_TRUE(wm::IsWindowMinimized(window2.get()));
469 Cycle(WindowSelector::FORWARD);
470 EXPECT_FALSE(wm::IsWindowMinimized(window2.get()));
473 Cycle(WindowSelector::FORWARD);
474 EXPECT_TRUE(wm::IsWindowMinimized(window2.get()));
477 EXPECT_TRUE(wm::IsWindowMinimized(window2.get()));
480 // Tests beginning cycling while in overview mode.
481 TEST_F(WindowSelectorTest, OverviewTransitionToCycle) {
482 gfx::Rect bounds(0, 0, 400, 400);
483 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
484 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
485 wm::ActivateWindow(window2.get());
486 wm::ActivateWindow(window1.get());
489 Cycle(WindowSelector::FORWARD);
492 EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
493 EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
494 EXPECT_EQ(window2.get(), GetFocusedWindow());
497 // Tests cycles between panel and normal windows.
498 TEST_F(WindowSelectorTest, CyclePanels) {
499 gfx::Rect bounds(0, 0, 400, 400);
500 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
501 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
502 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
503 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
504 wm::ActivateWindow(window2.get());
505 wm::ActivateWindow(window1.get());
506 wm::ActivateWindow(panel2.get());
507 wm::ActivateWindow(panel1.get());
508 EXPECT_TRUE(wm::IsActiveWindow(panel1.get()));
510 // Cycling once should select window1 since the panels are grouped into a
511 // single selectable item.
512 Cycle(WindowSelector::FORWARD);
514 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
516 // Cycling again should select the most recently used panel.
517 Cycle(WindowSelector::FORWARD);
519 EXPECT_TRUE(wm::IsActiveWindow(panel1.get()));
522 // Tests the visibility of panel windows during cycling.
523 TEST_F(WindowSelectorTest, CyclePanelVisibility) {
524 gfx::Rect bounds(0, 0, 400, 400);
525 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
526 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
527 wm::ActivateWindow(panel1.get());
528 wm::ActivateWindow(window1.get());
530 Cycle(WindowSelector::FORWARD);
531 FireOverviewStartTimer();
532 EXPECT_EQ(1.0f, panel1->layer()->GetTargetOpacity());
536 // Tests cycles between panel and normal windows.
537 TEST_F(WindowSelectorTest, CyclePanelsDestroyed) {
538 gfx::Rect bounds(0, 0, 400, 400);
539 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
540 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
541 scoped_ptr<aura::Window> window3(CreateWindow(bounds));
542 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
543 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
544 wm::ActivateWindow(window3.get());
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()));
551 // Cycling once highlights window2.
552 Cycle(WindowSelector::FORWARD);
553 // All panels are destroyed.
556 // Cycling again should now select window3.
557 Cycle(WindowSelector::FORWARD);
559 EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
562 // Tests cycles between panel and normal windows.
563 TEST_F(WindowSelectorTest, CycleMruPanelDestroyed) {
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 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
568 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
569 wm::ActivateWindow(panel2.get());
570 wm::ActivateWindow(panel1.get());
571 wm::ActivateWindow(window2.get());
572 wm::ActivateWindow(window1.get());
573 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
575 // Cycling once highlights window2.
576 Cycle(WindowSelector::FORWARD);
577 // Panel 1 is the next item as the MRU panel, removing it should make panel 2
578 // the next window to be selected.
580 // Cycling again should now select window3.
581 Cycle(WindowSelector::FORWARD);
583 EXPECT_TRUE(wm::IsActiveWindow(panel2.get()));
586 // Tests that a newly created window aborts overview.
587 TEST_F(WindowSelectorTest, NewWindowCancelsOveriew) {
588 gfx::Rect bounds(0, 0, 400, 400);
589 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
590 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
592 EXPECT_TRUE(IsSelecting());
594 // A window being created should exit overview mode.
595 scoped_ptr<aura::Window> window3(CreateWindow(bounds));
596 EXPECT_FALSE(IsSelecting());
599 // Tests that a window activation exits overview mode.
600 TEST_F(WindowSelectorTest, ActivationCancelsOveriew) {
601 gfx::Rect bounds(0, 0, 400, 400);
602 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
603 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
606 EXPECT_TRUE(IsSelecting());
608 // A window being activated should exit overview mode.
610 EXPECT_FALSE(IsSelecting());
612 // window1 should be focused after exiting even though window2 was focused on
613 // entering overview because we exited due to an activation.
614 EXPECT_EQ(window1.get(), GetFocusedWindow());
617 // Verifies that overview mode only begins after a delay when cycling.
618 TEST_F(WindowSelectorTest, CycleOverviewDelay) {
619 gfx::Rect bounds(0, 0, 400, 400);
620 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
621 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
622 EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get()));
624 // When cycling first starts, the windows will still be overlapping.
625 Cycle(WindowSelector::FORWARD);
626 EXPECT_TRUE(IsSelecting());
627 EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get()));
629 // Once the overview timer fires, the windows should no longer overlap.
630 FireOverviewStartTimer();
631 EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get()));
635 // Tests that exiting overview mode without selecting a window restores focus
636 // to the previously focused window.
637 TEST_F(WindowSelectorTest, CancelRestoresFocus) {
638 gfx::Rect bounds(0, 0, 400, 400);
639 scoped_ptr<aura::Window> window(CreateWindow(bounds));
640 wm::ActivateWindow(window.get());
641 EXPECT_EQ(window.get(), GetFocusedWindow());
643 // In overview mode, focus should be removed.
645 EXPECT_EQ(NULL, GetFocusedWindow());
647 // If canceling overview mode, focus should be restored.
649 EXPECT_EQ(window.get(), GetFocusedWindow());
652 // Tests that overview mode is exited if the last remaining window is destroyed.
653 TEST_F(WindowSelectorTest, LastWindowDestroyed) {
654 gfx::Rect bounds(0, 0, 400, 400);
655 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
656 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
661 EXPECT_FALSE(IsSelecting());
664 // Tests that entering overview mode restores a window to its original
666 TEST_F(WindowSelectorTest, QuickReentryRestoresInitialTransform) {
667 gfx::Rect bounds(0, 0, 400, 400);
668 scoped_ptr<aura::Window> window(CreateWindow(bounds));
669 gfx::Rect initial_bounds = ToEnclosingRect(
670 GetTransformedBounds(window.get()));
672 // Quickly exit and reenter overview mode. The window should still be
673 // animating when we reenter. We cannot short circuit animations for this but
674 // we also don't have to wait for them to complete.
676 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
677 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
681 EXPECT_NE(initial_bounds, ToEnclosingRect(
682 GetTransformedTargetBounds(window.get())));
684 EXPECT_FALSE(IsSelecting());
685 EXPECT_EQ(initial_bounds, ToEnclosingRect(
686 GetTransformedTargetBounds(window.get())));
689 // Tests that non-activatable windows are hidden when entering overview mode.
690 TEST_F(WindowSelectorTest, NonActivatableWindowsHidden) {
691 gfx::Rect bounds(0, 0, 400, 400);
692 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
693 scoped_ptr<aura::Window> window2(CreateWindow(bounds));
694 scoped_ptr<aura::Window> non_activatable_window(
695 CreateNonActivatableWindow(Shell::GetPrimaryRootWindow()->bounds()));
696 EXPECT_TRUE(non_activatable_window->IsVisible());
698 EXPECT_FALSE(non_activatable_window->IsVisible());
700 EXPECT_TRUE(non_activatable_window->IsVisible());
702 // Test that a window behind the fullscreen non-activatable window can be
704 non_activatable_window->parent()->StackChildAtTop(
705 non_activatable_window.get());
707 ClickWindow(window1.get());
708 EXPECT_FALSE(IsSelecting());
709 EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
712 // Tests that windows with modal child windows are transformed with the modal
713 // child even though not activatable themselves.
714 TEST_F(WindowSelectorTest, ModalChild) {
715 gfx::Rect bounds(0, 0, 400, 400);
716 scoped_ptr<aura::Window> window1(CreateWindow(bounds));
717 scoped_ptr<aura::Window> child1(CreateWindow(bounds));
718 child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
719 views::corewm::AddTransientChild(window1.get(), child1.get());
720 EXPECT_EQ(window1->parent(), child1->parent());
722 EXPECT_TRUE(window1->IsVisible());
723 EXPECT_TRUE(child1->IsVisible());
724 EXPECT_EQ(ToEnclosingRect(GetTransformedTargetBounds(child1.get())),
725 ToEnclosingRect(GetTransformedTargetBounds(window1.get())));
729 // Tests that clicking a modal window's parent activates the modal window in
731 TEST_F(WindowSelectorTest, ClickModalWindowParent) {
732 scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 180, 180)));
733 scoped_ptr<aura::Window> child1(CreateWindow(gfx::Rect(200, 0, 180, 180)));
734 child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
735 views::corewm::AddTransientChild(window1.get(), child1.get());
736 EXPECT_FALSE(WindowsOverlapping(window1.get(), child1.get()));
737 EXPECT_EQ(window1->parent(), child1->parent());
739 // Given that their relative positions are preserved, the windows should still
741 EXPECT_FALSE(WindowsOverlapping(window1.get(), child1.get()));
742 ClickWindow(window1.get());
743 EXPECT_FALSE(IsSelecting());
745 // Clicking on window1 should activate child1.
746 EXPECT_TRUE(wm::IsActiveWindow(child1.get()));
749 // Tests that windows remain on the display they are currently on in overview
751 TEST_F(WindowSelectorTest, MultipleDisplays) {
752 if (!SupportsMultipleDisplays())
755 UpdateDisplay("600x400,600x400");
756 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
757 gfx::Rect bounds1(0, 0, 400, 400);
758 gfx::Rect bounds2(650, 0, 400, 400);
760 scoped_ptr<aura::Window> window1(CreateWindow(bounds1));
761 scoped_ptr<aura::Window> window2(CreateWindow(bounds1));
762 scoped_ptr<aura::Window> window3(CreateWindow(bounds2));
763 scoped_ptr<aura::Window> window4(CreateWindow(bounds2));
764 scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds1));
765 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds1));
766 scoped_ptr<aura::Window> panel3(CreatePanelWindow(bounds2));
767 scoped_ptr<aura::Window> panel4(CreatePanelWindow(bounds2));
768 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
769 EXPECT_EQ(root_windows[0], window2->GetRootWindow());
770 EXPECT_EQ(root_windows[1], window3->GetRootWindow());
771 EXPECT_EQ(root_windows[1], window4->GetRootWindow());
773 EXPECT_EQ(root_windows[0], panel1->GetRootWindow());
774 EXPECT_EQ(root_windows[0], panel2->GetRootWindow());
775 EXPECT_EQ(root_windows[1], panel3->GetRootWindow());
776 EXPECT_EQ(root_windows[1], panel4->GetRootWindow());
778 // In overview mode, each window remains in the same root window.
780 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
781 EXPECT_EQ(root_windows[0], window2->GetRootWindow());
782 EXPECT_EQ(root_windows[1], window3->GetRootWindow());
783 EXPECT_EQ(root_windows[1], window4->GetRootWindow());
784 EXPECT_EQ(root_windows[0], panel1->GetRootWindow());
785 EXPECT_EQ(root_windows[0], panel2->GetRootWindow());
786 EXPECT_EQ(root_windows[1], panel3->GetRootWindow());
787 EXPECT_EQ(root_windows[1], panel4->GetRootWindow());
789 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
790 ToEnclosingRect(GetTransformedTargetBounds(window1.get()))));
791 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
792 ToEnclosingRect(GetTransformedTargetBounds(window2.get()))));
793 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
794 ToEnclosingRect(GetTransformedTargetBounds(window3.get()))));
795 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
796 ToEnclosingRect(GetTransformedTargetBounds(window4.get()))));
798 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
799 ToEnclosingRect(GetTransformedTargetBounds(panel1.get()))));
800 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
801 ToEnclosingRect(GetTransformedTargetBounds(panel2.get()))));
802 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
803 ToEnclosingRect(GetTransformedTargetBounds(panel3.get()))));
804 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
805 ToEnclosingRect(GetTransformedTargetBounds(panel4.get()))));
806 EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
807 EXPECT_TRUE(WindowsOverlapping(panel3.get(), panel4.get()));
808 EXPECT_FALSE(WindowsOverlapping(panel1.get(), panel3.get()));
811 // Verifies that the single display overview used during alt tab cycling uses
812 // the display of the selected window by default.
813 TEST_F(WindowSelectorTest, CycleOverviewUsesCurrentDisplay) {
814 if (!SupportsMultipleDisplays())
817 UpdateDisplay("400x400,400x400");
818 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
820 scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 100, 100)));
821 scoped_ptr<aura::Window> window2(CreateWindow(gfx::Rect(450, 0, 100, 100)));
822 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
823 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
824 wm::ActivateWindow(window2.get());
825 wm::ActivateWindow(window1.get());
826 EXPECT_EQ(root_windows[0], Shell::GetTargetRootWindow());
828 Cycle(WindowSelector::FORWARD);
829 FireOverviewStartTimer();
831 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
832 ToEnclosingRect(GetTransformedTargetBounds(window1.get()))));
833 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
834 ToEnclosingRect(GetTransformedTargetBounds(window2.get()))));
838 // Verifies that the windows being shown on another display are copied.
839 TEST_F(WindowSelectorTest, CycleMultipleDisplaysCopiesWindows) {
840 if (!SupportsMultipleDisplays())
843 UpdateDisplay("400x400,400x400");
844 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
846 gfx::Rect root1_rect(0, 0, 100, 100);
847 gfx::Rect root2_rect(450, 0, 100, 100);
848 scoped_ptr<aura::Window> unmoved1(CreateWindow(root2_rect));
849 scoped_ptr<aura::Window> unmoved2(CreateWindow(root2_rect));
850 scoped_ptr<aura::Window> moved1_trans_parent(CreateWindow(root1_rect));
851 scoped_ptr<aura::Window> moved1(CreateWindow(root1_rect));
852 unmoved1->SetName("unmoved1");
853 unmoved2->SetName("unmoved2");
854 moved1->SetName("moved1");
855 moved1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
856 views::corewm::AddTransientChild(moved1_trans_parent.get(), moved1.get());
857 moved1_trans_parent->SetName("moved1_trans_parent");
859 EXPECT_EQ(root_windows[0], moved1->GetRootWindow());
860 EXPECT_EQ(root_windows[0], moved1_trans_parent->GetRootWindow());
861 EXPECT_EQ(root_windows[1], unmoved1->GetRootWindow());
862 EXPECT_EQ(root_windows[1], unmoved2->GetRootWindow());
863 wm::ActivateWindow(unmoved2.get());
864 wm::ActivateWindow(unmoved1.get());
866 Cycle(WindowSelector::FORWARD);
867 FireOverviewStartTimer();
869 // All windows are moved to second root window.
870 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
871 ToEnclosingRect(GetTransformedTargetBounds(unmoved1.get()))));
872 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
873 ToEnclosingRect(GetTransformedTargetBounds(unmoved2.get()))));
874 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
875 ToEnclosingRect(GetTransformedTargetBounds(moved1.get()))));
876 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
877 ToEnclosingRect(GetTransformedTargetBounds(moved1_trans_parent.get()))));
879 // unmoved1 and unmoved2 were already on the correct display and should not
881 EXPECT_TRUE(!GetCopyWindow(unmoved1.get()));
882 EXPECT_TRUE(!GetCopyWindow(unmoved2.get()));
884 // moved1 and its transient parent moved1_trans_parent should have also been
885 // copied for displaying on root_windows[1].
886 aura::Window* copy1 = GetCopyWindow(moved1.get());
887 aura::Window* copy1_trans_parent = GetCopyWindow(moved1_trans_parent.get());
888 ASSERT_FALSE(!copy1);
889 ASSERT_FALSE(!copy1_trans_parent);
891 // Verify that the bounds and transform of the copy match the original window
892 // but that it is on the other root window.
893 EXPECT_EQ(root_windows[1], copy1->GetRootWindow());
894 EXPECT_EQ(moved1->GetBoundsInScreen().ToString(),
895 copy1->GetBoundsInScreen().ToString());
896 EXPECT_EQ(moved1->layer()->GetTargetTransform().ToString(),
897 copy1->layer()->GetTargetTransform().ToString());
900 // After cycling the copy windows should have been destroyed.
901 RunAllPendingInMessageLoop();
902 EXPECT_TRUE(!GetCopyWindow(moved1.get()));
903 EXPECT_TRUE(!GetCopyWindow(moved1_trans_parent.get()));
906 // Tests that beginning to cycle from overview mode moves windows to the
908 TEST_F(WindowSelectorTest, MultipleDisplaysOverviewTransitionToCycle) {
909 if (!SupportsMultipleDisplays())
912 UpdateDisplay("400x400,400x400");
913 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
915 scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 100, 100)));
916 scoped_ptr<aura::Window> window2(CreateWindow(gfx::Rect(450, 0, 100, 100)));
917 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
918 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
919 wm::ActivateWindow(window2.get());
920 wm::ActivateWindow(window1.get());
923 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
924 ToEnclosingRect(GetTransformedTargetBounds(window1.get()))));
925 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
926 ToEnclosingRect(GetTransformedTargetBounds(window2.get()))));
928 Cycle(WindowSelector::FORWARD);
929 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
930 ToEnclosingRect(GetTransformedTargetBounds(window1.get()))));
931 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
932 ToEnclosingRect(GetTransformedTargetBounds(window2.get()))));
936 // Tests that a bounds change during overview is corrected for.
937 TEST_F(WindowSelectorTest, BoundsChangeDuringCycleOnOtherDisplay) {
938 if (!SupportsMultipleDisplays())
941 UpdateDisplay("400x400,400x400");
942 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
944 scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 100, 100)));
945 scoped_ptr<aura::Window> window2(CreateWindow(gfx::Rect(450, 0, 100, 100)));
946 scoped_ptr<aura::Window> window3(CreateWindow(gfx::Rect(450, 0, 100, 100)));
947 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
948 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
949 EXPECT_EQ(root_windows[1], window3->GetRootWindow());
950 wm::ActivateWindow(window1.get());
951 wm::ActivateWindow(window2.get());
952 wm::ActivateWindow(window3.get());
954 Cycle(WindowSelector::FORWARD);
955 FireOverviewStartTimer();
957 gfx::Rect overview_bounds(
958 ToEnclosingRect(GetTransformedTargetBounds(window1.get())));
959 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(overview_bounds));
961 // Change the position and size of window1 (being displayed on the second
962 // root window) and it should remain within the same bounds.
963 window1->SetBounds(gfx::Rect(100, 0, 200, 200));
964 gfx::Rect new_overview_bounds =
965 ToEnclosingRect(GetTransformedTargetBounds(window1.get()));
966 EXPECT_EQ(overview_bounds.x(), new_overview_bounds.x());
967 EXPECT_EQ(overview_bounds.y(), new_overview_bounds.y());
968 EXPECT_EQ(overview_bounds.width(), new_overview_bounds.width());
969 EXPECT_EQ(overview_bounds.height(), new_overview_bounds.height());
973 // Tests shutting down during overview.
974 TEST_F(WindowSelectorTest, Shutdown) {
975 gfx::Rect bounds(0, 0, 400, 400);
976 // These windows will be deleted when the test exits and the Shell instance
978 aura::Window* window1(CreateWindow(bounds));
979 aura::Window* window2(CreateWindow(bounds));
980 aura::Window* window3(CreatePanelWindow(bounds));
981 aura::Window* window4(CreatePanelWindow(bounds));
983 wm::ActivateWindow(window4);
984 wm::ActivateWindow(window3);
985 wm::ActivateWindow(window2);
986 wm::ActivateWindow(window1);
991 // Tests removing a display during overview.
992 TEST_F(WindowSelectorTest, RemoveDisplay) {
993 if (!SupportsMultipleDisplays())
996 UpdateDisplay("400x400,400x400");
997 gfx::Rect bounds1(0, 0, 100, 100);
998 gfx::Rect bounds2(450, 0, 100, 100);
999 scoped_ptr<aura::Window> window1(CreateWindow(bounds1));
1000 scoped_ptr<aura::Window> window2(CreateWindow(bounds2));
1001 scoped_ptr<aura::Window> window3(CreatePanelWindow(bounds1));
1002 scoped_ptr<aura::Window> window4(CreatePanelWindow(bounds2));
1004 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1005 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
1006 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
1007 EXPECT_EQ(root_windows[0], window3->GetRootWindow());
1008 EXPECT_EQ(root_windows[1], window4->GetRootWindow());
1010 wm::ActivateWindow(window4.get());
1011 wm::ActivateWindow(window3.get());
1012 wm::ActivateWindow(window2.get());
1013 wm::ActivateWindow(window1.get());
1016 EXPECT_TRUE(IsSelecting());
1017 UpdateDisplay("400x400");
1018 EXPECT_FALSE(IsSelecting());
1021 // Tests starting overview during a drag and drop tracking operation.
1022 // TODO(flackr): Fix memory corruption crash when running locally (not failing
1023 // on bots). See http://crbug.com/342528.
1024 TEST_F(WindowSelectorTest, DISABLED_DragDropInProgress) {
1025 bool drag_canceled_by_test = false;
1026 gfx::Rect bounds(0, 0, 400, 400);
1027 scoped_ptr<aura::Window> window(CreateWindow(bounds));
1028 test::ShellTestApi shell_test_api(Shell::GetInstance());
1029 ash::internal::DragDropController* drag_drop_controller =
1030 shell_test_api.drag_drop_controller();
1031 ui::OSExchangeData data;
1032 base::MessageLoopForUI::current()->PostTask(FROM_HERE,
1033 base::Bind(&WindowSelectorTest::ToggleOverview,
1034 base::Unretained(this)));
1035 base::MessageLoopForUI::current()->PostTask(FROM_HERE,
1036 base::Bind(&CancelDrag, drag_drop_controller, &drag_canceled_by_test));
1037 data.SetString(base::UTF8ToUTF16("I am being dragged"));
1038 drag_drop_controller->StartDragAndDrop(data, window->GetRootWindow(),
1039 window.get(), gfx::Point(5, 5), ui::DragDropTypes::DRAG_MOVE,
1040 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
1041 RunAllPendingInMessageLoop();
1042 EXPECT_FALSE(drag_canceled_by_test);
1043 ASSERT_TRUE(IsSelecting());
1044 RunAllPendingInMessageLoop();
1047 TEST_F(WindowSelectorTest, HitTestingInOverview) {
1048 gfx::Rect window_bounds(20, 10, 200, 300);
1049 aura::Window* root_window = Shell::GetPrimaryRootWindow();
1050 scoped_ptr<aura::Window> window1(CreateWindow(window_bounds));
1051 scoped_ptr<aura::Window> window2(CreateWindow(window_bounds));
1054 gfx::RectF bounds1 = GetTransformedBoundsInRootWindow(window1.get());
1055 gfx::RectF bounds2 = GetTransformedBoundsInRootWindow(window2.get());
1056 EXPECT_NE(bounds1.ToString(), bounds2.ToString());
1058 ui::EventTarget* root_target = root_window;
1059 ui::EventTargeter* targeter = root_target->GetEventTargeter();
1060 aura::Window* windows[] = { window1.get(), window2.get() };
1061 for (size_t w = 0; w < arraysize(windows); ++w) {
1062 gfx::RectF bounds = GetTransformedBoundsInRootWindow(windows[w]);
1063 gfx::Point points[] = {
1064 gfx::Point(bounds.x(), bounds.y()),
1065 gfx::Point(bounds.right() - 1, bounds.y()),
1066 gfx::Point(bounds.x(), bounds.bottom() - 1),
1067 gfx::Point(bounds.right() - 1, bounds.bottom() - 1),
1070 for (size_t p = 0; p < arraysize(points); ++p) {
1071 ui::MouseEvent event(ui::ET_MOUSE_MOVED, points[p], points[p],
1072 ui::EF_NONE, ui::EF_NONE);
1073 EXPECT_EQ(windows[w],
1074 targeter->FindTargetForEvent(root_target, &event));
1079 } // namespace internal