1// Copyright 2014 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 "athena/home/public/home_card.h"
6
7#include "athena/activity/public/activity_factory.h"
8#include "athena/home/home_card_constants.h"
9#include "athena/home/home_card_impl.h"
10#include "athena/test/athena_test_base.h"
11#include "athena/wm/public/window_manager.h"
12#include "ui/aura/window.h"
13#include "ui/events/test/event_generator.h"
14#include "ui/gfx/display.h"
15#include "ui/gfx/screen.h"
16#include "ui/views/controls/textfield/textfield.h"
17#include "ui/views/focus/focus_manager.h"
18#include "ui/views/widget/widget.h"
19#include "ui/wm/core/shadow_types.h"
20#include "ui/wm/core/window_util.h"
21
22namespace athena {
23
24aura::Window* GetHomeCardWindow() {
25  return static_cast<HomeCardImpl*>(HomeCard::Get())->
26      GetHomeCardWindowForTest();
27}
28
29// Returns true if the keyboard focus is on the search box.
30bool IsSearchBoxFocused(aura::Window* home_card) {
31  return views::Widget::GetWidgetForNativeWindow(home_card)->
32      GetContentsView()->GetViewByID(kHomeCardSearchBoxId)->HasFocus();
33}
34
35typedef test::AthenaTestBase HomeCardTest;
36
37TEST_F(HomeCardTest, BasicTransition) {
38  ASSERT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
39  aura::Window* home_card = GetHomeCardWindow();
40  const int screen_height = root_window()->bounds().height();
41  const int work_area_height = gfx::Screen::GetScreenFor(root_window())->
42      GetDisplayNearestWindow(root_window()).work_area().height();
43  ASSERT_TRUE(home_card);
44
45  // In the minimized state, home card should be outside (below) the work area.
46  EXPECT_EQ(screen_height - kHomeCardMinimizedHeight,
47            home_card->GetTargetBounds().y());
48  EXPECT_EQ(work_area_height, home_card->GetTargetBounds().y());
49  EXPECT_EQ(wm::ShadowType::SHADOW_TYPE_NONE, wm::GetShadowType(home_card));
50
51  WindowManager::Get()->ToggleOverview();
52  EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
53  EXPECT_EQ(screen_height - kHomeCardHeight, home_card->GetTargetBounds().y());
54  EXPECT_EQ(wm::ShadowType::SHADOW_TYPE_RECTANGULAR,
55            wm::GetShadowType(home_card));
56
57  WindowManager::Get()->ToggleOverview();
58  EXPECT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
59  EXPECT_EQ(work_area_height, home_card->GetTargetBounds().y());
60  EXPECT_EQ(wm::ShadowType::SHADOW_TYPE_NONE, wm::GetShadowType(home_card));
61}
62
63TEST_F(HomeCardTest, VirtualKeyboardTransition) {
64  // Minimized -> Hidden for virtual keyboard.
65  EXPECT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
66  const gfx::Rect vk_bounds(0, 0, 100, 100);
67  HomeCard::Get()->UpdateVirtualKeyboardBounds(vk_bounds);
68  EXPECT_EQ(HomeCard::HIDDEN, HomeCard::Get()->GetState());
69  HomeCard::Get()->UpdateVirtualKeyboardBounds(gfx::Rect());
70  EXPECT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
71
72  // bottom -> centered for virtual keyboard.
73  WindowManager::Get()->ToggleOverview();
74  EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
75  HomeCard::Get()->UpdateVirtualKeyboardBounds(vk_bounds);
76  EXPECT_EQ(HomeCard::VISIBLE_CENTERED, HomeCard::Get()->GetState());
77
78  aura::Window* home_card = GetHomeCardWindow();
79  EXPECT_EQ(0, home_card->GetTargetBounds().y());
80  EXPECT_EQ(wm::ShadowType::SHADOW_TYPE_RECTANGULAR,
81            wm::GetShadowType(home_card));
82
83  HomeCard::Get()->UpdateVirtualKeyboardBounds(gfx::Rect());
84  EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
85}
86
87TEST_F(HomeCardTest, ToggleOverviewWithVirtualKeyboard) {
88  // Minimized -> Hidden for virtual keyboard.
89  EXPECT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
90  const gfx::Rect vk_bounds(0, 0, 100, 100);
91  HomeCard::Get()->UpdateVirtualKeyboardBounds(vk_bounds);
92  EXPECT_EQ(HomeCard::HIDDEN, HomeCard::Get()->GetState());
93
94  // Toogle overview revives the bottom home card. Home card also gets
95  /// activated which will close the virtual keyboard.
96  WindowManager::Get()->ToggleOverview();
97  EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
98  aura::Window* home_card = GetHomeCardWindow();
99  EXPECT_TRUE(wm::IsActiveWindow(home_card));
100}
101
102// Verify if the home card is correctly minimized after app launch.
103TEST_F(HomeCardTest, AppSelection) {
104  EXPECT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
105
106  WindowManager::Get()->ToggleOverview();
107  EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
108
109  athena::ActivityFactory::Get()->CreateWebActivity(
110      NULL, base::string16(), GURL("http://www.google.com/"));
111  EXPECT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
112}
113
114TEST_F(HomeCardTest, Accelerators) {
115  EXPECT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
116
117  ui::test::EventGenerator generator(root_window());
118  generator.PressKey(ui::VKEY_L, ui::EF_CONTROL_DOWN);
119  EXPECT_EQ(HomeCard::VISIBLE_CENTERED, HomeCard::Get()->GetState());
120
121  generator.PressKey(ui::VKEY_L, ui::EF_CONTROL_DOWN);
122  EXPECT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
123
124  // Do nothing for BOTTOM.
125  WindowManager::Get()->ToggleOverview();
126  EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
127  generator.PressKey(ui::VKEY_L, ui::EF_CONTROL_DOWN);
128  EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
129
130  // Do nothing if the centered state is a temporary state.
131  HomeCard::Get()->UpdateVirtualKeyboardBounds(gfx::Rect(0, 0, 100, 100));
132  EXPECT_EQ(HomeCard::VISIBLE_CENTERED, HomeCard::Get()->GetState());
133  generator.PressKey(ui::VKEY_L, ui::EF_CONTROL_DOWN);
134  EXPECT_EQ(HomeCard::VISIBLE_CENTERED, HomeCard::Get()->GetState());
135}
136
137TEST_F(HomeCardTest, MouseClick) {
138  ASSERT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
139
140  // Mouse click at the bottom of the screen should invokes overview mode and
141  // changes the state to BOTTOM.
142  gfx::Rect screen_rect(root_window()->bounds());
143  ui::test::EventGenerator generator(
144      root_window(), gfx::Point(
145          screen_rect.x() + screen_rect.width() / 2, screen_rect.bottom() - 1));
146  generator.ClickLeftButton();
147
148  EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
149  EXPECT_TRUE(WindowManager::Get()->IsOverviewModeActive());
150
151  // Further clicks are simply ignored.
152  generator.ClickLeftButton();
153  EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
154  EXPECT_TRUE(WindowManager::Get()->IsOverviewModeActive());
155}
156
157TEST_F(HomeCardTest, Gestures) {
158  ASSERT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
159  ui::test::EventGenerator generator(root_window());
160  gfx::Rect screen_rect(root_window()->bounds());
161
162  const int bottom = screen_rect.bottom();
163  const int x = screen_rect.x() + 1;
164
165  generator.GestureScrollSequence(gfx::Point(x, bottom - 1),
166                                  gfx::Point(x, bottom - 70),
167                                  base::TimeDelta::FromSeconds(1),
168                                  10);
169  EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
170  EXPECT_TRUE(WindowManager::Get()->IsOverviewModeActive());
171
172  // Too short moves. Nothing has changed.
173  generator.GestureScrollSequence(gfx::Point(x, bottom - 40),
174                                  gfx::Point(x, bottom - 80),
175                                  base::TimeDelta::FromSeconds(1),
176                                  10);
177  EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
178  EXPECT_TRUE(WindowManager::Get()->IsOverviewModeActive());
179
180  generator.GestureScrollSequence(gfx::Point(x, bottom - 40),
181                                  gfx::Point(x, bottom - 20),
182                                  base::TimeDelta::FromSeconds(1),
183                                  10);
184  EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
185  EXPECT_TRUE(WindowManager::Get()->IsOverviewModeActive());
186
187  // Swipe up to the centered state.
188  generator.GestureScrollSequence(gfx::Point(x, bottom - 40),
189                                  gfx::Point(x, bottom - 300),
190                                  base::TimeDelta::FromSeconds(1),
191                                  10);
192  EXPECT_EQ(HomeCard::VISIBLE_CENTERED, HomeCard::Get()->GetState());
193  EXPECT_TRUE(WindowManager::Get()->IsOverviewModeActive());
194
195  // Swipe up from centered; nothing has to be changed.
196  generator.GestureScrollSequence(gfx::Point(x, bottom - 300),
197                                  gfx::Point(x, bottom - 350),
198                                  base::TimeDelta::FromSeconds(1),
199                                  10);
200  EXPECT_EQ(HomeCard::VISIBLE_CENTERED, HomeCard::Get()->GetState());
201  EXPECT_TRUE(WindowManager::Get()->IsOverviewModeActive());
202
203  // Swipe down slightly; nothing has to be changed.
204  generator.GestureScrollSequence(gfx::Point(x, bottom - 300),
205                                  gfx::Point(x, bottom - 250),
206                                  base::TimeDelta::FromSeconds(1),
207                                  10);
208  EXPECT_EQ(HomeCard::VISIBLE_CENTERED, HomeCard::Get()->GetState());
209  EXPECT_TRUE(WindowManager::Get()->IsOverviewModeActive());
210
211  // Swipe down to the bottom state.
212  generator.GestureScrollSequence(gfx::Point(x, 10),
213                                  gfx::Point(x, bottom - 90),
214                                  base::TimeDelta::FromSeconds(1),
215                                  10);
216  EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
217  EXPECT_TRUE(WindowManager::Get()->IsOverviewModeActive());
218
219  generator.GestureScrollSequence(gfx::Point(x, bottom - 40),
220                                  gfx::Point(x, bottom - 300),
221                                  base::TimeDelta::FromSeconds(1),
222                                  10);
223  EXPECT_EQ(HomeCard::VISIBLE_CENTERED, HomeCard::Get()->GetState());
224  EXPECT_TRUE(WindowManager::Get()->IsOverviewModeActive());
225
226  // Swipe down to the minimized state.
227  generator.GestureScrollSequence(gfx::Point(x, 10),
228                                  gfx::Point(x, bottom - 1),
229                                  base::TimeDelta::FromSeconds(1),
230                                  10);
231  EXPECT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
232  EXPECT_FALSE(WindowManager::Get()->IsOverviewModeActive());
233}
234
235TEST_F(HomeCardTest, GesturesToFullDirectly) {
236  ASSERT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
237  ui::test::EventGenerator generator(root_window());
238  gfx::Rect screen_rect(root_window()->bounds());
239
240  const int bottom = screen_rect.bottom();
241  const int x = screen_rect.x() + 1;
242
243  generator.GestureScrollSequence(gfx::Point(x, bottom - 1),
244                                  gfx::Point(x, 20),
245                                  base::TimeDelta::FromSeconds(1),
246                                  10);
247  EXPECT_EQ(HomeCard::VISIBLE_CENTERED, HomeCard::Get()->GetState());
248  EXPECT_TRUE(WindowManager::Get()->IsOverviewModeActive());
249}
250
251TEST_F(HomeCardTest, KeyboardFocus) {
252  ASSERT_EQ(HomeCard::VISIBLE_MINIMIZED, HomeCard::Get()->GetState());
253  aura::Window* home_card = GetHomeCardWindow();
254  ASSERT_FALSE(IsSearchBoxFocused(home_card));
255
256  WindowManager::Get()->ToggleOverview();
257  ASSERT_FALSE(IsSearchBoxFocused(home_card));
258
259  ui::test::EventGenerator generator(root_window());
260  gfx::Rect screen_rect(root_window()->bounds());
261
262  const int bottom = screen_rect.bottom();
263  const int x = screen_rect.x() + 1;
264
265  generator.GestureScrollSequence(gfx::Point(x, bottom - 40),
266                                  gfx::Point(x, 10),
267                                  base::TimeDelta::FromSeconds(1),
268                                  10);
269  EXPECT_EQ(HomeCard::VISIBLE_CENTERED, HomeCard::Get()->GetState());
270  EXPECT_TRUE(IsSearchBoxFocused(home_card));
271
272  generator.GestureScrollSequence(gfx::Point(x, 10),
273                                  gfx::Point(x, bottom - 100),
274                                  base::TimeDelta::FromSeconds(1),
275                                  10);
276  EXPECT_EQ(HomeCard::VISIBLE_BOTTOM, HomeCard::Get()->GetState());
277  EXPECT_FALSE(IsSearchBoxFocused(home_card));
278}
279
280}  // namespace athena
281