Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / ash / wm / overview / window_selector_unittest.cc
index 4ca0713..adb8f1d 100644 (file)
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_vector.h"
 #include "base/run_loop.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/client/focus_client.h"
-#include "ui/aura/test/event_generator.h"
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/test/test_windows.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
+#include "ui/events/test/event_generator.h"
 #include "ui/gfx/rect_conversions.h"
 #include "ui/gfx/transform.h"
 #include "ui/views/controls/label.h"
@@ -169,13 +170,13 @@ class WindowSelectorTest : public test::AshTestBase {
   }
 
   void ClickWindow(aura::Window* window) {
-    aura::test::EventGenerator event_generator(window->GetRootWindow(), window);
+    ui::test::EventGenerator event_generator(window->GetRootWindow(), window);
     gfx::RectF target = GetTransformedBounds(window);
     event_generator.ClickLeftButton();
   }
 
   void SendKey(ui::KeyboardCode key) {
-      aura::test::EventGenerator event_generator(Shell::GetPrimaryRootWindow());
+    ui::test::EventGenerator event_generator(Shell::GetPrimaryRootWindow());
       event_generator.PressKey(key, 0);
       event_generator.ReleaseKey(key, 0);
   }
@@ -202,12 +203,25 @@ class WindowSelectorTest : public test::AshTestBase {
         SelectedWindow()->SelectionWindow();
   }
 
+  const bool selection_widget_active() {
+    WindowSelector* ws = ash::Shell::GetInstance()->
+        window_selector_controller()->window_selector_.get();
+    return ws->grid_list_[ws->selected_grid_index_]->is_selecting();
+  }
+
+  bool showing_filter_widget() {
+    WindowSelector* ws = ash::Shell::GetInstance()->
+        window_selector_controller()->window_selector_.get();
+    return ws->text_filter_widget_->GetNativeWindow()->layer()->
+        GetTargetTransform().IsIdentity();
+  }
+
   views::Widget* GetCloseButton(ash::WindowSelectorItem* window) {
     return window->close_button_.get();
   }
 
-  views::Widget* GetLabelWidget(ash::WindowSelectorItem* window) {
-    return window->window_label_.get();
+  views::Label* GetLabelView(ash::WindowSelectorItem* window) {
+    return window->window_label_view_;
   }
 
   // Tests that a window is contained within a given WindowSelectorItem, and
@@ -224,10 +238,22 @@ class WindowSelectorTest : public test::AshTestBase {
             GetCloseButton(window_item)->GetNativeView()))));
   }
 
+  void FilterItems(const base::StringPiece& pattern) {
+    ash::Shell::GetInstance()->
+        window_selector_controller()->window_selector_.get()->
+            ContentsChanged(NULL, base::UTF8ToUTF16(pattern));
+  }
+
   test::ShelfViewTestAPI* shelf_view_test() {
     return shelf_view_test_.get();
   }
 
+  views::Widget* text_filter_widget() {
+    return ash::Shell::GetInstance()->
+        window_selector_controller()->window_selector_.get()->
+            text_filter_widget_.get();
+  }
+
  private:
   aura::test::TestWindowDelegate delegate_;
   NonActivatableActivationDelegate non_activatable_activation_delegate_;
@@ -266,10 +292,10 @@ TEST_F(WindowSelectorTest, Basic) {
   // Hide the cursor before entering overview to test that it will be shown.
   aura::client::GetCursorClient(root_window)->HideCursor();
 
-  // In overview mode the windows should no longer overlap and focus should
-  // be removed from the window.
+  // In overview mode the windows should no longer overlap and the text filter
+  // widget should be focused.
   ToggleOverview();
-  EXPECT_EQ(NULL, GetFocusedWindow());
+  EXPECT_EQ(text_filter_widget()->GetNativeWindow(), GetFocusedWindow());
   EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get()));
   EXPECT_FALSE(WindowsOverlapping(window1.get(), panel1.get()));
   // Panels 1 and 2 should still be overlapping being in a single selector
@@ -294,9 +320,9 @@ TEST_F(WindowSelectorTest, BasicGesture) {
   wm::ActivateWindow(window1.get());
   EXPECT_EQ(window1.get(), GetFocusedWindow());
   ToggleOverview();
-  EXPECT_EQ(NULL, GetFocusedWindow());
-  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
-                                       window2.get());
+  EXPECT_EQ(text_filter_widget()->GetNativeWindow(), GetFocusedWindow());
+  ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
+                                     window2.get());
   generator.GestureTapAt(gfx::ToEnclosingRect(
       GetTransformedTargetBounds(window2.get())).CenterPoint());
   EXPECT_EQ(window2.get(), GetFocusedWindow());
@@ -351,7 +377,7 @@ TEST_F(WindowSelectorTest, CloseButton) {
   aura::Window* window2 = widget->GetNativeWindow();
   gfx::RectF bounds = GetTransformedBoundsInRootWindow(window2);
   gfx::Point point(bounds.top_right().x() - 1, bounds.top_right().y() - 1);
-  aura::test::EventGenerator event_generator(window2->GetRootWindow(), point);
+  ui::test::EventGenerator event_generator(window2->GetRootWindow(), point);
 
   EXPECT_FALSE(widget->IsClosed());
   event_generator.ClickLeftButton();
@@ -413,7 +439,7 @@ TEST_F(WindowSelectorTest, SelectingHidesAppList) {
   gfx::Rect bounds(0, 0, 400, 400);
   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
   scoped_ptr<aura::Window> window2(CreateWindow(bounds));
-  Shell::GetInstance()->ToggleAppList(NULL);
+  Shell::GetInstance()->ShowAppList(NULL);
   EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility());
   ToggleOverview();
   EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility());
@@ -432,15 +458,15 @@ TEST_F(WindowSelectorTest, DISABLED_MinimizedWindowVisibility) {
   EXPECT_FALSE(window1->IsVisible());
   EXPECT_FALSE(window1->layer()->GetTargetVisibility());
   {
-    ui::ScopedAnimationDurationScaleMode normal_duration_mode(
-        ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
+    ui::ScopedAnimationDurationScaleMode test_duration_mode(
+        ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
     ToggleOverview();
     EXPECT_TRUE(window1->IsVisible());
     EXPECT_TRUE(window1->layer()->GetTargetVisibility());
   }
   {
-    ui::ScopedAnimationDurationScaleMode normal_duration_mode(
-        ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
+    ui::ScopedAnimationDurationScaleMode test_duration_mode(
+        ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
     ToggleOverview();
     EXPECT_FALSE(window1->IsVisible());
     EXPECT_FALSE(window1->layer()->GetTargetVisibility());
@@ -502,9 +528,9 @@ TEST_F(WindowSelectorTest, CancelRestoresFocus) {
   wm::ActivateWindow(window.get());
   EXPECT_EQ(window.get(), GetFocusedWindow());
 
-  // In overview mode, focus should be removed.
+  // In overview mode, the text filter widget should be focused.
   ToggleOverview();
-  EXPECT_EQ(NULL, GetFocusedWindow());
+  EXPECT_EQ(text_filter_widget()->GetNativeWindow(), GetFocusedWindow());
 
   // If canceling overview mode, focus should be restored.
   ToggleOverview();
@@ -535,8 +561,8 @@ TEST_F(WindowSelectorTest, QuickReentryRestoresInitialTransform) {
   // animating when we reenter. We cannot short circuit animations for this but
   // we also don't have to wait for them to complete.
   {
-    ui::ScopedAnimationDurationScaleMode normal_duration_mode(
-        ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
+    ui::ScopedAnimationDurationScaleMode test_duration_mode(
+        ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
     ToggleOverview();
     ToggleOverview();
   }
@@ -747,24 +773,31 @@ TEST_F(WindowSelectorTest, DISABLED_DragDropInProgress) {
 TEST_F(WindowSelectorTest, CreateLabelUnderWindow) {
   scoped_ptr<aura::Window> window(CreateWindow(gfx::Rect(0, 0, 100, 100)));
   base::string16 window_title = base::UTF8ToUTF16("My window");
-  window->set_title(window_title);
+  window->SetTitle(window_title);
   ToggleOverview();
   WindowSelectorItem* window_item = GetWindowItemsForRoot(0).back();
-  views::Widget* widget = GetLabelWidget(window_item);
-  // Has the label widget been created?
-  ASSERT_TRUE(widget);
-  views::Label* label = static_cast<views::Label*>(widget->GetContentsView());
+  views::Label* label = GetLabelView(window_item);
+  // Has the label view been created?
+  ASSERT_TRUE(label);
+
   // Verify the label matches the window title.
   EXPECT_EQ(label->text(), window_title);
+
+  // Update the window title and check that the label is updated, too.
+  base::string16 updated_title = base::UTF8ToUTF16("Updated title");
+  window->SetTitle(updated_title);
+  EXPECT_EQ(label->text(), updated_title);
+
   // Labels are located based on target_bounds, not the actual window item
   // bounds.
   gfx::Rect target_bounds(window_item->target_bounds());
   gfx::Rect expected_label_bounds(target_bounds.x(),
-                                  target_bounds.bottom(),
+                                  target_bounds.bottom() - label->
+                                      GetPreferredSize().height(),
                                   target_bounds.width(),
                                   label->GetPreferredSize().height());
-  gfx::Rect real_label_bounds = widget->GetNativeWindow()->bounds();
-  EXPECT_EQ(widget->GetNativeWindow()->bounds(), real_label_bounds);
+  gfx::Rect real_label_bounds = label->GetWidget()->GetNativeWindow()->bounds();
+  EXPECT_EQ(real_label_bounds, expected_label_bounds);
 }
 
 // Tests that a label is created for the active panel in a group of panels in
@@ -774,17 +807,29 @@ TEST_F(WindowSelectorTest, CreateLabelUnderPanel) {
   scoped_ptr<aura::Window> panel2(CreatePanelWindow(gfx::Rect(0, 0, 100, 100)));
   base::string16 panel1_title = base::UTF8ToUTF16("My panel");
   base::string16 panel2_title = base::UTF8ToUTF16("Another panel");
-  panel1->set_title(panel1_title);
-  panel2->set_title(panel2_title);
+  base::string16 updated_panel1_title = base::UTF8ToUTF16("WebDriver Torso");
+  base::string16 updated_panel2_title = base::UTF8ToUTF16("Da panel");
+  panel1->SetTitle(panel1_title);
+  panel2->SetTitle(panel2_title);
   wm::ActivateWindow(panel1.get());
   ToggleOverview();
   WindowSelectorItem* window_item = GetWindowItemsForRoot(0).back();
-  views::Widget* widget = GetLabelWidget(window_item);
-  // Has the label widget been created?
-  ASSERT_TRUE(widget);
-  views::Label* label = static_cast<views::Label*>(widget->GetContentsView());
+  views::Label* label = GetLabelView(window_item);
+  // Has the label view been created?
+  ASSERT_TRUE(label);
+
   // Verify the label matches the active window title.
   EXPECT_EQ(label->text(), panel1_title);
+  // Verify that updating the title also updates the label.
+  panel1->SetTitle(updated_panel1_title);
+  EXPECT_EQ(label->text(), updated_panel1_title);
+  // After destroying the first panel, the label should match the second panel.
+  panel1.reset();
+  label = GetLabelView(window_item);
+  EXPECT_EQ(label->text(), panel2_title);
+  // Also test updating the title on the second panel.
+  panel2->SetTitle(updated_panel2_title);
+  EXPECT_EQ(label->text(), updated_panel2_title);
 }
 
 // Tests that overview updates the window positions if the display orientation
@@ -820,13 +865,28 @@ TEST_F(WindowSelectorTest, DisplayOrientationChanged) {
   }
 }
 
+// Tests traversing some windows in overview mode with the tab key.
+TEST_F(WindowSelectorTest, BasicTabKeyNavigation) {
+  gfx::Rect bounds(0, 0, 100, 100);
+  scoped_ptr<aura::Window> window2(CreateWindow(bounds));
+  scoped_ptr<aura::Window> window1(CreateWindow(bounds));
+  ToggleOverview();
+
+  SendKey(ui::VKEY_TAB);
+  EXPECT_EQ(GetSelectedWindow(), window1.get());
+  SendKey(ui::VKEY_TAB);
+  EXPECT_EQ(GetSelectedWindow(), window2.get());
+  SendKey(ui::VKEY_TAB);
+  EXPECT_EQ(GetSelectedWindow(), window1.get());
+}
+
 // Tests traversing some windows in overview mode with the arrow keys in every
 // possible direction.
 TEST_F(WindowSelectorTest, BasicArrowKeyNavigation) {
   if (!SupportsHostWindowResize())
     return;
-  const size_t test_windows = 7;
-  UpdateDisplay("400x300");
+  const size_t test_windows = 9;
+  UpdateDisplay("800x600");
   ScopedVector<aura::Window> windows;
   for (size_t i = test_windows; i > 0; i--)
     windows.push_back(CreateWindowWithId(gfx::Rect(0, 0, 100, 100), i));
@@ -837,29 +897,31 @@ TEST_F(WindowSelectorTest, BasicArrowKeyNavigation) {
       ui::VKEY_LEFT,
       ui::VKEY_UP
   };
-  // Expected window layout:
-  // +-------+  +-------+  +-------+
-  // |   1   |  |   2   |  |   3   |
-  // +-------+  +-------+  +-------+
-  // +-------+  +-------+  +-------+
-  // |   4   |  |   5   |  |   6   |
-  // +-------+  +-------+  +-------+
+  // Expected window layout, assuming that the text filtering feature is
+  // enabled by default (i.e., --ash-disable-text-filtering-in-overview-mode
+  // is not being used).
+  // +-------+  +-------+  +-------+  +-------+
+  // |   1   |  |   2   |  |   3   |  |   4   |
+  // +-------+  +-------+  +-------+  +-------+
+  // +-------+  +-------+  +-------+  +-------+
+  // |   5   |  |   6   |  |   7   |  |   8   |
+  // +-------+  +-------+  +-------+  +-------+
   // +-------+
-  // |   7   |
+  // |   9   |
   // +-------+
   // Index for each window during a full loop plus wrapping around.
   int index_path_for_direction[][test_windows + 1] = {
-      {1, 2, 3, 4, 5, 6, 7, 1},  // Right
-      {1, 4, 7, 2, 5, 3, 6, 1},  // Down
-      {7, 6, 5, 4, 3, 2, 1, 7},  // Left
-      {6, 3, 5, 2, 7, 4, 1, 6}   // Up
+      {1, 2, 3, 4, 5, 6, 7, 8, 9, 1},  // Right
+      {1, 5, 9, 2, 6, 3, 7, 4, 8, 1},  // Down
+      {9, 8, 7, 6, 5, 4, 3, 2, 1, 9},  // Left
+      {8, 4, 7, 3, 6, 2, 9, 5, 1, 8}   // Up
   };
 
   for (size_t key_index = 0; key_index < arraysize(arrow_keys); key_index++) {
     ToggleOverview();
     for (size_t i = 0; i < test_windows + 1; i++) {
       SendKey(arrow_keys[key_index]);
-      // TODO(nsatragno): Add a more readable error message by constructing a
+      // TODO(flackr): Add a more readable error message by constructing a
       // string from the window IDs.
       EXPECT_EQ(GetSelectedWindow()->id(),
                 index_path_for_direction[key_index][i]);
@@ -961,14 +1023,14 @@ TEST_F(WindowSelectorTest, CloseButtonOnPanels) {
   aura::Window* window2 = widget2->GetNativeWindow();
   base::string16 panel1_title = base::UTF8ToUTF16("Panel 1");
   base::string16 panel2_title = base::UTF8ToUTF16("Panel 2");
-  window1->set_title(panel1_title);
-  window2->set_title(panel2_title);
+  window1->SetTitle(panel1_title);
+  window2->SetTitle(panel2_title);
   wm::ActivateWindow(window1);
   ToggleOverview();
 
   gfx::RectF bounds1 = GetTransformedBoundsInRootWindow(window1);
   gfx::Point point1(bounds1.top_right().x() - 1, bounds1.top_right().y() - 1);
-  aura::test::EventGenerator event_generator1(window1->GetRootWindow(), point1);
+  ui::test::EventGenerator event_generator1(window1->GetRootWindow(), point1);
 
   EXPECT_FALSE(widget1->IsClosed());
   event_generator1.ClickLeftButton();
@@ -980,13 +1042,13 @@ TEST_F(WindowSelectorTest, CloseButtonOnPanels) {
   EXPECT_TRUE(window_item->Contains(window2));
   EXPECT_TRUE(GetCloseButton(window_item)->IsVisible());
 
-  views::Widget* widget = GetLabelWidget(window_item);
-  views::Label* label = static_cast<views::Label*>(widget->GetContentsView());
+
+  views::Label* label = GetLabelView(window_item);
   EXPECT_EQ(label->text(), panel2_title);
 
   gfx::RectF bounds2 = GetTransformedBoundsInRootWindow(window2);
   gfx::Point point2(bounds2.top_right().x() - 1, bounds2.top_right().y() - 1);
-  aura::test::EventGenerator event_generator2(window2->GetRootWindow(), point2);
+  ui::test::EventGenerator event_generator2(window2->GetRootWindow(), point2);
 
   EXPECT_FALSE(widget2->IsClosed());
   event_generator2.ClickLeftButton();
@@ -995,4 +1057,142 @@ TEST_F(WindowSelectorTest, CloseButtonOnPanels) {
   EXPECT_FALSE(IsSelecting());
 }
 
+// Creates three windows and tests filtering them by title.
+TEST_F(WindowSelectorTest, BasicTextFiltering) {
+  gfx::Rect bounds(0, 0, 100, 100);
+  scoped_ptr<aura::Window> window2(CreateWindow(bounds));
+  scoped_ptr<aura::Window> window1(CreateWindow(bounds));
+  scoped_ptr<aura::Window> window0(CreateWindow(bounds));
+  base::string16 window2_title = base::UTF8ToUTF16("Highway to test");
+  base::string16 window1_title = base::UTF8ToUTF16("For those about to test");
+  base::string16 window0_title = base::UTF8ToUTF16("We salute you");
+  window0->SetTitle(window0_title);
+  window1->SetTitle(window1_title);
+  window2->SetTitle(window2_title);
+  ToggleOverview();
+  EXPECT_FALSE(selection_widget_active());
+  EXPECT_FALSE(showing_filter_widget());
+  FilterItems("Test");
+
+  // The selection widget should appear when filtering starts, and should be
+  // selecting the first matching window.
+  EXPECT_TRUE(selection_widget_active());
+  EXPECT_TRUE(showing_filter_widget());
+  EXPECT_EQ(GetSelectedWindow(), window1.get());
+
+  // Window 0 has no "test" on it so it should be the only dimmed item.
+  std::vector<WindowSelectorItem*> items = GetWindowItemsForRoot(0);
+  EXPECT_TRUE(items[0]->dimmed());
+  EXPECT_FALSE(items[1]->dimmed());
+  EXPECT_FALSE(items[2]->dimmed());
+
+  // No items match the search.
+  FilterItems("I'm testing 'n testing");
+  EXPECT_TRUE(items[0]->dimmed());
+  EXPECT_TRUE(items[1]->dimmed());
+  EXPECT_TRUE(items[2]->dimmed());
+
+  // All the items should match the empty string. The filter widget should also
+  // disappear.
+  FilterItems("");
+  EXPECT_FALSE(showing_filter_widget());
+  EXPECT_FALSE(items[0]->dimmed());
+  EXPECT_FALSE(items[1]->dimmed());
+  EXPECT_FALSE(items[2]->dimmed());
+}
+
+// Tests selecting in the overview with dimmed and undimmed items.
+TEST_F(WindowSelectorTest, TextFilteringSelection) {
+  gfx::Rect bounds(0, 0, 100, 100);
+   scoped_ptr<aura::Window> window2(CreateWindow(bounds));
+   scoped_ptr<aura::Window> window1(CreateWindow(bounds));
+   scoped_ptr<aura::Window> window0(CreateWindow(bounds));
+   base::string16 window2_title = base::UTF8ToUTF16("Rock and roll");
+   base::string16 window1_title = base::UTF8ToUTF16("Rock and");
+   base::string16 window0_title = base::UTF8ToUTF16("Rock");
+   window0->SetTitle(window0_title);
+   window1->SetTitle(window1_title);
+   window2->SetTitle(window2_title);
+   ToggleOverview();
+   SendKey(ui::VKEY_RIGHT);
+   EXPECT_TRUE(selection_widget_active());
+   EXPECT_EQ(GetSelectedWindow(), window0.get());
+
+   // Dim the first item, the selection should jump to the next item.
+   std::vector<WindowSelectorItem*> items = GetWindowItemsForRoot(0);
+   FilterItems("Rock and");
+   EXPECT_EQ(GetSelectedWindow(), window1.get());
+
+   // Cycle the selection, the dimmed window should not be selected.
+   SendKey(ui::VKEY_RIGHT);
+   EXPECT_EQ(GetSelectedWindow(), window2.get());
+   SendKey(ui::VKEY_RIGHT);
+   EXPECT_EQ(GetSelectedWindow(), window1.get());
+
+   // Dimming all the items should hide the selection widget.
+   FilterItems("Pop");
+   EXPECT_FALSE(selection_widget_active());
+
+   // Undimming one window should automatically select it.
+   FilterItems("Rock and roll");
+   EXPECT_EQ(GetSelectedWindow(), window2.get());
+}
+
+// Tests clicking on the desktop itself to cancel overview mode.
+TEST_F(WindowSelectorTest, CancelOverviewOnMouseClick) {
+  // Overview disabled by default.
+  EXPECT_FALSE(IsSelecting());
+
+  // Point and bounds selected so that they don't intersect. This causes
+  // events located at the point to be passed to DesktopBackgroundController,
+  // and not the window.
+  gfx::Point point_in_background_page(0, 0);
+  gfx::Rect bounds(10, 10, 100, 100);
+  scoped_ptr<aura::Window> window1(CreateWindow(bounds));
+  ui::test::EventGenerator& generator = GetEventGenerator();
+  // Move mouse to point in the background page. Sending an event here will pass
+  // it to the DesktopBackgroundController in both regular and overview mode.
+  generator.MoveMouseTo(point_in_background_page);
+
+  // Clicking on the background page while not in overview should not toggle
+  // overview.
+  generator.ClickLeftButton();
+  EXPECT_FALSE(IsSelecting());
+
+  // Switch to overview mode.
+  ToggleOverview();
+  ASSERT_TRUE(IsSelecting());
+
+  // Click should now exit overview mode.
+  generator.ClickLeftButton();
+  EXPECT_FALSE(IsSelecting());
+}
+
+// Tests tapping on the desktop itself to cancel overview mode.
+TEST_F(WindowSelectorTest, CancelOverviewOnTap) {
+  // Overview disabled by default.
+  EXPECT_FALSE(IsSelecting());
+
+  // Point and bounds selected so that they don't intersect. This causes
+  // events located at the point to be passed to DesktopBackgroundController,
+  // and not the window.
+  gfx::Point point_in_background_page(0, 0);
+  gfx::Rect bounds(10, 10, 100, 100);
+  scoped_ptr<aura::Window> window1(CreateWindow(bounds));
+  ui::test::EventGenerator& generator = GetEventGenerator();
+
+  // Tapping on the background page while not in overview should not toggle
+  // overview.
+  generator.GestureTapAt(point_in_background_page);
+  EXPECT_FALSE(IsSelecting());
+
+  // Switch to overview mode.
+  ToggleOverview();
+  ASSERT_TRUE(IsSelecting());
+
+  // Tap should now exit overview mode.
+  generator.GestureTapAt(point_in_background_page);
+  EXPECT_FALSE(IsSelecting());
+}
+
 }  // namespace ash