blob: aebede49b07bf1833734531daa8e4e90c60246a7 [file] [log] [blame]
[email protected]df1c9862012-02-27 10:37:311// Copyright (c) 2012 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.
4
5#include "ash/focus_cycler.h"
6
7#include "ash/launcher/launcher.h"
[email protected]16059276d2012-10-22 18:59:508#include "ash/root_window_controller.h"
[email protected]478c6c32013-03-09 02:50:589#include "ash/shelf/shelf_widget.h"
[email protected]df1c9862012-02-27 10:37:3110#include "ash/shell.h"
11#include "ash/shell_window_ids.h"
[email protected]6d6546e2012-05-30 23:12:0212#include "ash/system/status_area_widget.h"
13#include "ash/system/status_area_widget_delegate.h"
[email protected]860f5942012-04-24 16:11:3914#include "ash/system/tray/system_tray.h"
[email protected]df1c9862012-02-27 10:37:3115#include "ash/wm/window_util.h"
16#include "ash/test/ash_test_base.h"
17#include "ash/shell_factory.h"
[email protected]242aa4f2013-04-30 01:04:0818#include "ui/aura/root_window.h"
19#include "ui/aura/test/event_generator.h"
[email protected]df1c9862012-02-27 10:37:3120#include "ui/aura/test/test_windows.h"
21#include "ui/aura/window.h"
[email protected]242aa4f2013-04-30 01:04:0822#include "ui/views/accessible_pane_view.h"
[email protected]df1c9862012-02-27 10:37:3123#include "ui/views/controls/button/menu_button.h"
24#include "ui/views/widget/widget.h"
25
26namespace ash {
27namespace test {
28
[email protected]df1c9862012-02-27 10:37:3129using aura::Window;
30using internal::FocusCycler;
31
[email protected]8676f0472012-03-29 20:30:1232namespace {
33
[email protected]6d6546e2012-05-30 23:12:0234internal::StatusAreaWidgetDelegate* GetStatusAreaWidgetDelegate(
35 views::Widget* widget) {
36 return static_cast<internal::StatusAreaWidgetDelegate*>(
[email protected]82157fb82012-04-11 22:07:4937 widget->GetContentsView());
[email protected]8676f0472012-03-29 20:30:1238}
39
[email protected]242aa4f2013-04-30 01:04:0840class PanedWidgetDelegate : public views::WidgetDelegate {
41 public:
42 PanedWidgetDelegate(views::Widget* widget) : widget_(widget) {}
43
44 void SetAccessiblePanes(const std::vector<views::View*>& panes) {
45 accessible_panes_ = panes;
46 }
47
48 // views::WidgetDelegate.
[email protected]8020c932013-05-07 06:24:2749 virtual void GetAccessiblePanes(std::vector<views::View*>* panes) OVERRIDE {
50 std::copy(accessible_panes_.begin(),
51 accessible_panes_.end(),
[email protected]242aa4f2013-04-30 01:04:0852 std::back_inserter(*panes));
53 }
54 virtual views::Widget* GetWidget() OVERRIDE {
55 return widget_;
56 };
57 virtual const views::Widget* GetWidget() const OVERRIDE {
58 return widget_;
59 }
60
61 private:
62 views::Widget* widget_;
63 std::vector<views::View*> accessible_panes_;
64};
65
[email protected]8676f0472012-03-29 20:30:1266} // namespace
67
[email protected]eb5a0ab2012-10-20 00:50:2568class FocusCyclerTest : public AshTestBase {
69 public:
70 FocusCyclerTest() {}
[email protected]df1c9862012-02-27 10:37:3171
[email protected]eb5a0ab2012-10-20 00:50:2572 virtual void SetUp() OVERRIDE {
73 AshTestBase::SetUp();
[email protected]df1c9862012-02-27 10:37:3174
[email protected]eb5a0ab2012-10-20 00:50:2575 focus_cycler_.reset(new FocusCycler());
76
77 ASSERT_TRUE(Launcher::ForPrimaryDisplay());
78 }
79
80 virtual void TearDown() OVERRIDE {
[email protected]7f7f65c2013-04-17 16:47:1381 if (tray_) {
[email protected]eb5a0ab2012-10-20 00:50:2582 GetStatusAreaWidgetDelegate(tray_->GetWidget())->
83 SetFocusCyclerForTesting(NULL);
84 tray_.reset();
85 }
86
[email protected]478c6c32013-03-09 02:50:5887 shelf_widget()->SetFocusCycler(NULL);
[email protected]eb5a0ab2012-10-20 00:50:2588
89 focus_cycler_.reset();
90
91 AshTestBase::TearDown();
92 }
93
94 protected:
95 // Creates the system tray, returning true on success.
96 bool CreateTray() {
[email protected]7f7f65c2013-04-17 16:47:1397 if (tray_)
[email protected]eb5a0ab2012-10-20 00:50:2598 return false;
[email protected]16059276d2012-10-22 18:59:5099 aura::Window* parent = Shell::GetPrimaryRootWindowController()->
100 GetContainer(ash::internal::kShellWindowId_StatusContainer);
101
102 internal::StatusAreaWidget* widget = new internal::StatusAreaWidget(parent);
[email protected]51ed5992012-11-07 10:14:39103 widget->CreateTrayViews();
[email protected]eb5a0ab2012-10-20 00:50:25104 widget->Show();
105 tray_.reset(widget->system_tray());
106 if (!tray_->GetWidget())
107 return false;
108 focus_cycler_->AddWidget(tray()->GetWidget());
109 GetStatusAreaWidgetDelegate(tray_->GetWidget())->SetFocusCyclerForTesting(
110 focus_cycler());
111 return true;
112 }
113
114 FocusCycler* focus_cycler() { return focus_cycler_.get(); }
115
116 SystemTray* tray() { return tray_.get(); }
117
[email protected]478c6c32013-03-09 02:50:58118 ShelfWidget* shelf_widget() {
119 return Launcher::ForPrimaryDisplay()->shelf_widget();
[email protected]eb5a0ab2012-10-20 00:50:25120 }
121
[email protected]478c6c32013-03-09 02:50:58122 void InstallFocusCycleOnShelf() {
123 // Add the shelf.
124 shelf_widget()->SetFocusCycler(focus_cycler());
[email protected]eb5a0ab2012-10-20 00:50:25125 }
126
127 private:
128 scoped_ptr<FocusCycler> focus_cycler_;
129 scoped_ptr<SystemTray> tray_;
130
131 DISALLOW_COPY_AND_ASSIGN(FocusCyclerTest);
132};
133
134TEST_F(FocusCyclerTest, CycleFocusBrowserOnly) {
[email protected]df1c9862012-02-27 10:37:31135 // Create a single test window.
[email protected]5ebe6102012-11-28 21:00:03136 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
[email protected]f3c7b252012-02-27 12:17:54137 wm::ActivateWindow(window0.get());
138 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
[email protected]df1c9862012-02-27 10:37:31139
140 // Cycle the window
[email protected]eb5a0ab2012-10-20 00:50:25141 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
[email protected]f3c7b252012-02-27 12:17:54142 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
[email protected]df1c9862012-02-27 10:37:31143}
144
[email protected]eb5a0ab2012-10-20 00:50:25145TEST_F(FocusCyclerTest, CycleFocusForward) {
146 ASSERT_TRUE(CreateTray());
[email protected]df1c9862012-02-27 10:37:31147
[email protected]478c6c32013-03-09 02:50:58148 InstallFocusCycleOnShelf();
[email protected]df1c9862012-02-27 10:37:31149
150 // Create a single test window.
[email protected]5ebe6102012-11-28 21:00:03151 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
[email protected]f3c7b252012-02-27 12:17:54152 wm::ActivateWindow(window0.get());
153 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
[email protected]df1c9862012-02-27 10:37:31154
[email protected]478c6c32013-03-09 02:50:58155 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25156 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
157 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]df1c9862012-02-27 10:37:31158
[email protected]478c6c32013-03-09 02:50:58159 // Cycle focus to the shelf.
[email protected]eb5a0ab2012-10-20 00:50:25160 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
[email protected]478c6c32013-03-09 02:50:58161 EXPECT_TRUE(shelf_widget()->IsActive());
[email protected]df1c9862012-02-27 10:37:31162
[email protected]478c6c32013-03-09 02:50:58163 // Cycle focus to the browser.
[email protected]eb5a0ab2012-10-20 00:50:25164 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
[email protected]f3c7b252012-02-27 12:17:54165 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
[email protected]df1c9862012-02-27 10:37:31166}
167
[email protected]eb5a0ab2012-10-20 00:50:25168TEST_F(FocusCyclerTest, CycleFocusBackward) {
169 ASSERT_TRUE(CreateTray());
[email protected]df1c9862012-02-27 10:37:31170
[email protected]478c6c32013-03-09 02:50:58171 InstallFocusCycleOnShelf();
[email protected]df1c9862012-02-27 10:37:31172
173 // Create a single test window.
[email protected]5ebe6102012-11-28 21:00:03174 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
[email protected]f3c7b252012-02-27 12:17:54175 wm::ActivateWindow(window0.get());
176 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
[email protected]df1c9862012-02-27 10:37:31177
[email protected]478c6c32013-03-09 02:50:58178 // Cycle focus to the shelf.
[email protected]eb5a0ab2012-10-20 00:50:25179 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
[email protected]478c6c32013-03-09 02:50:58180 EXPECT_TRUE(shelf_widget()->IsActive());
[email protected]df1c9862012-02-27 10:37:31181
[email protected]478c6c32013-03-09 02:50:58182 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25183 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
184 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]df1c9862012-02-27 10:37:31185
[email protected]478c6c32013-03-09 02:50:58186 // Cycle focus to the browser.
[email protected]eb5a0ab2012-10-20 00:50:25187 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
[email protected]f3c7b252012-02-27 12:17:54188 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
[email protected]df1c9862012-02-27 10:37:31189}
190
[email protected]eb5a0ab2012-10-20 00:50:25191TEST_F(FocusCyclerTest, CycleFocusForwardBackward) {
192 ASSERT_TRUE(CreateTray());
[email protected]ce711ac2012-06-14 07:05:41193
[email protected]478c6c32013-03-09 02:50:58194 InstallFocusCycleOnShelf();
[email protected]ce711ac2012-06-14 07:05:41195
196 // Create a single test window.
[email protected]5ebe6102012-11-28 21:00:03197 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
[email protected]ce711ac2012-06-14 07:05:41198 wm::ActivateWindow(window0.get());
199 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
200
[email protected]478c6c32013-03-09 02:50:58201 // Cycle focus to the shelf.
[email protected]eb5a0ab2012-10-20 00:50:25202 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
[email protected]478c6c32013-03-09 02:50:58203 EXPECT_TRUE(shelf_widget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41204
[email protected]478c6c32013-03-09 02:50:58205 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25206 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
207 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41208
[email protected]478c6c32013-03-09 02:50:58209 // Cycle focus to the browser.
[email protected]eb5a0ab2012-10-20 00:50:25210 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
[email protected]ce711ac2012-06-14 07:05:41211 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
212
[email protected]478c6c32013-03-09 02:50:58213 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25214 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
215 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41216
[email protected]478c6c32013-03-09 02:50:58217 // Cycle focus to the shelf.
[email protected]eb5a0ab2012-10-20 00:50:25218 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
[email protected]478c6c32013-03-09 02:50:58219 EXPECT_TRUE(shelf_widget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41220
[email protected]478c6c32013-03-09 02:50:58221 // Cycle focus to the browser.
[email protected]eb5a0ab2012-10-20 00:50:25222 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
[email protected]ce711ac2012-06-14 07:05:41223 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
224}
225
[email protected]eb5a0ab2012-10-20 00:50:25226TEST_F(FocusCyclerTest, CycleFocusNoBrowser) {
227 ASSERT_TRUE(CreateTray());
[email protected]ce711ac2012-06-14 07:05:41228
[email protected]478c6c32013-03-09 02:50:58229 InstallFocusCycleOnShelf();
[email protected]ce711ac2012-06-14 07:05:41230
[email protected]478c6c32013-03-09 02:50:58231 // Add the shelf and focus it.
232 focus_cycler()->FocusWidget(shelf_widget());
[email protected]ce711ac2012-06-14 07:05:41233
[email protected]478c6c32013-03-09 02:50:58234 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25235 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
236 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41237
[email protected]478c6c32013-03-09 02:50:58238 // Cycle focus to the shelf.
[email protected]eb5a0ab2012-10-20 00:50:25239 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
[email protected]478c6c32013-03-09 02:50:58240 EXPECT_TRUE(shelf_widget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41241
[email protected]478c6c32013-03-09 02:50:58242 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25243 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
244 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41245
[email protected]478c6c32013-03-09 02:50:58246 // Cycle focus to the shelf.
[email protected]eb5a0ab2012-10-20 00:50:25247 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
[email protected]478c6c32013-03-09 02:50:58248 EXPECT_TRUE(shelf_widget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41249
[email protected]478c6c32013-03-09 02:50:58250 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25251 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
252 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41253}
254
[email protected]478c6c32013-03-09 02:50:58255TEST_F(FocusCyclerTest, Shelf_CycleFocusForward) {
[email protected]eb5a0ab2012-10-20 00:50:25256 ASSERT_TRUE(CreateTray());
[email protected]478c6c32013-03-09 02:50:58257 InstallFocusCycleOnShelf();
258 shelf_widget()->Hide();
[email protected]057dc5752012-03-06 23:59:31259
260 // Create a single test window.
[email protected]5ebe6102012-11-28 21:00:03261 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
[email protected]057dc5752012-03-06 23:59:31262 wm::ActivateWindow(window0.get());
263 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
264
[email protected]478c6c32013-03-09 02:50:58265 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25266 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
267 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]057dc5752012-03-06 23:59:31268
[email protected]478c6c32013-03-09 02:50:58269 // Cycle focus to the browser.
[email protected]eb5a0ab2012-10-20 00:50:25270 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
[email protected]057dc5752012-03-06 23:59:31271 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
272}
273
[email protected]478c6c32013-03-09 02:50:58274TEST_F(FocusCyclerTest, Shelf_CycleFocusBackwardInvisible) {
[email protected]eb5a0ab2012-10-20 00:50:25275 ASSERT_TRUE(CreateTray());
[email protected]478c6c32013-03-09 02:50:58276 InstallFocusCycleOnShelf();
277 shelf_widget()->Hide();
[email protected]057dc5752012-03-06 23:59:31278
279 // Create a single test window.
[email protected]5ebe6102012-11-28 21:00:03280 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
[email protected]057dc5752012-03-06 23:59:31281 wm::ActivateWindow(window0.get());
282 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
283
[email protected]478c6c32013-03-09 02:50:58284 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25285 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
286 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]057dc5752012-03-06 23:59:31287
[email protected]478c6c32013-03-09 02:50:58288 // Cycle focus to the browser.
[email protected]eb5a0ab2012-10-20 00:50:25289 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
[email protected]057dc5752012-03-06 23:59:31290 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
291}
292
[email protected]242aa4f2013-04-30 01:04:08293TEST_F(FocusCyclerTest, CycleFocusThroughWindowWithPanes) {
294 ASSERT_TRUE(CreateTray());
295
296 InstallFocusCycleOnShelf();
297
298 scoped_ptr<views::Widget> browser_widget(new views::Widget);
299 PanedWidgetDelegate* test_widget_delegate =
300 new PanedWidgetDelegate(browser_widget.get());
301 views::Widget::InitParams widget_params(
302 views::Widget::InitParams::TYPE_WINDOW);
303 widget_params.context = CurrentContext();
304 widget_params.delegate = test_widget_delegate;
305 widget_params.ownership =
306 views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
307 browser_widget->Init(widget_params);
308 browser_widget->Show();
309
310 aura::Window* browser_window = browser_widget->GetNativeView();
311
312 views::View* root_view = browser_widget->GetRootView();
313
314 views::AccessiblePaneView* pane1 = new views::AccessiblePaneView();
315 root_view->AddChildView(pane1);
316
317 views::View* view1 = new views::View;
318 view1->set_focusable(true);
319 pane1->AddChildView(view1);
320
321 views::View* view2 = new views::View;
322 view2->set_focusable(true);
323 pane1->AddChildView(view2);
324
325 views::AccessiblePaneView* pane2 = new views::AccessiblePaneView();
326 root_view->AddChildView(pane2);
327
328 views::View* view3 = new views::View;
329 view3->set_focusable(true);
330 pane2->AddChildView(view3);
331
332 views::View* view4 = new views::View;
333 view4->set_focusable(true);
334 pane2->AddChildView(view4);
335
336 std::vector<views::View*> panes;
337 panes.push_back(pane1);
338 panes.push_back(pane2);
339
340 test_widget_delegate->SetAccessiblePanes(panes);
341
342 views::FocusManager* focus_manager = browser_widget->GetFocusManager();
343
344 // Cycle focus to the status area.
345 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
346 EXPECT_TRUE(tray()->GetWidget()->IsActive());
347
348 // Cycle focus to the shelf.
349 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
350 EXPECT_TRUE(shelf_widget()->IsActive());
351
352 // Cycle focus to the first pane in the browser.
353 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
354 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
355 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
356
357 // Cycle focus to the second pane in the browser.
358 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
359 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
360 EXPECT_EQ(focus_manager->GetFocusedView(), view3);
361
362 // Cycle focus back to the status area.
363 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
364 EXPECT_TRUE(tray()->GetWidget()->IsActive());
365
366 // Reverse direction - back to the second pane in the browser.
367 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
368 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
369 EXPECT_EQ(focus_manager->GetFocusedView(), view3);
370
371 // Back to the first pane in the browser.
372 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
373 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
374 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
375
376 // Back to the shelf.
377 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
378 EXPECT_TRUE(shelf_widget()->IsActive());
379
380 // Back to the status area.
381 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
382 EXPECT_TRUE(tray()->GetWidget()->IsActive());
383
384 // Pressing "Escape" while on the status area should
385 // deactivate it, and activate the browser window.
386 aura::RootWindow* root = Shell::GetPrimaryRootWindow();
387 aura::test::EventGenerator event_generator(root, root);
388 event_generator.PressKey(ui::VKEY_ESCAPE, 0);
389 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
390 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
391
392 // Similarly, pressing "Escape" while on the shelf.
393 // should do the same thing.
394 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
395 EXPECT_TRUE(shelf_widget()->IsActive());
396 event_generator.PressKey(ui::VKEY_ESCAPE, 0);
397 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
398 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
399}
400
[email protected]df1c9862012-02-27 10:37:31401} // namespace test
402} // namespace ash