952260e9d7704a24c1bdb3d2c032e721913f964e
[platform/framework/web/crosswalk.git] / src / ash / wm / overview / window_selector_unittest.cc
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 <algorithm>
6
7 #include "ash/accessibility_delegate.h"
8 #include "ash/drag_drop/drag_drop_controller.h"
9 #include "ash/root_window_controller.h"
10 #include "ash/screen_util.h"
11 #include "ash/shelf/shelf.h"
12 #include "ash/shelf/shelf_widget.h"
13 #include "ash/shell.h"
14 #include "ash/shell_window_ids.h"
15 #include "ash/test/ash_test_base.h"
16 #include "ash/test/shelf_test_api.h"
17 #include "ash/test/shelf_view_test_api.h"
18 #include "ash/test/shell_test_api.h"
19 #include "ash/test/test_shelf_delegate.h"
20 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
21 #include "ash/wm/mru_window_tracker.h"
22 #include "ash/wm/overview/window_grid.h"
23 #include "ash/wm/overview/window_selector.h"
24 #include "ash/wm/overview/window_selector_controller.h"
25 #include "ash/wm/overview/window_selector_item.h"
26 #include "ash/wm/panels/panel_layout_manager.h"
27 #include "ash/wm/window_state.h"
28 #include "ash/wm/window_util.h"
29 #include "ash/wm/wm_event.h"
30 #include "base/basictypes.h"
31 #include "base/compiler_specific.h"
32 #include "base/memory/scoped_vector.h"
33 #include "base/run_loop.h"
34 #include "base/strings/string_piece.h"
35 #include "base/strings/utf_string_conversions.h"
36 #include "ui/aura/client/aura_constants.h"
37 #include "ui/aura/client/cursor_client.h"
38 #include "ui/aura/client/focus_client.h"
39 #include "ui/aura/test/test_window_delegate.h"
40 #include "ui/aura/test/test_windows.h"
41 #include "ui/aura/window.h"
42 #include "ui/aura/window_event_dispatcher.h"
43 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
44 #include "ui/events/test/event_generator.h"
45 #include "ui/gfx/rect_conversions.h"
46 #include "ui/gfx/transform.h"
47 #include "ui/views/controls/label.h"
48 #include "ui/views/widget/native_widget_aura.h"
49 #include "ui/views/widget/widget_delegate.h"
50 #include "ui/wm/core/window_util.h"
51 #include "ui/wm/public/activation_delegate.h"
52
53 namespace ash {
54 namespace {
55
56 class NonActivatableActivationDelegate
57     : public aura::client::ActivationDelegate {
58  public:
59   bool ShouldActivate() const override { return false; }
60 };
61
62 void CancelDrag(DragDropController* controller, bool* canceled) {
63   if (controller->IsDragDropInProgress()) {
64     *canceled = true;
65     controller->DragCancel();
66   }
67 }
68
69 }  // namespace
70
71 class WindowSelectorTest : public test::AshTestBase {
72  public:
73   WindowSelectorTest() {}
74   ~WindowSelectorTest() override {}
75
76   void SetUp() override {
77     test::AshTestBase::SetUp();
78     ASSERT_TRUE(test::TestShelfDelegate::instance());
79
80     shelf_view_test_.reset(new test::ShelfViewTestAPI(
81         test::ShelfTestAPI(Shelf::ForPrimaryDisplay()).shelf_view()));
82     shelf_view_test_->SetAnimationDuration(1);
83   }
84
85   aura::Window* CreateWindow(const gfx::Rect& bounds) {
86     return CreateTestWindowInShellWithDelegate(&delegate_, -1, bounds);
87   }
88
89   aura::Window* CreateWindowWithId(const gfx::Rect& bounds, int id) {
90     return CreateTestWindowInShellWithDelegate(&delegate_, id, bounds);
91   }
92   aura::Window* CreateNonActivatableWindow(const gfx::Rect& bounds) {
93     aura::Window* window = CreateWindow(bounds);
94     aura::client::SetActivationDelegate(window,
95                                         &non_activatable_activation_delegate_);
96     EXPECT_FALSE(ash::wm::CanActivateWindow(window));
97     return window;
98   }
99
100   aura::Window* CreatePanelWindow(const gfx::Rect& bounds) {
101     aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
102         NULL, ui::wm::WINDOW_TYPE_PANEL, 0, bounds);
103     test::TestShelfDelegate::instance()->AddShelfItem(window);
104     shelf_view_test()->RunMessageLoopUntilAnimationsDone();
105     return window;
106   }
107
108   views::Widget* CreatePanelWindowWidget(const gfx::Rect& bounds) {
109     views::Widget* widget = new views::Widget;
110     views::Widget::InitParams params;
111     params.bounds = bounds;
112     params.type = views::Widget::InitParams::TYPE_PANEL;
113     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
114     widget->Init(params);
115     widget->Show();
116     ParentWindowInPrimaryRootWindow(widget->GetNativeWindow());
117     return widget;
118   }
119
120   bool WindowsOverlapping(aura::Window* window1, aura::Window* window2) {
121     gfx::RectF window1_bounds = GetTransformedTargetBounds(window1);
122     gfx::RectF window2_bounds = GetTransformedTargetBounds(window2);
123     return window1_bounds.Intersects(window2_bounds);
124   }
125
126   void ToggleOverview() {
127     ash::Shell::GetInstance()->window_selector_controller()->ToggleOverview();
128   }
129
130   gfx::Transform GetTransformRelativeTo(gfx::PointF origin,
131                                         const gfx::Transform& transform) {
132     gfx::Transform t;
133     t.Translate(origin.x(), origin.y());
134     t.PreconcatTransform(transform);
135     t.Translate(-origin.x(), -origin.y());
136     return t;
137   }
138
139   gfx::RectF GetTransformedBounds(aura::Window* window) {
140     gfx::RectF bounds(ScreenUtil::ConvertRectToScreen(
141         window->parent(), window->layer()->bounds()));
142     gfx::Transform transform(GetTransformRelativeTo(bounds.origin(),
143         window->layer()->transform()));
144     transform.TransformRect(&bounds);
145     return bounds;
146   }
147
148   gfx::RectF GetTransformedTargetBounds(aura::Window* window) {
149     gfx::RectF bounds(ScreenUtil::ConvertRectToScreen(
150         window->parent(), window->layer()->GetTargetBounds()));
151     gfx::Transform transform(GetTransformRelativeTo(bounds.origin(),
152         window->layer()->GetTargetTransform()));
153     transform.TransformRect(&bounds);
154     return bounds;
155   }
156
157   gfx::RectF GetTransformedBoundsInRootWindow(aura::Window* window) {
158     gfx::RectF bounds = gfx::Rect(window->bounds().size());
159     aura::Window* root = window->GetRootWindow();
160     CHECK(window->layer());
161     CHECK(root->layer());
162     gfx::Transform transform;
163     if (!window->layer()->GetTargetTransformRelativeTo(root->layer(),
164                                                        &transform)) {
165       return gfx::RectF();
166     }
167     transform.TransformRect(&bounds);
168     return bounds;
169   }
170
171   void ClickWindow(aura::Window* window) {
172     ui::test::EventGenerator event_generator(window->GetRootWindow(), window);
173     gfx::RectF target = GetTransformedBounds(window);
174     event_generator.ClickLeftButton();
175   }
176
177   void SendKey(ui::KeyboardCode key) {
178     ui::test::EventGenerator event_generator(Shell::GetPrimaryRootWindow());
179       event_generator.PressKey(key, 0);
180       event_generator.ReleaseKey(key, 0);
181   }
182
183   bool IsSelecting() {
184     return ash::Shell::GetInstance()->window_selector_controller()->
185         IsSelecting();
186   }
187
188   aura::Window* GetFocusedWindow() {
189     return aura::client::GetFocusClient(
190         Shell::GetPrimaryRootWindow())->GetFocusedWindow();
191     }
192
193   const std::vector<WindowSelectorItem*>& GetWindowItemsForRoot(int index) {
194     return ash::Shell::GetInstance()->window_selector_controller()->
195         window_selector_->grid_list_[index]->window_list_.get();
196     }
197
198   const aura::Window* GetSelectedWindow() {
199     WindowSelector* ws = ash::Shell::GetInstance()->
200         window_selector_controller()->window_selector_.get();
201     return ws->grid_list_[ws->selected_grid_index_]->
202         SelectedWindow()->SelectionWindow();
203   }
204
205   bool selection_widget_active() {
206     WindowSelector* ws = ash::Shell::GetInstance()->
207         window_selector_controller()->window_selector_.get();
208     return ws->grid_list_[ws->selected_grid_index_]->is_selecting();
209   }
210
211   bool showing_filter_widget() {
212     WindowSelector* ws = ash::Shell::GetInstance()->
213         window_selector_controller()->window_selector_.get();
214     return ws->text_filter_widget_->GetNativeWindow()->layer()->
215         GetTargetTransform().IsIdentity();
216   }
217
218   views::Widget* GetCloseButton(ash::WindowSelectorItem* window) {
219     return window->close_button_.get();
220   }
221
222   views::Label* GetLabelView(ash::WindowSelectorItem* window) {
223     return window->window_label_view_;
224   }
225
226   // Tests that a window is contained within a given WindowSelectorItem, and
227   // that both the window and its matching close button are within the same
228   // screen.
229   void IsWindowAndCloseButtonInScreen(aura::Window* window,
230                                       WindowSelectorItem* window_item) {
231     aura::Window* root_window = window_item->GetRootWindow();
232     EXPECT_TRUE(window_item->Contains(window));
233     EXPECT_TRUE(root_window->GetBoundsInScreen().Contains(
234         ToEnclosingRect(GetTransformedTargetBounds(window))));
235     EXPECT_TRUE(root_window->GetBoundsInScreen().Contains(
236         ToEnclosingRect(GetTransformedTargetBounds(
237             GetCloseButton(window_item)->GetNativeView()))));
238   }
239
240   void FilterItems(const base::StringPiece& pattern) {
241     ash::Shell::GetInstance()->
242         window_selector_controller()->window_selector_.get()->
243             ContentsChanged(NULL, base::UTF8ToUTF16(pattern));
244   }
245
246   test::ShelfViewTestAPI* shelf_view_test() {
247     return shelf_view_test_.get();
248   }
249
250   views::Widget* text_filter_widget() {
251     return ash::Shell::GetInstance()->
252         window_selector_controller()->window_selector_.get()->
253             text_filter_widget_.get();
254   }
255
256  private:
257   aura::test::TestWindowDelegate delegate_;
258   NonActivatableActivationDelegate non_activatable_activation_delegate_;
259   scoped_ptr<test::ShelfViewTestAPI> shelf_view_test_;
260
261   DISALLOW_COPY_AND_ASSIGN(WindowSelectorTest);
262 };
263
264 // Tests that an a11y alert is sent on entering overview mode.
265 TEST_F(WindowSelectorTest, A11yAlertOnOverviewMode) {
266   gfx::Rect bounds(0, 0, 400, 400);
267   AccessibilityDelegate* delegate =
268       ash::Shell::GetInstance()->accessibility_delegate();
269   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
270   EXPECT_NE(delegate->GetLastAccessibilityAlert(),
271             ui::A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED);
272   ToggleOverview();
273   EXPECT_EQ(delegate->GetLastAccessibilityAlert(),
274             ui::A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED);
275 }
276
277 // Tests entering overview mode with two windows and selecting one by clicking.
278 TEST_F(WindowSelectorTest, Basic) {
279   gfx::Rect bounds(0, 0, 400, 400);
280   aura::Window* root_window = Shell::GetPrimaryRootWindow();
281   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
282   scoped_ptr<aura::Window> window2(CreateWindow(bounds));
283   scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
284   scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds));
285   EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get()));
286   EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
287   wm::ActivateWindow(window2.get());
288   EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
289   EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
290   EXPECT_EQ(window2.get(), GetFocusedWindow());
291   // Hide the cursor before entering overview to test that it will be shown.
292   aura::client::GetCursorClient(root_window)->HideCursor();
293
294   // In overview mode the windows should no longer overlap and the text filter
295   // widget should be focused.
296   ToggleOverview();
297   EXPECT_EQ(text_filter_widget()->GetNativeWindow(), GetFocusedWindow());
298   EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get()));
299   EXPECT_FALSE(WindowsOverlapping(window1.get(), panel1.get()));
300   // Panels 1 and 2 should still be overlapping being in a single selector
301   // item.
302   EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
303
304   // Clicking window 1 should activate it.
305   ClickWindow(window1.get());
306   EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
307   EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
308   EXPECT_EQ(window1.get(), GetFocusedWindow());
309
310   // Cursor should have been unlocked.
311   EXPECT_FALSE(aura::client::GetCursorClient(root_window)->IsCursorLocked());
312 }
313
314 // Tests selecting a window by tapping on it.
315 TEST_F(WindowSelectorTest, BasicGesture) {
316   gfx::Rect bounds(0, 0, 400, 400);
317   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
318   scoped_ptr<aura::Window> window2(CreateWindow(bounds));
319   wm::ActivateWindow(window1.get());
320   EXPECT_EQ(window1.get(), GetFocusedWindow());
321   ToggleOverview();
322   EXPECT_EQ(text_filter_widget()->GetNativeWindow(), GetFocusedWindow());
323   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
324                                      window2.get());
325   generator.GestureTapAt(gfx::ToEnclosingRect(
326       GetTransformedTargetBounds(window2.get())).CenterPoint());
327   EXPECT_EQ(window2.get(), GetFocusedWindow());
328 }
329
330 // Tests that we do not crash and overview mode remains engaged if the desktop
331 // is tapped while a finger is already down over a window.
332 TEST_F(WindowSelectorTest, NoCrashWithDesktopTap) {
333   scoped_ptr<aura::Window> window(CreateWindow(gfx::Rect(200, 300, 250, 450)));
334
335   // We need a widget for the close button to work, a bare window will crash.
336   scoped_ptr<views::Widget> widget(new views::Widget);
337   views::Widget::InitParams params;
338   params.bounds = gfx::Rect(0, 0, 400, 400);
339   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
340   params.parent = window->parent();
341   widget->Init(params);
342   widget->Show();
343
344   ToggleOverview();
345
346   gfx::Rect bounds =
347       gfx::ToEnclosingRect(GetTransformedBoundsInRootWindow(window.get()));
348   ui::test::EventGenerator event_generator(window->GetRootWindow(),
349                                            bounds.CenterPoint());
350
351   // Press down on the window.
352   const int kTouchId = 19;
353   event_generator.PressTouchId(kTouchId);
354
355   // Tap on the desktop, which should not cause a crash. Overview mode should
356   // remain engaged because the transparent widget over the window has capture.
357   event_generator.GestureTapAt(gfx::Point(0, 0));
358   EXPECT_TRUE(IsSelecting());
359
360   event_generator.ReleaseTouchId(kTouchId);
361 }
362
363 // Tests that a window does not receive located events when in overview mode.
364 TEST_F(WindowSelectorTest, WindowDoesNotReceiveEvents) {
365   gfx::Rect window_bounds(20, 10, 200, 300);
366   aura::Window* root_window = Shell::GetPrimaryRootWindow();
367   scoped_ptr<aura::Window> window(CreateWindow(window_bounds));
368
369   gfx::Point point1(window_bounds.x() + 10, window_bounds.y() + 10);
370
371   ui::MouseEvent event1(ui::ET_MOUSE_PRESSED, point1, point1,
372                         ui::EF_NONE, ui::EF_NONE);
373
374   ui::EventTarget* root_target = root_window;
375   ui::EventTargeter* targeter = root_target->GetEventTargeter();
376
377   // The event should target the window because we are still not in overview
378   // mode.
379   EXPECT_EQ(window, static_cast<aura::Window*>(
380       targeter->FindTargetForEvent(root_target, &event1)));
381
382   ToggleOverview();
383
384   // The bounds have changed, take that into account.
385   gfx::RectF bounds = GetTransformedBoundsInRootWindow(window.get());
386   gfx::Point point2(bounds.x() + 10, bounds.y() + 10);
387   ui::MouseEvent event2(ui::ET_MOUSE_PRESSED, point2, point2,
388                         ui::EF_NONE, ui::EF_NONE);
389
390   // Now the transparent window should be intercepting this event.
391   EXPECT_NE(window, static_cast<aura::Window*>(
392         targeter->FindTargetForEvent(root_target, &event2)));
393 }
394
395 // Tests that clicking on the close button effectively closes the window.
396 TEST_F(WindowSelectorTest, CloseButton) {
397   scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(200, 300, 250, 450)));
398
399   // We need a widget for the close button to work, a bare window will crash.
400   scoped_ptr<views::Widget> widget(new views::Widget);
401   views::Widget::InitParams params;
402   params.bounds = gfx::Rect(0, 0, 400, 400);
403   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
404   params.parent = window1->parent();
405   widget->Init(params);
406   widget->Show();
407   ToggleOverview();
408
409   aura::Window* window2 = widget->GetNativeWindow();
410   gfx::RectF bounds = GetTransformedBoundsInRootWindow(window2);
411   gfx::Point point(bounds.top_right().x() - 1, bounds.top_right().y() - 1);
412   ui::test::EventGenerator event_generator(window2->GetRootWindow(), point);
413
414   EXPECT_FALSE(widget->IsClosed());
415   event_generator.ClickLeftButton();
416   EXPECT_TRUE(widget->IsClosed());
417 }
418
419 // Tests entering overview mode with two windows and selecting one.
420 TEST_F(WindowSelectorTest, FullscreenWindow) {
421   gfx::Rect bounds(0, 0, 400, 400);
422   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
423   scoped_ptr<aura::Window> window2(CreateWindow(bounds));
424   scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds));
425   wm::ActivateWindow(window1.get());
426
427   const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
428   wm::GetWindowState(window1.get())->OnWMEvent(&toggle_fullscreen_event);
429   // The panel is hidden in fullscreen mode.
430   EXPECT_FALSE(panel1->IsVisible());
431   EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen());
432
433   // Enter overview and select the fullscreen window.
434   ToggleOverview();
435
436   // The panel becomes temporarily visible for the overview.
437   EXPECT_TRUE(panel1->IsVisible());
438   ClickWindow(window1.get());
439
440   // The window is still fullscreen as it was selected. The panel should again
441   // be hidden.
442   EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen());
443   EXPECT_FALSE(panel1->IsVisible());
444
445   // Entering overview and selecting another window, the previous window remains
446   // fullscreen.
447   // TODO(flackr): Currently the panel remains hidden, but should become visible
448   // again.
449   ToggleOverview();
450   ClickWindow(window2.get());
451   EXPECT_TRUE(wm::GetWindowState(window1.get())->IsFullscreen());
452 }
453
454 // Tests that the shelf dimming state is removed while in overview and restored
455 // on exiting overview.
456 TEST_F(WindowSelectorTest, OverviewUndimsShelf) {
457   gfx::Rect bounds(0, 0, 400, 400);
458   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
459   wm::WindowState* window_state = wm::GetWindowState(window1.get());
460   window_state->Maximize();
461   ash::ShelfWidget* shelf = Shell::GetPrimaryRootWindowController()->shelf();
462   EXPECT_TRUE(shelf->GetDimsShelf());
463   ToggleOverview();
464   EXPECT_FALSE(shelf->GetDimsShelf());
465   ToggleOverview();
466   EXPECT_TRUE(shelf->GetDimsShelf());
467 }
468
469 // Tests that entering overview when a fullscreen window is active in maximized
470 // mode correctly applies the transformations to the window and correctly
471 // updates the window bounds on exiting overview mode: http://crbug.com/401664.
472 TEST_F(WindowSelectorTest, FullscreenWindowMaximizeMode) {
473   gfx::Rect bounds(0, 0, 400, 400);
474   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
475   scoped_ptr<aura::Window> window2(CreateWindow(bounds));
476   Shell::GetInstance()->maximize_mode_controller()->
477       EnableMaximizeModeWindowManager(true);
478   wm::ActivateWindow(window2.get());
479   wm::ActivateWindow(window1.get());
480   gfx::Rect normal_window_bounds(window1->bounds());
481   const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
482   wm::GetWindowState(window1.get())->OnWMEvent(&toggle_fullscreen_event);
483   gfx::Rect fullscreen_window_bounds(window1->bounds());
484   EXPECT_NE(normal_window_bounds.ToString(),
485             fullscreen_window_bounds.ToString());
486   EXPECT_EQ(fullscreen_window_bounds.ToString(),
487             window2->GetTargetBounds().ToString());
488   ToggleOverview();
489   // Window 2 would normally resize to normal window bounds on showing the shelf
490   // for overview but this is deferred until overview is exited.
491   EXPECT_EQ(fullscreen_window_bounds.ToString(),
492             window2->GetTargetBounds().ToString());
493   EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get()));
494   ToggleOverview();
495
496   // Since the fullscreen window is still active, window2 will still have the
497   // larger bounds.
498   EXPECT_EQ(fullscreen_window_bounds.ToString(),
499             window2->GetTargetBounds().ToString());
500
501   // Enter overview again and select window 2. Selecting window 2 should show
502   // the shelf bringing window2 back to the normal bounds.
503   ToggleOverview();
504   ClickWindow(window2.get());
505   EXPECT_EQ(normal_window_bounds.ToString(),
506             window2->GetTargetBounds().ToString());
507 }
508
509 // Tests that beginning window selection hides the app list.
510 TEST_F(WindowSelectorTest, SelectingHidesAppList) {
511   gfx::Rect bounds(0, 0, 400, 400);
512   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
513   scoped_ptr<aura::Window> window2(CreateWindow(bounds));
514   Shell::GetInstance()->ShowAppList(NULL);
515   EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility());
516   ToggleOverview();
517   EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility());
518   ToggleOverview();
519 }
520
521 // Tests that a minimized window's visibility and layer visibility is correctly
522 // changed when entering overview and restored when leaving overview mode.
523 // Crashes after the skia roll in http://crrev.com/274114.
524 // http://crbug.com/379570
525 TEST_F(WindowSelectorTest, DISABLED_MinimizedWindowVisibility) {
526   gfx::Rect bounds(0, 0, 400, 400);
527   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
528   wm::WindowState* window_state = wm::GetWindowState(window1.get());
529   window_state->Minimize();
530   EXPECT_FALSE(window1->IsVisible());
531   EXPECT_FALSE(window1->layer()->GetTargetVisibility());
532   {
533     ui::ScopedAnimationDurationScaleMode test_duration_mode(
534         ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
535     ToggleOverview();
536     EXPECT_TRUE(window1->IsVisible());
537     EXPECT_TRUE(window1->layer()->GetTargetVisibility());
538   }
539   {
540     ui::ScopedAnimationDurationScaleMode test_duration_mode(
541         ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
542     ToggleOverview();
543     EXPECT_FALSE(window1->IsVisible());
544     EXPECT_FALSE(window1->layer()->GetTargetVisibility());
545   }
546 }
547
548 // Tests that a bounds change during overview is corrected for.
549 TEST_F(WindowSelectorTest, BoundsChangeDuringOverview) {
550   scoped_ptr<aura::Window> window(CreateWindow(gfx::Rect(0, 0, 400, 400)));
551   ToggleOverview();
552   gfx::Rect overview_bounds =
553       ToEnclosingRect(GetTransformedTargetBounds(window.get()));
554   window->SetBounds(gfx::Rect(200, 0, 200, 200));
555   gfx::Rect new_overview_bounds =
556       ToEnclosingRect(GetTransformedTargetBounds(window.get()));
557   EXPECT_EQ(overview_bounds.x(), new_overview_bounds.x());
558   EXPECT_EQ(overview_bounds.y(), new_overview_bounds.y());
559   EXPECT_EQ(overview_bounds.width(), new_overview_bounds.width());
560   EXPECT_EQ(overview_bounds.height(), new_overview_bounds.height());
561   ToggleOverview();
562 }
563
564 // Tests that a newly created window aborts overview.
565 TEST_F(WindowSelectorTest, NewWindowCancelsOveriew) {
566   gfx::Rect bounds(0, 0, 400, 400);
567   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
568   scoped_ptr<aura::Window> window2(CreateWindow(bounds));
569   ToggleOverview();
570   EXPECT_TRUE(IsSelecting());
571
572   // A window being created should exit overview mode.
573   scoped_ptr<aura::Window> window3(CreateWindow(bounds));
574   EXPECT_FALSE(IsSelecting());
575 }
576
577 // Tests that a window activation exits overview mode.
578 TEST_F(WindowSelectorTest, ActivationCancelsOveriew) {
579   gfx::Rect bounds(0, 0, 400, 400);
580   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
581   scoped_ptr<aura::Window> window2(CreateWindow(bounds));
582   window2->Focus();
583   ToggleOverview();
584   EXPECT_TRUE(IsSelecting());
585
586   // A window being activated should exit overview mode.
587   window1->Focus();
588   EXPECT_FALSE(IsSelecting());
589
590   // window1 should be focused after exiting even though window2 was focused on
591   // entering overview because we exited due to an activation.
592   EXPECT_EQ(window1.get(), GetFocusedWindow());
593 }
594
595 // Tests that exiting overview mode without selecting a window restores focus
596 // to the previously focused window.
597 TEST_F(WindowSelectorTest, CancelRestoresFocus) {
598   gfx::Rect bounds(0, 0, 400, 400);
599   scoped_ptr<aura::Window> window(CreateWindow(bounds));
600   wm::ActivateWindow(window.get());
601   EXPECT_EQ(window.get(), GetFocusedWindow());
602
603   // In overview mode, the text filter widget should be focused.
604   ToggleOverview();
605   EXPECT_EQ(text_filter_widget()->GetNativeWindow(), GetFocusedWindow());
606
607   // If canceling overview mode, focus should be restored.
608   ToggleOverview();
609   EXPECT_EQ(window.get(), GetFocusedWindow());
610 }
611
612 // Tests that overview mode is exited if the last remaining window is destroyed.
613 TEST_F(WindowSelectorTest, LastWindowDestroyed) {
614   gfx::Rect bounds(0, 0, 400, 400);
615   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
616   scoped_ptr<aura::Window> window2(CreateWindow(bounds));
617   ToggleOverview();
618
619   window1.reset();
620   window2.reset();
621   EXPECT_FALSE(IsSelecting());
622 }
623
624 // Tests that entering overview mode restores a window to its original
625 // target location.
626 TEST_F(WindowSelectorTest, QuickReentryRestoresInitialTransform) {
627   gfx::Rect bounds(0, 0, 400, 400);
628   scoped_ptr<aura::Window> window(CreateWindow(bounds));
629   gfx::Rect initial_bounds = ToEnclosingRect(
630       GetTransformedBounds(window.get()));
631   ToggleOverview();
632   // Quickly exit and reenter overview mode. The window should still be
633   // animating when we reenter. We cannot short circuit animations for this but
634   // we also don't have to wait for them to complete.
635   {
636     ui::ScopedAnimationDurationScaleMode test_duration_mode(
637         ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
638     ToggleOverview();
639     ToggleOverview();
640   }
641   EXPECT_NE(initial_bounds, ToEnclosingRect(
642       GetTransformedTargetBounds(window.get())));
643   ToggleOverview();
644   EXPECT_FALSE(IsSelecting());
645   EXPECT_EQ(initial_bounds, ToEnclosingRect(
646       GetTransformedTargetBounds(window.get())));
647 }
648
649 // Tests that non-activatable windows are hidden when entering overview mode.
650 TEST_F(WindowSelectorTest, NonActivatableWindowsHidden) {
651   gfx::Rect bounds(0, 0, 400, 400);
652   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
653   scoped_ptr<aura::Window> window2(CreateWindow(bounds));
654   scoped_ptr<aura::Window> non_activatable_window(
655       CreateNonActivatableWindow(Shell::GetPrimaryRootWindow()->bounds()));
656   EXPECT_TRUE(non_activatable_window->IsVisible());
657   ToggleOverview();
658   EXPECT_FALSE(non_activatable_window->IsVisible());
659   ToggleOverview();
660   EXPECT_TRUE(non_activatable_window->IsVisible());
661
662   // Test that a window behind the fullscreen non-activatable window can be
663   // clicked.
664   non_activatable_window->parent()->StackChildAtTop(
665       non_activatable_window.get());
666   ToggleOverview();
667   ClickWindow(window1.get());
668   EXPECT_FALSE(IsSelecting());
669   EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
670 }
671
672 // Tests that windows with modal child windows are transformed with the modal
673 // child even though not activatable themselves.
674 TEST_F(WindowSelectorTest, ModalChild) {
675   gfx::Rect bounds(0, 0, 400, 400);
676   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
677   scoped_ptr<aura::Window> child1(CreateWindow(bounds));
678   child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
679   ::wm::AddTransientChild(window1.get(), child1.get());
680   EXPECT_EQ(window1->parent(), child1->parent());
681   ToggleOverview();
682   EXPECT_TRUE(window1->IsVisible());
683   EXPECT_TRUE(child1->IsVisible());
684   EXPECT_EQ(ToEnclosingRect(GetTransformedTargetBounds(child1.get())),
685       ToEnclosingRect(GetTransformedTargetBounds(window1.get())));
686   ToggleOverview();
687 }
688
689 // Tests that clicking a modal window's parent activates the modal window in
690 // overview.
691 TEST_F(WindowSelectorTest, ClickModalWindowParent) {
692   scoped_ptr<aura::Window> window1(CreateWindow(gfx::Rect(0, 0, 180, 180)));
693   scoped_ptr<aura::Window> child1(CreateWindow(gfx::Rect(200, 0, 180, 180)));
694   child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
695   ::wm::AddTransientChild(window1.get(), child1.get());
696   EXPECT_FALSE(WindowsOverlapping(window1.get(), child1.get()));
697   EXPECT_EQ(window1->parent(), child1->parent());
698   ToggleOverview();
699   // Given that their relative positions are preserved, the windows should still
700   // not overlap.
701   EXPECT_FALSE(WindowsOverlapping(window1.get(), child1.get()));
702   ClickWindow(window1.get());
703   EXPECT_FALSE(IsSelecting());
704
705   // Clicking on window1 should activate child1.
706   EXPECT_TRUE(wm::IsActiveWindow(child1.get()));
707 }
708
709 // Tests that windows remain on the display they are currently on in overview
710 // mode, and that the close buttons are on matching displays.
711 TEST_F(WindowSelectorTest, MultipleDisplays) {
712   if (!SupportsMultipleDisplays())
713     return;
714
715   UpdateDisplay("600x400,600x400");
716   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
717   gfx::Rect bounds1(0, 0, 400, 400);
718   gfx::Rect bounds2(650, 0, 400, 400);
719
720   scoped_ptr<aura::Window> window1(CreateWindow(bounds1));
721   scoped_ptr<aura::Window> window2(CreateWindow(bounds1));
722   scoped_ptr<aura::Window> window3(CreateWindow(bounds2));
723   scoped_ptr<aura::Window> window4(CreateWindow(bounds2));
724   scoped_ptr<aura::Window> panel1(CreatePanelWindow(bounds1));
725   scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds1));
726   scoped_ptr<aura::Window> panel3(CreatePanelWindow(bounds2));
727   scoped_ptr<aura::Window> panel4(CreatePanelWindow(bounds2));
728   EXPECT_EQ(root_windows[0], window1->GetRootWindow());
729   EXPECT_EQ(root_windows[0], window2->GetRootWindow());
730   EXPECT_EQ(root_windows[1], window3->GetRootWindow());
731   EXPECT_EQ(root_windows[1], window4->GetRootWindow());
732
733   EXPECT_EQ(root_windows[0], panel1->GetRootWindow());
734   EXPECT_EQ(root_windows[0], panel2->GetRootWindow());
735   EXPECT_EQ(root_windows[1], panel3->GetRootWindow());
736   EXPECT_EQ(root_windows[1], panel4->GetRootWindow());
737
738   // In overview mode, each window remains in the same root window.
739   ToggleOverview();
740   EXPECT_EQ(root_windows[0], window1->GetRootWindow());
741   EXPECT_EQ(root_windows[0], window2->GetRootWindow());
742   EXPECT_EQ(root_windows[1], window3->GetRootWindow());
743   EXPECT_EQ(root_windows[1], window4->GetRootWindow());
744   EXPECT_EQ(root_windows[0], panel1->GetRootWindow());
745   EXPECT_EQ(root_windows[0], panel2->GetRootWindow());
746   EXPECT_EQ(root_windows[1], panel3->GetRootWindow());
747   EXPECT_EQ(root_windows[1], panel4->GetRootWindow());
748
749   const std::vector<WindowSelectorItem*>& primary_window_items =
750       GetWindowItemsForRoot(0);
751   const std::vector<WindowSelectorItem*>& secondary_window_items =
752       GetWindowItemsForRoot(1);
753
754   // Window indices are based on top-down order. The reverse of our creation.
755   IsWindowAndCloseButtonInScreen(window1.get(), primary_window_items[2]);
756   IsWindowAndCloseButtonInScreen(window2.get(), primary_window_items[1]);
757   IsWindowAndCloseButtonInScreen(window3.get(), secondary_window_items[2]);
758   IsWindowAndCloseButtonInScreen(window4.get(), secondary_window_items[1]);
759
760   IsWindowAndCloseButtonInScreen(panel1.get(), primary_window_items[0]);
761   IsWindowAndCloseButtonInScreen(panel2.get(), primary_window_items[0]);
762   IsWindowAndCloseButtonInScreen(panel3.get(), secondary_window_items[0]);
763   IsWindowAndCloseButtonInScreen(panel4.get(), secondary_window_items[0]);
764
765   EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get()));
766   EXPECT_TRUE(WindowsOverlapping(panel3.get(), panel4.get()));
767   EXPECT_FALSE(WindowsOverlapping(panel1.get(), panel3.get()));
768 }
769
770 // Tests shutting down during overview.
771 TEST_F(WindowSelectorTest, Shutdown) {
772   gfx::Rect bounds(0, 0, 400, 400);
773   // These windows will be deleted when the test exits and the Shell instance
774   // is shut down.
775   aura::Window* window1(CreateWindow(bounds));
776   aura::Window* window2(CreateWindow(bounds));
777   aura::Window* window3(CreatePanelWindow(bounds));
778   aura::Window* window4(CreatePanelWindow(bounds));
779
780   wm::ActivateWindow(window4);
781   wm::ActivateWindow(window3);
782   wm::ActivateWindow(window2);
783   wm::ActivateWindow(window1);
784
785   ToggleOverview();
786 }
787
788 // Tests removing a display during overview.
789 TEST_F(WindowSelectorTest, RemoveDisplay) {
790   if (!SupportsMultipleDisplays())
791     return;
792
793   UpdateDisplay("400x400,400x400");
794   gfx::Rect bounds1(0, 0, 100, 100);
795   gfx::Rect bounds2(450, 0, 100, 100);
796   scoped_ptr<aura::Window> window1(CreateWindow(bounds1));
797   scoped_ptr<aura::Window> window2(CreateWindow(bounds2));
798   scoped_ptr<aura::Window> window3(CreatePanelWindow(bounds1));
799   scoped_ptr<aura::Window> window4(CreatePanelWindow(bounds2));
800
801   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
802   EXPECT_EQ(root_windows[0], window1->GetRootWindow());
803   EXPECT_EQ(root_windows[1], window2->GetRootWindow());
804   EXPECT_EQ(root_windows[0], window3->GetRootWindow());
805   EXPECT_EQ(root_windows[1], window4->GetRootWindow());
806
807   wm::ActivateWindow(window4.get());
808   wm::ActivateWindow(window3.get());
809   wm::ActivateWindow(window2.get());
810   wm::ActivateWindow(window1.get());
811
812   ToggleOverview();
813   EXPECT_TRUE(IsSelecting());
814   UpdateDisplay("400x400");
815   EXPECT_FALSE(IsSelecting());
816 }
817
818 // Tests starting overview during a drag and drop tracking operation.
819 // TODO(flackr): Fix memory corruption crash when running locally (not failing
820 // on bots). See http://crbug.com/342528.
821 TEST_F(WindowSelectorTest, DISABLED_DragDropInProgress) {
822   bool drag_canceled_by_test = false;
823   gfx::Rect bounds(0, 0, 400, 400);
824   scoped_ptr<aura::Window> window(CreateWindow(bounds));
825   test::ShellTestApi shell_test_api(Shell::GetInstance());
826   ash::DragDropController* drag_drop_controller =
827       shell_test_api.drag_drop_controller();
828   ui::OSExchangeData data;
829   base::MessageLoopForUI::current()->PostTask(FROM_HERE,
830       base::Bind(&WindowSelectorTest::ToggleOverview,
831                  base::Unretained(this)));
832   base::MessageLoopForUI::current()->PostTask(FROM_HERE,
833       base::Bind(&CancelDrag, drag_drop_controller, &drag_canceled_by_test));
834   data.SetString(base::UTF8ToUTF16("I am being dragged"));
835   drag_drop_controller->StartDragAndDrop(data, window->GetRootWindow(),
836       window.get(), gfx::Point(5, 5), ui::DragDropTypes::DRAG_MOVE,
837       ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
838   RunAllPendingInMessageLoop();
839   EXPECT_FALSE(drag_canceled_by_test);
840   ASSERT_TRUE(IsSelecting());
841   RunAllPendingInMessageLoop();
842 }
843
844 // Test that a label is created under the window on entering overview mode.
845 TEST_F(WindowSelectorTest, CreateLabelUnderWindow) {
846   scoped_ptr<aura::Window> window(CreateWindow(gfx::Rect(0, 0, 100, 100)));
847   base::string16 window_title = base::UTF8ToUTF16("My window");
848   window->SetTitle(window_title);
849   ToggleOverview();
850   WindowSelectorItem* window_item = GetWindowItemsForRoot(0).back();
851   views::Label* label = GetLabelView(window_item);
852   // Has the label view been created?
853   ASSERT_TRUE(label);
854
855   // Verify the label matches the window title.
856   EXPECT_EQ(label->text(), window_title);
857
858   // Update the window title and check that the label is updated, too.
859   base::string16 updated_title = base::UTF8ToUTF16("Updated title");
860   window->SetTitle(updated_title);
861   EXPECT_EQ(label->text(), updated_title);
862
863   // Labels are located based on target_bounds, not the actual window item
864   // bounds.
865   gfx::Rect target_bounds(window_item->target_bounds());
866   gfx::Rect expected_label_bounds(target_bounds.x(),
867                                   target_bounds.bottom() - label->
868                                       GetPreferredSize().height(),
869                                   target_bounds.width(),
870                                   label->GetPreferredSize().height());
871   gfx::Rect real_label_bounds = label->GetWidget()->GetNativeWindow()->bounds();
872   EXPECT_EQ(real_label_bounds, expected_label_bounds);
873 }
874
875 // Tests that a label is created for the active panel in a group of panels in
876 // overview mode.
877 TEST_F(WindowSelectorTest, CreateLabelUnderPanel) {
878   scoped_ptr<aura::Window> panel1(CreatePanelWindow(gfx::Rect(0, 0, 100, 100)));
879   scoped_ptr<aura::Window> panel2(CreatePanelWindow(gfx::Rect(0, 0, 100, 100)));
880   base::string16 panel1_title = base::UTF8ToUTF16("My panel");
881   base::string16 panel2_title = base::UTF8ToUTF16("Another panel");
882   base::string16 updated_panel1_title = base::UTF8ToUTF16("WebDriver Torso");
883   base::string16 updated_panel2_title = base::UTF8ToUTF16("Da panel");
884   panel1->SetTitle(panel1_title);
885   panel2->SetTitle(panel2_title);
886   wm::ActivateWindow(panel1.get());
887   ToggleOverview();
888   WindowSelectorItem* window_item = GetWindowItemsForRoot(0).back();
889   views::Label* label = GetLabelView(window_item);
890   // Has the label view been created?
891   ASSERT_TRUE(label);
892
893   // Verify the label matches the active window title.
894   EXPECT_EQ(label->text(), panel1_title);
895   // Verify that updating the title also updates the label.
896   panel1->SetTitle(updated_panel1_title);
897   EXPECT_EQ(label->text(), updated_panel1_title);
898   // After destroying the first panel, the label should match the second panel.
899   panel1.reset();
900   label = GetLabelView(window_item);
901   EXPECT_EQ(label->text(), panel2_title);
902   // Also test updating the title on the second panel.
903   panel2->SetTitle(updated_panel2_title);
904   EXPECT_EQ(label->text(), updated_panel2_title);
905 }
906
907 // Tests that overview updates the window positions if the display orientation
908 // changes.
909 TEST_F(WindowSelectorTest, DisplayOrientationChanged) {
910   if (!SupportsHostWindowResize())
911     return;
912
913   aura::Window* root_window = Shell::GetInstance()->GetPrimaryRootWindow();
914   UpdateDisplay("600x200");
915   EXPECT_EQ("0,0 600x200", root_window->bounds().ToString());
916   gfx::Rect window_bounds(0, 0, 150, 150);
917   ScopedVector<aura::Window> windows;
918   for (int i = 0; i < 3; i++) {
919     windows.push_back(CreateWindow(window_bounds));
920   }
921
922   ToggleOverview();
923   for (ScopedVector<aura::Window>::iterator iter = windows.begin();
924        iter != windows.end(); ++iter) {
925     EXPECT_TRUE(root_window->bounds().Contains(
926         ToEnclosingRect(GetTransformedTargetBounds(*iter))));
927   }
928
929   // Rotate the display, windows should be repositioned to be within the screen
930   // bounds.
931   UpdateDisplay("600x200/r");
932   EXPECT_EQ("0,0 200x600", root_window->bounds().ToString());
933   for (ScopedVector<aura::Window>::iterator iter = windows.begin();
934        iter != windows.end(); ++iter) {
935     EXPECT_TRUE(root_window->bounds().Contains(
936         ToEnclosingRect(GetTransformedTargetBounds(*iter))));
937   }
938 }
939
940 // Tests traversing some windows in overview mode with the tab key.
941 TEST_F(WindowSelectorTest, BasicTabKeyNavigation) {
942   gfx::Rect bounds(0, 0, 100, 100);
943   scoped_ptr<aura::Window> window2(CreateWindow(bounds));
944   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
945   ToggleOverview();
946
947   SendKey(ui::VKEY_TAB);
948   EXPECT_EQ(GetSelectedWindow(), window1.get());
949   SendKey(ui::VKEY_TAB);
950   EXPECT_EQ(GetSelectedWindow(), window2.get());
951   SendKey(ui::VKEY_TAB);
952   EXPECT_EQ(GetSelectedWindow(), window1.get());
953 }
954
955 // Tests traversing some windows in overview mode with the arrow keys in every
956 // possible direction.
957 TEST_F(WindowSelectorTest, BasicArrowKeyNavigation) {
958   if (!SupportsHostWindowResize())
959     return;
960   const size_t test_windows = 9;
961   UpdateDisplay("800x600");
962   ScopedVector<aura::Window> windows;
963   for (size_t i = test_windows; i > 0; i--)
964     windows.push_back(CreateWindowWithId(gfx::Rect(0, 0, 100, 100), i));
965
966   ui::KeyboardCode arrow_keys[] = {
967       ui::VKEY_RIGHT,
968       ui::VKEY_DOWN,
969       ui::VKEY_LEFT,
970       ui::VKEY_UP
971   };
972   // Expected window layout, assuming that the text filtering feature is
973   // enabled by default (i.e., --ash-disable-text-filtering-in-overview-mode
974   // is not being used).
975   // +-------+  +-------+  +-------+  +-------+
976   // |   1   |  |   2   |  |   3   |  |   4   |
977   // +-------+  +-------+  +-------+  +-------+
978   // +-------+  +-------+  +-------+  +-------+
979   // |   5   |  |   6   |  |   7   |  |   8   |
980   // +-------+  +-------+  +-------+  +-------+
981   // +-------+
982   // |   9   |
983   // +-------+
984   // Index for each window during a full loop plus wrapping around.
985   int index_path_for_direction[][test_windows + 1] = {
986       {1, 2, 3, 4, 5, 6, 7, 8, 9, 1},  // Right
987       {1, 5, 9, 2, 6, 3, 7, 4, 8, 1},  // Down
988       {9, 8, 7, 6, 5, 4, 3, 2, 1, 9},  // Left
989       {8, 4, 7, 3, 6, 2, 9, 5, 1, 8}   // Up
990   };
991
992   for (size_t key_index = 0; key_index < arraysize(arrow_keys); key_index++) {
993     ToggleOverview();
994     for (size_t i = 0; i < test_windows + 1; i++) {
995       SendKey(arrow_keys[key_index]);
996       // TODO(flackr): Add a more readable error message by constructing a
997       // string from the window IDs.
998       EXPECT_EQ(GetSelectedWindow()->id(),
999                 index_path_for_direction[key_index][i]);
1000     }
1001     ToggleOverview();
1002   }
1003 }
1004
1005 // Tests basic selection across multiple monitors.
1006 TEST_F(WindowSelectorTest, BasicMultiMonitorArrowKeyNavigation) {
1007   if (!SupportsMultipleDisplays())
1008     return;
1009
1010   UpdateDisplay("400x400,400x400");
1011   gfx::Rect bounds1(0, 0, 100, 100);
1012   gfx::Rect bounds2(450, 0, 100, 100);
1013   scoped_ptr<aura::Window> window4(CreateWindow(bounds2));
1014   scoped_ptr<aura::Window> window3(CreateWindow(bounds2));
1015   scoped_ptr<aura::Window> window2(CreateWindow(bounds1));
1016   scoped_ptr<aura::Window> window1(CreateWindow(bounds1));
1017
1018
1019   ToggleOverview();
1020
1021   SendKey(ui::VKEY_RIGHT);
1022   EXPECT_EQ(GetSelectedWindow(), window1.get());
1023   SendKey(ui::VKEY_RIGHT);
1024   EXPECT_EQ(GetSelectedWindow(), window2.get());
1025   SendKey(ui::VKEY_RIGHT);
1026   EXPECT_EQ(GetSelectedWindow(), window3.get());
1027   SendKey(ui::VKEY_RIGHT);
1028   EXPECT_EQ(GetSelectedWindow(), window4.get());
1029 }
1030
1031 // Tests selecting a window in overview mode with the return key.
1032 TEST_F(WindowSelectorTest, SelectWindowWithReturnKey) {
1033   gfx::Rect bounds(0, 0, 100, 100);
1034   scoped_ptr<aura::Window> window2(CreateWindow(bounds));
1035   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
1036   ToggleOverview();
1037
1038   // Pressing the return key without a selection widget should not do anything.
1039   SendKey(ui::VKEY_RETURN);
1040   EXPECT_TRUE(IsSelecting());
1041
1042   // Select the first window.
1043   SendKey(ui::VKEY_RIGHT);
1044   SendKey(ui::VKEY_RETURN);
1045   ASSERT_FALSE(IsSelecting());
1046   EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
1047
1048   // Select the second window.
1049   ToggleOverview();
1050   SendKey(ui::VKEY_RIGHT);
1051   SendKey(ui::VKEY_RIGHT);
1052   SendKey(ui::VKEY_RETURN);
1053   EXPECT_FALSE(IsSelecting());
1054   EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
1055 }
1056
1057 // Tests that overview mode hides the callout widget.
1058 TEST_F(WindowSelectorTest, WindowOverviewHidesCalloutWidgets) {
1059   scoped_ptr<aura::Window> panel1(CreatePanelWindow(gfx::Rect(0, 0, 100, 100)));
1060   scoped_ptr<aura::Window> panel2(CreatePanelWindow(gfx::Rect(0, 0, 100, 100)));
1061   PanelLayoutManager* panel_manager =
1062         static_cast<PanelLayoutManager*>(panel1->parent()->layout_manager());
1063
1064   // By default, panel callout widgets are visible.
1065   EXPECT_TRUE(
1066       panel_manager->GetCalloutWidgetForPanel(panel1.get())->IsVisible());
1067   EXPECT_TRUE(
1068       panel_manager->GetCalloutWidgetForPanel(panel2.get())->IsVisible());
1069
1070   // Toggling the overview should hide the callout widgets.
1071   ToggleOverview();
1072   EXPECT_FALSE(
1073       panel_manager->GetCalloutWidgetForPanel(panel1.get())->IsVisible());
1074   EXPECT_FALSE(
1075       panel_manager->GetCalloutWidgetForPanel(panel2.get())->IsVisible());
1076
1077   // Ending the overview should show them again.
1078   ToggleOverview();
1079   EXPECT_TRUE(
1080       panel_manager->GetCalloutWidgetForPanel(panel1.get())->IsVisible());
1081   EXPECT_TRUE(
1082       panel_manager->GetCalloutWidgetForPanel(panel2.get())->IsVisible());
1083 }
1084
1085 // Tests that when panels are grouped that the close button only closes the
1086 // currently active panel. After the removal window selection should still be
1087 // active, and the label should have changed. Removing the last panel should
1088 // cause selection to end.
1089 TEST_F(WindowSelectorTest, CloseButtonOnPanels) {
1090   scoped_ptr<views::Widget> widget1(CreatePanelWindowWidget(
1091       gfx::Rect(0, 0, 300, 100)));
1092   scoped_ptr<views::Widget> widget2(CreatePanelWindowWidget(
1093       gfx::Rect(100, 0, 100, 100)));
1094   aura::Window* window1 = widget1->GetNativeWindow();
1095   aura::Window* window2 = widget2->GetNativeWindow();
1096   base::string16 panel1_title = base::UTF8ToUTF16("Panel 1");
1097   base::string16 panel2_title = base::UTF8ToUTF16("Panel 2");
1098   window1->SetTitle(panel1_title);
1099   window2->SetTitle(panel2_title);
1100   wm::ActivateWindow(window1);
1101   ToggleOverview();
1102
1103   gfx::RectF bounds1 = GetTransformedBoundsInRootWindow(window1);
1104   gfx::Point point1(bounds1.top_right().x() - 1, bounds1.top_right().y() - 1);
1105   ui::test::EventGenerator event_generator1(window1->GetRootWindow(), point1);
1106
1107   EXPECT_FALSE(widget1->IsClosed());
1108   event_generator1.ClickLeftButton();
1109   EXPECT_TRUE(widget1->IsClosed());
1110   RunAllPendingInMessageLoop();
1111   EXPECT_TRUE(IsSelecting());
1112   WindowSelectorItem* window_item = GetWindowItemsForRoot(0).front();
1113   EXPECT_FALSE(window_item->empty());
1114   EXPECT_TRUE(window_item->Contains(window2));
1115   EXPECT_TRUE(GetCloseButton(window_item)->IsVisible());
1116
1117
1118   views::Label* label = GetLabelView(window_item);
1119   EXPECT_EQ(label->text(), panel2_title);
1120
1121   gfx::RectF bounds2 = GetTransformedBoundsInRootWindow(window2);
1122   gfx::Point point2(bounds2.top_right().x() - 1, bounds2.top_right().y() - 1);
1123   ui::test::EventGenerator event_generator2(window2->GetRootWindow(), point2);
1124
1125   EXPECT_FALSE(widget2->IsClosed());
1126   event_generator2.ClickLeftButton();
1127   EXPECT_TRUE(widget2->IsClosed());
1128   RunAllPendingInMessageLoop();
1129   EXPECT_FALSE(IsSelecting());
1130 }
1131
1132 // Creates three windows and tests filtering them by title.
1133 TEST_F(WindowSelectorTest, BasicTextFiltering) {
1134   gfx::Rect bounds(0, 0, 100, 100);
1135   scoped_ptr<aura::Window> window2(CreateWindow(bounds));
1136   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
1137   scoped_ptr<aura::Window> window0(CreateWindow(bounds));
1138   base::string16 window2_title = base::UTF8ToUTF16("Highway to test");
1139   base::string16 window1_title = base::UTF8ToUTF16("For those about to test");
1140   base::string16 window0_title = base::UTF8ToUTF16("We salute you");
1141   window0->SetTitle(window0_title);
1142   window1->SetTitle(window1_title);
1143   window2->SetTitle(window2_title);
1144   ToggleOverview();
1145   EXPECT_FALSE(selection_widget_active());
1146   EXPECT_FALSE(showing_filter_widget());
1147   FilterItems("Test");
1148
1149   // The selection widget should appear when filtering starts, and should be
1150   // selecting the first matching window.
1151   EXPECT_TRUE(selection_widget_active());
1152   EXPECT_TRUE(showing_filter_widget());
1153   EXPECT_EQ(GetSelectedWindow(), window1.get());
1154
1155   // Window 0 has no "test" on it so it should be the only dimmed item.
1156   std::vector<WindowSelectorItem*> items = GetWindowItemsForRoot(0);
1157   EXPECT_TRUE(items[0]->dimmed());
1158   EXPECT_FALSE(items[1]->dimmed());
1159   EXPECT_FALSE(items[2]->dimmed());
1160
1161   // No items match the search.
1162   FilterItems("I'm testing 'n testing");
1163   EXPECT_TRUE(items[0]->dimmed());
1164   EXPECT_TRUE(items[1]->dimmed());
1165   EXPECT_TRUE(items[2]->dimmed());
1166
1167   // All the items should match the empty string. The filter widget should also
1168   // disappear.
1169   FilterItems("");
1170   EXPECT_FALSE(showing_filter_widget());
1171   EXPECT_FALSE(items[0]->dimmed());
1172   EXPECT_FALSE(items[1]->dimmed());
1173   EXPECT_FALSE(items[2]->dimmed());
1174 }
1175
1176 // Tests selecting in the overview with dimmed and undimmed items.
1177 TEST_F(WindowSelectorTest, TextFilteringSelection) {
1178   gfx::Rect bounds(0, 0, 100, 100);
1179    scoped_ptr<aura::Window> window2(CreateWindow(bounds));
1180    scoped_ptr<aura::Window> window1(CreateWindow(bounds));
1181    scoped_ptr<aura::Window> window0(CreateWindow(bounds));
1182    base::string16 window2_title = base::UTF8ToUTF16("Rock and roll");
1183    base::string16 window1_title = base::UTF8ToUTF16("Rock and");
1184    base::string16 window0_title = base::UTF8ToUTF16("Rock");
1185    window0->SetTitle(window0_title);
1186    window1->SetTitle(window1_title);
1187    window2->SetTitle(window2_title);
1188    ToggleOverview();
1189    SendKey(ui::VKEY_RIGHT);
1190    EXPECT_TRUE(selection_widget_active());
1191    EXPECT_EQ(GetSelectedWindow(), window0.get());
1192
1193    // Dim the first item, the selection should jump to the next item.
1194    std::vector<WindowSelectorItem*> items = GetWindowItemsForRoot(0);
1195    FilterItems("Rock and");
1196    EXPECT_EQ(GetSelectedWindow(), window1.get());
1197
1198    // Cycle the selection, the dimmed window should not be selected.
1199    SendKey(ui::VKEY_RIGHT);
1200    EXPECT_EQ(GetSelectedWindow(), window2.get());
1201    SendKey(ui::VKEY_RIGHT);
1202    EXPECT_EQ(GetSelectedWindow(), window1.get());
1203
1204    // Dimming all the items should hide the selection widget.
1205    FilterItems("Pop");
1206    EXPECT_FALSE(selection_widget_active());
1207
1208    // Undimming one window should automatically select it.
1209    FilterItems("Rock and roll");
1210    EXPECT_EQ(GetSelectedWindow(), window2.get());
1211 }
1212
1213 // Tests clicking on the desktop itself to cancel overview mode.
1214 TEST_F(WindowSelectorTest, CancelOverviewOnMouseClick) {
1215   // Overview disabled by default.
1216   EXPECT_FALSE(IsSelecting());
1217
1218   // Point and bounds selected so that they don't intersect. This causes
1219   // events located at the point to be passed to DesktopBackgroundController,
1220   // and not the window.
1221   gfx::Point point_in_background_page(0, 0);
1222   gfx::Rect bounds(10, 10, 100, 100);
1223   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
1224   ui::test::EventGenerator& generator = GetEventGenerator();
1225   // Move mouse to point in the background page. Sending an event here will pass
1226   // it to the DesktopBackgroundController in both regular and overview mode.
1227   generator.MoveMouseTo(point_in_background_page);
1228
1229   // Clicking on the background page while not in overview should not toggle
1230   // overview.
1231   generator.ClickLeftButton();
1232   EXPECT_FALSE(IsSelecting());
1233
1234   // Switch to overview mode.
1235   ToggleOverview();
1236   ASSERT_TRUE(IsSelecting());
1237
1238   // Click should now exit overview mode.
1239   generator.ClickLeftButton();
1240   EXPECT_FALSE(IsSelecting());
1241 }
1242
1243 // Tests tapping on the desktop itself to cancel overview mode.
1244 TEST_F(WindowSelectorTest, CancelOverviewOnTap) {
1245   // Overview disabled by default.
1246   EXPECT_FALSE(IsSelecting());
1247
1248   // Point and bounds selected so that they don't intersect. This causes
1249   // events located at the point to be passed to DesktopBackgroundController,
1250   // and not the window.
1251   gfx::Point point_in_background_page(0, 0);
1252   gfx::Rect bounds(10, 10, 100, 100);
1253   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
1254   ui::test::EventGenerator& generator = GetEventGenerator();
1255
1256   // Tapping on the background page while not in overview should not toggle
1257   // overview.
1258   generator.GestureTapAt(point_in_background_page);
1259   EXPECT_FALSE(IsSelecting());
1260
1261   // Switch to overview mode.
1262   ToggleOverview();
1263   ASSERT_TRUE(IsSelecting());
1264
1265   // Tap should now exit overview mode.
1266   generator.GestureTapAt(point_in_background_page);
1267   EXPECT_FALSE(IsSelecting());
1268 }
1269
1270 }  // namespace ash