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.
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"
61 class NonActivatableActivationDelegate
62 : public aura::client::ActivationDelegate
{
64 bool ShouldActivate() const override
{ return false; }
67 void CancelDrag(DragDropController
* controller
, bool* canceled
) {
68 if (controller
->IsDragDropInProgress()) {
70 controller
->DragCancel();
76 // TODO(bruthig): Move all non-simple method definitions out of class
78 class WindowSelectorTest
: public test::AshTestBase
{
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
));
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
);
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();
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
);
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
);
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(),
171 transform
.TransformRect(&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);
188 return ash::Shell::GetInstance()->window_selector_controller()->
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
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();
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
);
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
));
290 EXPECT_TRUE(WindowsOverlapping(window1
.get(), window2
.get()));
291 EXPECT_TRUE(WindowsOverlapping(panel1
.get(), panel2
.get()));
292 wm::ActivateWindow(window2
.get());
293 EXPECT_FALSE(wm::IsActiveWindow(window1
.get()));
294 EXPECT_TRUE(wm::IsActiveWindow(window2
.get()));
295 EXPECT_EQ(window2
.get(), GetFocusedWindow());
296 // Hide the cursor before entering overview to test that it will be shown.
297 aura::client::GetCursorClient(root_window
)->HideCursor();
299 // In overview mode the windows should no longer overlap and the text filter
300 // widget should be focused.
302 EXPECT_EQ(text_filter_widget()->GetNativeWindow(), GetFocusedWindow());
303 EXPECT_FALSE(WindowsOverlapping(window1
.get(), window2
.get()));
304 EXPECT_FALSE(WindowsOverlapping(window1
.get(), panel1
.get()));
305 EXPECT_FALSE(WindowsOverlapping(panel1
.get(), panel2
.get()));
307 // Clicking window 1 should activate it.
308 ClickWindow(window1
.get());
309 EXPECT_TRUE(wm::IsActiveWindow(window1
.get()));
310 EXPECT_FALSE(wm::IsActiveWindow(window2
.get()));
311 EXPECT_EQ(window1
.get(), GetFocusedWindow());
313 // Cursor should have been unlocked.
314 EXPECT_FALSE(aura::client::GetCursorClient(root_window
)->IsCursorLocked());
317 // Tests entering overview mode with docked windows
318 TEST_F(WindowSelectorTest
, BasicWithDocked
) {
319 // aura::Window* root_window = Shell::GetPrimaryRootWindow();
320 gfx::Rect
bounds(300, 0, 200, 200);
321 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
322 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds
));
323 scoped_ptr
<aura::Window
> docked1(CreateWindow(bounds
));
324 scoped_ptr
<aura::Window
> docked2(CreateWindow(bounds
));
326 wm::WMEvent
dock_event(wm::WM_EVENT_DOCK
);
327 wm::GetWindowState(docked1
.get())->OnWMEvent(&dock_event
);
329 wm::WindowState
* docked_state2
= wm::GetWindowState(docked2
.get());
330 docked_state2
->OnWMEvent(&dock_event
);
331 wm::WMEvent
minimize_event(wm::WM_EVENT_MINIMIZE
);
332 docked_state2
->OnWMEvent(&minimize_event
);
334 EXPECT_TRUE(WindowsOverlapping(window1
.get(), window2
.get()));
335 gfx::Rect docked_bounds
= docked1
->GetBoundsInScreen();
337 EXPECT_NE(bounds
.ToString(), docked_bounds
.ToString());
338 EXPECT_FALSE(WindowsOverlapping(window1
.get(), docked1
.get()));
339 EXPECT_FALSE(WindowsOverlapping(window1
.get(), docked2
.get()));
340 EXPECT_FALSE(docked2
->IsVisible());
342 EXPECT_EQ(wm::WINDOW_STATE_TYPE_DOCKED
,
343 wm::GetWindowState(docked1
.get())->GetStateType());
344 EXPECT_EQ(wm::WINDOW_STATE_TYPE_DOCKED_MINIMIZED
,
345 wm::GetWindowState(docked2
.get())->GetStateType());
349 EXPECT_FALSE(WindowsOverlapping(window1
.get(), window2
.get()));
350 // Docked windows stays the same.
351 EXPECT_EQ(docked_bounds
.ToString(), docked1
->GetBoundsInScreen().ToString());
352 EXPECT_FALSE(docked2
->IsVisible());
354 // Docked window can still be activated, which will exit the overview mode.
355 ClickWindow(docked1
.get());
356 EXPECT_TRUE(wm::IsActiveWindow(docked1
.get()));
358 ash::Shell::GetInstance()->window_selector_controller()->IsSelecting());
361 // Tests selecting a window by tapping on it.
362 TEST_F(WindowSelectorTest
, BasicGesture
) {
363 gfx::Rect
bounds(0, 0, 400, 400);
364 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
365 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds
));
366 wm::ActivateWindow(window1
.get());
367 EXPECT_EQ(window1
.get(), GetFocusedWindow());
369 EXPECT_EQ(text_filter_widget()->GetNativeWindow(), GetFocusedWindow());
370 ui::test::EventGenerator
generator(Shell::GetPrimaryRootWindow(),
372 generator
.GestureTapAt(gfx::ToEnclosingRect(
373 GetTransformedTargetBounds(window2
.get())).CenterPoint());
374 EXPECT_EQ(window2
.get(), GetFocusedWindow());
377 // Tests that we do not crash and overview mode remains engaged if the desktop
378 // is tapped while a finger is already down over a window.
379 TEST_F(WindowSelectorTest
, NoCrashWithDesktopTap
) {
380 scoped_ptr
<aura::Window
> window(CreateWindow(gfx::Rect(200, 300, 250, 450)));
385 gfx::ToEnclosingRect(GetTransformedBoundsInRootWindow(window
.get()));
386 ui::test::EventGenerator
event_generator(window
->GetRootWindow(),
387 bounds
.CenterPoint());
389 // Press down on the window.
390 const int kTouchId
= 19;
391 event_generator
.PressTouchId(kTouchId
);
393 // Tap on the desktop, which should not cause a crash. Overview mode should
395 event_generator
.GestureTapAt(gfx::Point(0, 0));
396 EXPECT_FALSE(IsSelecting());
398 event_generator
.ReleaseTouchId(kTouchId
);
401 // Tests that we do not crash and a window is selected when appropriate when
402 // we click on a window during touch.
403 TEST_F(WindowSelectorTest
, ClickOnWindowDuringTouch
) {
404 gfx::Rect
bounds(0, 0, 400, 400);
405 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
406 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds
));
407 wm::ActivateWindow(window2
.get());
408 EXPECT_FALSE(wm::IsActiveWindow(window1
.get()));
409 EXPECT_TRUE(wm::IsActiveWindow(window2
.get()));
413 gfx::Rect window1_bounds
=
414 gfx::ToEnclosingRect(GetTransformedBoundsInRootWindow(window1
.get()));
415 ui::test::EventGenerator
event_generator(window1
->GetRootWindow(),
416 window1_bounds
.CenterPoint());
418 // Clicking on |window2| while touching on |window1| should not cause a
419 // crash, overview mode should be disengaged and |window2| should be active.
420 const int kTouchId
= 19;
421 event_generator
.PressTouchId(kTouchId
);
422 event_generator
.MoveMouseToCenterOf(window2
.get());
423 event_generator
.ClickLeftButton();
424 EXPECT_FALSE(IsSelecting());
425 EXPECT_TRUE(wm::IsActiveWindow(window2
.get()));
426 event_generator
.ReleaseTouchId(kTouchId
);
430 // Clicking on |window1| while touching on |window1| should not cause
431 // a crash, overview mode should be disengaged, and |window1| should
433 event_generator
.MoveMouseToCenterOf(window1
.get());
434 event_generator
.PressTouchId(kTouchId
);
435 event_generator
.ClickLeftButton();
436 EXPECT_FALSE(IsSelecting());
437 EXPECT_TRUE(wm::IsActiveWindow(window1
.get()));
438 EXPECT_FALSE(wm::IsActiveWindow(window2
.get()));
439 event_generator
.ReleaseTouchId(kTouchId
);
442 // Tests that a window does not receive located events when in overview mode.
443 TEST_F(WindowSelectorTest
, WindowDoesNotReceiveEvents
) {
444 gfx::Rect
window_bounds(20, 10, 200, 300);
445 aura::Window
* root_window
= Shell::GetPrimaryRootWindow();
446 scoped_ptr
<aura::Window
> window(CreateWindow(window_bounds
));
448 gfx::Point
point1(window_bounds
.x() + 10, window_bounds
.y() + 10);
450 ui::MouseEvent
event1(ui::ET_MOUSE_PRESSED
, point1
, point1
,
451 ui::EventTimeForNow(), ui::EF_NONE
, ui::EF_NONE
);
453 ui::EventTarget
* root_target
= root_window
;
454 ui::EventTargeter
* targeter
= root_target
->GetEventTargeter();
456 // The event should target the window because we are still not in overview
458 EXPECT_EQ(window
, static_cast<aura::Window
*>(
459 targeter
->FindTargetForEvent(root_target
, &event1
)));
463 // The bounds have changed, take that into account.
464 gfx::RectF bounds
= GetTransformedBoundsInRootWindow(window
.get());
465 gfx::Point
point2(bounds
.x() + 10, bounds
.y() + 10);
466 ui::MouseEvent
event2(ui::ET_MOUSE_PRESSED
, point2
, point2
,
467 ui::EventTimeForNow(), ui::EF_NONE
, ui::EF_NONE
);
469 // Now the transparent window should be intercepting this event.
470 EXPECT_NE(window
, static_cast<aura::Window
*>(
471 targeter
->FindTargetForEvent(root_target
, &event2
)));
474 // Tests that clicking on the close button effectively closes the window.
475 TEST_F(WindowSelectorTest
, CloseButton
) {
476 scoped_ptr
<views::Widget
> widget
=
477 CreateWindowWidget(gfx::Rect(0, 0, 400, 400));
481 aura::Window
* window
= widget
->GetNativeWindow();
482 gfx::RectF bounds
= GetTransformedBoundsInRootWindow(window
);
483 gfx::Point
point(bounds
.top_right().x() - 1, bounds
.top_right().y() - 1);
484 ui::test::EventGenerator
event_generator(window
->GetRootWindow(), point
);
486 EXPECT_FALSE(widget
->IsClosed());
487 event_generator
.ClickLeftButton();
488 EXPECT_TRUE(widget
->IsClosed());
491 // Tests that clicking on the close button on a secondary display effectively
492 // closes the window.
493 TEST_F(WindowSelectorTest
, CloseButtonOnMultipleDisplay
) {
494 if (!SupportsMultipleDisplays())
497 UpdateDisplay("600x400,600x400");
498 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
500 scoped_ptr
<aura::Window
> window1(CreateWindow(gfx::Rect(650, 300, 250, 450)));
502 // We need a widget for the close button to work because windows are closed
503 // via the widget. We also use the widget to determine if the window has been
504 // closed or not. We explicity create the widget so that the window can be
505 // parented to a non-primary root window.
506 scoped_ptr
<views::Widget
> widget(new views::Widget
);
507 views::Widget::InitParams params
;
508 params
.bounds
= gfx::Rect(650, 0, 400, 400);
509 params
.ownership
= views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
510 params
.parent
= window1
->parent();
511 widget
->Init(params
);
514 ASSERT_EQ(root_windows
[1], window1
->GetRootWindow());
518 aura::Window
* window2
= widget
->GetNativeWindow();
519 gfx::RectF bounds
= GetTransformedBoundsInRootWindow(window2
);
520 gfx::Point
point(bounds
.top_right().x() - 1, bounds
.top_right().y() - 1);
521 ui::test::EventGenerator
event_generator(window2
->GetRootWindow(), point
);
523 EXPECT_FALSE(widget
->IsClosed());
524 event_generator
.ClickLeftButton();
525 EXPECT_TRUE(widget
->IsClosed());
528 // Tests entering overview mode with two windows and selecting one.
529 TEST_F(WindowSelectorTest
, FullscreenWindow
) {
530 gfx::Rect
bounds(0, 0, 400, 400);
531 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
532 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds
));
533 scoped_ptr
<aura::Window
> panel1(CreatePanelWindow(bounds
));
534 wm::ActivateWindow(window1
.get());
536 const wm::WMEvent
toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN
);
537 wm::GetWindowState(window1
.get())->OnWMEvent(&toggle_fullscreen_event
);
538 // The panel is hidden in fullscreen mode.
539 EXPECT_FALSE(panel1
->IsVisible());
540 EXPECT_TRUE(wm::GetWindowState(window1
.get())->IsFullscreen());
542 // Enter overview and select the fullscreen window.
545 // The panel becomes temporarily visible for the overview.
546 EXPECT_TRUE(panel1
->IsVisible());
547 ClickWindow(window1
.get());
549 // The window is still fullscreen as it was selected. The panel should again
551 EXPECT_TRUE(wm::GetWindowState(window1
.get())->IsFullscreen());
552 EXPECT_FALSE(panel1
->IsVisible());
554 // Entering overview and selecting another window, the previous window remains
556 // TODO(flackr): Currently the panel remains hidden, but should become visible
559 ClickWindow(window2
.get());
560 EXPECT_TRUE(wm::GetWindowState(window1
.get())->IsFullscreen());
563 // Tests that the shelf dimming state is removed while in overview and restored
564 // on exiting overview.
565 TEST_F(WindowSelectorTest
, OverviewUndimsShelf
) {
566 gfx::Rect
bounds(0, 0, 400, 400);
567 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
568 wm::WindowState
* window_state
= wm::GetWindowState(window1
.get());
569 window_state
->Maximize();
570 ash::ShelfWidget
* shelf
= Shell::GetPrimaryRootWindowController()->shelf();
571 EXPECT_TRUE(shelf
->GetDimsShelf());
573 EXPECT_FALSE(shelf
->GetDimsShelf());
575 EXPECT_TRUE(shelf
->GetDimsShelf());
578 // Tests that entering overview when a fullscreen window is active in maximized
579 // mode correctly applies the transformations to the window and correctly
580 // updates the window bounds on exiting overview mode: http://crbug.com/401664.
581 TEST_F(WindowSelectorTest
, FullscreenWindowMaximizeMode
) {
582 gfx::Rect
bounds(0, 0, 400, 400);
583 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
584 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds
));
585 Shell::GetInstance()->maximize_mode_controller()->
586 EnableMaximizeModeWindowManager(true);
587 wm::ActivateWindow(window2
.get());
588 wm::ActivateWindow(window1
.get());
589 gfx::Rect
normal_window_bounds(window1
->bounds());
590 const wm::WMEvent
toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN
);
591 wm::GetWindowState(window1
.get())->OnWMEvent(&toggle_fullscreen_event
);
592 gfx::Rect
fullscreen_window_bounds(window1
->bounds());
593 EXPECT_NE(normal_window_bounds
.ToString(),
594 fullscreen_window_bounds
.ToString());
595 EXPECT_EQ(fullscreen_window_bounds
.ToString(),
596 window2
->GetTargetBounds().ToString());
598 // Window 2 would normally resize to normal window bounds on showing the shelf
599 // for overview but this is deferred until overview is exited.
600 EXPECT_EQ(fullscreen_window_bounds
.ToString(),
601 window2
->GetTargetBounds().ToString());
602 EXPECT_FALSE(WindowsOverlapping(window1
.get(), window2
.get()));
605 // Since the fullscreen window is still active, window2 will still have the
607 EXPECT_EQ(fullscreen_window_bounds
.ToString(),
608 window2
->GetTargetBounds().ToString());
610 // Enter overview again and select window 2. Selecting window 2 should show
611 // the shelf bringing window2 back to the normal bounds.
613 ClickWindow(window2
.get());
614 EXPECT_EQ(normal_window_bounds
.ToString(),
615 window2
->GetTargetBounds().ToString());
618 // Tests that beginning window selection hides the app list.
619 TEST_F(WindowSelectorTest
, SelectingHidesAppList
) {
620 gfx::Rect
bounds(0, 0, 400, 400);
621 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
622 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds
));
623 Shell::GetInstance()->ShowAppList(nullptr);
624 EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility());
626 EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility());
630 // Tests that a minimized window's visibility and layer visibility is correctly
631 // changed when entering overview and restored when leaving overview mode.
632 // Crashes after the skia roll in http://crrev.com/274114.
633 // http://crbug.com/379570
634 TEST_F(WindowSelectorTest
, DISABLED_MinimizedWindowVisibility
) {
635 gfx::Rect
bounds(0, 0, 400, 400);
636 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
637 wm::WindowState
* window_state
= wm::GetWindowState(window1
.get());
638 window_state
->Minimize();
639 EXPECT_FALSE(window1
->IsVisible());
640 EXPECT_FALSE(window1
->layer()->GetTargetVisibility());
642 ui::ScopedAnimationDurationScaleMode
test_duration_mode(
643 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
645 EXPECT_TRUE(window1
->IsVisible());
646 EXPECT_TRUE(window1
->layer()->GetTargetVisibility());
649 ui::ScopedAnimationDurationScaleMode
test_duration_mode(
650 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
652 EXPECT_FALSE(window1
->IsVisible());
653 EXPECT_FALSE(window1
->layer()->GetTargetVisibility());
657 // Tests that a bounds change during overview is corrected for.
658 TEST_F(WindowSelectorTest
, BoundsChangeDuringOverview
) {
659 scoped_ptr
<aura::Window
> window(CreateWindow(gfx::Rect(0, 0, 400, 400)));
661 gfx::Rect overview_bounds
=
662 ToEnclosingRect(GetTransformedTargetBounds(window
.get()));
663 window
->SetBounds(gfx::Rect(200, 0, 200, 200));
664 gfx::Rect new_overview_bounds
=
665 ToEnclosingRect(GetTransformedTargetBounds(window
.get()));
666 EXPECT_EQ(overview_bounds
.x(), new_overview_bounds
.x());
667 EXPECT_EQ(overview_bounds
.y(), new_overview_bounds
.y());
668 EXPECT_EQ(overview_bounds
.width(), new_overview_bounds
.width());
669 EXPECT_EQ(overview_bounds
.height(), new_overview_bounds
.height());
673 // Tests that a newly created window aborts overview.
674 TEST_F(WindowSelectorTest
, NewWindowCancelsOveriew
) {
675 gfx::Rect
bounds(0, 0, 400, 400);
676 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
677 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds
));
679 EXPECT_TRUE(IsSelecting());
681 // A window being created should exit overview mode.
682 scoped_ptr
<aura::Window
> window3(CreateWindow(bounds
));
683 EXPECT_FALSE(IsSelecting());
686 // Tests that a window activation exits overview mode.
687 TEST_F(WindowSelectorTest
, ActivationCancelsOveriew
) {
688 gfx::Rect
bounds(0, 0, 400, 400);
689 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
690 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds
));
693 EXPECT_TRUE(IsSelecting());
695 // A window being activated should exit overview mode.
697 EXPECT_FALSE(IsSelecting());
699 // window1 should be focused after exiting even though window2 was focused on
700 // entering overview because we exited due to an activation.
701 EXPECT_EQ(window1
.get(), GetFocusedWindow());
704 // Tests that exiting overview mode without selecting a window restores focus
705 // to the previously focused window.
706 TEST_F(WindowSelectorTest
, CancelRestoresFocus
) {
707 gfx::Rect
bounds(0, 0, 400, 400);
708 scoped_ptr
<aura::Window
> window(CreateWindow(bounds
));
709 wm::ActivateWindow(window
.get());
710 EXPECT_EQ(window
.get(), GetFocusedWindow());
712 // In overview mode, the text filter widget should be focused.
714 EXPECT_EQ(text_filter_widget()->GetNativeWindow(), GetFocusedWindow());
716 // If canceling overview mode, focus should be restored.
718 EXPECT_EQ(window
.get(), GetFocusedWindow());
721 // Tests that overview mode is exited if the last remaining window is destroyed.
722 TEST_F(WindowSelectorTest
, LastWindowDestroyed
) {
723 gfx::Rect
bounds(0, 0, 400, 400);
724 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
725 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds
));
730 EXPECT_FALSE(IsSelecting());
733 // Tests that entering overview mode restores a window to its original
735 TEST_F(WindowSelectorTest
, QuickReentryRestoresInitialTransform
) {
736 gfx::Rect
bounds(0, 0, 400, 400);
737 scoped_ptr
<aura::Window
> window(CreateWindow(bounds
));
738 gfx::Rect initial_bounds
= ToEnclosingRect(
739 GetTransformedBounds(window
.get()));
741 // Quickly exit and reenter overview mode. The window should still be
742 // animating when we reenter. We cannot short circuit animations for this but
743 // we also don't have to wait for them to complete.
745 ui::ScopedAnimationDurationScaleMode
test_duration_mode(
746 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
750 EXPECT_NE(initial_bounds
, ToEnclosingRect(
751 GetTransformedTargetBounds(window
.get())));
753 EXPECT_FALSE(IsSelecting());
754 EXPECT_EQ(initial_bounds
, ToEnclosingRect(
755 GetTransformedTargetBounds(window
.get())));
758 // Tests that windows with modal child windows are transformed with the modal
759 // child even though not activatable themselves.
760 TEST_F(WindowSelectorTest
, ModalChild
) {
761 gfx::Rect
bounds(0, 0, 400, 400);
762 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
763 scoped_ptr
<aura::Window
> child1(CreateWindow(bounds
));
764 child1
->SetProperty(aura::client::kModalKey
, ui::MODAL_TYPE_WINDOW
);
765 ::wm::AddTransientChild(window1
.get(), child1
.get());
766 EXPECT_EQ(window1
->parent(), child1
->parent());
768 EXPECT_TRUE(window1
->IsVisible());
769 EXPECT_TRUE(child1
->IsVisible());
770 EXPECT_EQ(ToEnclosingRect(GetTransformedTargetBounds(child1
.get())),
771 ToEnclosingRect(GetTransformedTargetBounds(window1
.get())));
775 // Tests that clicking a modal window's parent activates the modal window in
777 TEST_F(WindowSelectorTest
, ClickModalWindowParent
) {
778 scoped_ptr
<aura::Window
> window1(CreateWindow(gfx::Rect(0, 0, 180, 180)));
779 scoped_ptr
<aura::Window
> child1(CreateWindow(gfx::Rect(200, 0, 180, 180)));
780 child1
->SetProperty(aura::client::kModalKey
, ui::MODAL_TYPE_WINDOW
);
781 ::wm::AddTransientChild(window1
.get(), child1
.get());
782 EXPECT_FALSE(WindowsOverlapping(window1
.get(), child1
.get()));
783 EXPECT_EQ(window1
->parent(), child1
->parent());
785 // Given that their relative positions are preserved, the windows should still
787 EXPECT_FALSE(WindowsOverlapping(window1
.get(), child1
.get()));
788 ClickWindow(window1
.get());
789 EXPECT_FALSE(IsSelecting());
791 // Clicking on window1 should activate child1.
792 EXPECT_TRUE(wm::IsActiveWindow(child1
.get()));
795 // Tests that windows remain on the display they are currently on in overview
796 // mode, and that the close buttons are on matching displays.
797 TEST_F(WindowSelectorTest
, MultipleDisplays
) {
798 if (!SupportsMultipleDisplays())
801 UpdateDisplay("600x400,600x400");
802 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
803 gfx::Rect
bounds1(0, 0, 400, 400);
804 gfx::Rect
bounds2(650, 0, 400, 400);
806 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds1
));
807 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds1
));
808 scoped_ptr
<aura::Window
> window3(CreateWindow(bounds2
));
809 scoped_ptr
<aura::Window
> window4(CreateWindow(bounds2
));
810 scoped_ptr
<aura::Window
> panel1(CreatePanelWindow(bounds1
));
811 scoped_ptr
<aura::Window
> panel2(CreatePanelWindow(bounds1
));
812 scoped_ptr
<aura::Window
> panel3(CreatePanelWindow(bounds2
));
813 scoped_ptr
<aura::Window
> panel4(CreatePanelWindow(bounds2
));
814 EXPECT_EQ(root_windows
[0], window1
->GetRootWindow());
815 EXPECT_EQ(root_windows
[0], window2
->GetRootWindow());
816 EXPECT_EQ(root_windows
[1], window3
->GetRootWindow());
817 EXPECT_EQ(root_windows
[1], window4
->GetRootWindow());
819 EXPECT_EQ(root_windows
[0], panel1
->GetRootWindow());
820 EXPECT_EQ(root_windows
[0], panel2
->GetRootWindow());
821 EXPECT_EQ(root_windows
[1], panel3
->GetRootWindow());
822 EXPECT_EQ(root_windows
[1], panel4
->GetRootWindow());
824 // In overview mode, each window remains in the same root window.
826 EXPECT_EQ(root_windows
[0], window1
->GetRootWindow());
827 EXPECT_EQ(root_windows
[0], window2
->GetRootWindow());
828 EXPECT_EQ(root_windows
[1], window3
->GetRootWindow());
829 EXPECT_EQ(root_windows
[1], window4
->GetRootWindow());
830 EXPECT_EQ(root_windows
[0], panel1
->GetRootWindow());
831 EXPECT_EQ(root_windows
[0], panel2
->GetRootWindow());
832 EXPECT_EQ(root_windows
[1], panel3
->GetRootWindow());
833 EXPECT_EQ(root_windows
[1], panel4
->GetRootWindow());
835 const std::vector
<WindowSelectorItem
*>& primary_window_items
=
836 GetWindowItemsForRoot(0);
837 const std::vector
<WindowSelectorItem
*>& secondary_window_items
=
838 GetWindowItemsForRoot(1);
840 // Window indices are based on top-down order. The reverse of our creation.
841 IsWindowAndCloseButtonInScreen(window1
.get(), primary_window_items
[3]);
842 IsWindowAndCloseButtonInScreen(window2
.get(), primary_window_items
[2]);
843 IsWindowAndCloseButtonInScreen(window3
.get(), secondary_window_items
[3]);
844 IsWindowAndCloseButtonInScreen(window4
.get(), secondary_window_items
[2]);
846 IsWindowAndCloseButtonInScreen(panel1
.get(), primary_window_items
[1]);
847 IsWindowAndCloseButtonInScreen(panel2
.get(), primary_window_items
[0]);
848 IsWindowAndCloseButtonInScreen(panel3
.get(), secondary_window_items
[1]);
849 IsWindowAndCloseButtonInScreen(panel4
.get(), secondary_window_items
[0]);
852 // Tests shutting down during overview.
853 TEST_F(WindowSelectorTest
, Shutdown
) {
854 gfx::Rect
bounds(0, 0, 400, 400);
855 // These windows will be deleted when the test exits and the Shell instance
857 aura::Window
* window1(CreateWindow(bounds
));
858 aura::Window
* window2(CreateWindow(bounds
));
859 aura::Window
* window3(CreatePanelWindow(bounds
));
860 aura::Window
* window4(CreatePanelWindow(bounds
));
862 wm::ActivateWindow(window4
);
863 wm::ActivateWindow(window3
);
864 wm::ActivateWindow(window2
);
865 wm::ActivateWindow(window1
);
870 // Tests removing a display during overview.
871 TEST_F(WindowSelectorTest
, RemoveDisplay
) {
872 if (!SupportsMultipleDisplays())
875 UpdateDisplay("400x400,400x400");
876 gfx::Rect
bounds1(0, 0, 100, 100);
877 gfx::Rect
bounds2(450, 0, 100, 100);
878 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds1
));
879 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds2
));
880 scoped_ptr
<aura::Window
> window3(CreatePanelWindow(bounds1
));
881 scoped_ptr
<aura::Window
> window4(CreatePanelWindow(bounds2
));
883 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
884 EXPECT_EQ(root_windows
[0], window1
->GetRootWindow());
885 EXPECT_EQ(root_windows
[1], window2
->GetRootWindow());
886 EXPECT_EQ(root_windows
[0], window3
->GetRootWindow());
887 EXPECT_EQ(root_windows
[1], window4
->GetRootWindow());
889 wm::ActivateWindow(window4
.get());
890 wm::ActivateWindow(window3
.get());
891 wm::ActivateWindow(window2
.get());
892 wm::ActivateWindow(window1
.get());
895 EXPECT_TRUE(IsSelecting());
896 UpdateDisplay("400x400");
897 EXPECT_FALSE(IsSelecting());
900 // Tests starting overview during a drag and drop tracking operation.
901 // TODO(flackr): Fix memory corruption crash when running locally (not failing
902 // on bots). See http://crbug.com/342528.
903 TEST_F(WindowSelectorTest
, DISABLED_DragDropInProgress
) {
904 bool drag_canceled_by_test
= false;
905 gfx::Rect
bounds(0, 0, 400, 400);
906 scoped_ptr
<aura::Window
> window(CreateWindow(bounds
));
907 test::ShellTestApi
shell_test_api(Shell::GetInstance());
908 ash::DragDropController
* drag_drop_controller
=
909 shell_test_api
.drag_drop_controller();
910 ui::OSExchangeData data
;
911 base::MessageLoopForUI::current()->PostTask(FROM_HERE
,
912 base::Bind(&WindowSelectorTest::ToggleOverview
,
913 base::Unretained(this)));
914 base::MessageLoopForUI::current()->PostTask(FROM_HERE
,
915 base::Bind(&CancelDrag
, drag_drop_controller
, &drag_canceled_by_test
));
916 data
.SetString(base::UTF8ToUTF16("I am being dragged"));
917 drag_drop_controller
->StartDragAndDrop(data
, window
->GetRootWindow(),
918 window
.get(), gfx::Point(5, 5), ui::DragDropTypes::DRAG_MOVE
,
919 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE
);
920 RunAllPendingInMessageLoop();
921 EXPECT_FALSE(drag_canceled_by_test
);
922 ASSERT_TRUE(IsSelecting());
923 RunAllPendingInMessageLoop();
926 // Test that a label is created under the window on entering overview mode.
927 TEST_F(WindowSelectorTest
, CreateLabelUnderWindow
) {
928 scoped_ptr
<aura::Window
> window(CreateWindow(gfx::Rect(0, 0, 100, 100)));
929 base::string16 window_title
= base::UTF8ToUTF16("My window");
930 window
->SetTitle(window_title
);
932 WindowSelectorItem
* window_item
= GetWindowItemsForRoot(0).back();
933 views::LabelButton
* label
= GetLabelButtonView(window_item
);
934 // Has the label view been created?
937 // Verify the label matches the window title.
938 EXPECT_EQ(label
->GetText(), window_title
);
940 // Update the window title and check that the label is updated, too.
941 base::string16 updated_title
= base::UTF8ToUTF16("Updated title");
942 window
->SetTitle(updated_title
);
943 EXPECT_EQ(label
->GetText(), updated_title
);
945 // Labels are located based on target_bounds, not the actual window item
947 gfx::Rect label_bounds
= label
->GetWidget()->GetNativeWindow()->bounds();
948 EXPECT_EQ(label_bounds
, window_item
->target_bounds());
951 // Tests that overview updates the window positions if the display orientation
953 TEST_F(WindowSelectorTest
, DisplayOrientationChanged
) {
954 if (!SupportsHostWindowResize())
957 aura::Window
* root_window
= Shell::GetInstance()->GetPrimaryRootWindow();
958 UpdateDisplay("600x200");
959 EXPECT_EQ("0,0 600x200", root_window
->bounds().ToString());
960 gfx::Rect
window_bounds(0, 0, 150, 150);
961 ScopedVector
<aura::Window
> windows
;
962 for (int i
= 0; i
< 3; i
++) {
963 windows
.push_back(CreateWindow(window_bounds
));
967 for (ScopedVector
<aura::Window
>::iterator iter
= windows
.begin();
968 iter
!= windows
.end(); ++iter
) {
969 EXPECT_TRUE(root_window
->bounds().Contains(
970 ToEnclosingRect(GetTransformedTargetBounds(*iter
))));
973 // Rotate the display, windows should be repositioned to be within the screen
975 UpdateDisplay("600x200/r");
976 EXPECT_EQ("0,0 200x600", root_window
->bounds().ToString());
977 for (ScopedVector
<aura::Window
>::iterator iter
= windows
.begin();
978 iter
!= windows
.end(); ++iter
) {
979 EXPECT_TRUE(root_window
->bounds().Contains(
980 ToEnclosingRect(GetTransformedTargetBounds(*iter
))));
984 // Tests traversing some windows in overview mode with the tab key.
985 TEST_F(WindowSelectorTest
, BasicTabKeyNavigation
) {
986 gfx::Rect
bounds(0, 0, 100, 100);
987 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds
));
988 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
991 SendKey(ui::VKEY_TAB
);
992 EXPECT_EQ(GetSelectedWindow(), window1
.get());
993 SendKey(ui::VKEY_TAB
);
994 EXPECT_EQ(GetSelectedWindow(), window2
.get());
995 SendKey(ui::VKEY_TAB
);
996 EXPECT_EQ(GetSelectedWindow(), window1
.get());
999 // Tests traversing some windows in overview mode with the arrow keys in every
1000 // possible direction.
1001 TEST_F(WindowSelectorTest
, BasicArrowKeyNavigation
) {
1002 if (!SupportsHostWindowResize())
1004 const size_t test_windows
= 9;
1005 UpdateDisplay("800x600");
1006 ScopedVector
<aura::Window
> windows
;
1007 for (size_t i
= test_windows
; i
> 0; i
--)
1008 windows
.push_back(CreateWindowWithId(gfx::Rect(0, 0, 100, 100), i
));
1010 ui::KeyboardCode arrow_keys
[] = {
1016 // Expected window layout, assuming that the text filtering feature is
1017 // enabled by default (i.e., --ash-disable-text-filtering-in-overview-mode
1018 // is not being used).
1019 // +-------+ +-------+ +-------+ +-------+
1020 // | 1 | | 2 | | 3 | | 4 |
1021 // +-------+ +-------+ +-------+ +-------+
1022 // +-------+ +-------+ +-------+ +-------+
1023 // | 5 | | 6 | | 7 | | 8 |
1024 // +-------+ +-------+ +-------+ +-------+
1028 // Index for each window during a full loop plus wrapping around.
1029 int index_path_for_direction
[][test_windows
+ 1] = {
1030 {1, 2, 3, 4, 5, 6, 7, 8, 9, 1}, // Right
1031 {1, 5, 9, 2, 6, 3, 7, 4, 8, 1}, // Down
1032 {9, 8, 7, 6, 5, 4, 3, 2, 1, 9}, // Left
1033 {8, 4, 7, 3, 6, 2, 9, 5, 1, 8} // Up
1036 for (size_t key_index
= 0; key_index
< arraysize(arrow_keys
); key_index
++) {
1038 for (size_t i
= 0; i
< test_windows
+ 1; i
++) {
1039 SendKey(arrow_keys
[key_index
]);
1040 // TODO(flackr): Add a more readable error message by constructing a
1041 // string from the window IDs.
1042 EXPECT_EQ(GetSelectedWindow()->id(),
1043 index_path_for_direction
[key_index
][i
]);
1049 // Tests basic selection across multiple monitors.
1050 TEST_F(WindowSelectorTest
, BasicMultiMonitorArrowKeyNavigation
) {
1051 if (!SupportsMultipleDisplays())
1054 UpdateDisplay("400x400,400x400");
1055 gfx::Rect
bounds1(0, 0, 100, 100);
1056 gfx::Rect
bounds2(450, 0, 100, 100);
1057 scoped_ptr
<aura::Window
> window4(CreateWindow(bounds2
));
1058 scoped_ptr
<aura::Window
> window3(CreateWindow(bounds2
));
1059 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds1
));
1060 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds1
));
1065 SendKey(ui::VKEY_RIGHT
);
1066 EXPECT_EQ(GetSelectedWindow(), window1
.get());
1067 SendKey(ui::VKEY_RIGHT
);
1068 EXPECT_EQ(GetSelectedWindow(), window2
.get());
1069 SendKey(ui::VKEY_RIGHT
);
1070 EXPECT_EQ(GetSelectedWindow(), window3
.get());
1071 SendKey(ui::VKEY_RIGHT
);
1072 EXPECT_EQ(GetSelectedWindow(), window4
.get());
1075 // Tests selecting a window in overview mode with the return key.
1076 TEST_F(WindowSelectorTest
, SelectWindowWithReturnKey
) {
1077 gfx::Rect
bounds(0, 0, 100, 100);
1078 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds
));
1079 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
1082 // Pressing the return key without a selection widget should not do anything.
1083 SendKey(ui::VKEY_RETURN
);
1084 EXPECT_TRUE(IsSelecting());
1086 // Select the first window.
1087 SendKey(ui::VKEY_RIGHT
);
1088 SendKey(ui::VKEY_RETURN
);
1089 ASSERT_FALSE(IsSelecting());
1090 EXPECT_TRUE(wm::IsActiveWindow(window1
.get()));
1092 // Select the second window.
1094 SendKey(ui::VKEY_RIGHT
);
1095 SendKey(ui::VKEY_RIGHT
);
1096 SendKey(ui::VKEY_RETURN
);
1097 EXPECT_FALSE(IsSelecting());
1098 EXPECT_TRUE(wm::IsActiveWindow(window2
.get()));
1101 // Tests that overview mode hides the callout widget.
1102 TEST_F(WindowSelectorTest
, WindowOverviewHidesCalloutWidgets
) {
1103 scoped_ptr
<aura::Window
> panel1(CreatePanelWindow(gfx::Rect(0, 0, 100, 100)));
1104 scoped_ptr
<aura::Window
> panel2(CreatePanelWindow(gfx::Rect(0, 0, 100, 100)));
1105 PanelLayoutManager
* panel_manager
=
1106 static_cast<PanelLayoutManager
*>(panel1
->parent()->layout_manager());
1108 // By default, panel callout widgets are visible.
1110 panel_manager
->GetCalloutWidgetForPanel(panel1
.get())->IsVisible());
1112 panel_manager
->GetCalloutWidgetForPanel(panel2
.get())->IsVisible());
1114 // Toggling the overview should hide the callout widgets.
1117 panel_manager
->GetCalloutWidgetForPanel(panel1
.get())->IsVisible());
1119 panel_manager
->GetCalloutWidgetForPanel(panel2
.get())->IsVisible());
1121 // Ending the overview should show them again.
1124 panel_manager
->GetCalloutWidgetForPanel(panel1
.get())->IsVisible());
1126 panel_manager
->GetCalloutWidgetForPanel(panel2
.get())->IsVisible());
1129 // Creates three windows and tests filtering them by title.
1130 TEST_F(WindowSelectorTest
, BasicTextFiltering
) {
1131 gfx::Rect
bounds(0, 0, 100, 100);
1132 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds
));
1133 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
1134 scoped_ptr
<aura::Window
> window0(CreateWindow(bounds
));
1135 base::string16 window2_title
= base::UTF8ToUTF16("Highway to test");
1136 base::string16 window1_title
= base::UTF8ToUTF16("For those about to test");
1137 base::string16 window0_title
= base::UTF8ToUTF16("We salute you");
1138 window0
->SetTitle(window0_title
);
1139 window1
->SetTitle(window1_title
);
1140 window2
->SetTitle(window2_title
);
1142 EXPECT_FALSE(selection_widget_active());
1143 EXPECT_FALSE(showing_filter_widget());
1144 FilterItems("Test");
1146 // The selection widget should appear when filtering starts, and should be
1147 // selecting the first matching window.
1148 EXPECT_TRUE(selection_widget_active());
1149 EXPECT_TRUE(showing_filter_widget());
1150 EXPECT_EQ(GetSelectedWindow(), window1
.get());
1152 // Window 0 has no "test" on it so it should be the only dimmed item.
1153 std::vector
<WindowSelectorItem
*> items
= GetWindowItemsForRoot(0);
1154 EXPECT_TRUE(items
[0]->dimmed());
1155 EXPECT_FALSE(items
[1]->dimmed());
1156 EXPECT_FALSE(items
[2]->dimmed());
1158 // No items match the search.
1159 FilterItems("I'm testing 'n testing");
1160 EXPECT_TRUE(items
[0]->dimmed());
1161 EXPECT_TRUE(items
[1]->dimmed());
1162 EXPECT_TRUE(items
[2]->dimmed());
1164 // All the items should match the empty string. The filter widget should also
1167 EXPECT_FALSE(showing_filter_widget());
1168 EXPECT_FALSE(items
[0]->dimmed());
1169 EXPECT_FALSE(items
[1]->dimmed());
1170 EXPECT_FALSE(items
[2]->dimmed());
1173 // Tests selecting in the overview with dimmed and undimmed items.
1174 TEST_F(WindowSelectorTest
, TextFilteringSelection
) {
1175 gfx::Rect
bounds(0, 0, 100, 100);
1176 scoped_ptr
<aura::Window
> window2(CreateWindow(bounds
));
1177 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
1178 scoped_ptr
<aura::Window
> window0(CreateWindow(bounds
));
1179 base::string16 window2_title
= base::UTF8ToUTF16("Rock and roll");
1180 base::string16 window1_title
= base::UTF8ToUTF16("Rock and");
1181 base::string16 window0_title
= base::UTF8ToUTF16("Rock");
1182 window0
->SetTitle(window0_title
);
1183 window1
->SetTitle(window1_title
);
1184 window2
->SetTitle(window2_title
);
1186 SendKey(ui::VKEY_RIGHT
);
1187 EXPECT_TRUE(selection_widget_active());
1188 EXPECT_EQ(GetSelectedWindow(), window0
.get());
1190 // Dim the first item, the selection should jump to the next item.
1191 std::vector
<WindowSelectorItem
*> items
= GetWindowItemsForRoot(0);
1192 FilterItems("Rock and");
1193 EXPECT_EQ(GetSelectedWindow(), window1
.get());
1195 // Cycle the selection, the dimmed window should not be selected.
1196 SendKey(ui::VKEY_RIGHT
);
1197 EXPECT_EQ(GetSelectedWindow(), window2
.get());
1198 SendKey(ui::VKEY_RIGHT
);
1199 EXPECT_EQ(GetSelectedWindow(), window1
.get());
1201 // Dimming all the items should hide the selection widget.
1203 EXPECT_FALSE(selection_widget_active());
1205 // Undimming one window should automatically select it.
1206 FilterItems("Rock and roll");
1207 EXPECT_EQ(GetSelectedWindow(), window2
.get());
1210 // Tests clicking on the desktop itself to cancel overview mode.
1211 TEST_F(WindowSelectorTest
, CancelOverviewOnMouseClick
) {
1212 // Overview disabled by default.
1213 EXPECT_FALSE(IsSelecting());
1215 // Point and bounds selected so that they don't intersect. This causes
1216 // events located at the point to be passed to DesktopBackgroundController,
1217 // and not the window.
1218 gfx::Point
point_in_background_page(0, 0);
1219 gfx::Rect
bounds(10, 10, 100, 100);
1220 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
1221 ui::test::EventGenerator
& generator
= GetEventGenerator();
1222 // Move mouse to point in the background page. Sending an event here will pass
1223 // it to the DesktopBackgroundController in both regular and overview mode.
1224 generator
.MoveMouseTo(point_in_background_page
);
1226 // Clicking on the background page while not in overview should not toggle
1228 generator
.ClickLeftButton();
1229 EXPECT_FALSE(IsSelecting());
1231 // Switch to overview mode.
1233 ASSERT_TRUE(IsSelecting());
1235 // Click should now exit overview mode.
1236 generator
.ClickLeftButton();
1237 EXPECT_FALSE(IsSelecting());
1240 // Tests tapping on the desktop itself to cancel overview mode.
1241 TEST_F(WindowSelectorTest
, CancelOverviewOnTap
) {
1242 // Overview disabled by default.
1243 EXPECT_FALSE(IsSelecting());
1245 // Point and bounds selected so that they don't intersect. This causes
1246 // events located at the point to be passed to DesktopBackgroundController,
1247 // and not the window.
1248 gfx::Point
point_in_background_page(0, 0);
1249 gfx::Rect
bounds(10, 10, 100, 100);
1250 scoped_ptr
<aura::Window
> window1(CreateWindow(bounds
));
1251 ui::test::EventGenerator
& generator
= GetEventGenerator();
1253 // Tapping on the background page while not in overview should not toggle
1255 generator
.GestureTapAt(point_in_background_page
);
1256 EXPECT_FALSE(IsSelecting());
1258 // Switch to overview mode.
1260 ASSERT_TRUE(IsSelecting());
1262 // Tap should now exit overview mode.
1263 generator
.GestureTapAt(point_in_background_page
);
1264 EXPECT_FALSE(IsSelecting());