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