33c89c2c7f22c120ab3338138140cf3c995642d4
[platform/framework/web/crosswalk.git] / src / ash / focus_cycler_unittest.cc
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.
4
5 #include "ash/focus_cycler.h"
6
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/event_generator.h"
19 #include "ui/aura/test/test_windows.h"
20 #include "ui/aura/window.h"
21 #include "ui/aura/window_event_dispatcher.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"
25
26 namespace ash {
27 namespace test {
28
29 using aura::Window;
30
31 namespace {
32
33 StatusAreaWidgetDelegate* GetStatusAreaWidgetDelegate(views::Widget* widget) {
34   return static_cast<StatusAreaWidgetDelegate*>(widget->GetContentsView());
35 }
36
37 class PanedWidgetDelegate : public views::WidgetDelegate {
38  public:
39   PanedWidgetDelegate(views::Widget* widget) : widget_(widget) {}
40
41   void SetAccessiblePanes(const std::vector<views::View*>& panes) {
42     accessible_panes_ = panes;
43   }
44
45   // views::WidgetDelegate.
46   virtual void GetAccessiblePanes(std::vector<views::View*>* panes) OVERRIDE {
47     std::copy(accessible_panes_.begin(),
48               accessible_panes_.end(),
49               std::back_inserter(*panes));
50   }
51   virtual views::Widget* GetWidget() OVERRIDE {
52     return widget_;
53   };
54   virtual const views::Widget* GetWidget() const OVERRIDE {
55     return widget_;
56   }
57
58  private:
59   views::Widget* widget_;
60   std::vector<views::View*> accessible_panes_;
61 };
62
63 }  // namespace
64
65 class FocusCyclerTest : public AshTestBase {
66  public:
67   FocusCyclerTest() {}
68
69   virtual void SetUp() OVERRIDE {
70     AshTestBase::SetUp();
71
72     focus_cycler_.reset(new FocusCycler());
73
74     ASSERT_TRUE(Shelf::ForPrimaryDisplay());
75   }
76
77   virtual void TearDown() OVERRIDE {
78     if (tray_) {
79       GetStatusAreaWidgetDelegate(tray_->GetWidget())->
80           SetFocusCyclerForTesting(NULL);
81       tray_.reset();
82     }
83
84     shelf_widget()->SetFocusCycler(NULL);
85
86     focus_cycler_.reset();
87
88     AshTestBase::TearDown();
89   }
90
91  protected:
92   // Creates the system tray, returning true on success.
93   bool CreateTray() {
94     if (tray_)
95       return false;
96     aura::Window* parent =
97         Shell::GetPrimaryRootWindowController()->GetContainer(
98             ash::kShellWindowId_StatusContainer);
99
100     StatusAreaWidget* widget = new StatusAreaWidget(parent);
101     widget->CreateTrayViews();
102     widget->Show();
103     tray_.reset(widget->system_tray());
104     if (!tray_->GetWidget())
105       return false;
106     focus_cycler_->AddWidget(tray()->GetWidget());
107     GetStatusAreaWidgetDelegate(tray_->GetWidget())->SetFocusCyclerForTesting(
108         focus_cycler());
109     return true;
110   }
111
112   FocusCycler* focus_cycler() { return focus_cycler_.get(); }
113
114   SystemTray* tray() { return tray_.get(); }
115
116   ShelfWidget* shelf_widget() {
117     return Shelf::ForPrimaryDisplay()->shelf_widget();
118   }
119
120   void InstallFocusCycleOnShelf() {
121     // Add the shelf.
122     shelf_widget()->SetFocusCycler(focus_cycler());
123   }
124
125  private:
126   scoped_ptr<FocusCycler> focus_cycler_;
127   scoped_ptr<SystemTray> tray_;
128
129   DISALLOW_COPY_AND_ASSIGN(FocusCyclerTest);
130 };
131
132 TEST_F(FocusCyclerTest, CycleFocusBrowserOnly) {
133   // Create a single test window.
134   scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
135   wm::ActivateWindow(window0.get());
136   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
137
138   // Cycle the window
139   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
140   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
141 }
142
143 TEST_F(FocusCyclerTest, CycleFocusForward) {
144   ASSERT_TRUE(CreateTray());
145
146   InstallFocusCycleOnShelf();
147
148   // Create a single test window.
149   scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
150   wm::ActivateWindow(window0.get());
151   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
152
153   // Cycle focus to the status area.
154   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
155   EXPECT_TRUE(tray()->GetWidget()->IsActive());
156
157   // Cycle focus to the shelf.
158   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
159   EXPECT_TRUE(shelf_widget()->IsActive());
160
161   // Cycle focus to the browser.
162   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
163   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
164 }
165
166 TEST_F(FocusCyclerTest, CycleFocusBackward) {
167   ASSERT_TRUE(CreateTray());
168
169   InstallFocusCycleOnShelf();
170
171   // Create a single test window.
172   scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
173   wm::ActivateWindow(window0.get());
174   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
175
176   // Cycle focus to the shelf.
177   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
178   EXPECT_TRUE(shelf_widget()->IsActive());
179
180   // Cycle focus to the status area.
181   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
182   EXPECT_TRUE(tray()->GetWidget()->IsActive());
183
184   // Cycle focus to the browser.
185   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
186   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
187 }
188
189 TEST_F(FocusCyclerTest, CycleFocusForwardBackward) {
190   ASSERT_TRUE(CreateTray());
191
192   InstallFocusCycleOnShelf();
193
194   // Create a single test window.
195   scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
196   wm::ActivateWindow(window0.get());
197   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
198
199   // Cycle focus to the shelf.
200   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
201   EXPECT_TRUE(shelf_widget()->IsActive());
202
203   // Cycle focus to the status area.
204   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
205   EXPECT_TRUE(tray()->GetWidget()->IsActive());
206
207   // Cycle focus to the browser.
208   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
209   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
210
211   // Cycle focus to the status area.
212   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
213   EXPECT_TRUE(tray()->GetWidget()->IsActive());
214
215   // Cycle focus to the shelf.
216   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
217   EXPECT_TRUE(shelf_widget()->IsActive());
218
219   // Cycle focus to the browser.
220   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
221   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
222 }
223
224 TEST_F(FocusCyclerTest, CycleFocusNoBrowser) {
225   ASSERT_TRUE(CreateTray());
226
227   InstallFocusCycleOnShelf();
228
229   // Add the shelf and focus it.
230   focus_cycler()->FocusWidget(shelf_widget());
231
232   // Cycle focus to the status area.
233   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
234   EXPECT_TRUE(tray()->GetWidget()->IsActive());
235
236   // Cycle focus to the shelf.
237   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
238   EXPECT_TRUE(shelf_widget()->IsActive());
239
240   // Cycle focus to the status area.
241   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
242   EXPECT_TRUE(tray()->GetWidget()->IsActive());
243
244   // Cycle focus to the shelf.
245   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
246   EXPECT_TRUE(shelf_widget()->IsActive());
247
248   // Cycle focus to the status area.
249   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
250   EXPECT_TRUE(tray()->GetWidget()->IsActive());
251 }
252
253 // Tests that focus cycles from the active browser to the status area and back.
254 TEST_F(FocusCyclerTest, Shelf_CycleFocusForward) {
255   ASSERT_TRUE(CreateTray());
256   InstallFocusCycleOnShelf();
257   shelf_widget()->Hide();
258
259   // Create two test windows.
260   scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
261   scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1));
262   wm::ActivateWindow(window1.get());
263   wm::ActivateWindow(window0.get());
264   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
265
266   // Cycle focus to the status area.
267   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
268   EXPECT_TRUE(tray()->GetWidget()->IsActive());
269
270   // Cycle focus to the browser.
271   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
272   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
273
274   // Cycle focus to the status area.
275   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
276   EXPECT_TRUE(tray()->GetWidget()->IsActive());
277 }
278
279 TEST_F(FocusCyclerTest, Shelf_CycleFocusBackwardInvisible) {
280   ASSERT_TRUE(CreateTray());
281   InstallFocusCycleOnShelf();
282   shelf_widget()->Hide();
283
284   // Create a single test window.
285   scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
286   wm::ActivateWindow(window0.get());
287   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
288
289   // Cycle focus to the status area.
290   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
291   EXPECT_TRUE(tray()->GetWidget()->IsActive());
292
293   // Cycle focus to the browser.
294   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
295   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
296 }
297
298 TEST_F(FocusCyclerTest, CycleFocusThroughWindowWithPanes) {
299   ASSERT_TRUE(CreateTray());
300
301   InstallFocusCycleOnShelf();
302
303   scoped_ptr<PanedWidgetDelegate> test_widget_delegate;
304   scoped_ptr<views::Widget> browser_widget(new views::Widget);
305   test_widget_delegate.reset(new PanedWidgetDelegate(browser_widget.get()));
306   views::Widget::InitParams widget_params(
307       views::Widget::InitParams::TYPE_WINDOW);
308   widget_params.context = CurrentContext();
309   widget_params.delegate = test_widget_delegate.get();
310   widget_params.ownership =
311       views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
312   browser_widget->Init(widget_params);
313   browser_widget->Show();
314
315   aura::Window* browser_window = browser_widget->GetNativeView();
316
317   views::View* root_view = browser_widget->GetRootView();
318
319   views::AccessiblePaneView* pane1 = new views::AccessiblePaneView();
320   root_view->AddChildView(pane1);
321
322   views::View* view1 = new views::View;
323   view1->SetFocusable(true);
324   pane1->AddChildView(view1);
325
326   views::View* view2 = new views::View;
327   view2->SetFocusable(true);
328   pane1->AddChildView(view2);
329
330   views::AccessiblePaneView* pane2 = new views::AccessiblePaneView();
331   root_view->AddChildView(pane2);
332
333   views::View* view3 = new views::View;
334   view3->SetFocusable(true);
335   pane2->AddChildView(view3);
336
337   views::View* view4 = new views::View;
338   view4->SetFocusable(true);
339   pane2->AddChildView(view4);
340
341   std::vector<views::View*> panes;
342   panes.push_back(pane1);
343   panes.push_back(pane2);
344
345   test_widget_delegate->SetAccessiblePanes(panes);
346
347   views::FocusManager* focus_manager = browser_widget->GetFocusManager();
348
349   // Cycle focus to the status area.
350   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
351   EXPECT_TRUE(tray()->GetWidget()->IsActive());
352
353   // Cycle focus to the shelf.
354   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
355   EXPECT_TRUE(shelf_widget()->IsActive());
356
357   // Cycle focus to the first pane in the browser.
358   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
359   EXPECT_TRUE(wm::IsActiveWindow(browser_window));
360   EXPECT_EQ(focus_manager->GetFocusedView(), view1);
361
362   // Cycle focus to the second pane in the browser.
363   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
364   EXPECT_TRUE(wm::IsActiveWindow(browser_window));
365   EXPECT_EQ(focus_manager->GetFocusedView(), view3);
366
367   // Cycle focus back to the status area.
368   focus_cycler()->RotateFocus(FocusCycler::FORWARD);
369   EXPECT_TRUE(tray()->GetWidget()->IsActive());
370
371   // Reverse direction - back to the second pane in the browser.
372   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
373   EXPECT_TRUE(wm::IsActiveWindow(browser_window));
374   EXPECT_EQ(focus_manager->GetFocusedView(), view3);
375
376   // Back to the first pane in the browser.
377   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
378   EXPECT_TRUE(wm::IsActiveWindow(browser_window));
379   EXPECT_EQ(focus_manager->GetFocusedView(), view1);
380
381   // Back to the shelf.
382   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
383   EXPECT_TRUE(shelf_widget()->IsActive());
384
385   // Back to the status area.
386   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
387   EXPECT_TRUE(tray()->GetWidget()->IsActive());
388
389   // Pressing "Escape" while on the status area should
390   // deactivate it, and activate the browser window.
391   aura::Window* root = Shell::GetPrimaryRootWindow();
392   aura::test::EventGenerator event_generator(root, root);
393   event_generator.PressKey(ui::VKEY_ESCAPE, 0);
394   EXPECT_TRUE(wm::IsActiveWindow(browser_window));
395   EXPECT_EQ(focus_manager->GetFocusedView(), view1);
396
397   // Similarly, pressing "Escape" while on the shelf.
398   // should do the same thing.
399   focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
400   EXPECT_TRUE(shelf_widget()->IsActive());
401   event_generator.PressKey(ui::VKEY_ESCAPE, 0);
402   EXPECT_TRUE(wm::IsActiveWindow(browser_window));
403   EXPECT_EQ(focus_manager->GetFocusedView(), view1);
404 }
405
406 }  // namespace test
407 }  // namespace ash