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