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