Roll src/third_party/WebKit 9301d6f:4619053 (svn 201058:201059)
[chromium-blink-merge.git] / ash / focus_cycler_unittest.cc
blobe8a8ca867ad4b3dd36117fa8f232624a886c83d1
1 // 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.
5 #include "ash/focus_cycler.h"
7 #include "ash/root_window_controller.h"
8 #include "ash/shelf/shelf.h"
9 #include "ash/shelf/shelf_widget.h"
10 #include "ash/shell.h"
11 #include "ash/shell_factory.h"
12 #include "ash/shell_window_ids.h"
13 #include "ash/system/status_area_widget.h"
14 #include "ash/system/status_area_widget_delegate.h"
15 #include "ash/system/tray/system_tray.h"
16 #include "ash/test/ash_test_base.h"
17 #include "ash/wm/window_util.h"
18 #include "ui/aura/test/test_windows.h"
19 #include "ui/aura/window.h"
20 #include "ui/aura/window_event_dispatcher.h"
21 #include "ui/events/test/event_generator.h"
22 #include "ui/views/accessible_pane_view.h"
23 #include "ui/views/controls/button/menu_button.h"
24 #include "ui/views/widget/widget.h"
26 namespace ash {
27 namespace test {
29 using aura::Window;
31 namespace {
33 StatusAreaWidgetDelegate* GetStatusAreaWidgetDelegate(views::Widget* widget) {
34 return static_cast<StatusAreaWidgetDelegate*>(widget->GetContentsView());
37 class PanedWidgetDelegate : public views::WidgetDelegate {
38 public:
39 PanedWidgetDelegate(views::Widget* widget) : widget_(widget) {}
41 void SetAccessiblePanes(const std::vector<views::View*>& panes) {
42 accessible_panes_ = panes;
45 // views::WidgetDelegate.
46 void GetAccessiblePanes(std::vector<views::View*>* panes) override {
47 std::copy(accessible_panes_.begin(),
48 accessible_panes_.end(),
49 std::back_inserter(*panes));
51 views::Widget* GetWidget() override { return widget_; };
52 const views::Widget* GetWidget() const override { return widget_; }
54 private:
55 views::Widget* widget_;
56 std::vector<views::View*> accessible_panes_;
59 } // namespace
61 class FocusCyclerTest : public AshTestBase {
62 public:
63 FocusCyclerTest() {}
65 void SetUp() override {
66 AshTestBase::SetUp();
68 focus_cycler_.reset(new FocusCycler());
70 ASSERT_TRUE(Shelf::ForPrimaryDisplay());
73 void TearDown() override {
74 if (tray_) {
75 GetStatusAreaWidgetDelegate(tray_->GetWidget())->
76 SetFocusCyclerForTesting(NULL);
77 tray_.reset();
80 shelf_widget()->SetFocusCycler(NULL);
82 focus_cycler_.reset();
84 AshTestBase::TearDown();
87 protected:
88 // Creates the system tray, returning true on success.
89 bool CreateTray() {
90 if (tray_)
91 return false;
92 aura::Window* parent =
93 Shell::GetPrimaryRootWindowController()->GetContainer(
94 ash::kShellWindowId_StatusContainer);
96 StatusAreaWidget* widget = new StatusAreaWidget(parent);
97 widget->CreateTrayViews();
98 widget->Show();
99 tray_.reset(widget->system_tray());
100 if (!tray_->GetWidget())
101 return false;
102 focus_cycler_->AddWidget(tray()->GetWidget());
103 GetStatusAreaWidgetDelegate(tray_->GetWidget())->SetFocusCyclerForTesting(
104 focus_cycler());
105 return true;
108 FocusCycler* focus_cycler() { return focus_cycler_.get(); }
110 SystemTray* tray() { return tray_.get(); }
112 ShelfWidget* shelf_widget() {
113 return Shelf::ForPrimaryDisplay()->shelf_widget();
116 void InstallFocusCycleOnShelf() {
117 // Add the shelf.
118 shelf_widget()->SetFocusCycler(focus_cycler());
121 private:
122 scoped_ptr<FocusCycler> focus_cycler_;
123 scoped_ptr<SystemTray> tray_;
125 DISALLOW_COPY_AND_ASSIGN(FocusCyclerTest);
128 TEST_F(FocusCyclerTest, CycleFocusBrowserOnly) {
129 // Create a single test window.
130 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
131 wm::ActivateWindow(window0.get());
132 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
134 // Cycle the window
135 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
136 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
139 TEST_F(FocusCyclerTest, CycleFocusForward) {
140 ASSERT_TRUE(CreateTray());
142 InstallFocusCycleOnShelf();
144 // Create a single test window.
145 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
146 wm::ActivateWindow(window0.get());
147 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
149 // Cycle focus to the status area.
150 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
151 EXPECT_TRUE(tray()->GetWidget()->IsActive());
153 // Cycle focus to the shelf.
154 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
155 EXPECT_TRUE(shelf_widget()->IsActive());
157 // Cycle focus to the browser.
158 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
159 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
162 TEST_F(FocusCyclerTest, CycleFocusBackward) {
163 ASSERT_TRUE(CreateTray());
165 InstallFocusCycleOnShelf();
167 // Create a single test window.
168 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
169 wm::ActivateWindow(window0.get());
170 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
172 // Cycle focus to the shelf.
173 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
174 EXPECT_TRUE(shelf_widget()->IsActive());
176 // Cycle focus to the status area.
177 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
178 EXPECT_TRUE(tray()->GetWidget()->IsActive());
180 // Cycle focus to the browser.
181 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
182 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
185 TEST_F(FocusCyclerTest, CycleFocusForwardBackward) {
186 ASSERT_TRUE(CreateTray());
188 InstallFocusCycleOnShelf();
190 // Create a single test window.
191 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
192 wm::ActivateWindow(window0.get());
193 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
195 // Cycle focus to the shelf.
196 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
197 EXPECT_TRUE(shelf_widget()->IsActive());
199 // Cycle focus to the status area.
200 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
201 EXPECT_TRUE(tray()->GetWidget()->IsActive());
203 // Cycle focus to the browser.
204 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
205 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
207 // Cycle focus to the status area.
208 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
209 EXPECT_TRUE(tray()->GetWidget()->IsActive());
211 // Cycle focus to the shelf.
212 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
213 EXPECT_TRUE(shelf_widget()->IsActive());
215 // Cycle focus to the browser.
216 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
217 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
220 TEST_F(FocusCyclerTest, CycleFocusNoBrowser) {
221 ASSERT_TRUE(CreateTray());
223 InstallFocusCycleOnShelf();
225 // Add the shelf and focus it.
226 focus_cycler()->FocusWidget(shelf_widget());
228 // Cycle focus to the status area.
229 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
230 EXPECT_TRUE(tray()->GetWidget()->IsActive());
232 // Cycle focus to the shelf.
233 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
234 EXPECT_TRUE(shelf_widget()->IsActive());
236 // Cycle focus to the status area.
237 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
238 EXPECT_TRUE(tray()->GetWidget()->IsActive());
240 // Cycle focus to the shelf.
241 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
242 EXPECT_TRUE(shelf_widget()->IsActive());
244 // Cycle focus to the status area.
245 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
246 EXPECT_TRUE(tray()->GetWidget()->IsActive());
249 // Tests that focus cycles from the active browser to the status area and back.
250 TEST_F(FocusCyclerTest, Shelf_CycleFocusForward) {
251 ASSERT_TRUE(CreateTray());
252 InstallFocusCycleOnShelf();
253 shelf_widget()->Hide();
255 // Create two test windows.
256 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
257 scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1));
258 wm::ActivateWindow(window1.get());
259 wm::ActivateWindow(window0.get());
260 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
262 // Cycle focus to the status area.
263 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
264 EXPECT_TRUE(tray()->GetWidget()->IsActive());
266 // Cycle focus to the browser.
267 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
268 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
270 // Cycle focus to the status area.
271 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
272 EXPECT_TRUE(tray()->GetWidget()->IsActive());
275 TEST_F(FocusCyclerTest, Shelf_CycleFocusBackwardInvisible) {
276 ASSERT_TRUE(CreateTray());
277 InstallFocusCycleOnShelf();
278 shelf_widget()->Hide();
280 // Create a single test window.
281 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
282 wm::ActivateWindow(window0.get());
283 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
285 // Cycle focus to the status area.
286 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
287 EXPECT_TRUE(tray()->GetWidget()->IsActive());
289 // Cycle focus to the browser.
290 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
291 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
294 TEST_F(FocusCyclerTest, CycleFocusThroughWindowWithPanes) {
295 ASSERT_TRUE(CreateTray());
297 InstallFocusCycleOnShelf();
299 scoped_ptr<PanedWidgetDelegate> test_widget_delegate;
300 scoped_ptr<views::Widget> browser_widget(new views::Widget);
301 test_widget_delegate.reset(new PanedWidgetDelegate(browser_widget.get()));
302 views::Widget::InitParams widget_params(
303 views::Widget::InitParams::TYPE_WINDOW);
304 widget_params.context = CurrentContext();
305 widget_params.delegate = test_widget_delegate.get();
306 widget_params.ownership =
307 views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
308 browser_widget->Init(widget_params);
309 browser_widget->Show();
311 aura::Window* browser_window = browser_widget->GetNativeView();
313 views::View* root_view = browser_widget->GetRootView();
315 views::AccessiblePaneView* pane1 = new views::AccessiblePaneView();
316 root_view->AddChildView(pane1);
318 views::View* view1 = new views::View;
319 view1->SetFocusable(true);
320 pane1->AddChildView(view1);
322 views::View* view2 = new views::View;
323 view2->SetFocusable(true);
324 pane1->AddChildView(view2);
326 views::AccessiblePaneView* pane2 = new views::AccessiblePaneView();
327 root_view->AddChildView(pane2);
329 views::View* view3 = new views::View;
330 view3->SetFocusable(true);
331 pane2->AddChildView(view3);
333 views::View* view4 = new views::View;
334 view4->SetFocusable(true);
335 pane2->AddChildView(view4);
337 std::vector<views::View*> panes;
338 panes.push_back(pane1);
339 panes.push_back(pane2);
341 test_widget_delegate->SetAccessiblePanes(panes);
343 views::FocusManager* focus_manager = browser_widget->GetFocusManager();
345 // Cycle focus to the status area.
346 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
347 EXPECT_TRUE(tray()->GetWidget()->IsActive());
349 // Cycle focus to the shelf.
350 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
351 EXPECT_TRUE(shelf_widget()->IsActive());
353 // Cycle focus to the first pane in the browser.
354 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
355 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
356 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
358 // Cycle focus to the second pane in the browser.
359 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
360 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
361 EXPECT_EQ(focus_manager->GetFocusedView(), view3);
363 // Cycle focus back to the status area.
364 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
365 EXPECT_TRUE(tray()->GetWidget()->IsActive());
367 // Reverse direction - back to the second pane in the browser.
368 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
369 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
370 EXPECT_EQ(focus_manager->GetFocusedView(), view3);
372 // Back to the first pane in the browser.
373 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
374 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
375 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
377 // Back to the shelf.
378 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
379 EXPECT_TRUE(shelf_widget()->IsActive());
381 // Back to the status area.
382 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
383 EXPECT_TRUE(tray()->GetWidget()->IsActive());
385 // Pressing "Escape" while on the status area should
386 // deactivate it, and activate the browser window.
387 aura::Window* root = Shell::GetPrimaryRootWindow();
388 ui::test::EventGenerator event_generator(root, root);
389 event_generator.PressKey(ui::VKEY_ESCAPE, 0);
390 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
391 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
393 // Similarly, pressing "Escape" while on the shelf.
394 // should do the same thing.
395 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
396 EXPECT_TRUE(shelf_widget()->IsActive());
397 event_generator.PressKey(ui::VKEY_ESCAPE, 0);
398 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
399 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
402 } // namespace test
403 } // namespace ash