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