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