1 // Copyright 2013 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 <algorithm>
6 #include <memory>
7
8 #include "ash/accessibility/accessibility_controller_impl.h"
9 #include "ash/app_list/app_list_controller_impl.h"
10 #include "ash/app_list/app_list_presenter_impl.h"
11 #include "ash/app_list/model/app_list_item.h"
12 #include "ash/app_list/test/app_list_test_helper.h"
13 #include "ash/app_list/test/app_list_test_model.h"
14 #include "ash/app_list/test/app_list_test_view_delegate.h"
15 #include "ash/app_list/test/test_search_result.h"
16 #include "ash/app_list/views/app_list_folder_view.h"
17 #include "ash/app_list/views/app_list_item_view.h"
18 #include "ash/app_list/views/app_list_main_view.h"
19 #include "ash/app_list/views/app_list_view.h"
20 #include "ash/app_list/views/apps_container_view.h"
21 #include "ash/app_list/views/apps_grid_view.h"
22 #include "ash/app_list/views/contents_view.h"
23 #include "ash/app_list/views/expand_arrow_view.h"
24 #include "ash/app_list/views/privacy_container_view.h"
25 #include "ash/app_list/views/search_box_view.h"
26 #include "ash/app_list/views/search_result_actions_view.h"
27 #include "ash/app_list/views/search_result_base_view.h"
28 #include "ash/app_list/views/search_result_list_view.h"
29 #include "ash/app_list/views/search_result_page_anchored_dialog.h"
30 #include "ash/app_list/views/search_result_page_view.h"
31 #include "ash/app_list/views/test/apps_grid_view_test_api.h"
32 #include "ash/home_screen/home_screen_controller.h"
33 #include "ash/keyboard/keyboard_controller_impl.h"
34 #include "ash/keyboard/ui/keyboard_ui_controller.h"
35 #include "ash/keyboard/ui/test/keyboard_test_util.h"
36 #include "ash/public/cpp/app_list/app_list_color_provider.h"
37 #include "ash/public/cpp/app_list/app_list_config.h"
38 #include "ash/public/cpp/app_list/app_list_features.h"
39 #include "ash/public/cpp/app_list/app_list_switches.h"
40 #include "ash/public/cpp/app_list/app_list_types.h"
41 #include "ash/public/cpp/ash_features.h"
42 #include "ash/public/cpp/ash_switches.h"
43 #include "ash/public/cpp/keyboard/keyboard_switches.h"
44 #include "ash/public/cpp/shelf_config.h"
45 #include "ash/public/cpp/shelf_item_delegate.h"
46 #include "ash/public/cpp/shelf_model.h"
47 #include "ash/public/cpp/shelf_types.h"
48 #include "ash/public/cpp/shell_window_ids.h"
49 #include "ash/public/cpp/test/shell_test_api.h"
50 #include "ash/root_window_controller.h"
51 #include "ash/shelf/home_button.h"
52 #include "ash/shelf/scrollable_shelf_view.h"
53 #include "ash/shelf/shelf.h"
54 #include "ash/shelf/shelf_app_button.h"
55 #include "ash/shelf/shelf_layout_manager.h"
56 #include "ash/shelf/shelf_navigation_widget.h"
57 #include "ash/shelf/shelf_test_util.h"
58 #include "ash/shelf/shelf_view.h"
59 #include "ash/shelf/shelf_view_test_api.h"
60 #include "ash/shell.h"
61 #include "ash/system/unified/unified_system_tray.h"
62 #include "ash/test/ash_test_base.h"
63 #include "ash/wallpaper/wallpaper_controller_test_api.h"
64 #include "ash/wm/mru_window_tracker.h"
65 #include "ash/wm/overview/overview_controller.h"
66 #include "ash/wm/splitview/split_view_controller.h"
67 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
68 #include "ash/wm/window_state.h"
69 #include "ash/wm/window_util.h"
70 #include "ash/wm/workspace_controller_test_api.h"
71 #include "base/callback_helpers.h"
72 #include "base/command_line.h"
73 #include "base/macros.h"
74 #include "base/run_loop.h"
75 #include "base/test/metrics/histogram_tester.h"
76 #include "base/test/scoped_feature_list.h"
77 #include "ui/aura/client/aura_constants.h"
78 #include "ui/aura/test/test_windows.h"
79 #include "ui/aura/window.h"
80 #include "ui/base/ui_base_types.h"
81 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
82 #include "ui/display/display.h"
83 #include "ui/display/manager/display_manager.h"
84 #include "ui/display/screen.h"
85 #include "ui/display/test/display_manager_test_api.h"
86 #include "ui/events/test/event_generator.h"
87 #include "ui/views/controls/textfield/textfield.h"
88 #include "ui/views/test/widget_test.h"
89 #include "ui/wm/core/window_util.h"
90
91 namespace ash {
92 namespace {
93
94 constexpr int kAppListBezelMargin = 50;
95
GetPrimaryDisplayId()96 int64_t GetPrimaryDisplayId() {
97 return display::Screen::GetScreen()->GetPrimaryDisplay().id();
98 }
99
SetShelfAlignment(ShelfAlignment alignment)100 void SetShelfAlignment(ShelfAlignment alignment) {
101 AshTestBase::GetPrimaryShelf()->SetAlignment(alignment);
102 }
103
EnableTabletMode(bool enable)104 void EnableTabletMode(bool enable) {
105 // Avoid |TabletModeController::OnGetSwitchStates| from disabling tablet mode
106 // again at the end of |TabletModeController::TabletModeController|.
107 base::RunLoop().RunUntilIdle();
108
109 Shell::Get()->tablet_mode_controller()->SetEnabledForTest(enable);
110
111 // The app list will be shown automatically when tablet mode is enabled (Home
112 // launcher flag is enabled). Wait here for the animation complete.
113 base::RunLoop().RunUntilIdle();
114 }
115
116 // Generates a fling.
FlingUpOrDown(ui::test::EventGenerator * generator,AppListView * view,bool up)117 void FlingUpOrDown(ui::test::EventGenerator* generator,
118 AppListView* view,
119 bool up) {
120 int offset = up ? -100 : 100;
121 gfx::Point start_point = view->GetBoundsInScreen().origin();
122 gfx::Point target_point = start_point;
123 target_point.Offset(0, offset);
124
125 generator->GestureScrollSequence(start_point, target_point,
126 base::TimeDelta::FromMilliseconds(10), 2);
127 }
128
CreateOmniboxSuggestionResult(const std::string & result_id)129 std::unique_ptr<TestSearchResult> CreateOmniboxSuggestionResult(
130 const std::string& result_id) {
131 auto suggestion_result = std::make_unique<TestSearchResult>();
132 suggestion_result->set_result_id(result_id);
133 suggestion_result->set_is_omnibox_search(true);
134 suggestion_result->set_display_type(ash::SearchResultDisplayType::kList);
135 SearchResultActions actions;
136 actions.push_back(SearchResultAction(gfx::ImageSkia(),
137 base::ASCIIToUTF16("Remove"),
138 true /*visible_on_hover*/));
139 suggestion_result->SetActions(actions);
140
141 return suggestion_result;
142 }
143
144 } // namespace
145
146 class AppListPresenterDelegateTest : public AshTestBase,
147 public testing::WithParamInterface<bool> {
148 public:
149 AppListPresenterDelegateTest() = default;
150 AppListPresenterDelegateTest(const AppListPresenterDelegateTest&) = delete;
151 AppListPresenterDelegateTest& operator=(const AppListPresenterDelegateTest&) =
152 delete;
153 ~AppListPresenterDelegateTest() override = default;
154
155 // testing::Test:
SetUp()156 void SetUp() override {
157 AppListView::SetShortAnimationForTesting(true);
158 AshTestBase::SetUp();
159
160 // Make the display big enough to hold the app list.
161 UpdateDisplay("1024x768");
162 }
163
164 // testing::Test:
TearDown()165 void TearDown() override {
166 AshTestBase::TearDown();
167 AppListView::SetShortAnimationForTesting(false);
168 }
169
SetAppListStateAndWait(AppListViewState new_state)170 void SetAppListStateAndWait(AppListViewState new_state) {
171 GetAppListView()->SetState(new_state);
172 GetAppListTestHelper()->WaitUntilIdle();
173 GetAppListTestHelper()->CheckState(new_state);
174 }
175
176 // Whether to run the test with mouse or gesture events.
TestMouseEventParam()177 bool TestMouseEventParam() { return GetParam(); }
178
GetPointOutsideSearchbox()179 gfx::Point GetPointOutsideSearchbox() {
180 // Ensures that the point satisfies the following conditions:
181 // (1) The point is within AppListView.
182 // (2) The point is outside of the search box.
183 // (3) The touch event on the point should not be consumed by the handler
184 // for back gesture.
185 return GetAppListView()
186 ->search_box_view()
187 ->GetBoundsInScreen()
188 .bottom_right();
189 }
190
GetPointInsideSearchbox()191 gfx::Point GetPointInsideSearchbox() {
192 return GetAppListView()
193 ->search_box_view()
194 ->GetBoundsInScreen()
195 .CenterPoint();
196 }
197
GetAppListView()198 AppListView* GetAppListView() {
199 return GetAppListTestHelper()->GetAppListView();
200 }
201
search_result_page()202 SearchResultPageView* search_result_page() {
203 return GetAppListView()
204 ->app_list_main_view()
205 ->contents_view()
206 ->search_results_page_view();
207 }
208
ShowZeroStateSearchInHalfState()209 void ShowZeroStateSearchInHalfState() {
210 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
211 GetEventGenerator()->GestureTapAt(GetPointInsideSearchbox());
212 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
213 }
214
GetSearchResultListViewItemAt(int index)215 SearchResultBaseView* GetSearchResultListViewItemAt(int index) {
216 return GetAppListView()
217 ->app_list_main_view()
218 ->contents_view()
219 ->search_result_list_view_for_test()
220 ->GetResultViewAt(index);
221 }
222
ClickMouseAt(const gfx::Point & point)223 void ClickMouseAt(const gfx::Point& point) {
224 ui::test::EventGenerator* generator = GetEventGenerator();
225 generator->MoveMouseTo(point);
226 generator->PressLeftButton();
227 generator->ReleaseLeftButton();
228 }
229
LongPressAt(const gfx::Point & point)230 void LongPressAt(const gfx::Point& point) {
231 ui::TouchEvent long_press(ui::ET_GESTURE_LONG_PRESS, point,
232 base::TimeTicks::Now(),
233 ui::PointerDetails(ui::EventPointerType::kTouch));
234 GetEventGenerator()->Dispatch(&long_press);
235 }
236
GetSearchResultPageAnchoredDialog()237 views::DialogDelegate* GetSearchResultPageAnchoredDialog() {
238 return search_result_page()
239 ->anchored_dialog_for_test()
240 ->widget()
241 ->widget_delegate()
242 ->AsDialogDelegate();
243 }
244
245 // Verifies the current search result page anchored dialog bounds.
246 // The dialog is expected to be positioned horizontally centered within the
247 // search box bounds.
SanityCheckSearchResultsAnchoredDialogBounds(const views::Widget * dialog)248 void SanityCheckSearchResultsAnchoredDialogBounds(
249 const views::Widget* dialog) {
250 auto horizontal_center_offset = [](const gfx::Rect& inner,
251 const gfx::Rect& outer) -> int {
252 return outer.CenterPoint().x() - inner.CenterPoint().x();
253 };
254
255 const gfx::Rect dialog_bounds = dialog->GetWindowBoundsInScreen();
256 const gfx::Rect search_box_bounds = GetAppListView()
257 ->search_box_view()
258 ->GetWidget()
259 ->GetWindowBoundsInScreen();
260 // The dialog should be horizontally centered within the search box.
261 EXPECT_EQ(0, horizontal_center_offset(dialog_bounds, search_box_bounds));
262 // Verify the confirmation dialog is positioned with the top within search
263 // box bounds.
264 EXPECT_GT(dialog_bounds.y(), search_box_bounds.y());
265 EXPECT_LT(dialog_bounds.y(), search_box_bounds.bottom());
266 }
267
268 // Returns the |dialog| vertical offset from the top of the search box bounds.
GetSearchResultsAnchoredDialogTopOffset(const views::Widget * dialog)269 int GetSearchResultsAnchoredDialogTopOffset(const views::Widget* dialog) {
270 const gfx::Rect dialog_bounds = dialog->GetWindowBoundsInScreen();
271 const gfx::Rect search_box_bounds = GetAppListView()
272 ->search_box_view()
273 ->GetWidget()
274 ->GetWindowBoundsInScreen();
275 return dialog_bounds.y() - search_box_bounds.y();
276 }
277 };
278
279 // Used to test app_list behavior with a populated apps_grid
280 class PopulatedAppListTest : public AshTestBase,
281 public testing::WithParamInterface<bool> {
282 public:
283 PopulatedAppListTest() = default;
284 ~PopulatedAppListTest() override = default;
285
SetUp()286 void SetUp() override {
287 AppListConfigProvider::Get().ResetForTesting();
288 AshTestBase::SetUp();
289
290 // Make the display big enough to hold the app list.
291 UpdateDisplay("1024x768");
292
293 app_list_test_delegate_ = std::make_unique<test::AppListTestViewDelegate>();
294 app_list_test_model_ = app_list_test_delegate_->GetTestModel();
295 }
296
TearDown()297 void TearDown() override {
298 AshTestBase::TearDown();
299 AppListView::SetShortAnimationForTesting(false);
300 }
301
302 protected:
CreateAndOpenAppList()303 void CreateAndOpenAppList() {
304 app_list_view_ = new AppListView(app_list_test_delegate_.get());
305 app_list_view_->InitView(GetContext());
306 app_list_view_->Show(false /*is_side_shelf*/);
307 }
308
ShowAppListInAppsFullScreen()309 void ShowAppListInAppsFullScreen() {
310 // Press the ExpandArrowView and check that the AppListView is in
311 // fullscreen.
312 gfx::Point click_point = app_list_view_->app_list_main_view()
313 ->contents_view()
314 ->expand_arrow_view()
315 ->GetBoundsInScreen()
316 .CenterPoint();
317 GetEventGenerator()->GestureTapAt(click_point);
318 EXPECT_EQ(AppListViewState::kFullscreenAllApps,
319 app_list_view_->app_list_state());
320 }
321
InitializeAppsGrid()322 void InitializeAppsGrid() {
323 if (!app_list_view_)
324 CreateAndOpenAppList();
325 apps_grid_view_ = app_list_view_->app_list_main_view()
326 ->contents_view()
327 ->apps_container_view()
328 ->apps_grid_view();
329 apps_grid_test_api_ =
330 std::make_unique<test::AppsGridViewTestApi>(apps_grid_view_);
331 }
332
GetItemRectOnCurrentPageAt(int row,int col) const333 gfx::Rect GetItemRectOnCurrentPageAt(int row, int col) const {
334 DCHECK_GT(app_list_test_model_->top_level_item_list()->item_count(), 0u);
335 return apps_grid_test_api_->GetItemTileRectOnCurrentPageAt(row, col);
336 }
337
AppListIsInFolderView() const338 bool AppListIsInFolderView() const {
339 return app_list_view_->app_list_main_view()
340 ->contents_view()
341 ->apps_container_view()
342 ->IsInFolderView();
343 }
344
folder_view()345 AppListFolderView* folder_view() {
346 return app_list_view_->app_list_main_view()
347 ->contents_view()
348 ->apps_container_view()
349 ->app_list_folder_view();
350 }
351
352 test::AppListTestModel* app_list_test_model_ = nullptr;
353 std::unique_ptr<test::AppsGridViewTestApi> apps_grid_test_api_;
354 std::unique_ptr<test::AppListTestViewDelegate> app_list_test_delegate_;
355 AppListView* app_list_view_ = nullptr; // Owned by native widget.
356 AppsGridView* apps_grid_view_ = nullptr; // Owned by |app_list_view_|.
357 };
358
359 // Subclass of PopuplatedAppListTest which enables the animation and the virtual
360 // keyboard.
361 class PopulatedAppListWithVKEnabledTest : public PopulatedAppListTest {
362 public:
363 PopulatedAppListWithVKEnabledTest() = default;
364 ~PopulatedAppListWithVKEnabledTest() override = default;
365
SetUp()366 void SetUp() override {
367 AppListView::SetShortAnimationForTesting(true);
368 base::CommandLine::ForCurrentProcess()->AppendSwitch(
369 keyboard::switches::kEnableVirtualKeyboard);
370 PopulatedAppListTest::SetUp();
371 }
372 };
373
374 // Instantiate the Boolean which is used to toggle mouse and touch events in
375 // the parameterized tests.
376 INSTANTIATE_TEST_SUITE_P(All, AppListPresenterDelegateTest, testing::Bool());
377
378 // Verifies that context menu click should not activate the search box
379 // (see https://crbug.com/941428).
TEST_F(AppListPresenterDelegateTest,RightClickSearchBoxInPeeking)380 TEST_F(AppListPresenterDelegateTest, RightClickSearchBoxInPeeking) {
381 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
382 AppListView* app_list_view = GetAppListView();
383 gfx::Rect app_list_bounds = app_list_view->GetBoundsInScreen();
384 ASSERT_EQ(AppListViewState::kPeeking, app_list_view->app_list_state());
385
386 // Right click the search box and checks the following things:
387 // (1) AppListView's bounds in screen does not change.
388 // (2) AppListView is still in Peeking state.
389 ui::test::EventGenerator* generator = GetEventGenerator();
390 generator->MoveMouseTo(GetPointInsideSearchbox());
391 generator->PressRightButton();
392 EXPECT_EQ(app_list_bounds, app_list_view->GetBoundsInScreen());
393 EXPECT_EQ(AppListViewState::kPeeking, app_list_view->app_list_state());
394 }
395
TEST_F(AppListPresenterDelegateTest,ReshownAppListResetsSearchBoxActivation)396 TEST_F(AppListPresenterDelegateTest, ReshownAppListResetsSearchBoxActivation) {
397 // Activate the search box.
398 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
399 GetEventGenerator()->GestureTapAt(GetPointInsideSearchbox());
400
401 // Dismiss and re-show the AppList.
402 GetAppListTestHelper()->Dismiss();
403 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
404
405 // Test that the search box is no longer active.
406 EXPECT_FALSE(GetAppListTestHelper()
407 ->GetAppListView()
408 ->search_box_view()
409 ->is_search_box_active());
410 }
411
412 // Tests that the SearchBox activation is reset after the AppList is hidden with
413 // no animation from FULLSCREEN_SEARCH.
TEST_F(AppListPresenterDelegateTest,SideShelfAppListResetsSearchBoxActivationOnClose)414 TEST_F(AppListPresenterDelegateTest,
415 SideShelfAppListResetsSearchBoxActivationOnClose) {
416 // Set the shelf to one side, then show the AppList and activate the
417 // searchbox.
418 SetShelfAlignment(ShelfAlignment::kRight);
419 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
420 GetEventGenerator()->GestureTapAt(GetPointInsideSearchbox());
421 ASSERT_TRUE(GetAppListTestHelper()
422 ->GetAppListView()
423 ->search_box_view()
424 ->is_search_box_active());
425
426 // Dismiss the AppList using the controller, this is the same way we dismiss
427 // the AppList when a SearchResult is launched, and skips the
428 // FULLSCREEN_SEARCH -> FULLSCREEN_ALL_APPS transition.
429 Shell::Get()->app_list_controller()->DismissAppList();
430
431 // Test that the search box is not active.
432 EXPECT_FALSE(GetAppListTestHelper()
433 ->GetAppListView()
434 ->search_box_view()
435 ->is_search_box_active());
436 }
437
438 // Verifies that tapping on the search box in tablet mode with animation and
439 // zero state enabled should not bring Chrome crash (https://crbug.com/958267).
TEST_F(AppListPresenterDelegateTest,ClickSearchBoxInTabletMode)440 TEST_F(AppListPresenterDelegateTest, ClickSearchBoxInTabletMode) {
441 EnableTabletMode(true);
442 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
443 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
444
445 // Necessary for AppListView::StateAnimationMetricsReporter::Report being
446 // called when animation ends.
447 ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
448 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
449 AppListView::SetShortAnimationForTesting(false);
450
451 ui::test::EventGenerator* generator = GetEventGenerator();
452
453 // Gesture tap on the search box.
454 generator->GestureTapAt(GetPointInsideSearchbox());
455
456 // Wait until animation finishes. Verifies AppListView's state.
457 base::RunLoop().RunUntilIdle();
458 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
459
460 // Gesture tap on the area out of search box.
461 generator->GestureTapAt(GetPointOutsideSearchbox());
462
463 // Wait until animation finishes. Verifies AppListView's state.
464 base::RunLoop().RunUntilIdle();
465 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
466 }
467
TEST_F(AppListPresenterDelegateTest,RemoveSuggestionShowsConfirmDialog)468 TEST_F(AppListPresenterDelegateTest, RemoveSuggestionShowsConfirmDialog) {
469 ShowZeroStateSearchInHalfState();
470
471 // Mark the privacy notices as dismissed so that they do not interfere with
472 // the layout.
473 Shell::Get()->app_list_controller()->MarkAssistantPrivacyInfoDismissed();
474 Shell::Get()->app_list_controller()->MarkSuggestedContentInfoDismissed();
475 GetAppListView()
476 ->app_list_main_view()
477 ->contents_view()
478 ->privacy_container_view()
479 ->Update();
480
481 // Add a zero state suggestion results - the result that will be tested is in
482 // the second place.
483 Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
484 CreateOmniboxSuggestionResult("Another suggestion"));
485 const std::string kTestResultId = "Test suggestion";
486 Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
487 CreateOmniboxSuggestionResult(kTestResultId));
488 // The result list is updated asynchronously.
489 GetAppListTestHelper()->WaitUntilIdle();
490
491 SearchResultBaseView* result_view = GetSearchResultListViewItemAt(1);
492 ASSERT_TRUE(result_view);
493 ASSERT_TRUE(result_view->result());
494 ASSERT_EQ(kTestResultId, result_view->result()->id());
495
496 // Make sure the search results page is laid out after adding result action
497 // buttons.
498 GetAppListView()->GetWidget()->LayoutRootViewIfNecessary();
499
500 ASSERT_TRUE(result_view->actions_view());
501 EXPECT_EQ(1u, result_view->actions_view()->children().size());
502 views::View* const action_view = result_view->actions_view()->children()[0];
503
504 // The remove action button is visible on hover only.
505 EXPECT_FALSE(action_view->GetVisible());
506
507 ui::test::EventGenerator* generator = GetEventGenerator();
508 generator->MoveMouseTo(result_view->GetBoundsInScreen().CenterPoint());
509 EXPECT_TRUE(action_view->GetVisible());
510
511 // Ensure layout after the action view visibility has been updated.
512 GetAppListView()->GetWidget()->LayoutRootViewIfNecessary();
513
514 // Click the remove action button, this should surface a confirmation dialog.
515 ClickMouseAt(action_view->GetBoundsInScreen().CenterPoint());
516
517 EXPECT_TRUE(GetAppListTestHelper()
518 ->app_list_client()
519 ->GetAndClearInvokedResultActions()
520 .empty());
521 ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
522
523 // Cancel the dialog - the app list should remain in the search result page,
524 // the suggestion removal dialog should be hidden, and no result action should
525 // be invoked.
526 GetSearchResultPageAnchoredDialog()->CancelDialog();
527
528 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
529 EXPECT_FALSE(search_result_page()->anchored_dialog_for_test());
530 EXPECT_TRUE(GetAppListTestHelper()
531 ->app_list_client()
532 ->GetAndClearInvokedResultActions()
533 .empty());
534
535 // Click remove suggestion action button again.
536 ClickMouseAt(action_view->GetBoundsInScreen().CenterPoint());
537
538 // Expect the removal confirmation dialog - this time, accept it.
539 ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
540 GetSearchResultPageAnchoredDialog()->AcceptDialog();
541
542 // The app list should remain showing search results, the dialog should be
543 // closed, and result removal action should be invoked.
544 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
545 EXPECT_FALSE(search_result_page()->anchored_dialog_for_test());
546
547 std::vector<TestAppListClient::SearchResultActionId> expected_actions = {
548 {kTestResultId, OmniBoxZeroStateAction::kRemoveSuggestion}};
549 std::vector<TestAppListClient::SearchResultActionId> invoked_actions =
550 GetAppListTestHelper()
551 ->app_list_client()
552 ->GetAndClearInvokedResultActions();
553 EXPECT_EQ(expected_actions, invoked_actions);
554 }
555
TEST_F(AppListPresenterDelegateTest,RemoveSuggestionUsingLongTap)556 TEST_F(AppListPresenterDelegateTest, RemoveSuggestionUsingLongTap) {
557 ShowZeroStateSearchInHalfState();
558
559 // Add a zero state suggestion results - the result that will be tested is in
560 // the second place.
561 Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
562 CreateOmniboxSuggestionResult("Another suggestion"));
563 const std::string kTestResultId = "Test suggestion";
564 Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
565 CreateOmniboxSuggestionResult(kTestResultId));
566 GetAppListTestHelper()->WaitUntilIdle();
567
568 SearchResultBaseView* result_view = GetSearchResultListViewItemAt(1);
569 ASSERT_TRUE(result_view);
570 ASSERT_TRUE(result_view->result());
571 ASSERT_EQ(kTestResultId, result_view->result()->id());
572
573 // Make sure the search results page is laid out after adding result action
574 // buttons.
575 GetAppListView()->GetWidget()->LayoutRootViewIfNecessary();
576
577 // Long tap on the search result. This should show the removal confirmation
578 // dialog.
579 LongPressAt(result_view->GetBoundsInScreen().CenterPoint());
580
581 EXPECT_TRUE(result_view->selected());
582 EXPECT_TRUE(GetAppListTestHelper()
583 ->app_list_client()
584 ->GetAndClearInvokedResultActions()
585 .empty());
586 ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
587
588 // Cancel the dialog - the app list should remain in the search result page,
589 // the suggestion removal dialog should be hidden, and no result action should
590 // be invoked.
591 GetSearchResultPageAnchoredDialog()->CancelDialog();
592
593 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
594 EXPECT_FALSE(search_result_page()->anchored_dialog_for_test());
595 EXPECT_TRUE(GetAppListTestHelper()
596 ->app_list_client()
597 ->GetAndClearInvokedResultActions()
598 .empty());
599 EXPECT_FALSE(result_view->selected());
600
601 // Long tap on the result again.
602 LongPressAt(result_view->GetBoundsInScreen().CenterPoint());
603
604 // Expect the removal confirmation dialog - this time, accept it.
605 ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
606 GetSearchResultPageAnchoredDialog()->AcceptDialog();
607
608 // The app list should remain showing search results, the dialog should be
609 // closed, and result removal action should be invoked.
610 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
611 EXPECT_FALSE(search_result_page()->anchored_dialog_for_test());
612 EXPECT_FALSE(result_view->selected());
613
614 std::vector<TestAppListClient::SearchResultActionId> expected_actions = {
615 {kTestResultId, OmniBoxZeroStateAction::kRemoveSuggestion}};
616
617 std::vector<TestAppListClient::SearchResultActionId> invoked_actions =
618 GetAppListTestHelper()
619 ->app_list_client()
620 ->GetAndClearInvokedResultActions();
621 EXPECT_EQ(expected_actions, invoked_actions);
622 }
623
TEST_F(AppListPresenterDelegateTest,RemoveSuggestionDialogAnimatesWithAppListView)624 TEST_F(AppListPresenterDelegateTest,
625 RemoveSuggestionDialogAnimatesWithAppListView) {
626 ShowZeroStateSearchInHalfState();
627
628 // Add a zero state suggestion result.
629 const std::string kTestResultId = "Test suggestion";
630 Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
631 CreateOmniboxSuggestionResult(kTestResultId));
632 GetAppListTestHelper()->WaitUntilIdle();
633
634 SearchResultBaseView* result_view = GetSearchResultListViewItemAt(0);
635 ASSERT_TRUE(result_view);
636 ASSERT_TRUE(result_view->result());
637 ASSERT_EQ(kTestResultId, result_view->result()->id());
638
639 // Show remove suggestion dialog.
640 LongPressAt(result_view->GetBoundsInScreen().CenterPoint());
641 ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
642
643 views::Widget* const confirmation_dialog =
644 search_result_page()->anchored_dialog_for_test()->widget();
645 ASSERT_TRUE(confirmation_dialog);
646
647 SanityCheckSearchResultsAnchoredDialogBounds(confirmation_dialog);
648 const gfx::Rect initial_dialog_bounds =
649 confirmation_dialog->GetWindowBoundsInScreen();
650
651 ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
652 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
653 AppListView::SetShortAnimationForTesting(false);
654
655 // Transition to fullscreen search state.
656 GetAppListView()->SetState(AppListViewState::kFullscreenSearch);
657 ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
658
659 EXPECT_NE(confirmation_dialog->GetLayer()->transform(), gfx::Transform());
660 EXPECT_EQ(confirmation_dialog->GetLayer()->GetTargetTransform(),
661 gfx::Transform());
662
663 // Verify that the dialog position in screen does not change when the
664 // animation starts.
665 gfx::RectF current_bounds(confirmation_dialog->GetWindowBoundsInScreen());
666 confirmation_dialog->GetLayer()->transform().TransformRect(¤t_bounds);
667 EXPECT_EQ(gfx::RectF(initial_dialog_bounds), current_bounds);
668 }
669
TEST_F(AppListPresenterDelegateTest,RemoveSuggestionDialogBoundsUpdateWithAppListState)670 TEST_F(AppListPresenterDelegateTest,
671 RemoveSuggestionDialogBoundsUpdateWithAppListState) {
672 ShowZeroStateSearchInHalfState();
673
674 // Add a zero state suggestion result.
675 const std::string kTestResultId = "Test suggestion";
676 Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
677 CreateOmniboxSuggestionResult(kTestResultId));
678 GetAppListTestHelper()->WaitUntilIdle();
679
680 SearchResultBaseView* result_view = GetSearchResultListViewItemAt(0);
681 ASSERT_TRUE(result_view);
682 ASSERT_TRUE(result_view->result());
683 ASSERT_EQ(kTestResultId, result_view->result()->id());
684
685 // Show the remove suggestion dialog.
686 LongPressAt(result_view->GetBoundsInScreen().CenterPoint());
687 ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
688
689 views::Widget* const confirmation_dialog =
690 search_result_page()->anchored_dialog_for_test()->widget();
691 ASSERT_TRUE(confirmation_dialog);
692
693 SCOPED_TRACE("Initial confirmation dialog bounds");
694 SanityCheckSearchResultsAnchoredDialogBounds(confirmation_dialog);
695 const int dialog_margin =
696 GetSearchResultsAnchoredDialogTopOffset(confirmation_dialog);
697
698 // Transition to fullscreen search state.
699 GetAppListView()->SetState(AppListViewState::kFullscreenSearch);
700 ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
701
702 // Verify that the confirmation dialog followed the search box widget.
703 SCOPED_TRACE("Confirmation dialog bounds after transition");
704 SanityCheckSearchResultsAnchoredDialogBounds(confirmation_dialog);
705 EXPECT_EQ(dialog_margin,
706 GetSearchResultsAnchoredDialogTopOffset(confirmation_dialog));
707 }
708
TEST_F(AppListPresenterDelegateTest,TransitionToAppsContainerClosesRemoveSuggestionDialog)709 TEST_F(AppListPresenterDelegateTest,
710 TransitionToAppsContainerClosesRemoveSuggestionDialog) {
711 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
712 GetAppListView()->SetState(AppListViewState::kFullscreenAllApps);
713 ui::test::EventGenerator* generator = GetEventGenerator();
714 generator->GestureTapAt(GetPointInsideSearchbox());
715 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
716
717 // Add a zero state suggestion result.
718 const std::string kTestResultId = "Test suggestion";
719 Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
720 CreateOmniboxSuggestionResult(kTestResultId));
721 GetAppListTestHelper()->WaitUntilIdle();
722
723 SearchResultBaseView* result_view = GetSearchResultListViewItemAt(0);
724 ASSERT_TRUE(result_view);
725 ASSERT_TRUE(result_view->result());
726 ASSERT_EQ(kTestResultId, result_view->result()->id());
727
728 // Show remove suggestion dialog.
729 ui::TouchEvent long_press(
730 ui::ET_GESTURE_LONG_PRESS, result_view->GetBoundsInScreen().CenterPoint(),
731 base::TimeTicks::Now(), ui::PointerDetails(ui::EventPointerType::kTouch));
732 GetEventGenerator()->Dispatch(&long_press);
733 ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
734
735 views::Widget* const confirmation_dialog =
736 search_result_page()->anchored_dialog_for_test()->widget();
737 ASSERT_TRUE(confirmation_dialog);
738
739 SanityCheckSearchResultsAnchoredDialogBounds(confirmation_dialog);
740
741 // Verify that transition to apps page hides the removal confirmation dialog.
742 views::test::WidgetClosingObserver widget_close_waiter(confirmation_dialog);
743 GetAppListView()->SetState(AppListViewState::kFullscreenAllApps);
744
745 widget_close_waiter.Wait();
746 }
747
TEST_F(AppListPresenterDelegateTest,RemoveSuggestionDialogBoundsUpdateWhenVKHidden)748 TEST_F(AppListPresenterDelegateTest,
749 RemoveSuggestionDialogBoundsUpdateWhenVKHidden) {
750 // Enable virtual keyboard for this test.
751 KeyboardController* const keyboard_controller =
752 Shell::Get()->keyboard_controller();
753 keyboard_controller->SetEnableFlag(
754 keyboard::KeyboardEnableFlag::kCommandLineEnabled);
755
756 ShowZeroStateSearchInHalfState();
757
758 // Add a zero state suggestion result.
759 const std::string kTestResultId = "Test suggestion";
760 Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
761 CreateOmniboxSuggestionResult(kTestResultId));
762 GetAppListTestHelper()->WaitUntilIdle();
763
764 SearchResultBaseView* result_view = GetSearchResultListViewItemAt(0);
765 ASSERT_TRUE(result_view);
766 ASSERT_TRUE(result_view->result());
767 ASSERT_EQ(kTestResultId, result_view->result()->id());
768
769 auto* const keyboard_ui_controller = keyboard::KeyboardUIController::Get();
770 keyboard_ui_controller->ShowKeyboard(false /* locked */);
771 ASSERT_TRUE(keyboard::WaitUntilShown());
772
773 // Show remove suggestion dialog.
774 LongPressAt(result_view->GetBoundsInScreen().CenterPoint());
775 ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
776
777 // The search box should have lost the focus, which should have hidden the
778 // keyboard.
779 EXPECT_FALSE(keyboard_ui_controller->IsKeyboardVisible());
780
781 // Sanity check the confirmation dialog bounds (hiding the keyboard might have
782 // changed the position of the search box - the confirmation dialog should
783 // have followed it).
784 views::Widget* const confirmation_dialog =
785 search_result_page()->anchored_dialog_for_test()->widget();
786 SanityCheckSearchResultsAnchoredDialogBounds(confirmation_dialog);
787
788 views::test::WidgetClosingObserver widget_close_waiter(confirmation_dialog);
789
790 // Go to peeking state, and verify the keyboard is not reshown.
791 GetAppListView()->SetState(AppListViewState::kPeeking);
792 GetAppListTestHelper()->WaitUntilIdle();
793 // Exiting the search results page should close the dialog.
794 widget_close_waiter.Wait();
795 EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
796
797 GetAppListTestHelper()->DismissAndRunLoop();
798 GetAppListTestHelper()->CheckVisibility(false);
799 EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
800 }
801
802 // Verifies that the downward mouse drag on AppsGridView's first page should
803 // be handled by AppList.
TEST_F(PopulatedAppListTest,MouseDragAppsGridViewHandledByAppList)804 TEST_F(PopulatedAppListTest, MouseDragAppsGridViewHandledByAppList) {
805 InitializeAppsGrid();
806 app_list_test_model_->PopulateApps(2);
807 ShowAppListInAppsFullScreen();
808
809 // Calculate the drag start/end points.
810 gfx::Point drag_start_point = apps_grid_view_->GetBoundsInScreen().origin();
811 gfx::Point target_point = GetPrimaryDisplay().bounds().bottom_left();
812 target_point.set_x(drag_start_point.x());
813
814 // Drag AppsGridView downward by mouse. Check the following things:
815 // (1) Mouse events are processed by AppsGridView, including mouse press,
816 // mouse drag and mouse release.
817 // (2) AppList is closed after mouse drag.
818 ui::test::EventGenerator* event_generator = GetEventGenerator();
819 event_generator->MoveMouseTo(drag_start_point);
820 event_generator->DragMouseTo(target_point);
821 event_generator->ReleaseLeftButton();
822
823 base::RunLoop().RunUntilIdle();
824 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
825 }
826
827 // Verifies that the upward mouse drag on AppsGridView's first page should
828 // be handled by PaginationController.
TEST_F(PopulatedAppListTest,MouseDragAppsGridViewHandledByPaginationController)829 TEST_F(PopulatedAppListTest,
830 MouseDragAppsGridViewHandledByPaginationController) {
831 InitializeAppsGrid();
832 app_list_test_model_->PopulateApps(apps_grid_test_api_->TilesPerPage(0) + 1);
833 EXPECT_EQ(2, apps_grid_view_->pagination_model()->total_pages());
834 ShowAppListInAppsFullScreen();
835
836 // Calculate the drag start/end points. |drag_start_point| is between the
837 // first and the second AppListItem. Because in this test case, we want
838 // AppsGridView to receive mouse events instead of AppListItemView.
839 gfx::Point right_side =
840 apps_grid_view_->GetItemViewAt(0)->GetBoundsInScreen().right_center();
841 gfx::Point left_side =
842 apps_grid_view_->GetItemViewAt(1)->GetBoundsInScreen().left_center();
843 ASSERT_EQ(left_side.y(), right_side.y());
844 gfx::Point drag_start_point((right_side.x() + left_side.x()) / 2,
845 right_side.y());
846 gfx::Point target_point = GetPrimaryDisplay().bounds().top_right();
847 target_point.set_x(drag_start_point.x());
848
849 // Drag AppsGridView downward by mouse. Checks that PaginationController
850 // records the mouse drag.
851 base::HistogramTester histogram_tester;
852 ui::test::EventGenerator* event_generator = GetEventGenerator();
853 event_generator->MoveMouseTo(drag_start_point);
854 event_generator->DragMouseTo(target_point);
855 event_generator->ReleaseLeftButton();
856 histogram_tester.ExpectUniqueSample(
857 kAppListPageSwitcherSourceHistogramInClamshell,
858 AppListPageSwitcherSource::kMouseDrag, 1);
859 }
860
861 // Tests that mouse app list item drag is cancelled when mouse capture is lost
862 // (e.g. on screen rotation).
TEST_F(PopulatedAppListTest,CancelItemDragOnMouseCaptureLoss)863 TEST_F(PopulatedAppListTest, CancelItemDragOnMouseCaptureLoss) {
864 InitializeAppsGrid();
865 app_list_test_model_->PopulateApps(apps_grid_test_api_->TilesPerPage(0) + 1);
866 ShowAppListInAppsFullScreen();
867
868 AppListItemView* const dragged_view = apps_grid_view_->GetItemViewAt(0);
869
870 // Start dragging the first item - move it in between items 1 and 2.
871 ui::test::EventGenerator* event_generator = GetEventGenerator();
872 event_generator->MoveMouseTo(dragged_view->GetBoundsInScreen().CenterPoint());
873 event_generator->PressLeftButton();
874 dragged_view->FireMouseDragTimerForTest();
875 event_generator->MoveMouseTo(
876 apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().left_center());
877 EXPECT_TRUE(apps_grid_view_->dragging());
878
879 display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
880 display_manager()->SetDisplayRotation(
881 display.id(), display::Display::ROTATE_270,
882 display::Display::RotationSource::ACTIVE);
883 // AppListView is usually notified of display bounds changes by
884 // AppListPresenterDelegate, though the test delegate implementation does not
885 // track display metrics changes, so OnParentWindowBoundsChanged() has to be
886 // explicitly called here.
887 app_list_view_->OnParentWindowBoundsChanged();
888
889 // Verify that mouse drag has been canceled due to mouse capture loss.
890 EXPECT_FALSE(apps_grid_view_->dragging());
891 EXPECT_EQ("Item 0", apps_grid_view_->GetItemViewAt(0)->item()->id());
892 EXPECT_EQ("Item 1", apps_grid_view_->GetItemViewAt(1)->item()->id());
893 EXPECT_EQ("Item 2", apps_grid_view_->GetItemViewAt(2)->item()->id());
894 }
895
896 // Tests that apps grid item layers are not destroyed immediately after item
897 // drag ends.
TEST_F(PopulatedAppListTest,ItemLayersNotDestroyedDuringBoundsAnimationAfterDrag)898 TEST_F(PopulatedAppListTest,
899 ItemLayersNotDestroyedDuringBoundsAnimationAfterDrag) {
900 InitializeAppsGrid();
901 const int kItemCount = 5;
902 app_list_test_model_->PopulateApps(kItemCount);
903 ShowAppListInAppsFullScreen();
904
905 ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
906 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
907 AppListView::SetShortAnimationForTesting(false);
908
909 AppListItemView* const dragged_view = apps_grid_view_->GetItemViewAt(0);
910
911 // Drag the first item between items 1 and 2.
912 ui::test::EventGenerator* event_generator = GetEventGenerator();
913 event_generator->MoveMouseTo(dragged_view->GetBoundsInScreen().CenterPoint());
914 event_generator->PressLeftButton();
915 dragged_view->FireMouseDragTimerForTest();
916 event_generator->MoveMouseTo(
917 apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().left_center());
918
919 // Items should have layers during app list item drag.
920 for (int i = 0; i < kItemCount; ++i) {
921 views::View* item_view = apps_grid_view_->view_model()->view_at(i);
922 EXPECT_TRUE(item_view->layer()) << "at " << i;
923 }
924
925 EXPECT_TRUE(apps_grid_view_->dragging());
926 event_generator->ReleaseLeftButton();
927
928 // After the drag is released, the item bounds should animate to their final
929 // bounds.
930 EXPECT_TRUE(apps_grid_view_->bounds_animator_for_testing()->IsAnimating());
931 for (int i = 0; i < kItemCount; ++i) {
932 views::View* item_view = apps_grid_view_->view_model()->view_at(i);
933 EXPECT_TRUE(item_view->layer()) << "at " << i;
934 }
935
936 // Layers should be destroyed once the bounds animation completes.
937 apps_grid_view_->bounds_animator_for_testing()->Cancel();
938 for (int i = 0; i < kItemCount; ++i) {
939 views::View* item_view = apps_grid_view_->view_model()->view_at(i);
940 EXPECT_FALSE(item_view->layer()) << "at " << i;
941 }
942 }
943
944 // Tests that apps grid item drag operation can continue normally after display
945 // rotation (and app list config change).
TEST_F(PopulatedAppListTest,ScreenRotationDuringAppsGridItemDrag)946 TEST_F(PopulatedAppListTest, ScreenRotationDuringAppsGridItemDrag) {
947 // Set the display dimensions so rotation also changes the app list config.
948 UpdateDisplay("1200x600");
949
950 InitializeAppsGrid();
951 app_list_test_model_->PopulateApps(apps_grid_test_api_->TilesPerPage(0) + 1);
952 ShowAppListInAppsFullScreen();
953
954 AppListItemView* const dragged_view = apps_grid_view_->GetItemViewAt(0);
955
956 // Start dragging the first item.
957 ui::test::EventGenerator* event_generator = GetEventGenerator();
958 event_generator->MoveTouch(dragged_view->GetBoundsInScreen().CenterPoint());
959 event_generator->PressTouch();
960 ASSERT_TRUE(dragged_view->FireTouchDragTimerForTest());
961
962 event_generator->MoveTouch(
963 apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().CenterPoint());
964
965 display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
966 display_manager()->SetDisplayRotation(
967 display.id(), display::Display::ROTATE_270,
968 display::Display::RotationSource::ACTIVE);
969 // AppListView is usually notified of display bounds changes by
970 // AppListPresenterDelegate, though the test delegate implementation does not
971 // track display metrics changes, so OnParentWindowBoundsChanged() has to be
972 // explicitly called here.
973 app_list_view_->OnParentWindowBoundsChanged();
974
975 // End drag at the in between items 1 and 2 - note that these have been
976 // translated one slot left to fill in space left by the dragged view, so the
977 // expected drop slot is actually slot 1.
978 event_generator->MoveTouch(
979 apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().left_center());
980 event_generator->ReleaseTouch();
981
982 EXPECT_EQ("Item 1", apps_grid_view_->GetItemViewAt(0)->item()->id());
983 EXPECT_EQ("Item 0", apps_grid_view_->GetItemViewAt(1)->item()->id());
984 }
985
986 // Tests screen rotation during apps grid item drag where the drag item ends up
987 // in page-scroll area. Tests that the apps grid page scrolls without a crash,
988 // and that releasing drag does not change the item position in the model.
TEST_F(PopulatedAppListTest,ScreenRotationDuringAppsGridItemDragWithPageScroll)989 TEST_F(PopulatedAppListTest,
990 ScreenRotationDuringAppsGridItemDragWithPageScroll) {
991 // Set the display dimensions so rotation also changes the app list config.
992 UpdateDisplay("1200x600");
993
994 InitializeAppsGrid();
995 app_list_test_model_->PopulateApps(apps_grid_test_api_->TilesPerPage(0) + 1);
996 ShowAppListInAppsFullScreen();
997
998 AppListItemView* const dragged_view = apps_grid_view_->GetItemViewAt(0);
999
1000 // Start dragging the first item.
1001 ui::test::EventGenerator* event_generator = GetEventGenerator();
1002 event_generator->MoveTouch(dragged_view->GetBoundsInScreen().CenterPoint());
1003 event_generator->PressTouch();
1004 ASSERT_TRUE(dragged_view->FireTouchDragTimerForTest());
1005
1006 // Move the item close to screen edge, so it ends up in area that triggers
1007 // page scroll after rotation.
1008 event_generator->MoveTouch(app_list_view_->GetBoundsInScreen().left_center() +
1009 gfx::Vector2d(100, 0));
1010
1011 display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
1012 display_manager()->SetDisplayRotation(
1013 display.id(), display::Display::ROTATE_90,
1014 display::Display::RotationSource::ACTIVE);
1015 // AppListView is usually notified of display bounds changes by
1016 // AppListPresenterDelegate, though the test delegate implementation does not
1017 // track display metrics changes, so OnParentWindowBoundsChanged() has to be
1018 // explicitly called here.
1019 app_list_view_->OnParentWindowBoundsChanged();
1020
1021 event_generator->MoveTouchBy(0, 10);
1022 EXPECT_TRUE(apps_grid_view_->FirePageFlipTimerForTest());
1023 event_generator->ReleaseTouch();
1024
1025 // The model state should not have been changed.
1026 EXPECT_EQ("Item 0", apps_grid_view_->GetItemViewAt(0)->item()->id());
1027 EXPECT_EQ("Item 1", apps_grid_view_->GetItemViewAt(1)->item()->id());
1028 EXPECT_EQ("Item 2", apps_grid_view_->GetItemViewAt(2)->item()->id());
1029 }
1030
1031 // Tests screen rotation while app list folder item is in progress, and the item
1032 // remains in the folder bounds during the drag.
TEST_F(PopulatedAppListTest,ScreenRotationDuringFolderItemDrag)1033 TEST_F(PopulatedAppListTest, ScreenRotationDuringFolderItemDrag) {
1034 // Set the display dimensions so rotation also changes the app list config.
1035 UpdateDisplay("1200x600");
1036
1037 InitializeAppsGrid();
1038 app_list_test_model_->PopulateApps(2);
1039 AppListFolderItem* folder =
1040 app_list_test_model_->CreateAndPopulateFolderWithApps(3);
1041 app_list_test_model_->PopulateApps(10);
1042 ShowAppListInAppsFullScreen();
1043
1044 // Tap the folder item to show it.
1045 ui::test::EventGenerator* event_generator = GetEventGenerator();
1046 event_generator->GestureTapAt(
1047 apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().CenterPoint());
1048 ASSERT_TRUE(AppListIsInFolderView());
1049
1050 // Start dragging the first item in the active folder.
1051 AppListItemView* const dragged_view =
1052 folder_view()->items_grid_view()->GetItemViewAt(0);
1053 event_generator->MoveTouch(dragged_view->GetBoundsInScreen().CenterPoint());
1054 event_generator->PressTouch();
1055 ASSERT_TRUE(dragged_view->FireTouchDragTimerForTest());
1056
1057 // Drag the item within the folder bounds.
1058 event_generator->MoveTouch(
1059 apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().CenterPoint());
1060
1061 display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
1062 display_manager()->SetDisplayRotation(
1063 display.id(), display::Display::ROTATE_270,
1064 display::Display::RotationSource::ACTIVE);
1065 // AppListView is usually notified of display bounds changes by
1066 // AppListPresenterDelegate, though the test delegate implementation does not
1067 // track display metrics changes, so OnParentWindowBoundsChanged() has to be
1068 // explicitly called here.
1069 app_list_view_->OnParentWindowBoundsChanged();
1070
1071 // The current behavior on app list bounds change is to close the active
1072 // folder, canceling the drag.
1073 EXPECT_FALSE(AppListIsInFolderView());
1074 EXPECT_FALSE(apps_grid_view_->dragging());
1075 EXPECT_FALSE(folder_view()->items_grid_view()->dragging());
1076
1077 EXPECT_EQ("Item 0", apps_grid_view_->GetItemViewAt(0)->item()->id());
1078 EXPECT_EQ("Item 1", apps_grid_view_->GetItemViewAt(1)->item()->id());
1079 EXPECT_EQ(folder->id(), apps_grid_view_->GetItemViewAt(2)->item()->id());
1080 EXPECT_EQ(dragged_view, folder_view()->items_grid_view()->GetItemViewAt(0));
1081 EXPECT_EQ("Item 3", apps_grid_view_->GetItemViewAt(3)->item()->id());
1082 }
1083
1084 // Tests that app list folder item reparenting drag (where a folder item is
1085 // dragged outside the folder bounds, and dropped within the apps grid) can
1086 // continue normally after screen rotation.
TEST_F(PopulatedAppListTest,ScreenRotationDuringAppsGridItemReparentDrag)1087 TEST_F(PopulatedAppListTest, ScreenRotationDuringAppsGridItemReparentDrag) {
1088 UpdateDisplay("1200x600");
1089
1090 InitializeAppsGrid();
1091 app_list_test_model_->PopulateApps(2);
1092 AppListFolderItem* folder =
1093 app_list_test_model_->CreateAndPopulateFolderWithApps(3);
1094 app_list_test_model_->PopulateApps(10);
1095 ShowAppListInAppsFullScreen();
1096
1097 // Tap the folder item to show it.
1098 ui::test::EventGenerator* event_generator = GetEventGenerator();
1099 event_generator->GestureTapAt(
1100 apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().CenterPoint());
1101 ASSERT_TRUE(AppListIsInFolderView());
1102
1103 // Start dragging the first item in the active folder.
1104 AppListItemView* dragged_view =
1105 folder_view()->items_grid_view()->GetItemViewAt(0);
1106 event_generator->MoveTouch(dragged_view->GetBoundsInScreen().CenterPoint());
1107 event_generator->PressTouch();
1108 ASSERT_TRUE(dragged_view->FireTouchDragTimerForTest());
1109
1110 // Drag the item outside the folder bounds.
1111 event_generator->MoveTouch(
1112 apps_grid_view_->GetItemViewAt(1)->GetBoundsInScreen().CenterPoint());
1113 event_generator->MoveTouchBy(2, 2);
1114
1115 // Fire reparenting timer.
1116 EXPECT_TRUE(
1117 folder_view()->items_grid_view()->FireFolderItemReparentTimerForTest());
1118 EXPECT_FALSE(AppListIsInFolderView());
1119
1120 display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
1121 display_manager()->SetDisplayRotation(
1122 display.id(), display::Display::ROTATE_270,
1123 display::Display::RotationSource::ACTIVE);
1124 // AppListView is usually notified of display bounds changes by
1125 // AppListPresenterDelegate, though the test delegate implementation does not
1126 // track display metrics changes, so OnParentWindowBoundsChanged() has to be
1127 // explicitly called here.
1128 app_list_view_->OnParentWindowBoundsChanged();
1129
1130 // End drag at the in between items 1 and 2.
1131 event_generator->MoveTouch(
1132 apps_grid_view_->GetItemViewAt(1)->GetBoundsInScreen().right_center());
1133 event_generator->ReleaseTouch();
1134
1135 // Verify the new item location within the apps grid.
1136 EXPECT_EQ("Item 0", apps_grid_view_->GetItemViewAt(0)->item()->id());
1137 EXPECT_EQ("Item 1", apps_grid_view_->GetItemViewAt(1)->item()->id());
1138 EXPECT_EQ(dragged_view->item()->id(),
1139 apps_grid_view_->GetItemViewAt(2)->item()->id());
1140 EXPECT_EQ(folder->id(), apps_grid_view_->GetItemViewAt(3)->item()->id());
1141 }
1142
1143 // Tests that app list folder item reparenting drag to another folder.
TEST_F(PopulatedAppListTest,AppsGridItemReparentToFolderDrag)1144 TEST_F(PopulatedAppListTest, AppsGridItemReparentToFolderDrag) {
1145 UpdateDisplay("1200x600");
1146
1147 InitializeAppsGrid();
1148 app_list_test_model_->PopulateApps(2);
1149 AppListFolderItem* folder =
1150 app_list_test_model_->CreateAndPopulateFolderWithApps(3);
1151 app_list_test_model_->PopulateApps(10);
1152 ShowAppListInAppsFullScreen();
1153
1154 // Tap the folder item to show it.
1155 ui::test::EventGenerator* event_generator = GetEventGenerator();
1156 event_generator->GestureTapAt(
1157 apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().CenterPoint());
1158 ASSERT_TRUE(AppListIsInFolderView());
1159
1160 // Start dragging the first item in the active folder.
1161 AppListItemView* dragged_view =
1162 folder_view()->items_grid_view()->GetItemViewAt(0);
1163 event_generator->MoveTouch(dragged_view->GetBoundsInScreen().CenterPoint());
1164 event_generator->PressTouch();
1165 ASSERT_TRUE(dragged_view->FireTouchDragTimerForTest());
1166
1167 // Drag the item outside the folder bounds.
1168 event_generator->MoveTouch(
1169 apps_grid_view_->GetItemViewAt(0)->GetBoundsInScreen().CenterPoint());
1170 event_generator->MoveTouchBy(2, 2);
1171
1172 EXPECT_TRUE(
1173 folder_view()->items_grid_view()->FireFolderItemReparentTimerForTest());
1174 EXPECT_FALSE(AppListIsInFolderView());
1175
1176 // Move the pointer over the item 3, and drop the dragged item.
1177 gfx::Point target =
1178 apps_grid_view_->GetItemViewAt(3)->GetBoundsInScreen().CenterPoint();
1179 event_generator->MoveTouch(target);
1180 EXPECT_TRUE(apps_grid_view_->FireFolderDroppingTimerForTest());
1181 event_generator->ReleaseTouch();
1182
1183 // Verify the new item location within the apps grid.
1184 EXPECT_EQ("Item 0", apps_grid_view_->GetItemViewAt(0)->item()->id());
1185 EXPECT_EQ("Item 1", apps_grid_view_->GetItemViewAt(1)->item()->id());
1186 EXPECT_EQ(folder->id(), apps_grid_view_->GetItemViewAt(2)->item()->id());
1187
1188 EXPECT_TRUE(apps_grid_view_->GetItemViewAt(3)->item()->is_folder());
1189 EXPECT_EQ(dragged_view->item()->folder_id(),
1190 apps_grid_view_->GetItemViewAt(3)->item()->id());
1191 }
1192
1193 // Tests that an item can be removed just after creating a folder that contains
1194 // that item. See https://crbug.com/1083942
TEST_F(PopulatedAppListTest,RemoveFolderItemAfterFolderCreation)1195 TEST_F(PopulatedAppListTest, RemoveFolderItemAfterFolderCreation) {
1196 InitializeAppsGrid();
1197 const int kItemCount = 5;
1198 app_list_test_model_->PopulateApps(kItemCount);
1199 ShowAppListInAppsFullScreen();
1200
1201 // Dragging the item with index 4.
1202 AppListItemView* const dragged_view = apps_grid_view_->GetItemViewAt(4);
1203 AppListItem* const dragged_item = dragged_view->item();
1204
1205 // Drag the item on top of the item with index 3.
1206 ui::test::EventGenerator* event_generator = GetEventGenerator();
1207 event_generator->MoveMouseTo(dragged_view->GetBoundsInScreen().CenterPoint());
1208 event_generator->PressLeftButton();
1209 dragged_view->FireMouseDragTimerForTest();
1210 event_generator->MoveMouseTo(
1211 apps_grid_view_->GetItemViewAt(3)->GetBoundsInScreen().CenterPoint());
1212 EXPECT_TRUE(apps_grid_view_->FireFolderDroppingTimerForTest());
1213 event_generator->ReleaseLeftButton();
1214 EXPECT_FALSE(apps_grid_view_->dragging());
1215
1216 EXPECT_TRUE(apps_grid_view_->GetItemViewAt(3)->item()->is_folder());
1217 EXPECT_EQ(dragged_item->folder_id(),
1218 apps_grid_view_->GetItemViewAt(3)->item()->id());
1219
1220 // Verify that item layers have been destroyed after the drag operation ended.
1221 apps_grid_test_api_->WaitForItemMoveAnimationDone();
1222
1223 for (int i = 0; i < apps_grid_view_->view_model()->view_size(); ++i) {
1224 views::View* item_view = apps_grid_view_->view_model()->view_at(i);
1225 EXPECT_FALSE(item_view->layer()) << "at " << i;
1226 }
1227
1228 // Open the newly created folder.
1229 event_generator->MoveMouseTo(
1230 apps_grid_view_->GetItemViewAt(3)->GetBoundsInScreen().CenterPoint());
1231 event_generator->ClickLeftButton();
1232 event_generator->ReleaseLeftButton();
1233
1234 // Verify that item views have no layers after the folder has been opened.
1235 apps_grid_test_api_->WaitForItemMoveAnimationDone();
1236 EXPECT_TRUE(AppListIsInFolderView());
1237
1238 for (int i = 0; i < apps_grid_view_->view_model()->view_size(); ++i) {
1239 views::View* item_view = apps_grid_view_->view_model()->view_at(i);
1240 EXPECT_FALSE(item_view->layer()) << "at " << i;
1241 }
1242
1243 // Verify that a pending layout, if any, does not cause a crash.
1244 apps_grid_view_->InvalidateLayout();
1245 apps_grid_view_->GetWidget()->LayoutRootViewIfNecessary();
1246
1247 // Remove the original drag view item.
1248 app_list_test_model_->DeleteUninstalledItem(dragged_item->id());
1249 apps_grid_test_api_->WaitForItemMoveAnimationDone();
1250
1251 EXPECT_FALSE(AppListIsInFolderView());
1252 EXPECT_FALSE(apps_grid_view_->GetItemViewAt(3)->item()->is_folder());
1253
1254 // Verify that a pending layout, if any, does not cause a crash.
1255 apps_grid_view_->InvalidateLayout();
1256 apps_grid_view_->GetWidget()->LayoutRootViewIfNecessary();
1257 }
1258
TEST_F(PopulatedAppListWithVKEnabledTest,TappingAppsGridClosesVirtualKeyboard)1259 TEST_F(PopulatedAppListWithVKEnabledTest,
1260 TappingAppsGridClosesVirtualKeyboard) {
1261 InitializeAppsGrid();
1262 app_list_test_model_->PopulateApps(2);
1263 gfx::Point between_apps = GetItemRectOnCurrentPageAt(0, 0).right_center();
1264 gfx::Point empty_space = GetItemRectOnCurrentPageAt(0, 2).CenterPoint();
1265
1266 ui::GestureEvent tap_between(between_apps.x(), between_apps.y(), 0,
1267 base::TimeTicks(),
1268 ui::GestureEventDetails(ui::ET_GESTURE_TAP));
1269 ui::GestureEvent tap_outside(empty_space.x(), empty_space.y(), 0,
1270 base::TimeTicks(),
1271 ui::GestureEventDetails(ui::ET_GESTURE_TAP));
1272
1273 // Manually show the virtual keyboard.
1274 auto* const keyboard_controller = keyboard::KeyboardUIController::Get();
1275 keyboard_controller->ShowKeyboard(true /* locked */);
1276 ASSERT_TRUE(keyboard::WaitUntilShown());
1277
1278 // Touch the apps_grid outside of any apps
1279 apps_grid_view_->OnGestureEvent(&tap_outside);
1280 // Expect that the event is ignored here and allowed to propogate to app_list
1281 EXPECT_FALSE(tap_outside.handled());
1282 // Hit the app_list with the same event
1283 app_list_view_->OnGestureEvent(&tap_outside);
1284 // Expect that the event is handled and the keyboard is closed.
1285 EXPECT_TRUE(tap_outside.handled());
1286 EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
1287
1288 // Reshow the VKeyboard
1289 keyboard_controller->ShowKeyboard(true);
1290 ASSERT_TRUE(keyboard::WaitUntilShown());
1291
1292 // Touch the apps_grid between two apps
1293 apps_grid_view_->OnGestureEvent(&tap_between);
1294 // Expect the event to be handled in the grid, and the keyboard to be closed.
1295 EXPECT_TRUE(tap_between.handled());
1296 EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
1297 }
1298
1299 // Tests that a folder item that is dragged to the page flip area and released
1300 // will discard empty pages in the apps grid. If an empty page is not discarded,
1301 // the apps grid crashes (See http://crbug.com/1100011).
TEST_F(PopulatedAppListTest,FolderItemDroppedRemovesBlankPage)1302 TEST_F(PopulatedAppListTest, FolderItemDroppedRemovesBlankPage) {
1303 InitializeAppsGrid();
1304 app_list_test_model_->CreateAndPopulateFolderWithApps(3);
1305 app_list_test_model_->PopulateApps(2);
1306 ShowAppListInAppsFullScreen();
1307 ASSERT_EQ(1, apps_grid_view_->pagination_model()->total_pages());
1308
1309 // Tap the folder item to show its contents.
1310 ui::test::EventGenerator* event_generator = GetEventGenerator();
1311 event_generator->GestureTapAt(
1312 apps_grid_view_->GetItemViewAt(0)->GetBoundsInScreen().CenterPoint());
1313 ASSERT_TRUE(AppListIsInFolderView());
1314
1315 // Start dragging the first item in the active folder.
1316 AppListItemView* dragged_view =
1317 folder_view()->items_grid_view()->GetItemViewAt(0);
1318 event_generator->MoveTouch(dragged_view->GetBoundsInScreen().CenterPoint());
1319 event_generator->PressTouch();
1320 ASSERT_TRUE(dragged_view->FireTouchDragTimerForTest());
1321
1322 // Move the pointer over the page flip area in the apps grid. We first fire
1323 // the folder item reparent timer. The folder view should be hidden.
1324 const gfx::Rect apps_grid_bounds = apps_grid_view_->GetBoundsInScreen();
1325 const gfx::Point page_flip_bottom_center =
1326 gfx::Point(apps_grid_bounds.width() / 2, apps_grid_bounds.bottom() + 1);
1327 event_generator->MoveTouch(page_flip_bottom_center);
1328 event_generator->MoveTouchBy(0, 5);
1329 EXPECT_TRUE(
1330 folder_view()->items_grid_view()->FireFolderItemReparentTimerForTest());
1331 EXPECT_FALSE(AppListIsInFolderView());
1332
1333 // Move again to trigger the page flip timer, fire it and finish the page flip
1334 // animation. There should be 2 pages.
1335 event_generator->MoveTouchBy(0, -10);
1336 EXPECT_TRUE(apps_grid_view_->FirePageFlipTimerForTest());
1337 apps_grid_view_->pagination_model()->FinishAnimation();
1338 EXPECT_EQ(2, apps_grid_view_->pagination_model()->total_pages());
1339
1340 // Release the dragged app. The dragged app should be still in the folder. The
1341 // newly blank page should be discarded and there should be no crash.
1342 event_generator->ReleaseTouch();
1343 EXPECT_EQ(1, apps_grid_view_->pagination_model()->total_pages());
1344 EXPECT_EQ(dragged_view, folder_view()->items_grid_view()->GetItemViewAt(0));
1345 }
1346
1347 // Tests that app list hides when focus moves to a normal window.
TEST_F(AppListPresenterDelegateTest,HideOnFocusOut)1348 TEST_F(AppListPresenterDelegateTest, HideOnFocusOut) {
1349 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1350 GetAppListTestHelper()->CheckVisibility(true);
1351
1352 std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
1353 wm::ActivateWindow(window.get());
1354 GetAppListTestHelper()->WaitUntilIdle();
1355 GetAppListTestHelper()->CheckVisibility(false);
1356 }
1357
1358 // Tests that app list remains visible when focus is moved to a different
1359 // window in kShellWindowId_AppListContainer.
TEST_F(AppListPresenterDelegateTest,RemainVisibleWhenFocusingToApplistContainer)1360 TEST_F(AppListPresenterDelegateTest,
1361 RemainVisibleWhenFocusingToApplistContainer) {
1362 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1363 GetAppListTestHelper()->CheckVisibility(true);
1364
1365 aura::Window* applist_container = Shell::GetContainer(
1366 Shell::GetPrimaryRootWindow(), kShellWindowId_AppListContainer);
1367 std::unique_ptr<aura::Window> window(
1368 aura::test::CreateTestWindowWithId(0, applist_container));
1369 wm::ActivateWindow(window.get());
1370 GetAppListTestHelper()->WaitUntilIdle();
1371
1372 GetAppListTestHelper()->CheckVisibility(true);
1373 }
1374
1375 // Tests opening the app list on a secondary display, then deleting the display.
TEST_F(AppListPresenterDelegateTest,NonPrimaryDisplay)1376 TEST_F(AppListPresenterDelegateTest, NonPrimaryDisplay) {
1377 // Set up a screen with two displays (horizontally adjacent).
1378 UpdateDisplay("1024x768,1024x768");
1379
1380 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1381 ASSERT_EQ(2u, root_windows.size());
1382 ASSERT_EQ("1024,0 1024x768", root_windows[1]->GetBoundsInScreen().ToString());
1383
1384 GetAppListTestHelper()->ShowAndRunLoop(GetSecondaryDisplay().id());
1385 GetAppListTestHelper()->CheckVisibility(true);
1386
1387 // Remove the secondary display. Shouldn't crash (http://crbug.com/368990).
1388 UpdateDisplay("1024x768");
1389
1390 // Updating the displays should close the app list.
1391 GetAppListTestHelper()->WaitUntilIdle();
1392 GetAppListTestHelper()->CheckVisibility(false);
1393 }
1394
1395 // Tests updating display should not close the app list.
TEST_F(AppListPresenterDelegateTest,UpdateDisplayNotCloseAppList)1396 TEST_F(AppListPresenterDelegateTest, UpdateDisplayNotCloseAppList) {
1397 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1398 GetAppListTestHelper()->CheckVisibility(true);
1399
1400 // Change display bounds.
1401 UpdateDisplay("1024x768");
1402
1403 // Updating the display should not close the app list.
1404 GetAppListTestHelper()->WaitUntilIdle();
1405 GetAppListTestHelper()->CheckVisibility(true);
1406 }
1407
1408 // Tests the app list window's bounds under multi-displays environment.
TEST_F(AppListPresenterDelegateTest,AppListWindowBounds)1409 TEST_F(AppListPresenterDelegateTest, AppListWindowBounds) {
1410 // Set up a screen with two displays (horizontally adjacent).
1411 UpdateDisplay("1024x768,1024x768");
1412 const gfx::Size display_size(1024, 768);
1413
1414 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1415 ASSERT_EQ(2u, root_windows.size());
1416
1417 // Test the app list window's bounds on primary display.
1418 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1419 GetAppListTestHelper()->CheckVisibility(true);
1420 const gfx::Rect primary_display_rect(
1421 gfx::Point(0, display_size.height() -
1422 AppListConfig::instance().peeking_app_list_height()),
1423 display_size);
1424 EXPECT_EQ(
1425 primary_display_rect,
1426 GetAppListView()->GetWidget()->GetNativeView()->GetBoundsInScreen());
1427
1428 // Close the app list on primary display.
1429 GetAppListTestHelper()->DismissAndRunLoop();
1430 GetAppListTestHelper()->CheckVisibility(false);
1431
1432 // Test the app list window's bounds on secondary display.
1433 GetAppListTestHelper()->ShowAndRunLoop(GetSecondaryDisplay().id());
1434 GetAppListTestHelper()->CheckVisibility(true);
1435 const gfx::Rect secondary_display_rect(
1436 gfx::Point(display_size.width(),
1437 display_size.height() -
1438 AppListConfig::instance().peeking_app_list_height()),
1439 display_size);
1440 EXPECT_EQ(
1441 secondary_display_rect,
1442 GetAppListView()->GetWidget()->GetNativeView()->GetBoundsInScreen());
1443 }
1444
1445 // Tests that the app list window's bounds and the search box bounds are updated
1446 // when the display bounds change.
TEST_F(AppListPresenterDelegateTest,AppListBoundsChangeForDisplayChange)1447 TEST_F(AppListPresenterDelegateTest, AppListBoundsChangeForDisplayChange) {
1448 UpdateDisplay("1024x768");
1449 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1450 GetAppListTestHelper()->CheckVisibility(true);
1451
1452 const gfx::Rect app_list_bounds =
1453 GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1454 const gfx::Rect search_box_bounds = GetAppListView()
1455 ->search_box_view()
1456 ->GetWidget()
1457 ->GetWindowBoundsInScreen();
1458
1459 UpdateDisplay("800x600");
1460 GetAppListTestHelper()->WaitUntilIdle();
1461 GetAppListTestHelper()->CheckVisibility(true);
1462 const gfx::Rect app_list_bounds2 =
1463 GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1464 const gfx::Rect search_box_bounds2 = GetAppListView()
1465 ->search_box_view()
1466 ->GetWidget()
1467 ->GetWindowBoundsInScreen();
1468 EXPECT_GT(app_list_bounds.size().GetArea(),
1469 app_list_bounds2.size().GetArea());
1470 EXPECT_NE(search_box_bounds, search_box_bounds2);
1471 EXPECT_EQ(400, search_box_bounds2.CenterPoint().x());
1472 }
1473
1474 // Tests that the app list window's bounds and the search box bounds in the half
1475 // state are updated when the display bounds change.
TEST_F(AppListPresenterDelegateTest,AppListBoundsChangeForDisplayChangeSearch)1476 TEST_F(AppListPresenterDelegateTest,
1477 AppListBoundsChangeForDisplayChangeSearch) {
1478 UpdateDisplay("1024x768");
1479 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1480 GetAppListTestHelper()->CheckVisibility(true);
1481 SetAppListStateAndWait(AppListViewState::kHalf);
1482
1483 const gfx::Rect app_list_bounds =
1484 GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1485 const gfx::Rect search_box_bounds = GetAppListView()
1486 ->search_box_view()
1487 ->GetWidget()
1488 ->GetWindowBoundsInScreen();
1489
1490 UpdateDisplay("800x600");
1491 GetAppListTestHelper()->WaitUntilIdle();
1492 GetAppListTestHelper()->CheckVisibility(true);
1493 const gfx::Rect app_list_bounds2 =
1494 GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1495 const gfx::Rect search_box_bounds2 = GetAppListView()
1496 ->search_box_view()
1497 ->GetWidget()
1498 ->GetWindowBoundsInScreen();
1499 EXPECT_GT(app_list_bounds.size().GetArea(),
1500 app_list_bounds2.size().GetArea());
1501 EXPECT_NE(search_box_bounds, search_box_bounds2);
1502 EXPECT_EQ(400, search_box_bounds2.CenterPoint().x());
1503 }
1504
1505 // Tests that the app list window's bounds and the search box bounds in the
1506 // fullscreen state are updated when the display bounds change.
TEST_F(AppListPresenterDelegateTest,AppListBoundsChangeForDisplayChangeFullscreen)1507 TEST_F(AppListPresenterDelegateTest,
1508 AppListBoundsChangeForDisplayChangeFullscreen) {
1509 UpdateDisplay("1024x768");
1510 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1511 GetAppListTestHelper()->CheckVisibility(true);
1512 SetAppListStateAndWait(AppListViewState::kFullscreenAllApps);
1513
1514 const gfx::Rect app_list_bounds =
1515 GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1516 const gfx::Rect search_box_bounds = GetAppListView()
1517 ->search_box_view()
1518 ->GetWidget()
1519 ->GetWindowBoundsInScreen();
1520
1521 UpdateDisplay("800x600");
1522 GetAppListTestHelper()->WaitUntilIdle();
1523 GetAppListTestHelper()->CheckVisibility(true);
1524 const gfx::Rect app_list_bounds2 =
1525 GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1526 const gfx::Rect search_box_bounds2 = GetAppListView()
1527 ->search_box_view()
1528 ->GetWidget()
1529 ->GetWindowBoundsInScreen();
1530 EXPECT_GT(app_list_bounds.size().GetArea(),
1531 app_list_bounds2.size().GetArea());
1532 EXPECT_NE(search_box_bounds, search_box_bounds2);
1533 EXPECT_EQ(400, search_box_bounds2.CenterPoint().x());
1534 }
1535
1536 // Tests that the app list window's bounds and the search box bounds in the
1537 // fullscreen search state are updated when the display bounds change.
TEST_F(AppListPresenterDelegateTest,AppListBoundsChangeForDisplayChangeFullscreenSearch)1538 TEST_F(AppListPresenterDelegateTest,
1539 AppListBoundsChangeForDisplayChangeFullscreenSearch) {
1540 UpdateDisplay("1024x768");
1541 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1542 GetAppListTestHelper()->CheckVisibility(true);
1543 SetAppListStateAndWait(AppListViewState::kFullscreenAllApps);
1544 SetAppListStateAndWait(AppListViewState::kFullscreenSearch);
1545
1546 const gfx::Rect app_list_bounds =
1547 GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1548 const gfx::Rect search_box_bounds = GetAppListView()
1549 ->search_box_view()
1550 ->GetWidget()
1551 ->GetWindowBoundsInScreen();
1552
1553 UpdateDisplay("800x600");
1554 GetAppListTestHelper()->WaitUntilIdle();
1555 GetAppListTestHelper()->CheckVisibility(true);
1556 const gfx::Rect app_list_bounds2 =
1557 GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1558 const gfx::Rect search_box_bounds2 = GetAppListView()
1559 ->search_box_view()
1560 ->GetWidget()
1561 ->GetWindowBoundsInScreen();
1562 EXPECT_GT(app_list_bounds.size().GetArea(),
1563 app_list_bounds2.size().GetArea());
1564 EXPECT_NE(search_box_bounds, search_box_bounds2);
1565 EXPECT_EQ(400, search_box_bounds2.CenterPoint().x());
1566 }
1567
1568 // Tests that the app list is not draggable in side shelf alignment.
TEST_F(AppListPresenterDelegateTest,SideShelfAlignmentDragDisabled)1569 TEST_F(AppListPresenterDelegateTest, SideShelfAlignmentDragDisabled) {
1570 SetShelfAlignment(ShelfAlignment::kRight);
1571 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1572 const AppListView* app_list = GetAppListView();
1573 EXPECT_TRUE(app_list->is_fullscreen());
1574 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1575
1576 // Drag the widget across the screen over an arbitrary 100Ms, this would
1577 // normally result in the app list transitioning to PEEKING but will now
1578 // result in no state change.
1579 ui::test::EventGenerator* generator = GetEventGenerator();
1580 generator->GestureScrollSequence(GetPointOutsideSearchbox(),
1581 gfx::Point(10, 900),
1582 base::TimeDelta::FromMilliseconds(100), 10);
1583 GetAppListTestHelper()->WaitUntilIdle();
1584 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1585
1586 // Tap the app list body. This should still close the app list.
1587 generator->GestureTapAt(GetPointOutsideSearchbox());
1588 GetAppListTestHelper()->WaitUntilIdle();
1589 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
1590 GetAppListTestHelper()->CheckVisibility(false);
1591 }
1592
1593 // Tests that the app list initializes in fullscreen with side shelf alignment
1594 // and that the state transitions via text input act properly.
TEST_F(AppListPresenterDelegateTest,SideShelfAlignmentTextStateTransitions)1595 TEST_F(AppListPresenterDelegateTest, SideShelfAlignmentTextStateTransitions) {
1596 SetShelfAlignment(ShelfAlignment::kLeft);
1597
1598 // Open the app list with side shelf alignment, then check that it is in
1599 // fullscreen mode.
1600 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1601 AppListView* app_list = GetAppListView();
1602 EXPECT_TRUE(app_list->is_fullscreen());
1603 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1604
1605 // Enter text in the searchbox, the app list should transition to fullscreen
1606 // search.
1607 ui::test::EventGenerator* generator = GetEventGenerator();
1608 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
1609 GetAppListTestHelper()->WaitUntilIdle();
1610 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
1611
1612 // Pressing escape should transition the app list should to fullscreen all
1613 // apps state.
1614 generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
1615 GetAppListTestHelper()->WaitUntilIdle();
1616 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1617 }
1618
1619 // Tests that the app list initializes in peeking with bottom shelf alignment
1620 // and that the state transitions via text input act properly.
TEST_F(AppListPresenterDelegateTest,BottomShelfAlignmentTextStateTransitions)1621 TEST_F(AppListPresenterDelegateTest, BottomShelfAlignmentTextStateTransitions) {
1622 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1623 AppListView* app_list = GetAppListView();
1624 EXPECT_FALSE(app_list->is_fullscreen());
1625 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
1626
1627 // Enter text in the searchbox, this should transition the app list to half
1628 // state.
1629 ui::test::EventGenerator* generator = GetEventGenerator();
1630 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
1631 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
1632
1633 // Empty the searchbox - app list should remain in half state (and show zero
1634 // state results).
1635 generator->PressKey(ui::KeyboardCode::VKEY_BACK, 0);
1636 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
1637
1638 // ESC should transition app list to the peeking state.
1639 generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
1640 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
1641 }
1642
1643 // Tests that the app list initializes in fullscreen with tablet mode active
1644 // and that the state transitions via text input act properly.
TEST_F(AppListPresenterDelegateTest,TabletModeTextStateTransitions)1645 TEST_F(AppListPresenterDelegateTest, TabletModeTextStateTransitions) {
1646 EnableTabletMode(true);
1647 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1648 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1649
1650 // Enter text in the searchbox, the app list should transition to fullscreen
1651 // search.
1652 ui::test::EventGenerator* generator = GetEventGenerator();
1653 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
1654 GetAppListTestHelper()->WaitUntilIdle();
1655 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
1656
1657 // Pressing the escape key should transition the app list to the fullscreen
1658 // all apps state.
1659 generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
1660 GetAppListTestHelper()->WaitUntilIdle();
1661 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1662 }
1663
1664 // Tests that the app list closes when tablet mode deactivates.
TEST_F(AppListPresenterDelegateTest,AppListClosesWhenLeavingTabletMode)1665 TEST_F(AppListPresenterDelegateTest, AppListClosesWhenLeavingTabletMode) {
1666 EnableTabletMode(true);
1667 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1668 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1669
1670 EnableTabletMode(false);
1671 GetAppListTestHelper()->WaitUntilIdle();
1672 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
1673
1674 EnableTabletMode(true);
1675 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1676 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1677
1678 // Enter text in the searchbox, the app list should transition to fullscreen
1679 // search.
1680 ui::test::EventGenerator* generator = GetEventGenerator();
1681 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
1682 GetAppListTestHelper()->WaitUntilIdle();
1683 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
1684
1685 EnableTabletMode(false);
1686 GetAppListTestHelper()->WaitUntilIdle();
1687 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
1688 }
1689
1690 // Tests that the app list state responds correctly to tablet mode being
1691 // enabled while the app list is being shown with half launcher.
TEST_F(AppListPresenterDelegateTest,HalfToFullscreenWhenTabletModeIsActive)1692 TEST_F(AppListPresenterDelegateTest, HalfToFullscreenWhenTabletModeIsActive) {
1693 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1694 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
1695
1696 // Enter text in the search box to transition to half app list.
1697 ui::test::EventGenerator* generator = GetEventGenerator();
1698 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
1699 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
1700
1701 // Enable tablet mode and force the app list to transition to the fullscreen
1702 // equivalent of the current state.
1703 EnableTabletMode(true);
1704 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
1705 generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
1706 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1707 }
1708
1709 // Tests that the app list view handles drag properly in laptop mode.
TEST_F(AppListPresenterDelegateTest,AppListViewDragHandler)1710 TEST_F(AppListPresenterDelegateTest, AppListViewDragHandler) {
1711 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1712 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
1713
1714 ui::test::EventGenerator* generator = GetEventGenerator();
1715 // Execute a slow short upwards drag this should fail to transition the app
1716 // list.
1717 int top_of_app_list =
1718 GetAppListView()->GetWidget()->GetWindowBoundsInScreen().y();
1719 generator->GestureScrollSequence(gfx::Point(0, top_of_app_list + 20),
1720 gfx::Point(0, top_of_app_list - 20),
1721 base::TimeDelta::FromMilliseconds(500), 50);
1722 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
1723
1724 // Execute a long upwards drag, this should transition the app list.
1725 generator->GestureScrollSequence(gfx::Point(10, top_of_app_list + 20),
1726 gfx::Point(10, 10),
1727 base::TimeDelta::FromMilliseconds(100), 10);
1728 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1729
1730 // Execute a short downward drag, this should fail to transition the app list.
1731 gfx::Point start(10, 10);
1732 gfx::Point end(10, 100);
1733 generator->GestureScrollSequence(
1734 start, end,
1735 generator->CalculateScrollDurationForFlingVelocity(start, end, 1, 100),
1736 100);
1737 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1738
1739 // Execute a long and slow downward drag to switch to peeking.
1740 start = gfx::Point(10, 200);
1741 end = gfx::Point(10, 650);
1742 generator->GestureScrollSequence(
1743 start, end,
1744 generator->CalculateScrollDurationForFlingVelocity(start, end, 1, 100),
1745 100);
1746 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
1747
1748 // Transition to fullscreen.
1749 generator->GestureScrollSequence(gfx::Point(10, top_of_app_list + 20),
1750 gfx::Point(10, 10),
1751 base::TimeDelta::FromMilliseconds(100), 10);
1752 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1753
1754 // Enter text to transition to |FULLSCREEN_SEARCH|.
1755 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
1756 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
1757
1758 // Execute a short downward drag, this should fail to close the app list.
1759 start = gfx::Point(10, 10);
1760 end = gfx::Point(10, 100);
1761 generator->GestureScrollSequence(
1762 start, end,
1763 generator->CalculateScrollDurationForFlingVelocity(start, end, 1, 100),
1764 100);
1765 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
1766
1767 // Execute a long downward drag, this should close the app list.
1768 generator->GestureScrollSequence(gfx::Point(10, 10), gfx::Point(10, 900),
1769 base::TimeDelta::FromMilliseconds(100), 10);
1770 GetAppListTestHelper()->WaitUntilIdle();
1771 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
1772 GetAppListTestHelper()->CheckVisibility(false);
1773 }
1774
1775 // Tests that the bottom shelf background is hidden when the app list is shown
1776 // in laptop mode.
TEST_F(AppListPresenterDelegateTest,ShelfBackgroundIsHiddenWhenAppListIsShown)1777 TEST_F(AppListPresenterDelegateTest,
1778 ShelfBackgroundIsHiddenWhenAppListIsShown) {
1779 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1780 ShelfLayoutManager* shelf_layout_manager =
1781 Shelf::ForWindow(Shell::GetRootWindowForDisplayId(GetPrimaryDisplayId()))
1782 ->shelf_layout_manager();
1783 EXPECT_EQ(ShelfBackgroundType::kAppList,
1784 shelf_layout_manager->GetShelfBackgroundType());
1785 }
1786
1787 // Tests the shelf background type is as expected when a window is created after
1788 // going to tablet mode.
TEST_F(AppListPresenterDelegateTest,ShelfBackgroundWithHomeLauncher)1789 TEST_F(AppListPresenterDelegateTest, ShelfBackgroundWithHomeLauncher) {
1790 // Enter tablet mode to display the home launcher.
1791 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1792 EnableTabletMode(true);
1793 ShelfLayoutManager* shelf_layout_manager =
1794 Shelf::ForWindow(Shell::GetRootWindowForDisplayId(GetPrimaryDisplayId()))
1795 ->shelf_layout_manager();
1796 EXPECT_EQ(ShelfBackgroundType::kHomeLauncher,
1797 shelf_layout_manager->GetShelfBackgroundType());
1798
1799 // Add a window. It should be in-app because it is in tablet mode.
1800 auto window = CreateTestWindow();
1801 wm::ActivateWindow(window.get());
1802 EXPECT_EQ(ShelfBackgroundType::kInApp,
1803 shelf_layout_manager->GetShelfBackgroundType());
1804 }
1805
1806 // Tests that app list understands shelf rounded corners state while animating
1807 // out and in, and that it keeps getting notified of shelf state changes if
1808 // close animation is interrupted by another show request.
TEST_F(AppListPresenterDelegateTest,AppListShownWhileClosing)1809 TEST_F(AppListPresenterDelegateTest, AppListShownWhileClosing) {
1810 auto window = CreateTestWindow();
1811 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1812
1813 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1814 GetAppListTestHelper()->CheckVisibility(true);
1815
1816 ShelfLayoutManager* shelf_layout_manager =
1817 Shelf::ForWindow(Shell::GetRootWindowForDisplayId(GetPrimaryDisplayId()))
1818 ->shelf_layout_manager();
1819
1820 EXPECT_FALSE(GetAppListView()->shelf_has_rounded_corners());
1821 EXPECT_EQ(ShelfBackgroundType::kMaximizedWithAppList,
1822 shelf_layout_manager->GetShelfBackgroundType());
1823
1824 // Enable animation to account for delay between app list starting to close
1825 // and reporting visibility change (which happens when close animation
1826 // finishes).
1827 ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
1828 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1829 AppListView::SetShortAnimationForTesting(false);
1830
1831 // Dismiss and immediately show the app list (before close animation is done).
1832 GetAppListTestHelper()->Dismiss();
1833
1834 EXPECT_FALSE(GetAppListView()->shelf_has_rounded_corners());
1835 EXPECT_EQ(ShelfBackgroundType::kMaximizedWithAppList,
1836 shelf_layout_manager->GetShelfBackgroundType());
1837
1838 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1839
1840 // Finish app list animations.
1841 if (GetAppListView()->GetWidget()->GetLayer()->GetAnimator()->is_animating())
1842 GetAppListView()->GetWidget()->GetLayer()->GetAnimator()->StopAnimating();
1843
1844 EXPECT_FALSE(GetAppListView()->shelf_has_rounded_corners());
1845 EXPECT_EQ(ShelfBackgroundType::kMaximizedWithAppList,
1846 shelf_layout_manager->GetShelfBackgroundType());
1847
1848 // Verify that the app list still picks up shelf changes.
1849 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
1850 EXPECT_TRUE(GetAppListView()->shelf_has_rounded_corners());
1851 EXPECT_EQ(ShelfBackgroundType::kAppList,
1852 shelf_layout_manager->GetShelfBackgroundType());
1853 }
1854
1855 // Tests how shelf state is updated as app list state changes with a maximized
1856 // window open. It verifies that the app list knows that the maximized shelf had
1857 // no rounded corners.
TEST_F(AppListPresenterDelegateTest,AppListWithMaximizedShelf)1858 TEST_F(AppListPresenterDelegateTest, AppListWithMaximizedShelf) {
1859 auto window = CreateTestWindow();
1860 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1861
1862 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1863 GetAppListTestHelper()->CheckVisibility(true);
1864
1865 ShelfLayoutManager* shelf_layout_manager =
1866 Shelf::ForWindow(Shell::GetRootWindowForDisplayId(GetPrimaryDisplayId()))
1867 ->shelf_layout_manager();
1868
1869 EXPECT_FALSE(GetAppListView()->shelf_has_rounded_corners());
1870 EXPECT_EQ(ShelfBackgroundType::kMaximizedWithAppList,
1871 shelf_layout_manager->GetShelfBackgroundType());
1872
1873 // Enable animation to account for delay between app list starting to close
1874 // and reporting visibility change (which happens when close animation
1875 // finishes).
1876 ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
1877 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1878 AppListView::SetShortAnimationForTesting(false);
1879
1880 // Start closing the app list view.
1881 GetAppListTestHelper()->Dismiss();
1882
1883 EXPECT_FALSE(GetAppListView()->shelf_has_rounded_corners());
1884 EXPECT_EQ(ShelfBackgroundType::kMaximizedWithAppList,
1885 shelf_layout_manager->GetShelfBackgroundType());
1886
1887 // Minimize the window, and verify that the shelf state changed from a
1888 // maximized state, and that |shelf_has_rounded_corners()| value was updated.
1889 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
1890
1891 EXPECT_TRUE(GetAppListView()->shelf_has_rounded_corners());
1892 EXPECT_EQ(ShelfBackgroundType::kAppList,
1893 shelf_layout_manager->GetShelfBackgroundType());
1894
1895 // Stop app list hide animation.
1896 ASSERT_TRUE(
1897 GetAppListView()->GetWidget()->GetLayer()->GetAnimator()->is_animating());
1898 GetAppListView()->GetWidget()->GetLayer()->GetAnimator()->StopAnimating();
1899
1900 EXPECT_EQ(ShelfBackgroundType::kDefaultBg,
1901 shelf_layout_manager->GetShelfBackgroundType());
1902 }
1903
1904 // Verifies the shelf background state changes when a window is maximized while
1905 // app list is shown. Verifies that AppList::shelf_has_rounded_corners() is
1906 // updated.
TEST_F(AppListPresenterDelegateTest,WindowMaximizedWithAppListShown)1907 TEST_F(AppListPresenterDelegateTest, WindowMaximizedWithAppListShown) {
1908 auto window = CreateTestWindow();
1909
1910 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1911 GetAppListTestHelper()->CheckVisibility(true);
1912
1913 ShelfLayoutManager* shelf_layout_manager =
1914 Shelf::ForWindow(Shell::GetRootWindowForDisplayId(GetPrimaryDisplayId()))
1915 ->shelf_layout_manager();
1916
1917 EXPECT_TRUE(GetAppListView()->shelf_has_rounded_corners());
1918 EXPECT_EQ(ShelfBackgroundType::kAppList,
1919 shelf_layout_manager->GetShelfBackgroundType());
1920
1921 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1922
1923 EXPECT_FALSE(GetAppListView()->shelf_has_rounded_corners());
1924 EXPECT_EQ(ShelfBackgroundType::kMaximizedWithAppList,
1925 shelf_layout_manager->GetShelfBackgroundType());
1926
1927 GetAppListTestHelper()->Dismiss();
1928
1929 EXPECT_EQ(ShelfBackgroundType::kMaximized,
1930 shelf_layout_manager->GetShelfBackgroundType());
1931 }
1932
1933 // Tests that the bottom shelf is auto hidden when a window is fullscreened in
1934 // tablet mode (home launcher is shown behind).
TEST_F(AppListPresenterDelegateTest,ShelfAutoHiddenWhenFullscreen)1935 TEST_F(AppListPresenterDelegateTest, ShelfAutoHiddenWhenFullscreen) {
1936 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1937 EnableTabletMode(true);
1938 Shelf* shelf =
1939 Shelf::ForWindow(Shell::GetRootWindowForDisplayId(GetPrimaryDisplayId()));
1940 EXPECT_EQ(ShelfVisibilityState::SHELF_VISIBLE, shelf->GetVisibilityState());
1941
1942 // Create and fullscreen a window. The shelf should be auto hidden.
1943 auto window = CreateTestWindow();
1944 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
1945 EXPECT_EQ(ShelfVisibilityState::SHELF_AUTO_HIDE, shelf->GetVisibilityState());
1946 EXPECT_EQ(ShelfAutoHideState::SHELF_AUTO_HIDE_HIDDEN,
1947 shelf->GetAutoHideState());
1948 }
1949
1950 // Tests that the peeking app list closes if the user taps or clicks outside
1951 // its bounds.
TEST_P(AppListPresenterDelegateTest,TapAndClickOutsideClosesPeekingAppList)1952 TEST_P(AppListPresenterDelegateTest, TapAndClickOutsideClosesPeekingAppList) {
1953 const bool test_mouse_event = TestMouseEventParam();
1954 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1955 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
1956 ui::test::EventGenerator* generator = GetEventGenerator();
1957
1958 // Tapping outside the bounds closes the app list.
1959 const gfx::Rect peeking_bounds = GetAppListView()->GetBoundsInScreen();
1960 gfx::Point tap_point = peeking_bounds.origin();
1961 tap_point.Offset(10, -10);
1962 ASSERT_FALSE(peeking_bounds.Contains(tap_point));
1963
1964 if (test_mouse_event) {
1965 generator->MoveMouseTo(tap_point);
1966 generator->ClickLeftButton();
1967 generator->ReleaseLeftButton();
1968 } else {
1969 generator->GestureTapAt(tap_point);
1970 }
1971 GetAppListTestHelper()->WaitUntilIdle();
1972 GetAppListTestHelper()->CheckVisibility(false);
1973 }
1974
TEST_P(AppListPresenterDelegateTest,LongPressOutsideCloseAppList)1975 TEST_P(AppListPresenterDelegateTest, LongPressOutsideCloseAppList) {
1976 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1977 GetAppListTestHelper()->CheckVisibility(true);
1978
1979 // |outside_point| is outside the bounds of app list.
1980 gfx::Point outside_point = GetAppListView()->bounds().origin();
1981 outside_point.Offset(0, -10);
1982
1983 // Dispatch LONG_PRESS to AppListPresenterDelegate.
1984 ui::TouchEvent long_press(ui::ET_GESTURE_LONG_PRESS, outside_point,
1985 base::TimeTicks::Now(),
1986 ui::PointerDetails(ui::EventPointerType::kTouch));
1987 GetEventGenerator()->Dispatch(&long_press);
1988 GetAppListTestHelper()->WaitUntilIdle();
1989 GetAppListTestHelper()->CheckVisibility(false);
1990 }
1991
TEST_P(AppListPresenterDelegateTest,TwoFingerTapOutsideCloseAppList)1992 TEST_P(AppListPresenterDelegateTest, TwoFingerTapOutsideCloseAppList) {
1993 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1994 GetAppListTestHelper()->CheckVisibility(true);
1995
1996 // |outside_point| is outside the bounds of app list.
1997 gfx::Point outside_point = GetAppListView()->bounds().origin();
1998 outside_point.Offset(0, -10);
1999
2000 // Dispatch TWO_FINGER_TAP to AppListPresenterDelegate.
2001 ui::TouchEvent two_finger_tap(
2002 ui::ET_GESTURE_TWO_FINGER_TAP, outside_point, base::TimeTicks::Now(),
2003 ui::PointerDetails(ui::EventPointerType::kTouch));
2004 GetEventGenerator()->Dispatch(&two_finger_tap);
2005 GetAppListTestHelper()->WaitUntilIdle();
2006 GetAppListTestHelper()->CheckVisibility(false);
2007 }
2008
2009 // Tests that a keypress activates the searchbox and that clearing the
2010 // searchbox, the searchbox remains active.
TEST_F(AppListPresenterDelegateTest,KeyPressEnablesSearchBox)2011 TEST_F(AppListPresenterDelegateTest, KeyPressEnablesSearchBox) {
2012 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2013 ui::test::EventGenerator* generator = GetEventGenerator();
2014 SearchBoxView* search_box_view = GetAppListView()->search_box_view();
2015 EXPECT_FALSE(search_box_view->is_search_box_active());
2016
2017 // Press any key, the search box should be active.
2018 generator->PressKey(ui::VKEY_0, 0);
2019 EXPECT_TRUE(search_box_view->is_search_box_active());
2020
2021 // Delete the text, the search box should be inactive.
2022 search_box_view->ClearSearch();
2023 EXPECT_TRUE(search_box_view->is_search_box_active());
2024 }
2025
2026 // Tests that a tap/click on the AppListView from half launcher returns the
2027 // AppListView to Peeking, and that a tap/click on the AppListView from
2028 // Peeking closes the app list.
TEST_P(AppListPresenterDelegateTest,StateTransitionsByTapAndClickingAppListBodyFromHalf)2029 TEST_P(AppListPresenterDelegateTest,
2030 StateTransitionsByTapAndClickingAppListBodyFromHalf) {
2031 const bool test_mouse_event = TestMouseEventParam();
2032 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2033 AppListView* app_list_view = GetAppListView();
2034 SearchBoxView* search_box_view = app_list_view->search_box_view();
2035 ui::test::EventGenerator* generator = GetEventGenerator();
2036 GetAppListTestHelper()->WaitUntilIdle();
2037 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2038
2039 // Press a key, the AppListView should transition to half.
2040 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
2041 GetAppListTestHelper()->WaitUntilIdle();
2042 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2043 EXPECT_TRUE(search_box_view->is_search_box_active());
2044
2045 // Tap outside the search box, the AppListView should transition to Peeking
2046 // and the search box should be inactive.
2047 if (test_mouse_event) {
2048 generator->MoveMouseTo(GetPointOutsideSearchbox());
2049 generator->ClickLeftButton();
2050 generator->ReleaseLeftButton();
2051 } else {
2052 generator->GestureTapDownAndUp(GetPointOutsideSearchbox());
2053 }
2054 GetAppListTestHelper()->WaitUntilIdle();
2055 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2056 EXPECT_FALSE(search_box_view->is_search_box_active());
2057
2058 // Tap outside the search box again, the AppListView should hide.
2059 if (test_mouse_event) {
2060 generator->MoveMouseTo(GetPointOutsideSearchbox());
2061 generator->ClickLeftButton();
2062 generator->ReleaseLeftButton();
2063 } else {
2064 generator->GestureTapDownAndUp(GetPointOutsideSearchbox());
2065 }
2066 GetAppListTestHelper()->WaitUntilIdle();
2067 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2068 GetAppListTestHelper()->CheckVisibility(false);
2069 }
2070
2071 // Tests that a tap/click on the AppListView from Fullscreen search returns
2072 // the AppListView to fullscreen all apps, and that a tap/click on the
2073 // AppListView from fullscreen all apps closes the app list.
TEST_P(AppListPresenterDelegateTest,StateTransitionsByTappingAppListBodyFromFullscreen)2074 TEST_P(AppListPresenterDelegateTest,
2075 StateTransitionsByTappingAppListBodyFromFullscreen) {
2076 const bool test_mouse_event = TestMouseEventParam();
2077 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2078 AppListView* app_list_view = GetAppListView();
2079 SearchBoxView* search_box_view = app_list_view->search_box_view();
2080 ui::test::EventGenerator* generator = GetEventGenerator();
2081
2082 // Execute a long upwards drag, this should transition the app list to
2083 // fullscreen.
2084 const int top_of_app_list =
2085 app_list_view->GetWidget()->GetWindowBoundsInScreen().y();
2086 generator->GestureScrollSequence(gfx::Point(10, top_of_app_list + 20),
2087 gfx::Point(10, 10),
2088 base::TimeDelta::FromMilliseconds(100), 10);
2089 GetAppListTestHelper()->WaitUntilIdle();
2090 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2091
2092 // Press a key, this should activate the searchbox and transition to
2093 // fullscreen search.
2094 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
2095 GetAppListTestHelper()->WaitUntilIdle();
2096 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
2097 EXPECT_TRUE(search_box_view->is_search_box_active());
2098
2099 // Tap outside the searchbox, this should deactivate the searchbox and the
2100 // applistview should return to fullscreen all apps.
2101 if (test_mouse_event) {
2102 generator->MoveMouseTo(GetPointOutsideSearchbox());
2103 generator->ClickLeftButton();
2104 } else {
2105 generator->GestureTapDownAndUp(GetPointOutsideSearchbox());
2106 }
2107 GetAppListTestHelper()->WaitUntilIdle();
2108 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2109 EXPECT_FALSE(search_box_view->is_search_box_active());
2110
2111 // Tap outside the searchbox again, this should close the applistview.
2112 if (test_mouse_event) {
2113 generator->MoveMouseTo(GetPointOutsideSearchbox());
2114 generator->ClickLeftButton();
2115 } else {
2116 generator->GestureTapDownAndUp(GetPointOutsideSearchbox());
2117 }
2118 GetAppListTestHelper()->WaitUntilIdle();
2119 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2120 GetAppListTestHelper()->CheckVisibility(false);
2121 }
2122
2123 // Tests that the searchbox activates when it is tapped and that the widget is
2124 // closed after tapping outside the searchbox.
TEST_P(AppListPresenterDelegateTest,TapAndClickEnablesSearchBox)2125 TEST_P(AppListPresenterDelegateTest, TapAndClickEnablesSearchBox) {
2126 const bool test_mouse_event = TestMouseEventParam();
2127 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2128 SearchBoxView* search_box_view = GetAppListView()->search_box_view();
2129
2130 // Tap/Click the search box, it should activate.
2131 ui::test::EventGenerator* generator = GetEventGenerator();
2132 if (test_mouse_event) {
2133 generator->MoveMouseTo(GetPointInsideSearchbox());
2134 generator->PressLeftButton();
2135 generator->ReleaseLeftButton();
2136 } else {
2137 generator->GestureTapAt(GetPointInsideSearchbox());
2138 }
2139
2140 EXPECT_TRUE(search_box_view->is_search_box_active());
2141
2142 // Tap on the body of the app list, the search box should deactivate.
2143 if (test_mouse_event) {
2144 generator->MoveMouseTo(GetPointOutsideSearchbox());
2145 generator->PressLeftButton();
2146 generator->ReleaseLeftButton();
2147 } else {
2148 generator->GestureTapAt(GetPointOutsideSearchbox());
2149 }
2150 GetAppListTestHelper()->WaitUntilIdle();
2151 EXPECT_FALSE(search_box_view->is_search_box_active());
2152 GetAppListTestHelper()->CheckVisibility(true);
2153
2154 // Tap on the body of the app list again, the app list should hide.
2155 if (test_mouse_event) {
2156 generator->PressLeftButton();
2157 generator->ReleaseLeftButton();
2158 } else {
2159 generator->GestureTapAt(GetPointOutsideSearchbox());
2160 }
2161 GetAppListTestHelper()->WaitUntilIdle();
2162 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2163 GetAppListTestHelper()->CheckVisibility(false);
2164 }
2165
2166 // Tests that the shelf background displays/hides with bottom shelf
2167 // alignment.
TEST_F(AppListPresenterDelegateTest,ShelfBackgroundRespondsToAppListBeingShown)2168 TEST_F(AppListPresenterDelegateTest,
2169 ShelfBackgroundRespondsToAppListBeingShown) {
2170 GetPrimaryShelf()->SetAlignment(ShelfAlignment::kBottom);
2171
2172 // Show the app list, the shelf background should be transparent.
2173 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2174 ShelfLayoutManager* shelf_layout_manager =
2175 GetPrimaryShelf()->shelf_layout_manager();
2176 EXPECT_EQ(ShelfBackgroundType::kAppList,
2177 shelf_layout_manager->GetShelfBackgroundType());
2178 GetAppListTestHelper()->DismissAndRunLoop();
2179
2180 // Set the alignment to the side and show the app list. The background
2181 // should show.
2182 GetPrimaryShelf()->SetAlignment(ShelfAlignment::kLeft);
2183 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2184 EXPECT_FALSE(GetPrimaryShelf()->IsHorizontalAlignment());
2185 EXPECT_EQ(
2186 ShelfBackgroundType::kAppList,
2187 GetPrimaryShelf()->shelf_layout_manager()->GetShelfBackgroundType());
2188 }
2189
2190 // Tests that the half app list closes itself if the user taps outside its
2191 // bounds.
TEST_P(AppListPresenterDelegateTest,TapAndClickOutsideClosesHalfAppList)2192 TEST_P(AppListPresenterDelegateTest, TapAndClickOutsideClosesHalfAppList) {
2193 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2194 ui::test::EventGenerator* generator = GetEventGenerator();
2195
2196 // Transition to half app list by entering text.
2197 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
2198 GetAppListTestHelper()->WaitUntilIdle();
2199 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2200
2201 // A point outside the bounds of launcher.
2202 gfx::Point to_point(
2203 0, GetAppListView()->GetWidget()->GetWindowBoundsInScreen().y() - 1);
2204
2205 // Clicking/tapping outside the bounds closes the app list.
2206 if (TestMouseEventParam()) {
2207 generator->MoveMouseTo(to_point);
2208 generator->ClickLeftButton();
2209 } else {
2210 generator->GestureTapAt(to_point);
2211 }
2212 GetAppListTestHelper()->WaitUntilIdle();
2213 GetAppListTestHelper()->CheckVisibility(false);
2214 }
2215
2216 // Tests that the search box is set active with a whitespace query.
TEST_F(AppListPresenterDelegateTest,WhitespaceQuery)2217 TEST_F(AppListPresenterDelegateTest, WhitespaceQuery) {
2218 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2219 AppListView* view = GetAppListView();
2220 ui::test::EventGenerator* generator = GetEventGenerator();
2221 EXPECT_FALSE(view->search_box_view()->is_search_box_active());
2222 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2223
2224 // Enter a whitespace query, the searchbox should activate (in zero state).
2225 generator->PressKey(ui::VKEY_SPACE, 0);
2226 EXPECT_TRUE(view->search_box_view()->is_search_box_active());
2227 EXPECT_TRUE(view->search_box_view()->IsSearchBoxTrimmedQueryEmpty());
2228 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2229
2230 generator->PressKey(ui::VKEY_A, 0);
2231 EXPECT_TRUE(view->search_box_view()->is_search_box_active());
2232 EXPECT_FALSE(view->search_box_view()->IsSearchBoxTrimmedQueryEmpty());
2233 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2234
2235 // Delete the non-whitespace character, the Searchbox should not deactivate.
2236 generator->PressKey(ui::VKEY_BACK, 0);
2237 EXPECT_TRUE(view->search_box_view()->is_search_box_active());
2238 EXPECT_TRUE(view->search_box_view()->IsSearchBoxTrimmedQueryEmpty());
2239 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2240
2241 // Delete the whitespace, the search box remains active, in zero state.
2242 generator->PressKey(ui::VKEY_BACK, 0);
2243 EXPECT_TRUE(view->search_box_view()->is_search_box_active());
2244 EXPECT_TRUE(view->search_box_view()->IsSearchBoxTrimmedQueryEmpty());
2245 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2246 }
2247
2248 // Tests that an unhandled two finger tap/right click does not close the app
2249 // list, and an unhandled one finger tap/left click closes the app list in
2250 // Peeking mode.
TEST_P(AppListPresenterDelegateTest,UnhandledEventOnPeeking)2251 TEST_P(AppListPresenterDelegateTest, UnhandledEventOnPeeking) {
2252 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2253 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2254
2255 // Two finger tap or right click in the empty space below the searchbox. The
2256 // app list should not close.
2257 gfx::Point empty_space =
2258 GetAppListView()->search_box_view()->GetBoundsInScreen().bottom_left();
2259 empty_space.Offset(0, 10);
2260 ui::test::EventGenerator* generator = GetEventGenerator();
2261 if (TestMouseEventParam()) {
2262 generator->MoveMouseTo(empty_space);
2263 generator->PressRightButton();
2264 generator->ReleaseRightButton();
2265 } else {
2266 ui::GestureEvent two_finger_tap(
2267 empty_space.x(), empty_space.y(), 0, base::TimeTicks(),
2268 ui::GestureEventDetails(ui::ET_GESTURE_TWO_FINGER_TAP));
2269 generator->Dispatch(&two_finger_tap);
2270 }
2271 GetAppListTestHelper()->WaitUntilIdle();
2272 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2273 GetAppListTestHelper()->CheckVisibility(true);
2274
2275 // One finger tap or left click in the empty space below the searchbox. The
2276 // app list should close.
2277 if (TestMouseEventParam()) {
2278 generator->MoveMouseTo(empty_space);
2279 generator->ClickLeftButton();
2280 } else {
2281 generator->GestureTapAt(empty_space);
2282 }
2283 GetAppListTestHelper()->WaitUntilIdle();
2284 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2285 GetAppListTestHelper()->CheckVisibility(false);
2286 }
2287
2288 // Tests that a drag to the bezel from Fullscreen/Peeking will close the app
2289 // list.
TEST_P(AppListPresenterDelegateTest,DragToBezelClosesAppListFromFullscreenAndPeeking)2290 TEST_P(AppListPresenterDelegateTest,
2291 DragToBezelClosesAppListFromFullscreenAndPeeking) {
2292 const bool test_fullscreen = GetParam();
2293 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2294 AppListView* view = GetAppListView();
2295 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2296
2297 if (test_fullscreen) {
2298 FlingUpOrDown(GetEventGenerator(), view, true /* up */);
2299 GetAppListTestHelper()->WaitUntilIdle();
2300 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2301 }
2302
2303 // Drag the app list to 50 DIPs from the bottom bezel.
2304 ui::test::EventGenerator* generator = GetEventGenerator();
2305 const int bezel_y = display::Screen::GetScreen()
2306 ->GetDisplayNearestView(view->parent_window())
2307 .bounds()
2308 .bottom();
2309 generator->GestureScrollSequence(
2310 gfx::Point(0, bezel_y - (kAppListBezelMargin + 100)),
2311 gfx::Point(0, bezel_y - (kAppListBezelMargin)),
2312 base::TimeDelta::FromMilliseconds(1500), 100);
2313
2314 GetAppListTestHelper()->WaitUntilIdle();
2315 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2316 GetAppListTestHelper()->CheckVisibility(false);
2317 }
2318
2319 // Tests that a drag to the bezel from Fullscreen/Peeking will close the app
2320 // list even on external display with non zero y origin.
TEST_P(AppListPresenterDelegateTest,DragToBezelClosesAppListFromFullscreenAndPeekingOnExternal)2321 TEST_P(AppListPresenterDelegateTest,
2322 DragToBezelClosesAppListFromFullscreenAndPeekingOnExternal) {
2323 UpdateDisplay("800x600,1000x768");
2324
2325 const bool test_fullscreen = GetParam();
2326 GetAppListTestHelper()->ShowAndRunLoop(GetSecondaryDisplay().id());
2327 AppListView* view = GetAppListView();
2328 {
2329 SCOPED_TRACE("Peeking");
2330 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2331 }
2332 EXPECT_EQ(Shell::GetAllRootWindows()[1],
2333 view->GetWidget()->GetNativeWindow()->GetRootWindow());
2334
2335 if (test_fullscreen) {
2336 FlingUpOrDown(GetEventGenerator(), view, true /* up */);
2337 GetAppListTestHelper()->WaitUntilIdle();
2338 SCOPED_TRACE("FullscreenAllApps");
2339 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2340 }
2341
2342 // Drag the app list to 50 DIPs from the bottom bezel.
2343 display::Display display =
2344 display::Screen::GetScreen()->GetDisplayNearestView(
2345 view->GetWidget()->GetNativeWindow());
2346 const int bezel_y = display.bounds().bottom();
2347 const int drag_x = display.bounds().x() + 10;
2348 GetEventGenerator()->GestureScrollSequence(
2349 gfx::Point(drag_x, bezel_y - (kAppListBezelMargin + 100)),
2350 gfx::Point(drag_x, bezel_y - (kAppListBezelMargin)),
2351 base::TimeDelta::FromMilliseconds(1500), 100);
2352
2353 GetAppListTestHelper()->WaitUntilIdle();
2354 SCOPED_TRACE("Closed");
2355 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2356 GetAppListTestHelper()->CheckVisibility(false);
2357 }
2358
2359 // Tests that the app list window's bounds height (from the shelf) in kPeeking
2360 // state is the same whether the app list is shown on the primary display
2361 // or the secondary display fir different display placements.
TEST_F(AppListPresenterDelegateTest,AppListPeekingStateHeightOnMultiDisplay)2362 TEST_F(AppListPresenterDelegateTest, AppListPeekingStateHeightOnMultiDisplay) {
2363 UpdateDisplay("800x1000, 800x600");
2364
2365 const std::vector<display::DisplayPlacement::Position> placements = {
2366 display::DisplayPlacement::LEFT, display::DisplayPlacement::RIGHT,
2367 display::DisplayPlacement::BOTTOM, display::DisplayPlacement::TOP};
2368 for (const display::DisplayPlacement::Position placement : placements) {
2369 SCOPED_TRACE(testing::Message() << "Testing placement " << placement);
2370
2371 GetAppListTestHelper()->CheckVisibility(false);
2372 Shell::Get()->display_manager()->SetLayoutForCurrentDisplays(
2373 display::test::CreateDisplayLayout(display_manager(), placement, 0));
2374
2375 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2376 GetAppListTestHelper()->CheckVisibility(true);
2377 SetAppListStateAndWait(AppListViewState::kPeeking);
2378
2379 views::Widget* app_list_widget = GetAppListView()->GetWidget();
2380 EXPECT_EQ(Shell::GetAllRootWindows()[0],
2381 app_list_widget->GetNativeWindow()->GetRootWindow());
2382 const display::Display primary_display =
2383 display::Screen::GetScreen()->GetDisplayNearestView(
2384 app_list_widget->GetNativeWindow());
2385 const int primary_display_height =
2386 app_list_widget->GetWindowBoundsInScreen().y() -
2387 primary_display.bounds().bottom();
2388
2389 GetAppListTestHelper()->Dismiss();
2390 GetAppListTestHelper()->CheckVisibility(false);
2391 const int primary_display_closed_height =
2392 app_list_widget->GetWindowBoundsInScreen().y() -
2393 primary_display.bounds().bottom();
2394
2395 GetAppListTestHelper()->ShowAndRunLoop(GetSecondaryDisplay().id());
2396 GetAppListTestHelper()->CheckVisibility(true);
2397 SetAppListStateAndWait(AppListViewState::kPeeking);
2398
2399 app_list_widget = GetAppListView()->GetWidget();
2400 EXPECT_EQ(Shell::GetAllRootWindows()[1],
2401 app_list_widget->GetNativeWindow()->GetRootWindow());
2402 const display::Display secondary_display =
2403 display::Screen::GetScreen()->GetDisplayNearestView(
2404 app_list_widget->GetNativeWindow());
2405 const int secondary_display_height =
2406 app_list_widget->GetWindowBoundsInScreen().y() -
2407 secondary_display.bounds().bottom();
2408
2409 EXPECT_EQ(secondary_display_height, primary_display_height);
2410
2411 GetAppListTestHelper()->Dismiss();
2412 GetAppListTestHelper()->CheckVisibility(false);
2413
2414 const int secondary_display_closed_height =
2415 app_list_widget->GetWindowBoundsInScreen().y() -
2416 secondary_display.bounds().bottom();
2417 EXPECT_EQ(secondary_display_closed_height, primary_display_closed_height);
2418 }
2419 }
2420
2421 // Tests that the app list window's bounds height (from the shelf) in kHalf
2422 // state is the same whether the app list is shown on the primary display
2423 // or the secondary display fir different display placements.
TEST_F(AppListPresenterDelegateTest,AppListHalfStateHeightOnMultiDisplay)2424 TEST_F(AppListPresenterDelegateTest, AppListHalfStateHeightOnMultiDisplay) {
2425 UpdateDisplay("800x1000, 800x600");
2426
2427 const std::vector<display::DisplayPlacement::Position> placements = {
2428 display::DisplayPlacement::LEFT, display::DisplayPlacement::RIGHT,
2429 display::DisplayPlacement::BOTTOM, display::DisplayPlacement::TOP};
2430 for (const display::DisplayPlacement::Position placement : placements) {
2431 SCOPED_TRACE(testing::Message() << "Testing placement " << placement);
2432
2433 GetAppListTestHelper()->CheckVisibility(false);
2434 Shell::Get()->display_manager()->SetLayoutForCurrentDisplays(
2435 display::test::CreateDisplayLayout(display_manager(), placement, 0));
2436
2437 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2438 GetAppListTestHelper()->CheckVisibility(true);
2439 SetAppListStateAndWait(AppListViewState::kHalf);
2440
2441 views::Widget* app_list_widget = GetAppListView()->GetWidget();
2442 EXPECT_EQ(Shell::GetAllRootWindows()[0],
2443 app_list_widget->GetNativeWindow()->GetRootWindow());
2444 const display::Display primary_display =
2445 display::Screen::GetScreen()->GetDisplayNearestView(
2446 app_list_widget->GetNativeWindow());
2447 const int primary_display_height =
2448 app_list_widget->GetWindowBoundsInScreen().y() -
2449 primary_display.bounds().bottom();
2450
2451 GetAppListTestHelper()->Dismiss();
2452 GetAppListTestHelper()->CheckVisibility(false);
2453 const int primary_display_closed_height =
2454 app_list_widget->GetWindowBoundsInScreen().y() -
2455 primary_display.bounds().bottom();
2456
2457 GetAppListTestHelper()->ShowAndRunLoop(GetSecondaryDisplay().id());
2458 GetAppListTestHelper()->CheckVisibility(true);
2459 SetAppListStateAndWait(AppListViewState::kHalf);
2460
2461 app_list_widget = GetAppListView()->GetWidget();
2462 EXPECT_EQ(Shell::GetAllRootWindows()[1],
2463 app_list_widget->GetNativeWindow()->GetRootWindow());
2464 const display::Display secondary_display =
2465 display::Screen::GetScreen()->GetDisplayNearestView(
2466 app_list_widget->GetNativeWindow());
2467 const int secondary_display_height =
2468 app_list_widget->GetWindowBoundsInScreen().y() -
2469 secondary_display.bounds().bottom();
2470
2471 EXPECT_EQ(secondary_display_height, primary_display_height);
2472
2473 GetAppListTestHelper()->Dismiss();
2474 GetAppListTestHelper()->CheckVisibility(false);
2475
2476 const int secondary_display_closed_height =
2477 app_list_widget->GetWindowBoundsInScreen().y() -
2478 secondary_display.bounds().bottom();
2479 EXPECT_EQ(secondary_display_closed_height, primary_display_closed_height);
2480 }
2481 }
2482
2483 // Tests that a fling from Fullscreen/Peeking closes the app list.
TEST_P(AppListPresenterDelegateTest,FlingDownClosesAppListFromFullscreenAndPeeking)2484 TEST_P(AppListPresenterDelegateTest,
2485 FlingDownClosesAppListFromFullscreenAndPeeking) {
2486 const bool test_fullscreen = GetParam();
2487 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2488 AppListView* view = GetAppListView();
2489 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2490
2491 if (test_fullscreen) {
2492 FlingUpOrDown(GetEventGenerator(), view, true /* up */);
2493 GetAppListTestHelper()->WaitUntilIdle();
2494 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2495 }
2496
2497 // Fling down, the app list should close.
2498 FlingUpOrDown(GetEventGenerator(), view, false /* down */);
2499 GetAppListTestHelper()->WaitUntilIdle();
2500 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2501 GetAppListTestHelper()->CheckVisibility(false);
2502 }
2503
2504 // Tests that drag using a mouse does not always close the app list if the app
2505 // list was previously closed using a fling gesture.
TEST_P(AppListPresenterDelegateTest,MouseDragAfterDownwardFliing)2506 TEST_P(AppListPresenterDelegateTest, MouseDragAfterDownwardFliing) {
2507 const bool test_fullscreen = GetParam();
2508 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2509
2510 AppListView* view = GetAppListView();
2511 const gfx::Point expand_arrow_point = view->app_list_main_view()
2512 ->contents_view()
2513 ->expand_arrow_view()
2514 ->GetBoundsInScreen()
2515 .CenterPoint();
2516
2517 if (test_fullscreen)
2518 GetEventGenerator()->GestureTapAt(expand_arrow_point);
2519 GetAppListTestHelper()->CheckState(test_fullscreen
2520 ? AppListViewState::kFullscreenAllApps
2521 : AppListViewState::kPeeking);
2522
2523 // Fling down, the app list should close.
2524 FlingUpOrDown(GetEventGenerator(), view, false /* down */);
2525 GetAppListTestHelper()->WaitUntilIdle();
2526 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2527
2528 // Show the app list again, and perform mouse drag that ends up at the same
2529 // position.
2530 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2531 if (test_fullscreen)
2532 GetEventGenerator()->GestureTapAt(expand_arrow_point);
2533 GetAppListTestHelper()->CheckState(test_fullscreen
2534 ? AppListViewState::kFullscreenAllApps
2535 : AppListViewState::kPeeking);
2536
2537 GetEventGenerator()->MoveMouseTo(GetPointOutsideSearchbox());
2538 GetEventGenerator()->PressLeftButton();
2539 GetEventGenerator()->MoveMouseBy(0, -10);
2540 GetEventGenerator()->MoveMouseBy(0, 10);
2541 GetEventGenerator()->ReleaseLeftButton();
2542
2543 // Verify the app list state has not changed.
2544 GetAppListTestHelper()->CheckState(test_fullscreen
2545 ? AppListViewState::kFullscreenAllApps
2546 : AppListViewState::kPeeking);
2547 }
2548
TEST_F(AppListPresenterDelegateTest,MouseWheelFromAppListPresenterImplTransitionsAppListState)2549 TEST_F(AppListPresenterDelegateTest,
2550 MouseWheelFromAppListPresenterImplTransitionsAppListState) {
2551 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2552 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2553
2554 GetAppListView()->HandleScroll(gfx::Vector2d(0, -30), ui::ET_MOUSEWHEEL);
2555
2556 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2557 }
2558
TEST_P(AppListPresenterDelegateTest,LongUpwardDragInFullscreenShouldNotClose)2559 TEST_P(AppListPresenterDelegateTest, LongUpwardDragInFullscreenShouldNotClose) {
2560 const bool test_fullscreen_search = GetParam();
2561 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2562 AppListView* view = GetAppListView();
2563 FlingUpOrDown(GetEventGenerator(), view, true);
2564 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2565
2566 if (test_fullscreen_search) {
2567 // Enter a character into the searchbox to transition to FULLSCREEN_SEARCH.
2568 GetEventGenerator()->PressKey(ui::VKEY_0, 0);
2569 GetAppListTestHelper()->WaitUntilIdle();
2570 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
2571 }
2572
2573 // Drag from the center of the applist to the top of the screen very slowly.
2574 // This should not trigger a state transition.
2575 gfx::Point drag_start = view->GetBoundsInScreen().CenterPoint();
2576 drag_start.set_x(15);
2577 gfx::Point drag_end = view->GetBoundsInScreen().top_right();
2578 drag_end.set_x(15);
2579 GetEventGenerator()->GestureScrollSequence(
2580 drag_start, drag_end,
2581 GetEventGenerator()->CalculateScrollDurationForFlingVelocity(
2582 drag_start, drag_end, 1, 1000),
2583 1000);
2584 GetAppListTestHelper()->WaitUntilIdle();
2585 if (test_fullscreen_search)
2586 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
2587 else
2588 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2589 }
2590
2591 // Tests closing the app list during drag, and verifies the bounds get properly
2592 // updated when the app list is shown again..
TEST_P(AppListPresenterDelegateTest,CloseAppListDuringDrag)2593 TEST_P(AppListPresenterDelegateTest, CloseAppListDuringDrag) {
2594 const bool test_mouse_event = TestMouseEventParam();
2595 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2596 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2597 const gfx::Point drag_start = GetAppListView()->GetBoundsInScreen().origin();
2598
2599 // Start drag and press escape to close the app list view.
2600 ui::test::EventGenerator* generator = GetEventGenerator();
2601 if (test_mouse_event) {
2602 generator->MoveMouseTo(drag_start);
2603 generator->PressLeftButton();
2604 generator->MoveMouseBy(0, -10);
2605 } else {
2606 generator->MoveTouch(drag_start);
2607 generator->PressTouch();
2608 generator->MoveTouch(drag_start + gfx::Vector2d(0, -10));
2609 }
2610
2611 EXPECT_TRUE(GetAppListView()->is_in_drag());
2612 generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
2613 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2614 EXPECT_FALSE(GetAppListView()->is_in_drag());
2615
2616 // Show the app list and verify the app list returns to peeking position.
2617 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2618 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2619 EXPECT_EQ(drag_start, GetAppListView()->GetBoundsInScreen().origin());
2620 }
2621
2622 // Tests closing the app list during drag, and verifies that drag updates are
2623 // ignored while the app list is closing.
TEST_P(AppListPresenterDelegateTest,DragUpdateWhileAppListClosing)2624 TEST_P(AppListPresenterDelegateTest, DragUpdateWhileAppListClosing) {
2625 const bool test_mouse_event = TestMouseEventParam();
2626 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2627 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2628 const gfx::Point drag_start = GetAppListView()->GetBoundsInScreen().origin();
2629
2630 // Set up non zero animation duration to ensure app list is not closed
2631 // immediately.
2632 ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
2633 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2634 AppListView::SetShortAnimationForTesting(false);
2635
2636 // Start drag and press escape to close the app list view.
2637 ui::test::EventGenerator* generator = GetEventGenerator();
2638 if (test_mouse_event) {
2639 generator->MoveMouseTo(drag_start);
2640 generator->PressLeftButton();
2641 generator->MoveMouseBy(0, -10);
2642 } else {
2643 generator->MoveTouch(drag_start);
2644 generator->PressTouch();
2645 generator->MoveTouch(drag_start + gfx::Vector2d(0, -10));
2646 }
2647 EXPECT_TRUE(GetAppListView()->is_in_drag());
2648
2649 generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
2650
2651 // Update the drag before running the loop that waits for the close animation
2652 // to finish,
2653 if (test_mouse_event) {
2654 generator->MoveMouseBy(0, -10);
2655 } else {
2656 generator->MoveTouch(drag_start + gfx::Vector2d(0, -20));
2657 }
2658
2659 base::RunLoop().RunUntilIdle();
2660 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2661 EXPECT_FALSE(GetAppListView()->is_in_drag());
2662
2663 // Show the app list and verify the app list returns to peeking position.
2664 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2665 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2666 EXPECT_EQ(drag_start, GetAppListView()->GetBoundsInScreen().origin());
2667 }
2668
2669 // Tests that a drag can not make the app list smaller than the shelf height.
TEST_F(AppListPresenterDelegateTest,LauncherCannotGetSmallerThanShelf)2670 TEST_F(AppListPresenterDelegateTest, LauncherCannotGetSmallerThanShelf) {
2671 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2672 AppListView* view = GetAppListView();
2673
2674 // Try to place the app list 1 px below the shelf, it should stay at shelf
2675 // height.
2676 int target_y = GetPrimaryShelf()
2677 ->GetShelfViewForTesting()
2678 ->GetBoundsInScreen()
2679 .top_right()
2680 .y();
2681 const int expected_app_list_y = target_y;
2682 target_y += 1;
2683 view->UpdateYPositionAndOpacity(target_y, 1);
2684
2685 EXPECT_EQ(expected_app_list_y, view->GetBoundsInScreen().top_right().y());
2686 }
2687
2688 // Tests that the AppListView is on screen on a small display.
TEST_F(AppListPresenterDelegateTest,SearchBoxShownOnSmallDisplay)2689 TEST_F(AppListPresenterDelegateTest, SearchBoxShownOnSmallDisplay) {
2690 // Update the display to a small scale factor.
2691 UpdateDisplay("600x400");
2692 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2693
2694 // Animate to Half.
2695 ui::test::EventGenerator* generator = GetEventGenerator();
2696 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
2697 AppListView* view = GetAppListView();
2698 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2699 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2700 EXPECT_LE(0, view->GetWidget()->GetNativeView()->bounds().y());
2701
2702 // Animate to peeking.
2703 generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
2704 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2705 EXPECT_LE(0, view->GetWidget()->GetNativeView()->bounds().y());
2706
2707 // Animate back to Half.
2708 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
2709 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2710 EXPECT_LE(0, view->GetWidget()->GetNativeView()->bounds().y());
2711 }
2712
2713 // Tests that the AppListView is on screen on a small work area.
TEST_F(AppListPresenterDelegateTest,SearchBoxShownOnSmallWorkArea)2714 TEST_F(AppListPresenterDelegateTest, SearchBoxShownOnSmallWorkArea) {
2715 // Update the work area to a small size.
2716 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2717 ASSERT_TRUE(display_manager()->UpdateWorkAreaOfDisplay(
2718 GetPrimaryDisplayId(), gfx::Insets(400, 0, 0, 0)));
2719
2720 // Animate to Half.
2721 ui::test::EventGenerator* generator = GetEventGenerator();
2722 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
2723 AppListView* view = GetAppListView();
2724 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2725 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2726 EXPECT_LE(GetPrimaryDisplay().work_area().y(),
2727 view->GetWidget()->GetNativeView()->bounds().y());
2728
2729 // Animate to peeking.
2730 generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
2731 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2732 EXPECT_LE(GetPrimaryDisplay().work_area().y(),
2733 view->GetWidget()->GetNativeView()->bounds().y());
2734
2735 // Animate back to Half.
2736 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
2737 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2738 EXPECT_LE(GetPrimaryDisplay().work_area().y(),
2739 view->GetWidget()->GetNativeView()->bounds().y());
2740 }
2741
2742 // Tests that no crash occurs after an attempt to show app list in an invalid
2743 // display.
TEST_F(AppListPresenterDelegateTest,ShowInInvalidDisplay)2744 TEST_F(AppListPresenterDelegateTest, ShowInInvalidDisplay) {
2745 GetAppListTestHelper()->ShowAndRunLoop(display::kInvalidDisplayId);
2746 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2747 }
2748
2749 // Tests that tap the auto-hide shelf with app list opened should dismiss the
2750 // app list but keep shelf visible.
TEST_F(AppListPresenterDelegateTest,TapAutoHideShelfWithAppListOpened)2751 TEST_F(AppListPresenterDelegateTest, TapAutoHideShelfWithAppListOpened) {
2752 Shelf* shelf = GetPrimaryShelf();
2753 shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
2754
2755 // Create a normal unmaximized window; the shelf should be hidden.
2756 std::unique_ptr<views::Widget> window = CreateTestWidget();
2757 window->SetBounds(gfx::Rect(0, 0, 100, 100));
2758 GetAppListTestHelper()->CheckVisibility(false);
2759 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
2760 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
2761
2762 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2763 GetAppListTestHelper()->CheckVisibility(true);
2764 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2765
2766 // Tap the system tray should open system tray bubble and keep shelf visible.
2767 ui::test::EventGenerator* generator = GetEventGenerator();
2768 generator->GestureTapAt(
2769 GetPrimaryUnifiedSystemTray()->GetBoundsInScreen().CenterPoint());
2770 EXPECT_TRUE(GetPrimaryUnifiedSystemTray()->IsBubbleShown());
2771 GetAppListTestHelper()->CheckVisibility(false);
2772 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2773
2774 // Tap to dismiss the app list and the auto-hide shelf.
2775 generator->GestureTapAt(gfx::Point(0, 0));
2776 EXPECT_FALSE(GetPrimaryUnifiedSystemTray()->IsBubbleShown());
2777 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
2778 GetAppListTestHelper()->CheckVisibility(false);
2779
2780 // Show the AppList again.
2781 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2782 GetAppListTestHelper()->CheckVisibility(true);
2783 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2784
2785 // Make sure the shelf has at least one item.
2786 ShelfItem item =
2787 ShelfTestUtil::AddAppShortcut(base::NumberToString(1), TYPE_PINNED_APP);
2788
2789 // Wait for shelf view's bounds animation to end. Otherwise the scrollable
2790 // shelf's bounds are not updated yet.
2791 ShelfView* const shelf_view = shelf->GetShelfViewForTesting();
2792 ShelfViewTestAPI shelf_view_test_api(shelf_view);
2793 shelf_view_test_api.RunMessageLoopUntilAnimationsDone();
2794
2795 // Test that tapping the auto-hidden shelf dismisses the app list when tapping
2796 // part of the shelf that does not contain the apps.
2797 generator->GestureTapAt(shelf_view->GetBoundsInScreen().left_center() +
2798 gfx::Vector2d(10, 0));
2799 GetAppListTestHelper()->CheckVisibility(false);
2800 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
2801
2802 // Show the AppList again.
2803 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2804 GetAppListTestHelper()->CheckVisibility(true);
2805 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2806
2807 // App list should remain visible when tapping on a shelf app button.
2808 ASSERT_TRUE(shelf_view_test_api.GetButton(0));
2809 generator->GestureTapAt(
2810 shelf_view_test_api.GetButton(0)->GetBoundsInScreen().CenterPoint());
2811 GetAppListTestHelper()->CheckVisibility(true);
2812 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2813 }
2814
TEST_F(AppListPresenterDelegateTest,ClickingShelfArrowDoesNotHideAppList)2815 TEST_F(AppListPresenterDelegateTest, ClickingShelfArrowDoesNotHideAppList) {
2816 // Add enough shelf items for the shelf to enter overflow.
2817 Shelf* const shelf = GetPrimaryShelf();
2818 ScrollableShelfView* const scrollable_shelf_view =
2819 shelf->hotseat_widget()->scrollable_shelf_view();
2820 ShelfView* const shelf_view = shelf->GetShelfViewForTesting();
2821 int index = 0;
2822 while (scrollable_shelf_view->layout_strategy_for_test() ==
2823 ScrollableShelfView::kNotShowArrowButtons) {
2824 ShelfItem item = ShelfTestUtil::AddAppShortcut(
2825 base::NumberToString(index++), TYPE_PINNED_APP);
2826 }
2827
2828 ShelfViewTestAPI shelf_view_test_api(shelf_view);
2829 shelf_view_test_api.RunMessageLoopUntilAnimationsDone();
2830
2831 shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
2832
2833 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2834 GetAppListTestHelper()->CheckVisibility(true);
2835 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2836
2837 // Click right scrollable shelf arrow - verify the the app list remains
2838 // visible.
2839 const views::View* right_arrow = scrollable_shelf_view->right_arrow();
2840 ASSERT_TRUE(right_arrow->GetVisible());
2841 GetEventGenerator()->MoveMouseTo(
2842 right_arrow->GetBoundsInScreen().CenterPoint());
2843 GetEventGenerator()->ClickLeftButton();
2844
2845 GetAppListTestHelper()->CheckVisibility(true);
2846 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2847
2848 // Click left button - verify the app list stays visible.
2849 const views::View* left_arrow = scrollable_shelf_view->left_arrow();
2850 ASSERT_TRUE(left_arrow->GetVisible());
2851 GetEventGenerator()->MoveMouseTo(
2852 left_arrow->GetBoundsInScreen().CenterPoint());
2853 GetEventGenerator()->ClickLeftButton();
2854
2855 GetAppListTestHelper()->CheckVisibility(true);
2856 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2857
2858 // Click right of the right arrow - verify the app list gets dismissed.
2859 ASSERT_TRUE(right_arrow->GetVisible());
2860 GetEventGenerator()->MoveMouseTo(
2861 right_arrow->GetBoundsInScreen().right_center() + gfx::Vector2d(10, 0));
2862 GetEventGenerator()->ClickLeftButton();
2863
2864 GetAppListTestHelper()->CheckVisibility(false);
2865 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2866 }
2867
2868 // Verifies that in clamshell mode, AppList has the expected state based on the
2869 // drag distance after dragging from Peeking state.
TEST_F(AppListPresenterDelegateTest,DragAppListViewFromPeeking)2870 TEST_F(AppListPresenterDelegateTest, DragAppListViewFromPeeking) {
2871 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2872 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2873
2874 // Calculate |threshold| in the same way with AppListView::EndDrag.
2875 const int threshold = AppListConfig::instance().peeking_app_list_height() /
2876 kAppListThresholdDenominator;
2877
2878 // Drag AppListView downward by |threshold| then release the gesture.
2879 // Check the final state should be Peeking.
2880 ui::test::EventGenerator* generator = GetEventGenerator();
2881 AppListView* view = GetAppListView();
2882 const int drag_to_peeking_distance = threshold;
2883 gfx::Point drag_start = view->GetBoundsInScreen().top_center();
2884 gfx::Point drag_end(drag_start.x(),
2885 drag_start.y() + drag_to_peeking_distance);
2886 generator->GestureScrollSequence(
2887 drag_start, drag_end,
2888 generator->CalculateScrollDurationForFlingVelocity(drag_start, drag_end,
2889 2, 1000),
2890 1000);
2891 GetAppListTestHelper()->WaitUntilIdle();
2892 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2893
2894 // Drag AppListView upward by bigger distance then release the gesture.
2895 // Check the final state should be kFullscreenAllApps.
2896 const int drag_to_fullscreen_distance = threshold + 1;
2897 drag_start = view->GetBoundsInScreen().top_center();
2898 drag_end =
2899 gfx::Point(drag_start.x(), drag_start.y() - drag_to_fullscreen_distance);
2900
2901 generator->GestureScrollSequence(
2902 drag_start, drag_end,
2903 generator->CalculateScrollDurationForFlingVelocity(drag_start, drag_end,
2904 2, 1000),
2905 1000);
2906 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2907 }
2908
2909 // Tests that the app list background corner radius remains constant during app
2910 // list drag if the shelf is not in maximized state.
TEST_F(AppListPresenterDelegateTest,BackgroundCornerRadiusDuringDrag)2911 TEST_F(AppListPresenterDelegateTest, BackgroundCornerRadiusDuringDrag) {
2912 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2913 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2914
2915 const gfx::Point shelf_top = GetPrimaryShelf()
2916 ->GetShelfViewForTesting()
2917 ->GetBoundsInScreen()
2918 .top_center();
2919 const int background_radius = ShelfConfig::Get()->shelf_size() / 2;
2920
2921 AppListView* view = GetAppListView();
2922 const views::View* const background_shield =
2923 view->GetAppListBackgroundShieldForTest();
2924 ui::test::EventGenerator* generator = GetEventGenerator();
2925
2926 // Start drag at the peeking height, and move to different
2927 // positions relative to the shelf top.
2928 // Verify that the app list background shield never changes.
2929 const gfx::Point peeking_top = view->GetBoundsInScreen().top_center();
2930 generator->MoveTouch(peeking_top);
2931 generator->PressTouch();
2932 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2933 background_shield->layer()->rounded_corner_radii());
2934
2935 // Move above the shelf, with an offset less than the background radius.
2936 generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius / 5));
2937 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2938 background_shield->layer()->rounded_corner_radii());
2939
2940 // Move to the top of the shelf.
2941 generator->MoveTouch(shelf_top);
2942 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2943 background_shield->layer()->rounded_corner_radii());
2944
2945 // Move to half rounded background radius height.
2946 generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius / 2));
2947 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2948 background_shield->layer()->rounded_corner_radii());
2949
2950 // Move to the height just under the background radius.
2951 generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius - 1));
2952 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2953 background_shield->layer()->rounded_corner_radii());
2954
2955 // Move to the height that equals the background radius.
2956 generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius));
2957 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2958 background_shield->layer()->rounded_corner_radii());
2959
2960 // Move to the height just over the background radius.
2961 generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius + 1));
2962 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2963 background_shield->layer()->rounded_corner_radii());
2964 generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius + 5));
2965 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2966 background_shield->layer()->rounded_corner_radii());
2967
2968 // Move above the peeking height.
2969 generator->MoveTouch(gfx::Point(peeking_top.x(), peeking_top.y() + 5));
2970 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2971 background_shield->layer()->rounded_corner_radii());
2972
2973 // Move back to peeking height, and end drag.
2974 generator->MoveTouch(peeking_top);
2975 generator->ReleaseTouch();
2976 GetAppListTestHelper()->WaitUntilIdle();
2977 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2978
2979 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2980 background_shield->layer()->rounded_corner_radii());
2981 }
2982
2983 // Tests how app list background rounded corners are changed during a drag while
2984 // the shelf is in a maximized state (i.e. while a maximized window is shown).
TEST_F(AppListPresenterDelegateTest,BackgroundCornerRadiusDuringDragWithMaximizedShelf)2985 TEST_F(AppListPresenterDelegateTest,
2986 BackgroundCornerRadiusDuringDragWithMaximizedShelf) {
2987 auto window = CreateTestWindow();
2988 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
2989
2990 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2991 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2992
2993 const gfx::Point shelf_top = GetPrimaryShelf()
2994 ->GetShelfViewForTesting()
2995 ->GetBoundsInScreen()
2996 .top_center();
2997 const int background_radius = ShelfConfig::Get()->shelf_size() / 2;
2998
2999 AppListView* view = GetAppListView();
3000 const views::View* const background_shield =
3001 view->GetAppListBackgroundShieldForTest();
3002 ui::test::EventGenerator* generator = GetEventGenerator();
3003
3004 // Start drag at the peeking app list top.
3005 const gfx::Point peeking_top = view->GetBoundsInScreen().top_center();
3006 generator->MoveTouch(peeking_top);
3007 generator->PressTouch();
3008
3009 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
3010 background_shield->layer()->rounded_corner_radii());
3011
3012 // Move above the shelf, with an offset less than the background radius.
3013 // Verify that current background corner radius matches the offset from the
3014 // shelf.
3015 generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius / 5));
3016 EXPECT_EQ(
3017 gfx::RoundedCornersF(background_radius / 5, background_radius / 5, 0, 0),
3018 background_shield->layer()->rounded_corner_radii());
3019
3020 // Move to the shelf top - background should have no rounded corners.
3021 generator->MoveTouch(shelf_top);
3022 EXPECT_EQ(gfx::RoundedCornersF(),
3023 background_shield->layer()->rounded_corner_radii());
3024
3025 // Move to half background radius height - the background corner radius should
3026 // match the offset from the shelf.
3027 generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius / 2));
3028 EXPECT_EQ(
3029 gfx::RoundedCornersF(background_radius / 2, background_radius / 2, 0, 0),
3030 background_shield->layer()->rounded_corner_radii());
3031
3032 // Move to the height just under the background radius - the current
3033 // background corners should be equal to the offset from the shelf.
3034 generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius - 1));
3035 EXPECT_EQ(
3036 gfx::RoundedCornersF(background_radius - 1, background_radius - 1, 0, 0),
3037 background_shield->layer()->rounded_corner_radii());
3038
3039 // Move to the height that equals the background radius - the current
3040 // background corners should be equal to the offset from the shelf.
3041 generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius));
3042 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
3043 background_shield->layer()->rounded_corner_radii());
3044
3045 // Move to the height just over the background radius - the background corner
3046 // radius value should stay at the |background_radius| value.
3047 generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius + 1));
3048 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
3049 background_shield->layer()->rounded_corner_radii());
3050 generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius + 5));
3051 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
3052 background_shield->layer()->rounded_corner_radii());
3053
3054 // Move above the peeking height - the background radius should remain the
3055 // same.
3056 generator->MoveTouch(gfx::Point(peeking_top.x(), peeking_top.y() + 5));
3057 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
3058 background_shield->layer()->rounded_corner_radii());
3059
3060 // Move back to peeking height, and end drag.
3061 generator->MoveTouch(peeking_top);
3062 generator->ReleaseTouch();
3063 GetAppListTestHelper()->WaitUntilIdle();
3064 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3065
3066 EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
3067 background_shield->layer()->rounded_corner_radii());
3068 }
3069
3070 // Tests how app list is laid out during different state transitions and app
3071 // list drag.
3072 class AppListPresenterDelegateLayoutTest : public AppListPresenterDelegateTest {
3073 public:
AppListPresenterDelegateLayoutTest()3074 AppListPresenterDelegateLayoutTest() {
3075 scoped_feature_list_.InitAndEnableFeature(features::kEnableBackgroundBlur);
3076 }
3077 ~AppListPresenterDelegateLayoutTest() override = default;
3078
SetUp()3079 void SetUp() override {
3080 AppListPresenterDelegateTest::SetUp();
3081
3082 UpdateDisplay("1080x900");
3083 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3084 }
3085
ExpectedSuggestionChipContainerTop(const gfx::Rect & search_box_bounds)3086 int ExpectedSuggestionChipContainerTop(const gfx::Rect& search_box_bounds) {
3087 return search_box_bounds.bottom() + 16 /*suggesion chip top margin*/;
3088 }
3089
3090 // Calculates expected apps grid position based on display height and the
3091 // search box in-screen bounds.
3092 // NOTE: This assumes that the display size is such that the preferred apps
3093 // grid size is within min and max apps grid height (in which case the margin
3094 // when scalable app list is not enabled is 1 / 16 of the available height).
ExpectedAppsGridTop(const AppListConfig & config,int display_height,const gfx::Rect & search_box_bounds)3095 int ExpectedAppsGridTop(const AppListConfig& config,
3096 int display_height,
3097 const gfx::Rect& search_box_bounds) {
3098 return ExpectedSuggestionChipContainerTop(search_box_bounds) +
3099 32 /*suggestion chip container height*/ +
3100 config.grid_fadeout_zone_height() -
3101 config.grid_fadeout_mask_height();
3102 }
3103
3104 // Calculates expected apps grid position on the search results page based on
3105 // the display height and the search box in-screen bounds.
ExpectedAppsGridTopForSearchResults(const AppListConfig & config,int display_height,const gfx::Rect & search_box_bounds)3106 int ExpectedAppsGridTopForSearchResults(const AppListConfig& config,
3107 int display_height,
3108 const gfx::Rect& search_box_bounds) {
3109 const int top =
3110 ExpectedAppsGridTop(config, display_height, search_box_bounds);
3111 // In the search results page, the apps grid is shown 24 dip below where
3112 // they'd be shown in the apps page. The |top| was calculated relative to
3113 // search box bounds in the search results page, so it has to be further
3114 // offset by the difference between search box bottom bounds in the apps and
3115 // search results page.
3116 const int search_box_diff =
3117 contents_view()->GetSearchBoxBounds(AppListState::kStateApps).bottom() -
3118 contents_view()
3119 ->GetSearchBoxBounds(AppListState::kStateSearchResults)
3120 .bottom();
3121 return top + search_box_diff +
3122 24 /*apps grid offset in fullscreen search state*/;
3123 }
3124
contents_view()3125 ContentsView* contents_view() {
3126 return GetAppListView()->app_list_main_view()->contents_view();
3127 }
3128
apps_grid_view()3129 AppsGridView* apps_grid_view() {
3130 return GetAppListView()
3131 ->app_list_main_view()
3132 ->contents_view()
3133 ->apps_container_view()
3134 ->apps_grid_view();
3135 }
3136
3137 private:
3138 base::test::ScopedFeatureList scoped_feature_list_;
3139 };
3140
3141 // Tests that the app list contents top margin is gradually updated during drag
3142 // between peeking and fullscreen view state while showing apps page.
TEST_F(AppListPresenterDelegateLayoutTest,AppsPagePositionDuringDrag)3143 TEST_F(AppListPresenterDelegateLayoutTest, AppsPagePositionDuringDrag) {
3144 const AppListConfig& config = GetAppListView()->GetAppListConfig();
3145 const int shelf_height = ShelfConfig::Get()->shelf_size();
3146 const int fullscreen_y = 0;
3147 const int closed_y = 900 - shelf_height;
3148 const int fullscreen_search_box_padding = (900 - shelf_height) / 16;
3149
3150 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3151 const gfx::Point peeking_top =
3152 GetAppListView()->GetBoundsInScreen().top_center();
3153
3154 // Drag AppListView upwards half way to the top of the screen, and check the
3155 // search box padding has been updated to a value half-way between peeking and
3156 // fullscreen values.
3157 ui::test::EventGenerator* generator = GetEventGenerator();
3158 generator->MoveTouch(peeking_top);
3159 generator->PressTouch();
3160 generator->MoveTouch(
3161 gfx::Point(peeking_top.x(), (peeking_top.y() + fullscreen_y) / 2));
3162 GetAppListTestHelper()->WaitUntilIdle();
3163
3164 gfx::Rect search_box_bounds =
3165 GetAppListView()->search_box_view()->GetBoundsInScreen();
3166 search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3167
3168 float progress = GetAppListView()->GetAppListTransitionProgress(
3169 AppListView::kProgressFlagNone);
3170 EXPECT_LE(std::abs(progress - 1.5f), 0.01f);
3171
3172 EXPECT_EQ((peeking_top.y() + fullscreen_y) / 2 +
3173 gfx::Tween::IntValueBetween(
3174 progress - 1, config.search_box_peeking_top_padding(),
3175 fullscreen_search_box_padding),
3176 search_box_bounds.y());
3177
3178 EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds),
3179 apps_grid_view()->GetBoundsInScreen().y());
3180 EXPECT_TRUE(apps_grid_view()->GetVisible());
3181 // In apps state, search results page should be hidden behind the search
3182 // box.
3183 EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen());
3184
3185 // Move to the fullscreen position, and verify the search box padding is
3186 // equal to the expected fullscreen value.
3187 generator->MoveTouch(gfx::Point(peeking_top.x(), fullscreen_y));
3188 GetAppListTestHelper()->WaitUntilIdle();
3189
3190 EXPECT_EQ(2.0f, GetAppListView()->GetAppListTransitionProgress(
3191 AppListView::kProgressFlagNone));
3192
3193 search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3194 search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3195
3196 EXPECT_EQ(fullscreen_search_box_padding, search_box_bounds.y());
3197 EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds),
3198 apps_grid_view()->GetBoundsInScreen().y());
3199 EXPECT_TRUE(apps_grid_view()->GetVisible());
3200 EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen());
3201
3202 // Move half way between peeking and closed state - the search box padding
3203 // should be half distance between closed and peeking padding.
3204 generator->MoveTouch(
3205 gfx::Point(peeking_top.x(), (peeking_top.y() + closed_y) / 2));
3206 GetAppListTestHelper()->WaitUntilIdle();
3207
3208 search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3209 search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3210
3211 progress = GetAppListView()->GetAppListTransitionProgress(
3212 AppListView::kProgressFlagNone);
3213 EXPECT_LE(std::abs(progress - 0.5f), 0.01f);
3214
3215 EXPECT_EQ((peeking_top.y() + closed_y) / 2 +
3216 gfx::Tween::IntValueBetween(
3217 progress, config.search_box_peeking_top_padding(),
3218 config.search_box_closed_top_padding()),
3219 search_box_bounds.y());
3220 EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds),
3221 apps_grid_view()->GetBoundsInScreen().y());
3222 EXPECT_TRUE(apps_grid_view()->GetVisible());
3223 EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen());
3224
3225 // Move to the closed state height, and verify the search box padding matches
3226 // the state.
3227 generator->MoveTouch(gfx::Point(peeking_top.x(), closed_y));
3228 GetAppListTestHelper()->WaitUntilIdle();
3229 EXPECT_EQ(0.0f, GetAppListView()->GetAppListTransitionProgress(
3230 AppListView::kProgressFlagNone));
3231
3232 search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3233 search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3234
3235 EXPECT_EQ(closed_y + config.search_box_closed_top_padding(),
3236 search_box_bounds.y());
3237 EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds),
3238 apps_grid_view()->GetBoundsInScreen().y());
3239 EXPECT_TRUE(apps_grid_view()->GetVisible());
3240 EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen());
3241 }
3242
3243 // Tests that the app list contents top margin is gradually updated during drag
3244 // between half and fullscreen state while showing search results.
TEST_F(AppListPresenterDelegateLayoutTest,SearchResultsPagePositionDuringDrag)3245 TEST_F(AppListPresenterDelegateLayoutTest,
3246 SearchResultsPagePositionDuringDrag) {
3247 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3248
3249 // Enter text in the search box to transition to half app list.
3250 ui::test::EventGenerator* generator = GetEventGenerator();
3251 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
3252 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
3253
3254 const AppListConfig& config = GetAppListView()->GetAppListConfig();
3255 const int shelf_height = ShelfConfig::Get()->shelf_size();
3256 const int search_results_height = 440;
3257 const int fullscreen_y = 0;
3258 const int closed_y = 900 - shelf_height;
3259 const int fullscreen_search_box_padding = (900 - shelf_height) / 16;
3260
3261 const gfx::Point half_top =
3262 GetAppListView()->GetBoundsInScreen().top_center();
3263
3264 // Drag AppListView upwards half way to the top of the screen, and check the
3265 // search box padding has been updated to a value half-way between peeking and
3266 // fullscreen values.
3267 generator->MoveTouch(half_top);
3268 generator->PressTouch();
3269 generator->MoveTouch(
3270 gfx::Point(half_top.x(), (half_top.y() + fullscreen_y) / 2));
3271 GetAppListTestHelper()->WaitUntilIdle();
3272
3273 gfx::Rect search_box_bounds =
3274 GetAppListView()->search_box_view()->GetBoundsInScreen();
3275 search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3276
3277 float progress = GetAppListView()->GetAppListTransitionProgress(
3278 AppListView::kProgressFlagSearchResults);
3279 EXPECT_LE(std::abs(progress - 1.5f), 0.01f);
3280
3281 EXPECT_EQ((half_top.y() + fullscreen_y) / 2 +
3282 gfx::Tween::IntValueBetween(
3283 progress - 1, config.search_box_fullscreen_top_padding(),
3284 fullscreen_search_box_padding),
3285 search_box_bounds.y());
3286 EXPECT_EQ(search_box_bounds.y(),
3287 search_result_page()->GetBoundsInScreen().y());
3288 EXPECT_EQ(search_results_height,
3289 search_result_page()->GetBoundsInScreen().height());
3290 EXPECT_EQ(ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds),
3291 apps_grid_view()->GetBoundsInScreen().y());
3292 EXPECT_TRUE(apps_grid_view()->GetVisible());
3293
3294 // Move to the fullscreen position, and verify the search box padding is
3295 // equal to the expected fullscreen value.
3296 generator->MoveTouch(gfx::Point(half_top.x(), fullscreen_y));
3297 GetAppListTestHelper()->WaitUntilIdle();
3298 EXPECT_EQ(2.0f, GetAppListView()->GetAppListTransitionProgress(
3299 AppListView::kProgressFlagSearchResults));
3300
3301 search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3302 search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3303
3304 EXPECT_EQ(fullscreen_search_box_padding, search_box_bounds.y());
3305 EXPECT_EQ(search_box_bounds.y(),
3306 search_result_page()->GetBoundsInScreen().y());
3307 EXPECT_EQ(search_results_height,
3308 search_result_page()->GetBoundsInScreen().height());
3309 EXPECT_EQ(ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds),
3310 apps_grid_view()->GetBoundsInScreen().y());
3311 EXPECT_TRUE(apps_grid_view()->GetVisible());
3312
3313 // Move half way between peeking and closed state - the search box padding
3314 // should be half distance between closed and peeking padding.
3315 generator->MoveTouch(gfx::Point(half_top.x(), (half_top.y() + closed_y) / 2));
3316 GetAppListTestHelper()->WaitUntilIdle();
3317
3318 progress = GetAppListView()->GetAppListTransitionProgress(
3319 AppListView::kProgressFlagSearchResults);
3320 EXPECT_LE(std::abs(progress - 0.5f), 0.01f);
3321
3322 search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3323 search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3324
3325 EXPECT_EQ((half_top.y() + closed_y) / 2 +
3326 gfx::Tween::IntValueBetween(
3327 progress, config.search_box_fullscreen_top_padding(),
3328 config.search_box_closed_top_padding()),
3329 search_box_bounds.y());
3330 EXPECT_EQ(search_box_bounds.y(),
3331 search_result_page()->GetBoundsInScreen().y());
3332 EXPECT_EQ(search_results_height,
3333 search_result_page()->GetBoundsInScreen().height());
3334 EXPECT_EQ(ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds),
3335 apps_grid_view()->GetBoundsInScreen().y());
3336 EXPECT_TRUE(apps_grid_view()->GetVisible());
3337
3338 // Move to the closed state height, and verify the search box padding matches
3339 // the state.
3340 generator->MoveTouch(gfx::Point(half_top.x(), closed_y));
3341 GetAppListTestHelper()->WaitUntilIdle();
3342 EXPECT_EQ(0.0f, GetAppListView()->GetAppListTransitionProgress(
3343 AppListView::kProgressFlagSearchResults));
3344
3345 search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3346 search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3347
3348 EXPECT_EQ(closed_y + config.search_box_closed_top_padding(),
3349 search_box_bounds.y());
3350 EXPECT_EQ(search_box_bounds.y(),
3351 search_result_page()->GetBoundsInScreen().y());
3352 EXPECT_EQ(search_results_height,
3353 search_result_page()->GetBoundsInScreen().height());
3354 EXPECT_EQ(ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds),
3355 apps_grid_view()->GetBoundsInScreen().y());
3356 EXPECT_TRUE(apps_grid_view()->GetVisible());
3357 }
3358
3359 // Tests changing the active app list page while drag is in progress.
TEST_F(AppListPresenterDelegateLayoutTest,SwitchPageDuringDrag)3360 TEST_F(AppListPresenterDelegateLayoutTest, SwitchPageDuringDrag) {
3361 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3362 const gfx::Point peeking_top =
3363 GetAppListView()->GetBoundsInScreen().top_center();
3364
3365 // Enter text in the search box to transition to half app list.
3366 ui::test::EventGenerator* generator = GetEventGenerator();
3367 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
3368 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
3369
3370 const gfx::Point half_top =
3371 GetAppListView()->GetBoundsInScreen().top_center();
3372
3373 const AppListConfig& config = GetAppListView()->GetAppListConfig();
3374 const int shelf_height = ShelfConfig::Get()->shelf_size();
3375 const int search_results_height = 440;
3376 const int fullscreen_y = 0;
3377 const int fullscreen_search_box_padding = (900 - shelf_height) / 16;
3378
3379 // Drag AppListView upwards half way to the top of the screen, and check the
3380 // search box padding has been updated to a value half-way between peeking and
3381 // fullscreen values.
3382 generator->MoveTouch(half_top);
3383 generator->PressTouch();
3384 generator->MoveTouch(
3385 gfx::Point(half_top.x(), (half_top.y() + fullscreen_y) / 2));
3386 GetAppListTestHelper()->WaitUntilIdle();
3387
3388 gfx::Rect search_box_bounds =
3389 GetAppListView()->search_box_view()->GetBoundsInScreen();
3390 search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3391
3392 float progress = GetAppListView()->GetAppListTransitionProgress(
3393 AppListView::kProgressFlagSearchResults);
3394 EXPECT_LE(std::abs(progress - 1.5f), 0.01f);
3395 EXPECT_EQ((half_top.y() + fullscreen_y) / 2 +
3396 gfx::Tween::IntValueBetween(
3397 progress - 1, config.search_box_fullscreen_top_padding(),
3398 fullscreen_search_box_padding),
3399 search_box_bounds.y());
3400 EXPECT_EQ(search_box_bounds.y(),
3401 search_result_page()->GetBoundsInScreen().y());
3402 EXPECT_EQ(search_results_height,
3403 search_result_page()->GetBoundsInScreen().height());
3404 EXPECT_EQ(ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds),
3405 apps_grid_view()->GetBoundsInScreen().y());
3406 EXPECT_TRUE(apps_grid_view()->GetVisible());
3407
3408 const gfx::Rect apps_grid_bounds_in_results_page =
3409 apps_grid_view()->GetBoundsInScreen();
3410 const gfx::Rect app_list_bounds = GetAppListView()->GetBoundsInScreen();
3411
3412 // Press ESC key - this should move the UI back to the app list.
3413 generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
3414 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3415
3416 // The app list position should remain the same.
3417 EXPECT_EQ(app_list_bounds, GetAppListView()->GetBoundsInScreen());
3418
3419 // The search box should be moved so drag progress for peeking state matches
3420 // the current height.
3421 float new_progress = (0.5 * half_top.y()) / peeking_top.y();
3422 int expected_search_box_top =
3423 new_progress * peeking_top.y() +
3424 (1 - new_progress) * fullscreen_search_box_padding +
3425 new_progress * config.search_box_peeking_top_padding();
3426
3427 search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3428 search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3429
3430 EXPECT_EQ(expected_search_box_top, search_box_bounds.y());
3431 EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds),
3432 apps_grid_view()->GetBoundsInScreen().y());
3433 EXPECT_TRUE(apps_grid_view()->GetVisible());
3434 EXPECT_EQ(apps_grid_bounds_in_results_page.y() - 24,
3435 apps_grid_view()->GetBoundsInScreen().y());
3436 EXPECT_EQ(apps_grid_bounds_in_results_page.size(),
3437 apps_grid_view()->GetBoundsInScreen().size());
3438 EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen());
3439
3440 // Enter text in the search box to transition back to search results page.
3441 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
3442 GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
3443
3444 search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3445 search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3446
3447 progress = GetAppListView()->GetAppListTransitionProgress(
3448 AppListView::kProgressFlagSearchResults);
3449 EXPECT_LE(std::abs(progress - 1.5f), 0.01f);
3450 EXPECT_EQ((half_top.y() + fullscreen_y) / 2 +
3451 gfx::Tween::IntValueBetween(
3452 progress - 1, config.search_box_fullscreen_top_padding(),
3453 fullscreen_search_box_padding),
3454 search_box_bounds.y());
3455 EXPECT_EQ(search_box_bounds.y(),
3456 search_result_page()->GetBoundsInScreen().y());
3457 EXPECT_EQ(search_results_height,
3458 search_result_page()->GetBoundsInScreen().height());
3459 EXPECT_EQ(ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds),
3460 apps_grid_view()->GetBoundsInScreen().y());
3461 EXPECT_TRUE(apps_grid_view()->GetVisible());
3462 }
3463
3464 // Tests changing the active app list page in fullscreen state.
TEST_F(AppListPresenterDelegateLayoutTest,SwitchPageInFullscreen)3465 TEST_F(AppListPresenterDelegateLayoutTest, SwitchPageInFullscreen) {
3466 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3467 FlingUpOrDown(GetEventGenerator(), GetAppListView(), true);
3468 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
3469
3470 const AppListConfig& config = GetAppListView()->GetAppListConfig();
3471 const int shelf_height = ShelfConfig::Get()->shelf_size();
3472 const int search_results_height = 440;
3473 const int fullscreen_y = 0;
3474 const int fullscreen_search_box_padding = (900 - shelf_height) / 16;
3475
3476 gfx::Rect search_box_bounds =
3477 GetAppListView()->search_box_view()->GetBoundsInScreen();
3478 search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3479
3480 EXPECT_EQ(fullscreen_y + fullscreen_search_box_padding,
3481 search_box_bounds.y());
3482 EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds),
3483 apps_grid_view()->GetBoundsInScreen().y());
3484 EXPECT_TRUE(apps_grid_view()->GetVisible());
3485 EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen());
3486
3487 const gfx::Rect app_list_bounds = GetAppListView()->GetBoundsInScreen();
3488
3489 // Enter text in the search box to transition to half app list.
3490 ui::test::EventGenerator* generator = GetEventGenerator();
3491 generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
3492 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
3493
3494 search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3495 search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3496
3497 EXPECT_EQ(app_list_bounds, GetAppListView()->GetBoundsInScreen());
3498 EXPECT_EQ(fullscreen_y + fullscreen_search_box_padding,
3499 search_box_bounds.y());
3500 EXPECT_EQ(search_box_bounds.y(),
3501 search_result_page()->GetBoundsInScreen().y());
3502 EXPECT_EQ(search_results_height,
3503 search_result_page()->GetBoundsInScreen().height());
3504 EXPECT_EQ(ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds),
3505 apps_grid_view()->GetBoundsInScreen().y());
3506 EXPECT_TRUE(apps_grid_view()->GetVisible());
3507 const gfx::Rect apps_grid_bounds_in_results_page =
3508 apps_grid_view()->GetBoundsInScreen();
3509
3510 // Press ESC key - this should move the UI back to the app list.
3511 generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
3512 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
3513
3514 search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3515 search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3516
3517 EXPECT_EQ(app_list_bounds, GetAppListView()->GetBoundsInScreen());
3518 EXPECT_EQ(fullscreen_y + fullscreen_search_box_padding,
3519 search_box_bounds.y());
3520 EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds),
3521 apps_grid_view()->GetBoundsInScreen().y());
3522 EXPECT_TRUE(apps_grid_view()->GetVisible());
3523 EXPECT_EQ(apps_grid_bounds_in_results_page.y() - 24,
3524 apps_grid_view()->GetBoundsInScreen().y());
3525 EXPECT_EQ(apps_grid_bounds_in_results_page.size(),
3526 apps_grid_view()->GetBoundsInScreen().size());
3527 EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen());
3528 }
3529
3530 // Test a variety of behaviors for home launcher (app list in tablet mode).
3531 class AppListPresenterDelegateHomeLauncherTest
3532 : public AppListPresenterDelegateTest {
3533 public:
AppListPresenterDelegateHomeLauncherTest()3534 AppListPresenterDelegateHomeLauncherTest() {
3535 scoped_feature_list_.InitWithFeatures({features::kEnableBackgroundBlur},
3536 {});
3537 }
3538 AppListPresenterDelegateHomeLauncherTest(
3539 const AppListPresenterDelegateHomeLauncherTest&) = delete;
3540 AppListPresenterDelegateHomeLauncherTest& operator=(
3541 const AppListPresenterDelegateHomeLauncherTest&) = delete;
3542 ~AppListPresenterDelegateHomeLauncherTest() override = default;
3543
3544 // testing::Test:
SetUp()3545 void SetUp() override {
3546 AppListPresenterDelegateTest::SetUp();
3547 GetAppListTestHelper()->WaitUntilIdle();
3548 }
3549
TapHomeButton(int64_t display_id)3550 void TapHomeButton(int64_t display_id) {
3551 HomeButton* const home_button =
3552 Shell::GetRootWindowControllerWithDisplayId(display_id)
3553 ->shelf()
3554 ->navigation_widget()
3555 ->GetHomeButton();
3556 gfx::Point tap_point = home_button->GetBoundsInScreen().CenterPoint();
3557 GetEventGenerator()->GestureTapDownAndUp(tap_point);
3558 GetAppListTestHelper()->WaitUntilIdle();
3559 }
3560
3561 // Ensures transition to home screen in tablet mode (where home button is not
3562 // always shown).
GoHome()3563 void GoHome() {
3564 const int64_t primary_display_id = GetPrimaryDisplay().id();
3565 // If home button is not expected to be shown, use
3566 // HomeScreenController::GoHome() directly, otherwise tap on the primary
3567 // screen home button.
3568 if (!Shell::Get()->shelf_config()->shelf_controls_shown()) {
3569 Shell::Get()->home_screen_controller()->GoHome(primary_display_id);
3570 return;
3571 }
3572 TapHomeButton(primary_display_id);
3573 }
3574
split_view_controller()3575 SplitViewController* split_view_controller() {
3576 return SplitViewController::Get(Shell::GetPrimaryRootWindow());
3577 }
3578
3579 private:
3580 base::test::ScopedFeatureList scoped_feature_list_;
3581 };
3582
3583 // Verifies that mouse dragging AppListView is enabled.
TEST_P(AppListPresenterDelegateHomeLauncherTest,MouseDragAppList)3584 TEST_P(AppListPresenterDelegateHomeLauncherTest, MouseDragAppList) {
3585 std::unique_ptr<AppListItem> item(new AppListItem("fake id"));
3586 Shell::Get()->app_list_controller()->GetModel()->AddItem(std::move(item));
3587
3588 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3589 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3590
3591 // Drag AppListView upward by mouse. Before moving the mouse, AppsGridView
3592 // should be invisible.
3593 const gfx::Point start_point = GetAppListView()->GetBoundsInScreen().origin();
3594 ui::test::EventGenerator* generator = GetEventGenerator();
3595 generator->MoveMouseTo(start_point);
3596 generator->PressLeftButton();
3597 AppsGridView* apps_grid_view = GetAppListView()
3598 ->app_list_main_view()
3599 ->contents_view()
3600 ->apps_container_view()
3601 ->apps_grid_view();
3602 EXPECT_FALSE(apps_grid_view->GetVisible());
3603
3604 // Verifies that the AppListView state after mouse drag should be
3605 // FullscreenAllApps.
3606 generator->MoveMouseBy(0, -start_point.y());
3607 generator->ReleaseLeftButton();
3608 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
3609 EXPECT_TRUE(apps_grid_view->GetVisible());
3610 }
3611
3612 // Verifies that mouse dragging AppListView creates layers, causes to change the
3613 // opacity, and destroys the layers when done.
TEST_P(AppListPresenterDelegateHomeLauncherTest,MouseDragAppListItemOpacity)3614 TEST_P(AppListPresenterDelegateHomeLauncherTest, MouseDragAppListItemOpacity) {
3615 const int items_in_page = AppListConfig::instance().preferred_cols() *
3616 AppListConfig::instance().preferred_rows();
3617 for (int i = 0; i < items_in_page; ++i) {
3618 std::unique_ptr<AppListItem> item(
3619 new AppListItem(base::StringPrintf("fake id %d", i)));
3620 Shell::Get()->app_list_controller()->GetModel()->AddItem(std::move(item));
3621 }
3622
3623 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3624 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3625
3626 // Drag AppListView by mouse. Before moving the mouse, each AppListItem
3627 // doesn't have its own layer.
3628 const gfx::Point start_point = GetAppListView()->GetBoundsInScreen().origin();
3629 ui::test::EventGenerator* generator = GetEventGenerator();
3630 generator->MoveMouseTo(start_point);
3631 generator->PressLeftButton();
3632 AppsGridView* apps_grid_view = GetAppListView()
3633 ->app_list_main_view()
3634 ->contents_view()
3635 ->apps_container_view()
3636 ->apps_grid_view();
3637 // No items have layer.
3638 for (int i = 0; i < items_in_page; ++i) {
3639 views::View* item_view = apps_grid_view->view_model()->view_at(i);
3640 EXPECT_FALSE(item_view->layer()) << "at " << i;
3641 }
3642
3643 // Drags the mouse a bit above (twice as shelf's height). This should show the
3644 // item vaguely.
3645 const int shelf_height =
3646 GetPrimaryShelf()->GetShelfViewForTesting()->height();
3647 generator->MoveMouseBy(0, -shelf_height * 2);
3648 // All of the item should have the layer at this point.
3649 for (int i = 0; i < items_in_page; ++i) {
3650 views::View* item_view = apps_grid_view->view_model()->view_at(i);
3651 EXPECT_TRUE(item_view->layer()) << "at " << i;
3652 EXPECT_LE(0.f, item_view->layer()->opacity()) << "at " << i;
3653 EXPECT_GE(1.f, item_view->layer()->opacity()) << "at " << i;
3654 }
3655
3656 // Moves the mouse to the top edge of the screen; now all app-list items are
3657 // fully visible, but stays to keep layer. The opacity should be almost 1.0.
3658 generator->MoveMouseTo(start_point.x(), 0);
3659 for (int i = 0; i < items_in_page; ++i) {
3660 views::View* item_view = apps_grid_view->view_model()->view_at(i);
3661 EXPECT_TRUE(item_view->layer()) << "at " << i;
3662 EXPECT_LE(0.f, item_view->layer()->opacity()) << "at " << i;
3663 EXPECT_GE(1.f, item_view->layer()->opacity()) << "at " << i;
3664 }
3665
3666 // Finishes the drag. It should destruct the layer.
3667 generator->ReleaseLeftButton();
3668 for (int i = 0; i < items_in_page; ++i) {
3669 views::View* item_view = apps_grid_view->view_model()->view_at(i);
3670 EXPECT_FALSE(item_view->layer()) << "at " << i;
3671 }
3672 }
3673
3674 // Tests that ending of the mouse dragging of app-list destroys the layers for
3675 // the items which are in the second page. See https://crbug.com/990529.
TEST_P(AppListPresenterDelegateHomeLauncherTest,LayerOnSecondPage)3676 TEST_P(AppListPresenterDelegateHomeLauncherTest, LayerOnSecondPage) {
3677 const int items_in_page = AppListConfig::instance().preferred_cols() *
3678 AppListConfig::instance().preferred_rows();
3679 AppListModel* model = Shell::Get()->app_list_controller()->GetModel();
3680 for (int i = 0; i < items_in_page; ++i) {
3681 std::unique_ptr<AppListItem> item(
3682 new AppListItem(base::StringPrintf("fake id %02d", i)));
3683 model->AddItem(std::move(item));
3684 }
3685
3686 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3687 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3688
3689 const gfx::Point start_point = GetAppListView()->GetBoundsInScreen().origin();
3690 ui::test::EventGenerator* generator = GetEventGenerator();
3691 generator->MoveMouseTo(start_point);
3692 generator->PressLeftButton();
3693 AppsGridView* apps_grid_view = GetAppListView()
3694 ->app_list_main_view()
3695 ->contents_view()
3696 ->apps_container_view()
3697 ->apps_grid_view();
3698
3699 // Drags the mouse a bit above (twice as shelf's height). This should show the
3700 // item vaguely.
3701 const int shelf_height =
3702 GetPrimaryShelf()->GetShelfViewForTesting()->height();
3703 generator->MoveMouseBy(0, -shelf_height * 2);
3704 // All of the item should have the layer at this point.
3705 for (int i = 0; i < items_in_page; ++i) {
3706 views::View* item_view = apps_grid_view->view_model()->view_at(i);
3707 EXPECT_TRUE(item_view->layer()) << "at " << i;
3708 EXPECT_LE(0.f, item_view->layer()->opacity()) << "at " << i;
3709 EXPECT_GE(1.f, item_view->layer()->opacity()) << "at " << i;
3710 }
3711
3712 // Add items at the front of the items.
3713 const int additional_items = 10;
3714 syncer::StringOrdinal prev_position =
3715 model->top_level_item_list()->item_at(0)->position();
3716 for (int i = 0; i < additional_items; ++i) {
3717 std::unique_ptr<AppListItem> item(
3718 new AppListItem(base::StringPrintf("fake id %02d", i + items_in_page)));
3719 // Update the position so that the item is added at the front of the list.
3720 auto metadata = item->CloneMetadata();
3721 metadata->position = prev_position.CreateBefore();
3722 prev_position = metadata->position;
3723 item->SetMetadata(std::move(metadata));
3724 model->AddItem(std::move(item));
3725 }
3726
3727 generator->MoveMouseBy(0, -1);
3728
3729 // At this point, some items move out from the first page.
3730 EXPECT_LT(1, apps_grid_view->pagination_model()->total_pages());
3731
3732 // The items on the first page should have layers.
3733 for (int i = 0; i < items_in_page; ++i) {
3734 views::View* item_view = apps_grid_view->view_model()->view_at(i);
3735 EXPECT_TRUE(item_view->layer()) << "at " << i;
3736 EXPECT_LE(0.f, item_view->layer()->opacity()) << "at " << i;
3737 EXPECT_GE(1.f, item_view->layer()->opacity()) << "at " << i;
3738 }
3739
3740 // Drag to the top of the screen and finish the drag. It should destroy all
3741 // of the layers, including items on the second page.
3742 generator->MoveMouseTo(start_point.x(), 0);
3743 generator->ReleaseLeftButton();
3744 for (int i = 0; i < apps_grid_view->view_model()->view_size(); ++i) {
3745 views::View* item_view = apps_grid_view->view_model()->view_at(i);
3746 EXPECT_FALSE(item_view->layer()) << "at " << i;
3747 }
3748 }
3749
3750 // Tests that the app list is shown automatically when the tablet mode is on.
3751 // The app list is dismissed when the tablet mode is off.
TEST_P(AppListPresenterDelegateHomeLauncherTest,ShowAppListForTabletMode)3752 TEST_P(AppListPresenterDelegateHomeLauncherTest, ShowAppListForTabletMode) {
3753 GetAppListTestHelper()->CheckVisibility(false);
3754
3755 // Turns on tablet mode.
3756 EnableTabletMode(true);
3757 GetAppListTestHelper()->CheckVisibility(true);
3758
3759 // Turns off tablet mode.
3760 EnableTabletMode(false);
3761 GetAppListTestHelper()->CheckVisibility(false);
3762 }
3763
3764 // Tests that the app list window's parent is changed after entering tablet
3765 // mode.
TEST_P(AppListPresenterDelegateHomeLauncherTest,ParentWindowContainer)3766 TEST_P(AppListPresenterDelegateHomeLauncherTest, ParentWindowContainer) {
3767 // Show app list in non-tablet mode. The window container should be
3768 // kShellWindowId_AppListContainer.
3769 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3770 aura::Window* window = GetAppListView()->GetWidget()->GetNativeWindow();
3771 aura::Window* root_window = window->GetRootWindow();
3772 EXPECT_TRUE(root_window->GetChildById(kShellWindowId_AppListContainer)
3773 ->Contains(window));
3774
3775 // Turn on tablet mode. The window container should be
3776 // kShellWindowId_HomeScreenContainer.
3777 EnableTabletMode(true);
3778 EXPECT_TRUE(root_window->GetChildById(kShellWindowId_HomeScreenContainer)
3779 ->Contains(window));
3780 }
3781
3782 // Tests that the background opacity change for app list.
TEST_P(AppListPresenterDelegateHomeLauncherTest,BackgroundOpacity)3783 TEST_P(AppListPresenterDelegateHomeLauncherTest, BackgroundOpacity) {
3784 // Show app list in non-tablet mode. The background sheild opacity should be
3785 // 70%.
3786 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3787
3788 // The opacity should be set on the color, not the layer. Setting opacity on
3789 // the layer will change the opacity of the blur effect, which is not desired.
3790 const U8CPU clamshell_background_opacity = static_cast<U8CPU>(255 * 0.8);
3791 EXPECT_EQ(
3792 SkColorSetA(AppListColorProvider::Get()->GetAppListBackgroundColor(),
3793 clamshell_background_opacity),
3794 GetAppListView()->GetAppListBackgroundShieldColorForTest());
3795 EXPECT_EQ(1, GetAppListView()
3796 ->GetAppListBackgroundShieldForTest()
3797 ->layer()
3798 ->opacity());
3799
3800 // Turn on tablet mode. The background shield should be transparent.
3801 EnableTabletMode(true);
3802
3803 const U8CPU tablet_background_opacity = static_cast<U8CPU>(0);
3804 EXPECT_EQ(
3805 SkColorSetA(AppListColorProvider::Get()->GetAppListBackgroundColor(),
3806 tablet_background_opacity),
3807 GetAppListView()->GetAppListBackgroundShieldColorForTest());
3808 EXPECT_EQ(1, GetAppListView()
3809 ->GetAppListBackgroundShieldForTest()
3810 ->layer()
3811 ->opacity());
3812 }
3813
3814 // Tests that the background blur which is present in clamshell mode does not
3815 // show in tablet mode.
TEST_P(AppListPresenterDelegateHomeLauncherTest,BackgroundBlur)3816 TEST_P(AppListPresenterDelegateHomeLauncherTest, BackgroundBlur) {
3817 // Show app list in non-tablet mode. The background blur should be enabled.
3818 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3819 EXPECT_GT(GetAppListView()
3820 ->GetAppListBackgroundShieldForTest()
3821 ->layer()
3822 ->background_blur(),
3823 0.0f);
3824
3825 // Turn on tablet mode. The background blur should be disabled.
3826 EnableTabletMode(true);
3827 EXPECT_EQ(0.0f, GetAppListView()
3828 ->GetAppListBackgroundShieldForTest()
3829 ->layer()
3830 ->background_blur());
3831 }
3832
3833 // Tests that tapping or clicking on background cannot dismiss the app list.
TEST_P(AppListPresenterDelegateHomeLauncherTest,TapOrClickToDismiss)3834 TEST_P(AppListPresenterDelegateHomeLauncherTest, TapOrClickToDismiss) {
3835 // Show app list in non-tablet mode. Click outside search box.
3836 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3837 GetAppListTestHelper()->CheckVisibility(true);
3838 ui::test::EventGenerator* generator = GetEventGenerator();
3839 generator->MoveMouseTo(GetPointOutsideSearchbox());
3840 generator->ClickLeftButton();
3841 GetAppListTestHelper()->WaitUntilIdle();
3842 GetAppListTestHelper()->CheckVisibility(false);
3843
3844 // Show app list in non-tablet mode. Tap outside search box.
3845 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3846 GetAppListTestHelper()->CheckVisibility(true);
3847 generator->GestureTapDownAndUp(GetPointOutsideSearchbox());
3848 GetAppListTestHelper()->WaitUntilIdle();
3849 GetAppListTestHelper()->CheckVisibility(false);
3850
3851 // Show app list in tablet mode. Click outside search box.
3852 EnableTabletMode(true);
3853 GetAppListTestHelper()->CheckVisibility(true);
3854 generator->MoveMouseTo(GetPointOutsideSearchbox());
3855 generator->PressLeftButton();
3856 GetAppListTestHelper()->WaitUntilIdle();
3857 GetAppListTestHelper()->CheckVisibility(true);
3858
3859 // Tap outside search box.
3860 generator->GestureTapDownAndUp(GetPointOutsideSearchbox());
3861 GetAppListTestHelper()->WaitUntilIdle();
3862 GetAppListTestHelper()->CheckVisibility(true);
3863 }
3864
3865 // Tests that accelerator Escape, Broswer back and Search key cannot dismiss the
3866 // appt list.
TEST_P(AppListPresenterDelegateHomeLauncherTest,PressAcceleratorToDismiss)3867 TEST_P(AppListPresenterDelegateHomeLauncherTest, PressAcceleratorToDismiss) {
3868 // Show app list in non-tablet mode. Press Escape key.
3869 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3870 GetAppListTestHelper()->CheckVisibility(true);
3871 ui::test::EventGenerator* generator = GetEventGenerator();
3872 generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
3873 GetAppListTestHelper()->WaitUntilIdle();
3874 GetAppListTestHelper()->CheckVisibility(false);
3875
3876 // Show app list in non-tablet mode. Press Browser back key.
3877 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3878 GetAppListTestHelper()->CheckVisibility(true);
3879 generator->PressKey(ui::KeyboardCode::VKEY_BROWSER_BACK, 0);
3880 GetAppListTestHelper()->WaitUntilIdle();
3881 GetAppListTestHelper()->CheckVisibility(false);
3882
3883 // Show app list in non-tablet mode. Press search key.
3884 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3885 GetAppListTestHelper()->CheckVisibility(true);
3886 generator->PressKey(ui::KeyboardCode::VKEY_BROWSER_SEARCH, 0);
3887 GetAppListTestHelper()->WaitUntilIdle();
3888 GetAppListTestHelper()->CheckVisibility(false);
3889
3890 // Show app list in tablet mode. Press Escape key.
3891 EnableTabletMode(true);
3892 GetAppListTestHelper()->CheckVisibility(true);
3893 generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
3894 GetAppListTestHelper()->WaitUntilIdle();
3895 GetAppListTestHelper()->CheckVisibility(true);
3896
3897 // Press Browser back key.
3898 generator->PressKey(ui::KeyboardCode::VKEY_BROWSER_BACK, 0);
3899 GetAppListTestHelper()->WaitUntilIdle();
3900 GetAppListTestHelper()->CheckVisibility(true);
3901
3902 // Press search key.
3903 generator->PressKey(ui::KeyboardCode::VKEY_BROWSER_SEARCH, 0);
3904 GetAppListTestHelper()->WaitUntilIdle();
3905 GetAppListTestHelper()->CheckVisibility(true);
3906 }
3907
3908 // Tests that moving focus outside app list window can dismiss it.
TEST_P(AppListPresenterDelegateHomeLauncherTest,FocusOutToDismiss)3909 TEST_P(AppListPresenterDelegateHomeLauncherTest, FocusOutToDismiss) {
3910 // Show app list in non-tablet mode. Move focus to another window.
3911 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3912 GetAppListTestHelper()->CheckVisibility(true);
3913 std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
3914 wm::ActivateWindow(window.get());
3915 GetAppListTestHelper()->WaitUntilIdle();
3916 GetAppListTestHelper()->CheckVisibility(false);
3917
3918 // Go to tablet mode with a focused window, the AppList should not be visible.
3919 EnableTabletMode(true);
3920 GetAppListTestHelper()->WaitUntilIdle();
3921 GetAppListTestHelper()->CheckVisibility(false);
3922
3923 // Refocusing the already focused window should change nothing.
3924 wm::ActivateWindow(window.get());
3925
3926 GetAppListTestHelper()->WaitUntilIdle();
3927 GetAppListTestHelper()->CheckVisibility(false);
3928
3929 // Minimizing the focused window with no remaining windows should result in a
3930 // shown applist.
3931 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
3932
3933 GetAppListTestHelper()->WaitUntilIdle();
3934 GetAppListTestHelper()->CheckVisibility(true);
3935 }
3936
3937 // Tests that the gesture-scroll cannot dismiss the app list.
TEST_P(AppListPresenterDelegateHomeLauncherTest,GestureScrollToDismiss)3938 TEST_P(AppListPresenterDelegateHomeLauncherTest, GestureScrollToDismiss) {
3939 // Show app list in non-tablet mode. Fling down.
3940 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3941 GetAppListTestHelper()->CheckVisibility(true);
3942 FlingUpOrDown(GetEventGenerator(), GetAppListView(), false /* up */);
3943 GetAppListTestHelper()->WaitUntilIdle();
3944 GetAppListTestHelper()->CheckVisibility(false);
3945
3946 // Show app list in tablet mode. Fling down.
3947 EnableTabletMode(true);
3948 GetAppListTestHelper()->CheckVisibility(true);
3949 FlingUpOrDown(GetEventGenerator(), GetAppListView(), false /* up */);
3950 GetAppListTestHelper()->WaitUntilIdle();
3951 GetAppListTestHelper()->CheckVisibility(true);
3952 }
3953
3954 // Tests that the mouse-scroll cannot dismiss the app list.
TEST_P(AppListPresenterDelegateHomeLauncherTest,MouseScrollDoesntDismissPeekingLauncher)3955 TEST_P(AppListPresenterDelegateHomeLauncherTest,
3956 MouseScrollDoesntDismissPeekingLauncher) {
3957 // Show app list in non-tablet mode. Mouse-scroll up.
3958 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3959 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3960 GetAppListTestHelper()->CheckVisibility(true);
3961 ui::test::EventGenerator* generator = GetEventGenerator();
3962 generator->MoveMouseTo(GetPointOutsideSearchbox());
3963
3964 // Scroll up to get fullscreen.
3965 generator->MoveMouseWheel(0, 1);
3966 GetAppListTestHelper()->WaitUntilIdle();
3967 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
3968 GetAppListTestHelper()->CheckVisibility(true);
3969
3970 // Reset and show app list in non-tablet mode. Mouse-scroll down.
3971 GetAppListTestHelper()->DismissAndRunLoop();
3972 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3973 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3974 GetAppListTestHelper()->CheckVisibility(true);
3975
3976 // Scroll down to get fullscreen.
3977 generator->MoveMouseWheel(0, -1);
3978 GetAppListTestHelper()->WaitUntilIdle();
3979 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
3980 GetAppListTestHelper()->CheckVisibility(true);
3981 }
3982
3983 // Tests that mouse-scroll up at fullscreen will dismiss app list.
TEST_P(AppListPresenterDelegateHomeLauncherTest,MouseScrollToDismissFromFullscreen)3984 TEST_P(AppListPresenterDelegateHomeLauncherTest,
3985 MouseScrollToDismissFromFullscreen) {
3986 // Show app list in non-tablet mode. Mouse-scroll down.
3987 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3988 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3989 ui::test::EventGenerator* generator = GetEventGenerator();
3990 generator->MoveMouseTo(GetPointOutsideSearchbox());
3991
3992 // Scroll up with mouse wheel to fullscreen.
3993 generator->MoveMouseWheel(0, 1);
3994 GetAppListTestHelper()->WaitUntilIdle();
3995 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
3996 GetAppListTestHelper()->CheckVisibility(true);
3997 generator->MoveMouseTo(GetPointOutsideSearchbox());
3998
3999 // Scroll up with mouse wheel to close app list.
4000 generator->MoveMouseWheel(0, 1);
4001 GetAppListTestHelper()->WaitUntilIdle();
4002 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
4003 GetAppListTestHelper()->CheckVisibility(false);
4004 }
4005
4006 // Test that the AppListView opacity is reset after it is hidden during the
4007 // overview mode animation.
TEST_P(AppListPresenterDelegateHomeLauncherTest,LauncherShowsAfterOverviewMode)4008 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4009 LauncherShowsAfterOverviewMode) {
4010 // Show the AppList in clamshell mode.
4011 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
4012 GetAppListTestHelper()->CheckVisibility(true);
4013
4014 // Enable overview mode.
4015 OverviewController* overview_controller = Shell::Get()->overview_controller();
4016 overview_controller->StartOverview();
4017
4018 // Test that the AppListView is transparent.
4019 EXPECT_EQ(0.0f, GetAppListView()->GetWidget()->GetLayer()->opacity());
4020
4021 // Disable overview mode.
4022 overview_controller->EndOverview();
4023
4024 // Show the launcher, test that the opacity is restored.
4025 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
4026 GetAppListTestHelper()->CheckVisibility(true);
4027
4028 EXPECT_EQ(1.0f, GetAppListView()->GetWidget()->GetLayer()->opacity());
4029 EXPECT_TRUE(GetAppListView()->GetWidget()->IsVisible());
4030 }
4031
4032 // Tests that tapping home button while home screen is visible and showing
4033 // search results moves the home screen to apps container page.
TEST_P(AppListPresenterDelegateHomeLauncherTest,HomeButtonDismissesSearchResults)4034 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4035 HomeButtonDismissesSearchResults) {
4036 // Show app list in tablet mode.
4037 EnableTabletMode(true);
4038 GetAppListTestHelper()->CheckVisibility(true);
4039 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
4040
4041 // Enable accessibility feature that forces home button to be shown even with
4042 // kHideShelfControlsInTabletMode enabled.
4043 // TODO(https://crbug.com/1050544) Use the a11y feature specific to showing
4044 // navigation buttons in tablet mode once it lands.
4045 Shell::Get()->accessibility_controller()->autoclick().SetEnabled(true);
4046
4047 // Enter text in the searchbox, the app list should transition to fullscreen
4048 // search.
4049 ui::test::EventGenerator* generator = GetEventGenerator();
4050 generator->PressKey(ui::KeyboardCode::VKEY_0, ui::EF_NONE);
4051 GetAppListTestHelper()->WaitUntilIdle();
4052 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
4053
4054 // Tap home button - verify that home goes back to showing the apps page.
4055 TapHomeButton(GetPrimaryDisplay().id());
4056
4057 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
4058 }
4059
4060 // Tests the app list opacity in overview mode.
TEST_P(AppListPresenterDelegateHomeLauncherTest,OpacityInOverviewMode)4061 TEST_P(AppListPresenterDelegateHomeLauncherTest, OpacityInOverviewMode) {
4062 // Show app list in tablet mode.
4063 EnableTabletMode(true);
4064 GetAppListTestHelper()->CheckVisibility(true);
4065
4066 // Enable overview mode.
4067 OverviewController* overview_controller = Shell::Get()->overview_controller();
4068 overview_controller->StartOverview();
4069 EXPECT_TRUE(overview_controller->InOverviewSession());
4070 ui::Layer* layer = GetAppListView()->GetWidget()->GetNativeWindow()->layer();
4071 EXPECT_EQ(0.0f, layer->opacity());
4072
4073 // Disable overview mode.
4074 overview_controller->EndOverview();
4075 EXPECT_FALSE(overview_controller->InOverviewSession());
4076 EXPECT_EQ(1.0f, layer->opacity());
4077 }
4078
4079 // Tests the app list visibility during wallpaper preview.
TEST_P(AppListPresenterDelegateHomeLauncherTest,VisibilityDuringWallpaperPreview)4080 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4081 VisibilityDuringWallpaperPreview) {
4082 WallpaperControllerTestApi wallpaper_test_api(
4083 Shell::Get()->wallpaper_controller());
4084
4085 // The app list is hidden in the beginning.
4086 GetAppListTestHelper()->CheckVisibility(false);
4087 // Open wallpaper picker and start preview. Verify the app list remains
4088 // hidden.
4089 wallpaper_test_api.StartWallpaperPreview();
4090 GetAppListTestHelper()->CheckVisibility(false);
4091 // Enable tablet mode. Verify the app list is still hidden because wallpaper
4092 // preview is active.
4093 EnableTabletMode(true);
4094 GetAppListTestHelper()->CheckVisibility(false);
4095 // End preview by confirming the wallpaper. Verify the app list is shown.
4096 wallpaper_test_api.EndWallpaperPreview(true /*confirm_preview_wallpaper=*/);
4097 GetAppListTestHelper()->CheckVisibility(true);
4098
4099 // Start preview again. Verify the app list is hidden.
4100 wallpaper_test_api.StartWallpaperPreview();
4101 GetAppListTestHelper()->CheckVisibility(false);
4102 // End preview by canceling the wallpaper. Verify the app list is shown.
4103 wallpaper_test_api.EndWallpaperPreview(false /*confirm_preview_wallpaper=*/);
4104 GetAppListTestHelper()->CheckVisibility(true);
4105
4106 // Start preview again and enable overview mode during the wallpaper preview.
4107 // Verify the app list is hidden.
4108 wallpaper_test_api.StartWallpaperPreview();
4109 EXPECT_FALSE(GetAppListView()->GetWidget()->IsVisible());
4110 OverviewController* overview_controller = Shell::Get()->overview_controller();
4111 overview_controller->StartOverview();
4112 EXPECT_TRUE(overview_controller->InOverviewSession());
4113 GetAppListTestHelper()->CheckVisibility(false);
4114 // Disable overview mode. Verify the app list is still hidden because
4115 // wallpaper preview is still active.
4116 overview_controller->EndOverview();
4117 EXPECT_FALSE(overview_controller->InOverviewSession());
4118 GetAppListTestHelper()->CheckVisibility(false);
4119 // End preview by confirming the wallpaper. Verify the app list is shown.
4120 wallpaper_test_api.EndWallpaperPreview(true /*confirm_preview_wallpaper=*/);
4121 GetAppListTestHelper()->CheckVisibility(true);
4122 }
4123
4124 // Tests that going home will minimize all windows.
TEST_P(AppListPresenterDelegateHomeLauncherTest,GoingHomeMinimizesAllWindows)4125 TEST_P(AppListPresenterDelegateHomeLauncherTest, GoingHomeMinimizesAllWindows) {
4126 // Show app list in tablet mode. Maximize all windows.
4127 EnableTabletMode(true);
4128 GetAppListTestHelper()->CheckVisibility(true);
4129 std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)),
4130 window2(CreateTestWindowInShellWithId(1)),
4131 window3(CreateTestWindowInShellWithId(2));
4132 WindowState *state1 = WindowState::Get(window1.get()),
4133 *state2 = WindowState::Get(window2.get()),
4134 *state3 = WindowState::Get(window3.get());
4135 state1->Maximize();
4136 state2->Maximize();
4137 state3->Maximize();
4138 EXPECT_TRUE(state1->IsMaximized());
4139 EXPECT_TRUE(state2->IsMaximized());
4140 EXPECT_TRUE(state3->IsMaximized());
4141
4142 // The windows need to be activated for the mru window tracker.
4143 wm::ActivateWindow(window1.get());
4144 wm::ActivateWindow(window2.get());
4145 wm::ActivateWindow(window3.get());
4146 auto ordering =
4147 Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(kActiveDesk);
4148
4149 GoHome();
4150 EXPECT_TRUE(state1->IsMinimized());
4151 EXPECT_TRUE(state2->IsMinimized());
4152 EXPECT_TRUE(state3->IsMinimized());
4153 GetAppListTestHelper()->CheckVisibility(true);
4154
4155 // Tests that the window ordering remains the same as before we minimize.
4156 auto new_order =
4157 Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(kActiveDesk);
4158 EXPECT_TRUE(std::equal(ordering.begin(), ordering.end(), new_order.begin()));
4159 }
4160
4161 // Tests that going home will end split view mode.
TEST_P(AppListPresenterDelegateHomeLauncherTest,GoingHomeEndsSplitViewMode)4162 TEST_P(AppListPresenterDelegateHomeLauncherTest, GoingHomeEndsSplitViewMode) {
4163 // Show app list in tablet mode. Enter split view mode.
4164 EnableTabletMode(true);
4165 GetAppListTestHelper()->CheckVisibility(true);
4166 std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
4167 split_view_controller()->SnapWindow(window.get(), SplitViewController::LEFT);
4168 EXPECT_TRUE(split_view_controller()->InSplitViewMode());
4169
4170 GoHome();
4171 EXPECT_FALSE(split_view_controller()->InSplitViewMode());
4172 GetAppListTestHelper()->CheckVisibility(true);
4173 }
4174
4175 // Tests that going home will end overview mode.
TEST_P(AppListPresenterDelegateHomeLauncherTest,GoingHomeEndOverviewMode)4176 TEST_P(AppListPresenterDelegateHomeLauncherTest, GoingHomeEndOverviewMode) {
4177 // Show app list in tablet mode. Enter overview mode.
4178 EnableTabletMode(true);
4179 GetAppListTestHelper()->CheckVisibility(true);
4180 std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
4181 OverviewController* overview_controller = Shell::Get()->overview_controller();
4182 overview_controller->StartOverview();
4183 EXPECT_TRUE(overview_controller->InOverviewSession());
4184
4185 GoHome();
4186 EXPECT_FALSE(overview_controller->InOverviewSession());
4187 GetAppListTestHelper()->CheckVisibility(true);
4188 }
4189
4190 // Tests that going home will end overview and split view mode if both are
4191 // active (e.g. one side of the split view contains overview).
TEST_P(AppListPresenterDelegateHomeLauncherTest,GoingHomeEndsSplitViewModeWithOverview)4192 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4193 GoingHomeEndsSplitViewModeWithOverview) {
4194 // Show app list in tablet mode. Enter split view mode.
4195 EnableTabletMode(true);
4196 GetAppListTestHelper()->CheckVisibility(true);
4197
4198 std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
4199 std::unique_ptr<aura::Window> dummy_window(CreateTestWindowInShellWithId(1));
4200
4201 OverviewController* overview_controller = Shell::Get()->overview_controller();
4202 overview_controller->StartOverview();
4203 EXPECT_TRUE(overview_controller->InOverviewSession());
4204
4205 split_view_controller()->SnapWindow(window.get(), SplitViewController::LEFT);
4206 EXPECT_TRUE(split_view_controller()->InSplitViewMode());
4207 EXPECT_TRUE(overview_controller->InOverviewSession());
4208
4209 GoHome();
4210 EXPECT_FALSE(split_view_controller()->InSplitViewMode());
4211 EXPECT_FALSE(overview_controller->InOverviewSession());
4212
4213 GetAppListTestHelper()->CheckVisibility(true);
4214 }
4215
4216 // Tests that the context menu is triggered in the same way as if we are on
4217 // the wallpaper.
TEST_P(AppListPresenterDelegateHomeLauncherTest,WallpaperContextMenu)4218 TEST_P(AppListPresenterDelegateHomeLauncherTest, WallpaperContextMenu) {
4219 // Show app list in tablet mode.
4220 EnableTabletMode(true);
4221 GetAppListTestHelper()->CheckVisibility(true);
4222
4223 // Long press on the app list to open the context menu.
4224 // TODO(ginko) look into a way to populate an apps grid, then get a point
4225 // between these apps so that clicks/taps between apps can be tested
4226 const gfx::Point onscreen_point(GetPointOutsideSearchbox());
4227 ui::test::EventGenerator* generator = GetEventGenerator();
4228 ui::GestureEvent long_press(
4229 onscreen_point.x(), onscreen_point.y(), 0, base::TimeTicks(),
4230 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
4231 generator->Dispatch(&long_press);
4232 GetAppListTestHelper()->WaitUntilIdle();
4233 const aura::Window* root = window_util::GetRootWindowAt(onscreen_point);
4234 const RootWindowController* root_window_controller =
4235 RootWindowController::ForWindow(root);
4236 EXPECT_TRUE(root_window_controller->IsContextMenuShown());
4237
4238 // Tap down to close the context menu.
4239 ui::GestureEvent tap_down(onscreen_point.x(), onscreen_point.y(), 0,
4240 base::TimeTicks(),
4241 ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
4242 generator->Dispatch(&tap_down);
4243 GetAppListTestHelper()->WaitUntilIdle();
4244 EXPECT_FALSE(root_window_controller->IsContextMenuShown());
4245
4246 // Right click to open the context menu.
4247 generator->MoveMouseTo(onscreen_point);
4248 generator->ClickRightButton();
4249 GetAppListTestHelper()->WaitUntilIdle();
4250 EXPECT_TRUE(root_window_controller->IsContextMenuShown());
4251
4252 // Left click to close the context menu.
4253 generator->MoveMouseTo(onscreen_point);
4254 generator->ClickLeftButton();
4255 GetAppListTestHelper()->WaitUntilIdle();
4256 EXPECT_FALSE(root_window_controller->IsContextMenuShown());
4257 }
4258
4259 // Tests app list visibility when switching to tablet mode during dragging from
4260 // shelf.
TEST_P(AppListPresenterDelegateHomeLauncherTest,SwitchToTabletModeDuringDraggingFromShelf)4261 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4262 SwitchToTabletModeDuringDraggingFromShelf) {
4263 UpdateDisplay("1080x900");
4264 GetAppListTestHelper()->CheckVisibility(false);
4265
4266 // Drag from the shelf to show the app list.
4267 ui::test::EventGenerator* generator = GetEventGenerator();
4268 const int x = 540;
4269 const int closed_y = 890;
4270 const int fullscreen_y = 0;
4271 generator->MoveTouch(gfx::Point(x, closed_y));
4272 generator->PressTouch();
4273 generator->MoveTouch(gfx::Point(x, fullscreen_y));
4274 generator->ReleaseTouch();
4275 GetAppListTestHelper()->CheckVisibility(true);
4276
4277 // Drag to shelf to close app list.
4278 generator->MoveTouch(gfx::Point(x, fullscreen_y));
4279 generator->PressTouch();
4280 generator->MoveTouch(gfx::Point(x, closed_y));
4281 generator->ReleaseTouch();
4282 GetAppListTestHelper()->WaitUntilIdle();
4283 GetAppListTestHelper()->CheckVisibility(false);
4284
4285 // Drag from the shelf to show the app list.
4286 generator->MoveTouch(gfx::Point(x, closed_y));
4287 generator->PressTouch();
4288 generator->MoveTouch(gfx::Point(x, fullscreen_y));
4289 GetAppListTestHelper()->CheckVisibility(true);
4290
4291 // Switch to tablet mode.
4292 EnableTabletMode(true);
4293 GetAppListTestHelper()->CheckVisibility(true);
4294
4295 // Drag to shelf to try to close app list.
4296 generator->MoveTouch(gfx::Point(x, closed_y));
4297 generator->ReleaseTouch();
4298 GetAppListTestHelper()->WaitUntilIdle();
4299 GetAppListTestHelper()->CheckVisibility(true);
4300 }
4301
4302 // Tests app list visibility when switching to tablet mode during dragging to
4303 // close app list.
TEST_P(AppListPresenterDelegateHomeLauncherTest,SwitchToTabletModeDuringDraggingToClose)4304 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4305 SwitchToTabletModeDuringDraggingToClose) {
4306 UpdateDisplay("1080x900");
4307
4308 // Open app list.
4309 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
4310 GetAppListTestHelper()->CheckVisibility(true);
4311
4312 // Drag to shelf to close app list.
4313 ui::test::EventGenerator* generator = GetEventGenerator();
4314 const int x = 540;
4315 const int peeking_height =
4316 900 - AppListConfig::instance().peeking_app_list_height();
4317 const int closed_y = 890;
4318 generator->MoveTouch(gfx::Point(x, peeking_height));
4319 generator->PressTouch();
4320 generator->MoveTouch(gfx::Point(x, closed_y));
4321 generator->ReleaseTouch();
4322 GetAppListTestHelper()->WaitUntilIdle();
4323 GetAppListTestHelper()->CheckVisibility(false);
4324
4325 // Open app list.
4326 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
4327 GetAppListTestHelper()->CheckVisibility(true);
4328
4329 // Drag to shelf to close app list, meanwhile switch to tablet mode.
4330 generator->MoveTouch(gfx::Point(x, peeking_height));
4331 generator->PressTouch();
4332 generator->MoveTouch(gfx::Point(x, peeking_height + 10));
4333 EnableTabletMode(true);
4334 generator->MoveTouch(gfx::Point(x, closed_y));
4335 generator->ReleaseTouch();
4336 GetAppListTestHelper()->WaitUntilIdle();
4337 GetAppListTestHelper()->CheckVisibility(true);
4338 }
4339
4340 // Test backdrop exists for active non-fullscreen window in tablet mode.
TEST_P(AppListPresenterDelegateHomeLauncherTest,BackdropTest)4341 TEST_P(AppListPresenterDelegateHomeLauncherTest, BackdropTest) {
4342 WorkspaceControllerTestApi test_helper(ShellTestApi().workspace_controller());
4343 EnableTabletMode(true);
4344 GetAppListTestHelper()->CheckVisibility(true);
4345 EXPECT_FALSE(test_helper.GetBackdropWindow());
4346
4347 std::unique_ptr<aura::Window> non_fullscreen_window(
4348 CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
4349 non_fullscreen_window->Show();
4350 GetAppListTestHelper()->CheckVisibility(false);
4351 EXPECT_TRUE(test_helper.GetBackdropWindow());
4352 }
4353
4354 // Tests that app list is not active when switching to tablet mode if an active
4355 // window exists.
TEST_P(AppListPresenterDelegateHomeLauncherTest,NotActivateAppListWindowWhenActiveWindowExists)4356 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4357 NotActivateAppListWindowWhenActiveWindowExists) {
4358 // No window is active.
4359 EXPECT_EQ(nullptr, window_util::GetActiveWindow());
4360
4361 // Show app list in tablet mode. It should become active.
4362 EnableTabletMode(true);
4363 GetAppListTestHelper()->CheckVisibility(true);
4364 EXPECT_EQ(GetAppListView()->GetWidget()->GetNativeWindow(),
4365 window_util::GetActiveWindow());
4366
4367 // End tablet mode.
4368 EnableTabletMode(false);
4369 GetAppListTestHelper()->CheckVisibility(false);
4370 EXPECT_EQ(nullptr, window_util::GetActiveWindow());
4371
4372 // Activate a window.
4373 std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
4374 WindowState::Get(window.get())->Activate();
4375 EXPECT_EQ(window.get(), window_util::GetActiveWindow());
4376
4377 // Show app list in tablet mode. It should not be active.
4378 EnableTabletMode(true);
4379 GetAppListTestHelper()->CheckVisibility(false);
4380 EXPECT_EQ(window.get(), window_util::GetActiveWindow());
4381 }
4382
4383 // Tests that involve the virtual keyboard.
4384 class AppListPresenterDelegateVirtualKeyboardTest
4385 : public AppListPresenterDelegateTest {
4386 public:
4387 AppListPresenterDelegateVirtualKeyboardTest() = default;
4388 ~AppListPresenterDelegateVirtualKeyboardTest() override = default;
4389
4390 // AppListPresenterDelegateTest:
SetUp()4391 void SetUp() override {
4392 base::CommandLine::ForCurrentProcess()->AppendSwitch(
4393 keyboard::switches::kEnableVirtualKeyboard);
4394 AppListPresenterDelegateTest::SetUp();
4395 }
4396
4397 // Performs mouse click or tap gesture on the provided point, depending on
4398 // whether the test is parameterized to use mouse clicks or tap gestures.
ClickOrTap(const gfx::Point & point)4399 void ClickOrTap(const gfx::Point& point) {
4400 if (GetParam())
4401 ClickMouseAt(point);
4402 else
4403 GetEventGenerator()->GestureTapAt(point);
4404 }
4405 };
4406
4407 // Instantiate the Boolean which is used to toggle mouse and touch events in
4408 // the parameterized tests.
4409 INSTANTIATE_TEST_SUITE_P(All,
4410 AppListPresenterDelegateVirtualKeyboardTest,
4411 testing::Bool());
4412
4413 // Tests that tapping or clicking the body of the applist with an active virtual
4414 // keyboard when there exists text in the searchbox results in the virtual
4415 // keyboard closing with no side effects.
TEST_P(AppListPresenterDelegateVirtualKeyboardTest,TapAppListWithVirtualKeyboardDismissesVirtualKeyboardWithSearchText)4416 TEST_P(AppListPresenterDelegateVirtualKeyboardTest,
4417 TapAppListWithVirtualKeyboardDismissesVirtualKeyboardWithSearchText) {
4418 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
4419 EnableTabletMode(true);
4420
4421 // Tap to activate the searchbox.
4422 ClickOrTap(GetPointInsideSearchbox());
4423
4424 // Enter some text in the searchbox, the applist should transition to
4425 // fullscreen search.
4426 GetEventGenerator()->PressKey(ui::KeyboardCode::VKEY_0, 0);
4427 GetAppListTestHelper()->WaitUntilIdle();
4428 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
4429
4430 // Manually show the virtual keyboard.
4431 auto* const keyboard_controller = keyboard::KeyboardUIController::Get();
4432 keyboard_controller->ShowKeyboard(true);
4433 ASSERT_TRUE(keyboard::WaitUntilShown());
4434
4435 // Tap or click outside the searchbox, the virtual keyboard should hide.
4436 ClickOrTap(GetPointOutsideSearchbox());
4437 EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
4438
4439 // The searchbox should still be active and the AppListView should still be in
4440 // FULLSCREEN_SEARCH.
4441 GetAppListTestHelper()->WaitUntilIdle();
4442 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
4443 EXPECT_TRUE(GetAppListView()->search_box_view()->is_search_box_active());
4444
4445 // Tap or click the body of the AppList again, the searchbox should deactivate
4446 // and the applist should be in FULLSCREEN_ALL_APPS.
4447 ClickOrTap(GetPointOutsideSearchbox());
4448 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
4449 EXPECT_FALSE(GetAppListView()->search_box_view()->is_search_box_active());
4450 }
4451
4452 // Tests that tapping or clicking the body of the applist with an active virtual
4453 // keyboard when there is no text in the searchbox results in both the virtual
4454 // keyboard and searchbox closing with no side effects.
TEST_P(AppListPresenterDelegateVirtualKeyboardTest,TapAppListWithVirtualKeyboardDismissesVirtualKeyboardWithoutSearchText)4455 TEST_P(AppListPresenterDelegateVirtualKeyboardTest,
4456 TapAppListWithVirtualKeyboardDismissesVirtualKeyboardWithoutSearchText) {
4457 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
4458 EnableTabletMode(true);
4459
4460 // Tap to activate the searchbox.
4461 ClickOrTap(GetPointInsideSearchbox());
4462 GetAppListTestHelper()->WaitUntilIdle();
4463 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
4464
4465 // Manually show the virtual keyboard.
4466 auto* const keyboard_controller = keyboard::KeyboardUIController::Get();
4467 keyboard_controller->ShowKeyboard(true);
4468 ASSERT_TRUE(keyboard::WaitUntilShown());
4469
4470 // Tap or click outside the searchbox, the virtual keyboard should hide and
4471 // the searchbox should be inactive when there is no text in the searchbox.
4472 ClickOrTap(GetPointOutsideSearchbox());
4473 GetAppListTestHelper()->WaitUntilIdle();
4474 GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
4475 EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
4476 EXPECT_FALSE(GetAppListView()->search_box_view()->is_search_box_active());
4477 }
4478
TEST_P(AppListPresenterDelegateHomeLauncherTest,TapHomeButtonOnExternalDisplay)4479 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4480 TapHomeButtonOnExternalDisplay) {
4481 UpdateDisplay("800x600,1000x768");
4482
4483 TapHomeButton(GetSecondaryDisplay().id());
4484 {
4485 SCOPED_TRACE("1st tap");
4486 GetAppListTestHelper()->CheckVisibility(true);
4487 GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
4488 }
4489
4490 TapHomeButton(GetSecondaryDisplay().id());
4491 {
4492 SCOPED_TRACE("2nd tap");
4493 GetAppListTestHelper()->CheckVisibility(false);
4494 GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
4495 }
4496 }
4497
4498 } // namespace ash
4499