blob: 5854f8ddcdf4d03d420c4e2e70b0b4b83603275b [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.
49 virtual void GetAccessiblePanes(std::vector<views::View*>* panes) {
50 std::copy(accessible_panes_.begin(), accessible_panes_.end(),
51 std::back_inserter(*panes));
52 }
53 virtual views::Widget* GetWidget() OVERRIDE {
54 return widget_;
55 };
56 virtual const views::Widget* GetWidget() const OVERRIDE {
57 return widget_;
58 }
59
60 private:
61 views::Widget* widget_;
62 std::vector<views::View*> accessible_panes_;
63};
64
[email protected]8676f0472012-03-29 20:30:1265} // namespace
66
[email protected]eb5a0ab2012-10-20 00:50:2567class FocusCyclerTest : public AshTestBase {
68 public:
69 FocusCyclerTest() {}
[email protected]df1c9862012-02-27 10:37:3170
[email protected]eb5a0ab2012-10-20 00:50:2571 virtual void SetUp() OVERRIDE {
72 AshTestBase::SetUp();
[email protected]df1c9862012-02-27 10:37:3173
[email protected]eb5a0ab2012-10-20 00:50:2574 focus_cycler_.reset(new FocusCycler());
75
76 ASSERT_TRUE(Launcher::ForPrimaryDisplay());
77 }
78
79 virtual void TearDown() OVERRIDE {
[email protected]7f7f65c2013-04-17 16:47:1380 if (tray_) {
[email protected]eb5a0ab2012-10-20 00:50:2581 GetStatusAreaWidgetDelegate(tray_->GetWidget())->
82 SetFocusCyclerForTesting(NULL);
83 tray_.reset();
84 }
85
[email protected]478c6c32013-03-09 02:50:5886 shelf_widget()->SetFocusCycler(NULL);
[email protected]eb5a0ab2012-10-20 00:50:2587
88 focus_cycler_.reset();
89
90 AshTestBase::TearDown();
91 }
92
93 protected:
94 // Creates the system tray, returning true on success.
95 bool CreateTray() {
[email protected]7f7f65c2013-04-17 16:47:1396 if (tray_)
[email protected]eb5a0ab2012-10-20 00:50:2597 return false;
[email protected]16059276d2012-10-22 18:59:5098 aura::Window* parent = Shell::GetPrimaryRootWindowController()->
99 GetContainer(ash::internal::kShellWindowId_StatusContainer);
100
101 internal::StatusAreaWidget* widget = new internal::StatusAreaWidget(parent);
[email protected]51ed5992012-11-07 10:14:39102 widget->CreateTrayViews();
[email protected]eb5a0ab2012-10-20 00:50:25103 widget->Show();
104 tray_.reset(widget->system_tray());
105 if (!tray_->GetWidget())
106 return false;
107 focus_cycler_->AddWidget(tray()->GetWidget());
108 GetStatusAreaWidgetDelegate(tray_->GetWidget())->SetFocusCyclerForTesting(
109 focus_cycler());
110 return true;
111 }
112
113 FocusCycler* focus_cycler() { return focus_cycler_.get(); }
114
115 SystemTray* tray() { return tray_.get(); }
116
[email protected]478c6c32013-03-09 02:50:58117 ShelfWidget* shelf_widget() {
118 return Launcher::ForPrimaryDisplay()->shelf_widget();
[email protected]eb5a0ab2012-10-20 00:50:25119 }
120
[email protected]478c6c32013-03-09 02:50:58121 void InstallFocusCycleOnShelf() {
122 // Add the shelf.
123 shelf_widget()->SetFocusCycler(focus_cycler());
[email protected]eb5a0ab2012-10-20 00:50:25124 }
125
126 private:
127 scoped_ptr<FocusCycler> focus_cycler_;
128 scoped_ptr<SystemTray> tray_;
129
130 DISALLOW_COPY_AND_ASSIGN(FocusCyclerTest);
131};
132
133TEST_F(FocusCyclerTest, CycleFocusBrowserOnly) {
[email protected]df1c9862012-02-27 10:37:31134 // Create a single test window.
[email protected]5ebe6102012-11-28 21:00:03135 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
[email protected]f3c7b252012-02-27 12:17:54136 wm::ActivateWindow(window0.get());
137 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
[email protected]df1c9862012-02-27 10:37:31138
139 // Cycle the window
[email protected]eb5a0ab2012-10-20 00:50:25140 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
[email protected]f3c7b252012-02-27 12:17:54141 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
[email protected]df1c9862012-02-27 10:37:31142}
143
[email protected]eb5a0ab2012-10-20 00:50:25144TEST_F(FocusCyclerTest, CycleFocusForward) {
145 ASSERT_TRUE(CreateTray());
[email protected]df1c9862012-02-27 10:37:31146
[email protected]478c6c32013-03-09 02:50:58147 InstallFocusCycleOnShelf();
[email protected]df1c9862012-02-27 10:37:31148
149 // Create a single test window.
[email protected]5ebe6102012-11-28 21:00:03150 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
[email protected]f3c7b252012-02-27 12:17:54151 wm::ActivateWindow(window0.get());
152 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
[email protected]df1c9862012-02-27 10:37:31153
[email protected]478c6c32013-03-09 02:50:58154 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25155 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
156 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]df1c9862012-02-27 10:37:31157
[email protected]478c6c32013-03-09 02:50:58158 // Cycle focus to the shelf.
[email protected]eb5a0ab2012-10-20 00:50:25159 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
[email protected]478c6c32013-03-09 02:50:58160 EXPECT_TRUE(shelf_widget()->IsActive());
[email protected]df1c9862012-02-27 10:37:31161
[email protected]478c6c32013-03-09 02:50:58162 // Cycle focus to the browser.
[email protected]eb5a0ab2012-10-20 00:50:25163 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
[email protected]f3c7b252012-02-27 12:17:54164 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
[email protected]df1c9862012-02-27 10:37:31165}
166
[email protected]eb5a0ab2012-10-20 00:50:25167TEST_F(FocusCyclerTest, CycleFocusBackward) {
168 ASSERT_TRUE(CreateTray());
[email protected]df1c9862012-02-27 10:37:31169
[email protected]478c6c32013-03-09 02:50:58170 InstallFocusCycleOnShelf();
[email protected]df1c9862012-02-27 10:37:31171
172 // Create a single test window.
[email protected]5ebe6102012-11-28 21:00:03173 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
[email protected]f3c7b252012-02-27 12:17:54174 wm::ActivateWindow(window0.get());
175 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
[email protected]df1c9862012-02-27 10:37:31176
[email protected]478c6c32013-03-09 02:50:58177 // Cycle focus to the shelf.
[email protected]eb5a0ab2012-10-20 00:50:25178 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
[email protected]478c6c32013-03-09 02:50:58179 EXPECT_TRUE(shelf_widget()->IsActive());
[email protected]df1c9862012-02-27 10:37:31180
[email protected]478c6c32013-03-09 02:50:58181 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25182 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
183 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]df1c9862012-02-27 10:37:31184
[email protected]478c6c32013-03-09 02:50:58185 // Cycle focus to the browser.
[email protected]eb5a0ab2012-10-20 00:50:25186 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
[email protected]f3c7b252012-02-27 12:17:54187 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
[email protected]df1c9862012-02-27 10:37:31188}
189
[email protected]eb5a0ab2012-10-20 00:50:25190TEST_F(FocusCyclerTest, CycleFocusForwardBackward) {
191 ASSERT_TRUE(CreateTray());
[email protected]ce711ac2012-06-14 07:05:41192
[email protected]478c6c32013-03-09 02:50:58193 InstallFocusCycleOnShelf();
[email protected]ce711ac2012-06-14 07:05:41194
195 // Create a single test window.
[email protected]5ebe6102012-11-28 21:00:03196 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
[email protected]ce711ac2012-06-14 07:05:41197 wm::ActivateWindow(window0.get());
198 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
199
[email protected]478c6c32013-03-09 02:50:58200 // Cycle focus to the shelf.
[email protected]eb5a0ab2012-10-20 00:50:25201 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
[email protected]478c6c32013-03-09 02:50:58202 EXPECT_TRUE(shelf_widget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41203
[email protected]478c6c32013-03-09 02:50:58204 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25205 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
206 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41207
[email protected]478c6c32013-03-09 02:50:58208 // Cycle focus to the browser.
[email protected]eb5a0ab2012-10-20 00:50:25209 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
[email protected]ce711ac2012-06-14 07:05:41210 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
211
[email protected]478c6c32013-03-09 02:50:58212 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25213 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
214 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41215
[email protected]478c6c32013-03-09 02:50:58216 // Cycle focus to the shelf.
[email protected]eb5a0ab2012-10-20 00:50:25217 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
[email protected]478c6c32013-03-09 02:50:58218 EXPECT_TRUE(shelf_widget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41219
[email protected]478c6c32013-03-09 02:50:58220 // Cycle focus to the browser.
[email protected]eb5a0ab2012-10-20 00:50:25221 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
[email protected]ce711ac2012-06-14 07:05:41222 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
223}
224
[email protected]eb5a0ab2012-10-20 00:50:25225TEST_F(FocusCyclerTest, CycleFocusNoBrowser) {
226 ASSERT_TRUE(CreateTray());
[email protected]ce711ac2012-06-14 07:05:41227
[email protected]478c6c32013-03-09 02:50:58228 InstallFocusCycleOnShelf();
[email protected]ce711ac2012-06-14 07:05:41229
[email protected]478c6c32013-03-09 02:50:58230 // Add the shelf and focus it.
231 focus_cycler()->FocusWidget(shelf_widget());
[email protected]ce711ac2012-06-14 07:05:41232
[email protected]478c6c32013-03-09 02:50:58233 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25234 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
235 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41236
[email protected]478c6c32013-03-09 02:50:58237 // Cycle focus to the shelf.
[email protected]eb5a0ab2012-10-20 00:50:25238 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
[email protected]478c6c32013-03-09 02:50:58239 EXPECT_TRUE(shelf_widget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41240
[email protected]478c6c32013-03-09 02:50:58241 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25242 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
243 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41244
[email protected]478c6c32013-03-09 02:50:58245 // Cycle focus to the shelf.
[email protected]eb5a0ab2012-10-20 00:50:25246 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
[email protected]478c6c32013-03-09 02:50:58247 EXPECT_TRUE(shelf_widget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41248
[email protected]478c6c32013-03-09 02:50:58249 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25250 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
251 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]ce711ac2012-06-14 07:05:41252}
253
[email protected]478c6c32013-03-09 02:50:58254TEST_F(FocusCyclerTest, Shelf_CycleFocusForward) {
[email protected]eb5a0ab2012-10-20 00:50:25255 ASSERT_TRUE(CreateTray());
[email protected]478c6c32013-03-09 02:50:58256 InstallFocusCycleOnShelf();
257 shelf_widget()->Hide();
[email protected]057dc5752012-03-06 23:59:31258
259 // Create a single test window.
[email protected]5ebe6102012-11-28 21:00:03260 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
[email protected]057dc5752012-03-06 23:59:31261 wm::ActivateWindow(window0.get());
262 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
263
[email protected]478c6c32013-03-09 02:50:58264 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25265 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
266 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]057dc5752012-03-06 23:59:31267
[email protected]478c6c32013-03-09 02:50:58268 // Cycle focus to the browser.
[email protected]eb5a0ab2012-10-20 00:50:25269 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
[email protected]057dc5752012-03-06 23:59:31270 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
271}
272
[email protected]478c6c32013-03-09 02:50:58273TEST_F(FocusCyclerTest, Shelf_CycleFocusBackwardInvisible) {
[email protected]eb5a0ab2012-10-20 00:50:25274 ASSERT_TRUE(CreateTray());
[email protected]478c6c32013-03-09 02:50:58275 InstallFocusCycleOnShelf();
276 shelf_widget()->Hide();
[email protected]057dc5752012-03-06 23:59:31277
278 // Create a single test window.
[email protected]5ebe6102012-11-28 21:00:03279 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
[email protected]057dc5752012-03-06 23:59:31280 wm::ActivateWindow(window0.get());
281 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
282
[email protected]478c6c32013-03-09 02:50:58283 // Cycle focus to the status area.
[email protected]eb5a0ab2012-10-20 00:50:25284 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
285 EXPECT_TRUE(tray()->GetWidget()->IsActive());
[email protected]057dc5752012-03-06 23:59:31286
[email protected]478c6c32013-03-09 02:50:58287 // Cycle focus to the browser.
[email protected]eb5a0ab2012-10-20 00:50:25288 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
[email protected]057dc5752012-03-06 23:59:31289 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
290}
291
[email protected]242aa4f2013-04-30 01:04:08292TEST_F(FocusCyclerTest, CycleFocusThroughWindowWithPanes) {
293 ASSERT_TRUE(CreateTray());
294
295 InstallFocusCycleOnShelf();
296
297 scoped_ptr<views::Widget> browser_widget(new views::Widget);
298 PanedWidgetDelegate* test_widget_delegate =
299 new PanedWidgetDelegate(browser_widget.get());
300 views::Widget::InitParams widget_params(
301 views::Widget::InitParams::TYPE_WINDOW);
302 widget_params.context = CurrentContext();
303 widget_params.delegate = test_widget_delegate;
304 widget_params.ownership =
305 views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
306 browser_widget->Init(widget_params);
307 browser_widget->Show();
308
309 aura::Window* browser_window = browser_widget->GetNativeView();
310
311 views::View* root_view = browser_widget->GetRootView();
312
313 views::AccessiblePaneView* pane1 = new views::AccessiblePaneView();
314 root_view->AddChildView(pane1);
315
316 views::View* view1 = new views::View;
317 view1->set_focusable(true);
318 pane1->AddChildView(view1);
319
320 views::View* view2 = new views::View;
321 view2->set_focusable(true);
322 pane1->AddChildView(view2);
323
324 views::AccessiblePaneView* pane2 = new views::AccessiblePaneView();
325 root_view->AddChildView(pane2);
326
327 views::View* view3 = new views::View;
328 view3->set_focusable(true);
329 pane2->AddChildView(view3);
330
331 views::View* view4 = new views::View;
332 view4->set_focusable(true);
333 pane2->AddChildView(view4);
334
335 std::vector<views::View*> panes;
336 panes.push_back(pane1);
337 panes.push_back(pane2);
338
339 test_widget_delegate->SetAccessiblePanes(panes);
340
341 views::FocusManager* focus_manager = browser_widget->GetFocusManager();
342
343 // Cycle focus to the status area.
344 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
345 EXPECT_TRUE(tray()->GetWidget()->IsActive());
346
347 // Cycle focus to the shelf.
348 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
349 EXPECT_TRUE(shelf_widget()->IsActive());
350
351 // Cycle focus to the first pane in the browser.
352 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
353 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
354 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
355
356 // Cycle focus to the second pane in the browser.
357 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
358 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
359 EXPECT_EQ(focus_manager->GetFocusedView(), view3);
360
361 // Cycle focus back to the status area.
362 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
363 EXPECT_TRUE(tray()->GetWidget()->IsActive());
364
365 // Reverse direction - back to the second pane in the browser.
366 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
367 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
368 EXPECT_EQ(focus_manager->GetFocusedView(), view3);
369
370 // Back to the first pane in the browser.
371 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
372 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
373 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
374
375 // Back to the shelf.
376 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
377 EXPECT_TRUE(shelf_widget()->IsActive());
378
379 // Back to the status area.
380 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
381 EXPECT_TRUE(tray()->GetWidget()->IsActive());
382
383 // Pressing "Escape" while on the status area should
384 // deactivate it, and activate the browser window.
385 aura::RootWindow* root = Shell::GetPrimaryRootWindow();
386 aura::test::EventGenerator event_generator(root, root);
387 event_generator.PressKey(ui::VKEY_ESCAPE, 0);
388 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
389 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
390
391 // Similarly, pressing "Escape" while on the shelf.
392 // should do the same thing.
393 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
394 EXPECT_TRUE(shelf_widget()->IsActive());
395 event_generator.PressKey(ui::VKEY_ESCAPE, 0);
396 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
397 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
398}
399
[email protected]df1c9862012-02-27 10:37:31400} // namespace test
401} // namespace ash