app_list_controller_impl_unittest.cc 75 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890
  1. // Copyright 2019 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. #include "ash/app_list/app_list_controller_impl.h"
  5. #include <set>
  6. #include <string>
  7. #include "ash/app_list/app_list_badge_controller.h"
  8. #include "ash/app_list/app_list_bubble_presenter.h"
  9. #include "ash/app_list/app_list_metrics.h"
  10. #include "ash/app_list/app_list_presenter_impl.h"
  11. #include "ash/app_list/app_list_test_view_delegate.h"
  12. #include "ash/app_list/test/app_list_test_helper.h"
  13. #include "ash/app_list/views/app_list_bubble_view.h"
  14. #include "ash/app_list/views/app_list_item_view.h"
  15. #include "ash/app_list/views/app_list_main_view.h"
  16. #include "ash/app_list/views/app_list_view.h"
  17. #include "ash/app_list/views/apps_container_view.h"
  18. #include "ash/app_list/views/apps_grid_view.h"
  19. #include "ash/app_list/views/apps_grid_view_test_api.h"
  20. #include "ash/app_list/views/contents_view.h"
  21. #include "ash/app_list/views/expand_arrow_view.h"
  22. #include "ash/app_list/views/paged_apps_grid_view.h"
  23. #include "ash/app_list/views/search_box_view.h"
  24. #include "ash/app_list/views/suggestion_chip_container_view.h"
  25. #include "ash/assistant/model/assistant_ui_model.h"
  26. #include "ash/constants/ash_features.h"
  27. #include "ash/constants/ash_pref_names.h"
  28. #include "ash/ime/ime_controller_impl.h"
  29. #include "ash/ime/test_ime_controller_client.h"
  30. #include "ash/keyboard/keyboard_controller_impl.h"
  31. #include "ash/keyboard/ui/test/keyboard_test_util.h"
  32. #include "ash/public/cpp/app_list/app_list_config.h"
  33. #include "ash/public/cpp/assistant/controller/assistant_ui_controller.h"
  34. #include "ash/public/cpp/session/session_types.h"
  35. #include "ash/public/cpp/shelf_config.h"
  36. #include "ash/public/cpp/shelf_item_delegate.h"
  37. #include "ash/public/cpp/shelf_model.h"
  38. #include "ash/public/cpp/shelf_types.h"
  39. #include "ash/public/cpp/system_tray_test_api.h"
  40. #include "ash/public/cpp/test/assistant_test_api.h"
  41. #include "ash/public/cpp/test/shell_test_api.h"
  42. #include "ash/public/cpp/test/test_shelf_item_delegate.h"
  43. #include "ash/public/cpp/window_properties.h"
  44. #include "ash/session/session_controller_impl.h"
  45. #include "ash/shelf/shelf.h"
  46. #include "ash/shelf/shelf_layout_manager.h"
  47. #include "ash/shelf/shelf_view.h"
  48. #include "ash/shelf/shelf_view_test_api.h"
  49. #include "ash/shelf/shelf_widget.h"
  50. #include "ash/shell.h"
  51. #include "ash/test/ash_test_base.h"
  52. #include "ash/test/layer_animation_stopped_waiter.h"
  53. #include "ash/test/test_widget_builder.h"
  54. #include "ash/wm/overview/overview_controller.h"
  55. #include "ash/wm/tablet_mode/tablet_mode_controller.h"
  56. #include "ash/wm/window_state.h"
  57. #include "ash/wm/window_util.h"
  58. #include "base/bind.h"
  59. #include "base/i18n/number_formatting.h"
  60. #include "base/strings/stringprintf.h"
  61. #include "base/strings/utf_string_conversions.h"
  62. #include "base/test/metrics/histogram_tester.h"
  63. #include "base/test/scoped_feature_list.h"
  64. #include "base/test/with_feature_override.h"
  65. #include "components/session_manager/session_manager_types.h"
  66. #include "ui/base/emoji/emoji_panel_helper.h"
  67. #include "ui/compositor/layer.h"
  68. #include "ui/compositor/presentation_time_recorder.h"
  69. #include "ui/compositor/scoped_animation_duration_scale_mode.h"
  70. #include "ui/events/test/event_generator.h"
  71. #include "ui/message_center/message_center.h"
  72. #include "ui/message_center/views/message_popup_view.h"
  73. #include "ui/views/accessibility/accessibility_paint_checks.h"
  74. #include "ui/views/controls/textfield/textfield_test_api.h"
  75. #include "ui/views/test/widget_animation_waiter.h"
  76. namespace ash {
  77. namespace {
  78. void PressHomeButton() {
  79. Shell::Get()->app_list_controller()->ToggleAppList(
  80. display::Screen::GetScreen()->GetPrimaryDisplay().id(),
  81. AppListShowSource::kShelfButton, base::TimeTicks());
  82. }
  83. bool IsTabletMode() {
  84. return Shell::Get()->tablet_mode_controller()->InTabletMode();
  85. }
  86. AppListModel* GetAppListModel() {
  87. return AppListModelProvider::Get()->model();
  88. }
  89. AppListView* GetAppListView() {
  90. return Shell::Get()->app_list_controller()->fullscreen_presenter()->GetView();
  91. }
  92. ContentsView* GetContentsView() {
  93. return GetAppListView()->app_list_main_view()->contents_view();
  94. }
  95. SearchBoxView* GetSearchBoxView() {
  96. return GetContentsView()->GetSearchBoxView();
  97. }
  98. aura::Window* GetVirtualKeyboardWindow() {
  99. return Shell::Get()
  100. ->keyboard_controller()
  101. ->keyboard_ui_controller()
  102. ->GetKeyboardWindow();
  103. }
  104. AppsContainerView* GetAppsContainerView() {
  105. return GetContentsView()->apps_container_view();
  106. }
  107. PagedAppsGridView* GetAppsGridView() {
  108. return GetAppsContainerView()->apps_grid_view();
  109. }
  110. void ShowAppListNow(AppListViewState state) {
  111. Shell::Get()->app_list_controller()->fullscreen_presenter()->Show(
  112. state, display::Screen::GetScreen()->GetPrimaryDisplay().id(),
  113. base::TimeTicks::Now(), /*show_source*/ absl::nullopt);
  114. }
  115. void DismissAppListNow() {
  116. Shell::Get()->app_list_controller()->fullscreen_presenter()->Dismiss(
  117. base::TimeTicks::Now());
  118. }
  119. aura::Window* GetAppListViewNativeWindow() {
  120. return GetAppListView()->GetWidget()->GetNativeView();
  121. }
  122. void EnableTabletMode() {
  123. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  124. }
  125. class ShelfItemFactoryFake : public ShelfModel::ShelfItemFactory {
  126. public:
  127. virtual ~ShelfItemFactoryFake() = default;
  128. bool CreateShelfItemForAppId(
  129. const std::string& app_id,
  130. ShelfItem* item,
  131. std::unique_ptr<ShelfItemDelegate>* delegate) override {
  132. *item = ShelfItem();
  133. item->id = ShelfID(app_id);
  134. *delegate = std::make_unique<TestShelfItemDelegate>(item->id);
  135. return true;
  136. }
  137. };
  138. } // namespace
  139. class AppListControllerImplTest : public AshTestBase {
  140. public:
  141. AppListControllerImplTest() = default;
  142. AppListControllerImplTest(const AppListControllerImplTest&) = delete;
  143. AppListControllerImplTest& operator=(const AppListControllerImplTest&) =
  144. delete;
  145. ~AppListControllerImplTest() override = default;
  146. void SetUp() override {
  147. AshTestBase::SetUp();
  148. shelf_item_factory_ = std::make_unique<ShelfItemFactoryFake>();
  149. ShelfModel::Get()->SetShelfItemFactory(shelf_item_factory_.get());
  150. }
  151. void TearDown() override {
  152. ShelfModel::Get()->SetShelfItemFactory(nullptr);
  153. AshTestBase::TearDown();
  154. }
  155. void PopulateItem(int num) {
  156. AppListModel* const model = GetAppListModel();
  157. for (int i = 0; i < num; i++) {
  158. std::unique_ptr<AppListItem> item(new AppListItem(
  159. "app_id" +
  160. base::UTF16ToUTF8(base::FormatNumber(populated_item_count_))));
  161. model->AddItem(std::move(item));
  162. ++populated_item_count_;
  163. }
  164. }
  165. bool IsAppListBoundsAnimationRunning() {
  166. AppListView* app_list_view = GetAppListTestHelper()->GetAppListView();
  167. ui::Layer* widget_layer =
  168. app_list_view ? app_list_view->GetWidget()->GetLayer() : nullptr;
  169. return widget_layer && widget_layer->GetAnimator()->is_animating();
  170. }
  171. int CountPageBreakItems() {
  172. auto* top_list = GetAppListModel()->top_level_item_list();
  173. int count = 0;
  174. for (size_t index = 0; index < top_list->item_count(); ++index) {
  175. if (top_list->item_at(index)->is_page_break())
  176. ++count;
  177. }
  178. return count;
  179. }
  180. private:
  181. // The count of the items created by `PopulateItem()`.
  182. int populated_item_count_ = 0;
  183. std::unique_ptr<ShelfItemFactoryFake> shelf_item_factory_;
  184. };
  185. // Tests that the AppList hides when shelf alignment changes. This necessary
  186. // because the AppList is shown with certain assumptions based on shelf
  187. // orientation.
  188. TEST_F(AppListControllerImplTest, AppListHiddenWhenShelfAlignmentChanges) {
  189. Shelf* const shelf = AshTestBase::GetPrimaryShelf();
  190. shelf->SetAlignment(ShelfAlignment::kBottom);
  191. const std::vector<ShelfAlignment> alignments(
  192. {ShelfAlignment::kLeft, ShelfAlignment::kRight, ShelfAlignment::kBottom});
  193. for (ShelfAlignment alignment : alignments) {
  194. ShowAppListNow(AppListViewState::kPeeking);
  195. EXPECT_TRUE(Shell::Get()
  196. ->app_list_controller()
  197. ->fullscreen_presenter()
  198. ->IsVisibleDeprecated());
  199. shelf->SetAlignment(alignment);
  200. EXPECT_EQ(AppListViewState::kClosed, GetAppListView()->app_list_state());
  201. }
  202. }
  203. // In clamshell mode, when the AppListView's bottom is on the display edge
  204. // and app list state is HALF, the rounded corners should be hidden
  205. // (https://crbug.com/942084).
  206. TEST_F(AppListControllerImplTest, HideRoundingCorners) {
  207. Shell::Get()->keyboard_controller()->SetEnableFlag(
  208. keyboard::KeyboardEnableFlag::kShelfEnabled);
  209. // Show the app list view and click on the search box with mouse. So the
  210. // VirtualKeyboard is shown.
  211. ShowAppListNow(AppListViewState::kPeeking);
  212. GetSearchBoxView()->SetSearchBoxActive(true, ui::ET_MOUSE_PRESSED);
  213. // Wait until the virtual keyboard shows on the screen.
  214. base::RunLoop().RunUntilIdle();
  215. EXPECT_TRUE(GetVirtualKeyboardWindow()->IsVisible());
  216. // Test the following things:
  217. // (1) AppListView is at the top of the screen.
  218. // (2) AppListView's state is HALF.
  219. // (3) AppListBackgroundShield is translated to hide the rounded corners.
  220. aura::Window* native_window = GetAppListView()->GetWidget()->GetNativeView();
  221. gfx::Rect app_list_screen_bounds = native_window->GetBoundsInScreen();
  222. EXPECT_EQ(0, app_list_screen_bounds.y());
  223. EXPECT_EQ(AppListViewState::kHalf, GetAppListView()->app_list_state());
  224. gfx::Transform expected_transform;
  225. expected_transform.Translate(0, -(ShelfConfig::Get()->shelf_size() / 2));
  226. EXPECT_EQ(
  227. expected_transform,
  228. GetAppListView()->GetAppListBackgroundShieldForTest()->GetTransform());
  229. // Set the search box inactive and wait until the virtual keyboard is hidden.
  230. GetSearchBoxView()->SetSearchBoxActive(false, ui::ET_MOUSE_PRESSED);
  231. base::RunLoop().RunUntilIdle();
  232. EXPECT_EQ(nullptr, GetVirtualKeyboardWindow());
  233. // Test that the rounded corners should show again.
  234. expected_transform = gfx::Transform();
  235. EXPECT_EQ(
  236. expected_transform,
  237. GetAppListView()->GetAppListBackgroundShieldForTest()->GetTransform());
  238. }
  239. // Verify that when the emoji panel shows and AppListView is in Peeking state,
  240. // AppListView's rounded corners should be hidden (see https://crbug.com/950468)
  241. TEST_F(AppListControllerImplTest, HideRoundingCornersWhenEmojiShows) {
  242. ui::SetShowEmojiKeyboardCallback(
  243. base::BindRepeating(ui::ShowTabletModeEmojiPanel));
  244. // Set IME client. Otherwise the emoji panel is unable to show.
  245. ImeController* ime_controller = Shell::Get()->ime_controller();
  246. TestImeControllerClient client;
  247. ime_controller->SetClient(&client);
  248. // Show the app list view and right-click on the search box with mouse. So the
  249. // text field's context menu shows.
  250. ShowAppListNow(AppListViewState::kPeeking);
  251. SearchBoxView* search_box_view =
  252. GetAppListView()->app_list_main_view()->search_box_view();
  253. RightClickOn(search_box_view);
  254. // Expect that the first item in the context menu should be "Emoji". Show the
  255. // emoji panel.
  256. auto text_field_api =
  257. std::make_unique<views::TextfieldTestApi>(search_box_view->search_box());
  258. ASSERT_EQ("Emoji",
  259. base::UTF16ToUTF8(
  260. text_field_api->context_menu_contents()->GetLabelAt(0)));
  261. text_field_api->context_menu_contents()->ActivatedAt(0);
  262. // Wait for enough time. Then expect that AppListView is pushed up.
  263. base::RunLoop().RunUntilIdle();
  264. ASSERT_EQ(gfx::Point(0, 0), GetAppListView()->GetBoundsInScreen().origin());
  265. // AppListBackgroundShield is translated to hide the rounded corners.
  266. gfx::Transform expected_transform;
  267. expected_transform.Translate(0, -(ShelfConfig::Get()->shelf_size() / 2));
  268. EXPECT_EQ(
  269. expected_transform,
  270. GetAppListView()->GetAppListBackgroundShieldForTest()->GetTransform());
  271. }
  272. // Verifies that the dragged item has the correct focusable siblings after drag
  273. // (https://crbug.com/990071).
  274. TEST_F(AppListControllerImplTest, CheckTabOrderAfterDragIconToShelf) {
  275. // Adds three items to AppsGridView.
  276. PopulateItem(3);
  277. // Shows the app list in fullscreen.
  278. ShowAppListNow(AppListViewState::kFullscreenAllApps);
  279. ASSERT_EQ(AppListViewState::kFullscreenAllApps,
  280. GetAppListView()->app_list_state());
  281. test::AppsGridViewTestApi apps_grid_view_test_api(GetAppsGridView());
  282. const AppListItemView* item1 =
  283. apps_grid_view_test_api.GetViewAtIndex(GridIndex(0, 0));
  284. AppListItemView* item2 =
  285. apps_grid_view_test_api.GetViewAtIndex(GridIndex(0, 1));
  286. const AppListItemView* item3 =
  287. apps_grid_view_test_api.GetViewAtIndex(GridIndex(0, 2));
  288. // Verifies that AppListItemView has the correct focusable siblings before
  289. // drag.
  290. ASSERT_EQ(item1, item2->GetPreviousFocusableView());
  291. ASSERT_EQ(item3, item2->GetNextFocusableView());
  292. // Pins |item2| by dragging it to ShelfView.
  293. ShelfView* shelf_view = GetPrimaryShelf()->GetShelfViewForTesting();
  294. ASSERT_EQ(0u, shelf_view->view_model()->view_size());
  295. GetEventGenerator()->MoveMouseTo(item2->GetBoundsInScreen().CenterPoint());
  296. GetEventGenerator()->PressLeftButton();
  297. item2->FireMouseDragTimerForTest();
  298. GetEventGenerator()->MoveMouseTo(
  299. shelf_view->GetBoundsInScreen().CenterPoint());
  300. ASSERT_TRUE(GetAppsGridView()->FireDragToShelfTimerForTest());
  301. GetEventGenerator()->ReleaseLeftButton();
  302. ASSERT_EQ(1u, shelf_view->view_model()->view_size());
  303. // Verifies that the dragged item has the correct previous/next focusable
  304. // view after drag.
  305. EXPECT_EQ(item1, item2->GetPreviousFocusableView());
  306. EXPECT_EQ(item3, item2->GetNextFocusableView());
  307. }
  308. TEST_F(AppListControllerImplTest, PageResetByTimerInTabletMode) {
  309. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  310. PopulateItem(30);
  311. ShowAppListNow(AppListViewState::kFullscreenAllApps);
  312. PagedAppsGridView* apps_grid_view = GetAppsGridView();
  313. apps_grid_view->pagination_model()->SelectPage(1, false /* animate */);
  314. DismissAppListNow();
  315. // When timer is not skipped the selected page should not change when app list
  316. // is closed.
  317. EXPECT_EQ(1, apps_grid_view->pagination_model()->selected_page());
  318. // Skip the page reset timer to simulate timer exipration.
  319. GetAppListView()->SetSkipPageResetTimerForTesting(true);
  320. ShowAppListNow(AppListViewState::kFullscreenAllApps);
  321. EXPECT_EQ(1, apps_grid_view->pagination_model()->selected_page());
  322. DismissAppListNow();
  323. // Once the app list is closed, the page should be reset when the timer is
  324. // skipped.
  325. EXPECT_EQ(0, apps_grid_view->pagination_model()->selected_page());
  326. }
  327. // Verifies that in clamshell mode the bounds of AppListView are correct when
  328. // the AppListView is in PEEKING state and the virtual keyboard is enabled (see
  329. // https://crbug.com/944233).
  330. TEST_F(AppListControllerImplTest, CheckAppListViewBoundsWhenVKeyboardEnabled) {
  331. Shell::Get()->keyboard_controller()->SetEnableFlag(
  332. keyboard::KeyboardEnableFlag::kShelfEnabled);
  333. // Show the AppListView and click on the search box with mouse. So the
  334. // VirtualKeyboard is shown. Wait until the virtual keyboard shows.
  335. ShowAppListNow(AppListViewState::kPeeking);
  336. GetSearchBoxView()->SetSearchBoxActive(true, ui::ET_MOUSE_PRESSED);
  337. base::RunLoop().RunUntilIdle();
  338. EXPECT_TRUE(GetVirtualKeyboardWindow()->IsVisible());
  339. // Hide the AppListView. Wait until the virtual keyboard is hidden as well.
  340. DismissAppListNow();
  341. base::RunLoop().RunUntilIdle();
  342. EXPECT_EQ(nullptr, GetVirtualKeyboardWindow());
  343. // Show the AppListView again. Check the following things:
  344. // (1) Virtual keyboard does not show.
  345. // (2) AppListView is in PEEKING state.
  346. // (3) AppListView's bounds are the same as the preferred bounds for
  347. // the PEEKING state.
  348. ShowAppListNow(AppListViewState::kPeeking);
  349. base::RunLoop().RunUntilIdle();
  350. EXPECT_EQ(AppListViewState::kPeeking, GetAppListView()->app_list_state());
  351. EXPECT_EQ(nullptr, GetVirtualKeyboardWindow());
  352. EXPECT_EQ(GetAppListView()->GetPreferredWidgetBoundsForState(
  353. AppListViewState::kPeeking),
  354. GetAppListViewNativeWindow()->bounds());
  355. }
  356. // Verifies that the the virtual keyboard does not get shown if the search box
  357. // is activated by user typing when the app list in the peeking state.
  358. TEST_F(AppListControllerImplTest, VirtualKeyboardNotShownWhenUserStartsTyping) {
  359. Shell::Get()->keyboard_controller()->SetEnableFlag(
  360. keyboard::KeyboardEnableFlag::kShelfEnabled);
  361. // Show the AppListView, then simulate a key press - verify that the virtual
  362. // keyboard is not shown.
  363. ShowAppListNow(AppListViewState::kPeeking);
  364. EXPECT_EQ(AppListViewState::kPeeking, GetAppListView()->app_list_state());
  365. PressAndReleaseKey(ui::KeyboardCode::VKEY_0);
  366. EXPECT_EQ(AppListViewState::kHalf, GetAppListView()->app_list_state());
  367. base::RunLoop().RunUntilIdle();
  368. EXPECT_FALSE(GetVirtualKeyboardWindow()->IsVisible());
  369. // The keyboard should get shown if the user taps on the search box.
  370. GestureTapOn(GetAppListView()->search_box_view());
  371. ASSERT_TRUE(keyboard::WaitUntilShown());
  372. DismissAppListNow();
  373. base::RunLoop().RunUntilIdle();
  374. EXPECT_EQ(nullptr, GetVirtualKeyboardWindow());
  375. }
  376. // Verifies that in clamshell mode the AppListView bounds remain in the
  377. // fullscreen size while the virtual keyboard is shown, even if the app list
  378. // view state changes.
  379. TEST_F(AppListControllerImplTest,
  380. AppListViewBoundsRemainFullScreenWhenVKeyboardEnabled) {
  381. Shell::Get()->keyboard_controller()->SetEnableFlag(
  382. keyboard::KeyboardEnableFlag::kShelfEnabled);
  383. // Show the AppListView in fullscreen state and click on the search box with
  384. // the mouse. So the VirtualKeyboard is shown. Wait until the virtual keyboard
  385. // shows.
  386. ShowAppListNow(AppListViewState::kPeeking);
  387. GetSearchBoxView()->SetSearchBoxActive(true, ui::ET_MOUSE_PRESSED);
  388. base::RunLoop().RunUntilIdle();
  389. EXPECT_EQ(AppListViewState::kHalf, GetAppListView()->app_list_state());
  390. EXPECT_TRUE(GetVirtualKeyboardWindow()->IsVisible());
  391. EXPECT_EQ(0, GetAppListView()->GetBoundsInScreen().y());
  392. // Simulate half state getting set again, and but verify the app list bounds
  393. // remain at the top of the screen.
  394. GetAppListView()->SetState(AppListViewState::kHalf);
  395. base::RunLoop().RunUntilIdle();
  396. EXPECT_EQ(AppListViewState::kHalf, GetAppListView()->app_list_state());
  397. EXPECT_EQ(0, GetAppListView()->GetBoundsInScreen().y());
  398. // Close the virtual keyboard. Wait until it is hidden.
  399. Shell::Get()->keyboard_controller()->HideKeyboard(HideReason::kUser);
  400. base::RunLoop().RunUntilIdle();
  401. EXPECT_EQ(nullptr, GetVirtualKeyboardWindow());
  402. // Verify the app list bounds have been updated to match kHalf state.
  403. EXPECT_EQ(AppListViewState::kHalf, GetAppListView()->app_list_state());
  404. const gfx::Rect shelf_bounds =
  405. AshTestBase::GetPrimaryShelf()->shelf_widget()->GetWindowBoundsInScreen();
  406. EXPECT_EQ(shelf_bounds.bottom() - 545 /*half app list height*/,
  407. GetAppListView()->GetBoundsInScreen().y());
  408. }
  409. // Verifies that in tablet mode, the AppListView has correct bounds when the
  410. // virtual keyboard is dismissed (see https://crbug.com/944133).
  411. TEST_F(AppListControllerImplTest, CheckAppListViewBoundsWhenDismissVKeyboard) {
  412. // This isn't relevant with ProductivityLauncher, which uses separate widgets
  413. // in clamshell versus tablet mode. See bug above. Also, the clamshell
  414. // launcher closes when transitioning into tablet mode. This test can be
  415. // deleted when ProductivityLauncher is the default.
  416. if (features::IsProductivityLauncherEnabled())
  417. return;
  418. Shell::Get()->keyboard_controller()->SetEnableFlag(
  419. keyboard::KeyboardEnableFlag::kShelfEnabled);
  420. // Show the AppListView and click on the search box with mouse so the
  421. // VirtualKeyboard is shown. Wait until the virtual keyboard shows.
  422. ShowAppListNow(AppListViewState::kPeeking);
  423. GetSearchBoxView()->SetSearchBoxActive(true, ui::ET_MOUSE_PRESSED);
  424. base::RunLoop().RunUntilIdle();
  425. EXPECT_TRUE(GetVirtualKeyboardWindow()->IsVisible());
  426. // Turn on the tablet mode. The virtual keyboard should still show.
  427. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  428. EXPECT_TRUE(IsTabletMode());
  429. EXPECT_TRUE(GetVirtualKeyboardWindow()->IsVisible());
  430. // Close the virtual keyboard. Wait until it is hidden.
  431. Shell::Get()->keyboard_controller()->HideKeyboard(HideReason::kUser);
  432. base::RunLoop().RunUntilIdle();
  433. EXPECT_EQ(nullptr, GetVirtualKeyboardWindow());
  434. // Check the following things:
  435. // (1) AppListView's state is FULLSCREEN_SEARCH
  436. // (2) AppListView's bounds are the same as the preferred bounds for
  437. // the FULLSCREEN_SEARCH state.
  438. EXPECT_EQ(AppListViewState::kFullscreenSearch,
  439. GetAppListView()->app_list_state());
  440. EXPECT_EQ(GetAppListView()->GetPreferredWidgetBoundsForState(
  441. AppListViewState::kFullscreenSearch),
  442. GetAppListViewNativeWindow()->bounds());
  443. }
  444. #if defined(ADDRESS_SANITIZER)
  445. #define MAYBE_CloseNotificationWithAppListShown \
  446. DISABLED_CloseNotificationWithAppListShown
  447. #else
  448. #define MAYBE_CloseNotificationWithAppListShown \
  449. CloseNotificationWithAppListShown
  450. #endif
  451. // Verifies that closing notification by gesture should not dismiss the AppList.
  452. // (see https://crbug.com/948344)
  453. // TODO(crbug.com/1120501): Test is flaky on ASAN builds.
  454. TEST_F(AppListControllerImplTest, MAYBE_CloseNotificationWithAppListShown) {
  455. ShowAppListNow(AppListViewState::kPeeking);
  456. // Add one notification.
  457. ASSERT_EQ(
  458. 0u, message_center::MessageCenter::Get()->GetPopupNotifications().size());
  459. const std::string notification_id("id");
  460. const std::string notification_title("title");
  461. message_center::MessageCenter::Get()->AddNotification(
  462. std::make_unique<message_center::Notification>(
  463. message_center::NOTIFICATION_TYPE_SIMPLE, notification_id,
  464. base::UTF8ToUTF16(notification_title), u"test message",
  465. ui::ImageModel(), std::u16string() /* display_source */, GURL(),
  466. message_center::NotifierId(), message_center::RichNotificationData(),
  467. new message_center::NotificationDelegate()));
  468. base::RunLoop().RunUntilIdle();
  469. ASSERT_EQ(
  470. 1u, message_center::MessageCenter::Get()->GetPopupNotifications().size());
  471. // Calculate the drag start point and end point.
  472. SystemTrayTestApi test_api;
  473. message_center::MessagePopupView* popup_view =
  474. test_api.GetPopupViewForNotificationID(notification_id);
  475. ASSERT_TRUE(popup_view);
  476. gfx::Rect bounds_in_screen = popup_view->GetBoundsInScreen();
  477. const gfx::Point drag_start = bounds_in_screen.left_center();
  478. const gfx::Point drag_end = bounds_in_screen.right_center();
  479. // Swipe away notification by gesture. Verifies that AppListView still shows.
  480. ui::test::EventGenerator* event_generator = GetEventGenerator();
  481. event_generator->GestureScrollSequence(drag_start, drag_end,
  482. base::Microseconds(500), 10);
  483. base::RunLoop().RunUntilIdle();
  484. EXPECT_TRUE(GetAppListView());
  485. EXPECT_EQ(
  486. 0u, message_center::MessageCenter::Get()->GetPopupNotifications().size());
  487. }
  488. // Verifiy that when showing the launcher, the virtual keyboard dismissed before
  489. // will not show automatically due to the feature called "transient blur" (see
  490. // https://crbug.com/1057320).
  491. TEST_F(AppListControllerImplTest,
  492. TransientBlurIsNotTriggeredWhenShowingLauncher) {
  493. // Enable animation.
  494. ui::ScopedAnimationDurationScaleMode non_zero_duration(
  495. ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
  496. // Enable virtual keyboard.
  497. KeyboardController* const keyboard_controller =
  498. Shell::Get()->keyboard_controller();
  499. keyboard_controller->SetEnableFlag(
  500. keyboard::KeyboardEnableFlag::kCommandLineEnabled);
  501. // Create |window1| which contains a textfield as child view.
  502. std::unique_ptr<aura::Window> window1 =
  503. AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 200, 200));
  504. auto* widget = views::Widget::GetWidgetForNativeView(window1.get());
  505. std::unique_ptr<views::Textfield> text_field =
  506. std::make_unique<views::Textfield>();
  507. // TODO(crbug.com/1218186): Remove this, this is in place temporarily to be
  508. // able to submit accessibility checks, but this focusable View needs to
  509. // add a name so that the screen reader knows what to announce.
  510. text_field->SetProperty(views::kSkipAccessibilityPaintChecks, true);
  511. // Note that the bounds of |text_field| cannot be too small. Otherwise, it
  512. // may not receive the gesture event.
  513. text_field->SetBoundsRect(gfx::Rect(0, 0, 100, 100));
  514. const auto* text_field_p = text_field.get();
  515. widget->GetRootView()->AddChildView(std::move(text_field));
  516. wm::ActivateWindow(window1.get());
  517. widget->Show();
  518. // Create |window2|.
  519. std::unique_ptr<aura::Window> window2 =
  520. AshTestBase::CreateTestWindow(gfx::Rect(200, 0, 200, 200));
  521. window2->Show();
  522. // Tap at the textfield in |window1|. The virtual keyboard should be visible.
  523. GestureTapOn(text_field_p);
  524. ASSERT_TRUE(keyboard::WaitUntilShown());
  525. // Tap at the center of |window2| to hide the virtual keyboard.
  526. GetEventGenerator()->GestureTapAt(window2->GetBoundsInScreen().CenterPoint());
  527. ASSERT_TRUE(keyboard::WaitUntilHidden());
  528. // Press the home button to show the launcher. Wait for the animation of
  529. // launcher to finish. Note that the launcher does not exist before toggling
  530. // the home button.
  531. PressHomeButton();
  532. const base::TimeDelta delta = base::Milliseconds(200);
  533. do {
  534. base::RunLoop run_loop;
  535. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
  536. FROM_HERE, run_loop.QuitClosure(), delta);
  537. run_loop.Run();
  538. } while (IsAppListBoundsAnimationRunning());
  539. // Expect that the virtual keyboard is invisible when the launcher shows.
  540. EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
  541. }
  542. // Tests that full screen apps list opens when user touches on or near the
  543. // expand view arrow. (see https://crbug.com/906858)
  544. TEST_F(AppListControllerImplTest,
  545. EnterFullScreenModeAfterTappingNearExpandArrow) {
  546. // The bounds for the tap target of the expand arrow button, taken from
  547. // expand_arrow_view.cc |kTapTargetWidth| and |kTapTargetHeight|.
  548. constexpr int tapping_width = 156;
  549. constexpr int tapping_height = 72;
  550. ShowAppListNow(AppListViewState::kPeeking);
  551. ASSERT_EQ(AppListViewState::kPeeking, GetAppListView()->app_list_state());
  552. // Get in screen bounds of arrow
  553. gfx::Rect expand_arrow = GetAppListView()
  554. ->app_list_main_view()
  555. ->contents_view()
  556. ->expand_arrow_view()
  557. ->GetBoundsInScreen();
  558. const int horizontal_padding = (tapping_width - expand_arrow.width()) / 2;
  559. const int vertical_padding = (tapping_height - expand_arrow.height()) / 2;
  560. expand_arrow.Inset(gfx::Insets::VH(-vertical_padding, -horizontal_padding));
  561. // Tap expand arrow icon and check that full screen apps view is entered.
  562. ui::test::EventGenerator* event_generator = GetEventGenerator();
  563. event_generator->GestureTapAt(expand_arrow.CenterPoint());
  564. ASSERT_EQ(AppListViewState::kFullscreenAllApps,
  565. GetAppListView()->app_list_state());
  566. // Hide the AppListView. Wait until animation is finished
  567. DismissAppListNow();
  568. base::RunLoop().RunUntilIdle();
  569. // Re-enter peeking mode and test that tapping on one of the bounds of the
  570. // tap target for the expand arrow icon still brings up full app list
  571. // view.
  572. ShowAppListNow(AppListViewState::kPeeking);
  573. ASSERT_EQ(AppListViewState::kPeeking, GetAppListView()->app_list_state());
  574. event_generator->GestureTapAt(gfx::Point(expand_arrow.top_right().x() - 1,
  575. expand_arrow.top_right().y() + 1));
  576. ASSERT_EQ(AppListViewState::kFullscreenAllApps,
  577. GetAppListView()->app_list_state());
  578. }
  579. // Regression test for https://crbug.com/1073548
  580. // Verifies that app list shown from overview after toggling tablet mode can be
  581. // closed.
  582. TEST_F(AppListControllerImplTest,
  583. CloseAppListShownFromOverviewAfterTabletExit) {
  584. // This test is not relevant for ProductivityLauncher because it uses separate
  585. // widgets in clamshell and tablet mode. This test can be deleted when
  586. // ProductivityLauncher is the default.
  587. if (features::IsProductivityLauncherEnabled())
  588. return;
  589. auto* shell = Shell::Get();
  590. auto* tablet_mode_controller = shell->tablet_mode_controller();
  591. // Move to tablet mode and back.
  592. tablet_mode_controller->SetEnabledForTest(true);
  593. tablet_mode_controller->SetEnabledForTest(false);
  594. std::unique_ptr<aura::Window> w(
  595. AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400)));
  596. EnterOverview();
  597. // Press home button - verify overview exits and the app list is shown.
  598. PressHomeButton();
  599. EXPECT_FALSE(shell->overview_controller()->InOverviewSession());
  600. EXPECT_EQ(AppListViewState::kPeeking, GetAppListView()->app_list_state());
  601. GetAppListTestHelper()->CheckVisibility(true);
  602. ASSERT_TRUE(GetAppListView()->GetWidget());
  603. EXPECT_TRUE(GetAppListView()->GetWidget()->GetNativeWindow()->IsVisible());
  604. // Pressing home button again should close the app list.
  605. PressHomeButton();
  606. EXPECT_EQ(AppListViewState::kClosed, GetAppListView()->app_list_state());
  607. GetAppListTestHelper()->CheckVisibility(false);
  608. ASSERT_TRUE(GetAppListView()->GetWidget());
  609. EXPECT_FALSE(GetAppListView()->GetWidget()->GetNativeWindow()->IsVisible());
  610. }
  611. // Tests that swapping out an AppListModel (simulating a profile swap with
  612. // multiprofile enabled) drops all references to previous folders (see
  613. // https://crbug.com/1130901).
  614. TEST_F(AppListControllerImplTest, SimulateProfileSwapNoCrashOnDestruct) {
  615. // Add a folder, whose AppListItemList the AppListModel will observe.
  616. AppListModel* model = GetAppListModel();
  617. const std::string folder_id("folder_1");
  618. model->CreateFolderItem(folder_id);
  619. for (int i = 0; i < 2; ++i) {
  620. auto item = std::make_unique<AppListItem>(base::StringPrintf("app_%d", i));
  621. model->AddItemToFolder(std::move(item), folder_id);
  622. }
  623. // Set a new model, simulating profile switching in multi-profile mode. This
  624. // should cleanly drop the reference to the folder added earlier.
  625. auto updated_model = std::make_unique<test::AppListTestModel>();
  626. auto update_search_model = std::make_unique<SearchModel>();
  627. Shell::Get()->app_list_controller()->SetActiveModel(
  628. /*profile_id=*/1, updated_model.get(), update_search_model.get());
  629. Shell::Get()->app_list_controller()->ClearActiveModel();
  630. updated_model.reset();
  631. // Test that there is no crash on ~AppListModel() when the test finishes.
  632. }
  633. class AppListControllerImplTestWithNotificationBadging
  634. : public AppListControllerImplTest {
  635. public:
  636. AppListControllerImplTestWithNotificationBadging() = default;
  637. AppListControllerImplTestWithNotificationBadging(
  638. const AppListControllerImplTestWithNotificationBadging& other) = delete;
  639. AppListControllerImplTestWithNotificationBadging& operator=(
  640. const AppListControllerImplTestWithNotificationBadging& other) = delete;
  641. ~AppListControllerImplTestWithNotificationBadging() override = default;
  642. void UpdateAppHasBadge(const std::string& app_id, bool app_has_badge) {
  643. AppListControllerImpl* controller = Shell::Get()->app_list_controller();
  644. AccountId account_id = AccountId::FromUserEmail("test@gmail.com");
  645. apps::App test_app(apps::AppType::kArc, app_id);
  646. test_app.has_badge = app_has_badge;
  647. apps::AppUpdate test_update(nullptr, /*delta=*/&test_app, account_id);
  648. controller->badge_controller_for_test()->OnAppUpdate(test_update);
  649. }
  650. };
  651. // Tests that when an app has an update to its notification badge, the change
  652. // gets propagated to the corresponding AppListItemView.
  653. TEST_F(AppListControllerImplTestWithNotificationBadging,
  654. NotificationBadgeUpdateTest) {
  655. PopulateItem(1);
  656. ShowAppListNow(AppListViewState::kFullscreenAllApps);
  657. test::AppsGridViewTestApi apps_grid_view_test_api(GetAppsGridView());
  658. const AppListItemView* item_view =
  659. apps_grid_view_test_api.GetViewAtIndex(GridIndex(0, 0));
  660. ASSERT_TRUE(item_view);
  661. const std::string app_id = item_view->item()->id();
  662. EXPECT_FALSE(item_view->IsNotificationIndicatorShownForTest());
  663. UpdateAppHasBadge(app_id, /*app_has_badge=*/true);
  664. EXPECT_TRUE(item_view->IsNotificationIndicatorShownForTest());
  665. UpdateAppHasBadge(app_id, /*app_has_badge=*/false);
  666. EXPECT_FALSE(item_view->IsNotificationIndicatorShownForTest());
  667. }
  668. TEST_F(AppListControllerImplTestWithNotificationBadging,
  669. NotificationBadgeUpdateForFolderTest) {
  670. std::string folder_id = "folder_1";
  671. AppListModel* model = GetAppListModel();
  672. model->CreateFolderItem(folder_id);
  673. model->AddItemToFolder(std::make_unique<AppListItem>("app_1"), folder_id);
  674. model->AddItemToFolder(std::make_unique<AppListItem>("app_2"), folder_id);
  675. ShowAppListNow(AppListViewState::kFullscreenAllApps);
  676. test::AppsGridViewTestApi apps_grid_view_test_api(GetAppsGridView());
  677. const AppListItemView* folder_view =
  678. apps_grid_view_test_api.GetViewAtIndex(GridIndex(0, 0));
  679. ASSERT_TRUE(folder_view);
  680. EXPECT_FALSE(folder_view->IsNotificationIndicatorShownForTest());
  681. UpdateAppHasBadge("app_1", /*app_has_badge=*/true);
  682. EXPECT_TRUE(folder_view->IsNotificationIndicatorShownForTest());
  683. UpdateAppHasBadge("app_2", /*app_has_badge=*/true);
  684. EXPECT_TRUE(folder_view->IsNotificationIndicatorShownForTest());
  685. UpdateAppHasBadge("app_1", /*app_has_badge=*/false);
  686. EXPECT_TRUE(folder_view->IsNotificationIndicatorShownForTest());
  687. UpdateAppHasBadge("app_2", /*app_has_badge=*/false);
  688. EXPECT_FALSE(folder_view->IsNotificationIndicatorShownForTest());
  689. }
  690. TEST_F(AppListControllerImplTestWithNotificationBadging,
  691. NotificationBadgeUpdateAfterAddingRemovingAppTest) {
  692. std::string folder_id = "folder_1";
  693. AppListModel* model = GetAppListModel();
  694. model->CreateFolderItem(folder_id);
  695. AppListItem* app = model->AddItem(std::make_unique<AppListItem>("app_1"));
  696. model->AddItemToFolder(std::make_unique<AppListItem>("app_2"), folder_id);
  697. ShowAppListNow(AppListViewState::kFullscreenAllApps);
  698. test::AppsGridViewTestApi apps_grid_view_test_api(GetAppsGridView());
  699. const AppListItemView* folder_view =
  700. apps_grid_view_test_api.GetViewAtIndex(GridIndex(0, 0));
  701. ASSERT_TRUE(folder_view);
  702. EXPECT_FALSE(folder_view->IsNotificationIndicatorShownForTest());
  703. UpdateAppHasBadge("app_1", /*app_has_badge=*/true);
  704. EXPECT_FALSE(folder_view->IsNotificationIndicatorShownForTest());
  705. model->MoveItemToFolder(app, folder_id);
  706. EXPECT_TRUE(folder_view->IsNotificationIndicatorShownForTest());
  707. model->MoveItemToRootAt(app, model->FindFolderItem(folder_id)->position());
  708. EXPECT_FALSE(folder_view->IsNotificationIndicatorShownForTest());
  709. }
  710. // Verifies that the pinned app should still show after canceling the drag from
  711. // AppsGridView to Shelf (https://crbug.com/1021768).
  712. TEST_F(AppListControllerImplTest, DragItemFromAppsGridView) {
  713. // Turn on the tablet mode.
  714. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  715. EXPECT_TRUE(IsTabletMode());
  716. Shelf* const shelf = GetPrimaryShelf();
  717. // Add icons with the same app id to Shelf and AppsGridView respectively.
  718. ShelfViewTestAPI shelf_view_test_api(shelf->GetShelfViewForTesting());
  719. std::string app_id = shelf_view_test_api.AddItem(TYPE_PINNED_APP).app_id;
  720. GetAppListModel()->AddItem(std::make_unique<AppListItem>(app_id));
  721. AppsGridView* apps_grid_view = GetAppsGridView();
  722. apps_grid_view->Layout();
  723. AppListItemView* app_list_item_view =
  724. test::AppsGridViewTestApi(apps_grid_view).GetViewAtIndex(GridIndex(0, 0));
  725. views::View* shelf_icon_view =
  726. shelf->GetShelfViewForTesting()->view_model()->view_at(0);
  727. // Drag the app icon from AppsGridView to Shelf. Then move the icon back to
  728. // AppsGridView before drag ends.
  729. GetEventGenerator()->MoveMouseTo(
  730. app_list_item_view->GetBoundsInScreen().CenterPoint());
  731. GetEventGenerator()->PressLeftButton();
  732. app_list_item_view->FireMouseDragTimerForTest();
  733. GetEventGenerator()->MoveMouseTo(
  734. shelf_icon_view->GetBoundsInScreen().CenterPoint());
  735. GetEventGenerator()->MoveMouseTo(
  736. apps_grid_view->GetBoundsInScreen().CenterPoint());
  737. GetEventGenerator()->ReleaseLeftButton();
  738. // The icon's opacity updates at the end of animation.
  739. shelf_view_test_api.RunMessageLoopUntilAnimationsDone();
  740. // The icon is pinned before drag starts. So the shelf icon should show in
  741. // spite that drag is canceled.
  742. EXPECT_TRUE(shelf_icon_view->GetVisible());
  743. EXPECT_EQ(1.0f, shelf_icon_view->layer()->opacity());
  744. }
  745. // Verifies that apps grid and hotseat bounds do not overlap when switching from
  746. // side shelf app list to tablet mode.
  747. TEST_F(AppListControllerImplTest, NoOverlapWithHotseatOnSwitchFromSideShelf) {
  748. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
  749. Shelf* const shelf = GetPrimaryShelf();
  750. shelf->SetAlignment(ShelfAlignment::kRight);
  751. ShowAppListNow(AppListViewState::kFullscreenAllApps);
  752. ASSERT_EQ(AppListViewState::kFullscreenAllApps,
  753. GetAppListView()->app_list_state());
  754. gfx::Rect apps_grid_view_bounds = GetAppsGridView()->GetBoundsInScreen();
  755. EXPECT_FALSE(apps_grid_view_bounds.Intersects(
  756. shelf->shelf_widget()->GetWindowBoundsInScreen()));
  757. EXPECT_FALSE(apps_grid_view_bounds.Intersects(
  758. shelf->hotseat_widget()->GetWindowBoundsInScreen()));
  759. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  760. EXPECT_EQ(AppListViewState::kFullscreenAllApps,
  761. GetAppListView()->app_list_state());
  762. apps_grid_view_bounds = GetAppsGridView()->GetBoundsInScreen();
  763. EXPECT_FALSE(apps_grid_view_bounds.Intersects(
  764. shelf->shelf_widget()->GetWindowBoundsInScreen()));
  765. EXPECT_FALSE(apps_grid_view_bounds.Intersects(
  766. shelf->hotseat_widget()->GetWindowBoundsInScreen()));
  767. }
  768. TEST_F(AppListControllerImplTest, OnlyMinimizeCycleListWindows) {
  769. std::unique_ptr<aura::Window> w1(CreateTestWindow(gfx::Rect(0, 0, 400, 400)));
  770. std::unique_ptr<aura::Window> w2(CreateTestWindow(
  771. gfx::Rect(0, 0, 400, 400), aura::client::WINDOW_TYPE_POPUP));
  772. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  773. std::unique_ptr<ui::Event> test_event = std::make_unique<ui::KeyEvent>(
  774. ui::EventType::ET_MOUSE_PRESSED, ui::VKEY_UNKNOWN, ui::EF_NONE);
  775. Shell::Get()->app_list_controller()->GoHome(GetPrimaryDisplay().id());
  776. EXPECT_TRUE(WindowState::Get(w1.get())->IsMinimized());
  777. EXPECT_FALSE(WindowState::Get(w2.get())->IsMinimized());
  778. }
  779. // Tests that the home screen is visible after rotating the screen in overview
  780. // mode.
  781. TEST_F(AppListControllerImplTest,
  782. HomeScreenVisibleAfterDisplayUpdateInOverview) {
  783. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  784. EnterOverview();
  785. // Trigger a display configuration change, this simulates screen rotation.
  786. Shell::Get()->app_list_controller()->OnDisplayConfigurationChanged();
  787. // End overview mode, the home launcher should be visible.
  788. ExitOverview();
  789. ShellTestApi().WaitForOverviewAnimationState(
  790. OverviewAnimationState::kExitAnimationComplete);
  791. EXPECT_TRUE(
  792. Shell::Get()->app_list_controller()->GetHomeScreenWindow()->IsVisible());
  793. }
  794. TEST_F(AppListControllerImplTest, CreatePage) {
  795. ShowAppListNow(AppListViewState::kFullscreenAllApps);
  796. PagedAppsGridView* apps_grid_view = GetAppsGridView();
  797. test::AppsGridViewTestApi test_api(apps_grid_view);
  798. PopulateItem(test_api.TilesPerPage(0));
  799. EXPECT_EQ(1, apps_grid_view->pagination_model()->total_pages());
  800. // Add an extra item and verify that the page count is 2 now.
  801. PopulateItem(1);
  802. EXPECT_EQ(2, apps_grid_view->pagination_model()->total_pages());
  803. // Verify that there is no page break items.
  804. EXPECT_EQ(0, CountPageBreakItems());
  805. }
  806. // The test parameter indicates whether the shelf should auto-hide. In either
  807. // case the animation behaviors should be the same.
  808. class AppListAnimationTest : public AshTestBase,
  809. public testing::WithParamInterface<bool> {
  810. public:
  811. AppListAnimationTest() = default;
  812. AppListAnimationTest(const AppListAnimationTest&) = delete;
  813. AppListAnimationTest& operator=(const AppListAnimationTest&) = delete;
  814. ~AppListAnimationTest() override = default;
  815. void SetUp() override {
  816. AshTestBase::SetUp();
  817. Shelf* const shelf = AshTestBase::GetPrimaryShelf();
  818. shelf->SetAlignment(ShelfAlignment::kBottom);
  819. if (GetParam()) {
  820. shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
  821. }
  822. // The shelf should be shown at this point despite auto hide behavior, given
  823. // that no windows are shown.
  824. shown_shelf_bounds_ = shelf->shelf_widget()->GetWindowBoundsInScreen();
  825. }
  826. int GetAppListCurrentTop() {
  827. gfx::Point app_list_top =
  828. GetAppListView()->GetBoundsInScreen().top_center();
  829. GetAppListView()->GetWidget()->GetLayer()->transform().TransformPoint(
  830. &app_list_top);
  831. return app_list_top.y();
  832. }
  833. int GetAppListTargetTop() {
  834. gfx::Point app_list_top =
  835. GetAppListView()->GetBoundsInScreen().top_center();
  836. GetAppListView()
  837. ->GetWidget()
  838. ->GetLayer()
  839. ->GetTargetTransform()
  840. .TransformPoint(&app_list_top);
  841. return app_list_top.y();
  842. }
  843. int shown_shelf_top() const { return shown_shelf_bounds_.y(); }
  844. // The offset that should be animated between kPeeking and kClosed app list
  845. // view states - the vertical distance between shelf top (in shown state) and
  846. // the app list top in peeking state.
  847. int PeekingHeightOffset() const {
  848. return shown_shelf_bounds_.y() - PeekingHeightTop();
  849. }
  850. // The app list view y coordinate in peeking state.
  851. int PeekingHeightTop() const {
  852. return shown_shelf_bounds_.bottom() -
  853. GetAppListView()->GetHeightForState(AppListViewState::kPeeking);
  854. }
  855. private:
  856. // Set during setup.
  857. gfx::Rect shown_shelf_bounds_;
  858. };
  859. INSTANTIATE_TEST_SUITE_P(AutoHideShelf, AppListAnimationTest, testing::Bool());
  860. // Tests app list animation to peeking state.
  861. TEST_P(AppListAnimationTest, AppListShowPeekingAnimation) {
  862. // Set the normal transition duration so tests can easily determine intended
  863. // animation length, and calculate expected app list position at different
  864. // animation step points. Also, prevents the app list view to snapping to the
  865. // final position.
  866. ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
  867. ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
  868. ShowAppListNow(AppListViewState::kPeeking);
  869. // Verify that the app list view's top matches the shown shelf top as the show
  870. // animation starts.
  871. EXPECT_EQ(shown_shelf_top(), GetAppListCurrentTop());
  872. EXPECT_EQ(PeekingHeightTop(), GetAppListTargetTop());
  873. }
  874. // Tests app list animation from peeking to closed state.
  875. TEST_P(AppListAnimationTest, AppListCloseFromPeekingAnimation) {
  876. ShowAppListNow(AppListViewState::kPeeking);
  877. // Set the normal transition duration so tests can easily determine intended
  878. // animation length, and calculate expected app list position at different
  879. // animation step points. Also, prevents the app list view to snapping to the
  880. // final position.
  881. ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
  882. ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
  883. // Dismiss app list, initial app list position should be at peeking height.
  884. const int offset_to_animate = PeekingHeightOffset();
  885. DismissAppListNow();
  886. EXPECT_EQ(shown_shelf_top() - offset_to_animate, GetAppListCurrentTop());
  887. EXPECT_EQ(shown_shelf_top(), GetAppListTargetTop());
  888. }
  889. // Tests app list close animation when app list gets dismissed while animating
  890. // to peeking state.
  891. TEST_P(AppListAnimationTest, AppListDismissWhileShowingPeeking) {
  892. // Set the normal transition duration so tests can easily determine intended
  893. // animation length, and calculate expected app list position at different
  894. // animation step points. Also, prevents the app list view to snapping to the
  895. // final position.
  896. ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
  897. ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
  898. ShowAppListNow(AppListViewState::kPeeking);
  899. // Verify that the app list view's top matches the shown shelf top as the show
  900. // animation starts.
  901. EXPECT_EQ(shown_shelf_top(), GetAppListCurrentTop());
  902. EXPECT_EQ(PeekingHeightTop(), GetAppListTargetTop());
  903. // Start dismissing app list. Verify the new animation starts at the same
  904. // point the show animation ended.
  905. DismissAppListNow();
  906. EXPECT_EQ(shown_shelf_top(), GetAppListTargetTop());
  907. }
  908. // Tests app list animation when show is requested while app list close
  909. // animation is in progress.
  910. TEST_P(AppListAnimationTest, AppListShowPeekingWhileClosing) {
  911. // Show app list while animations are still instantanious.
  912. ShowAppListNow(AppListViewState::kPeeking);
  913. // Set the normal transition duration so tests can easily determine intended
  914. // animation length, and calculate expected app list position at different
  915. // animation step points. Also, prevents the app list view to snapping to the
  916. // final position.
  917. ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
  918. ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
  919. int offset_to_animate = PeekingHeightOffset();
  920. DismissAppListNow();
  921. // Verify that the app list view's top initially matches the peeking height.
  922. EXPECT_EQ(shown_shelf_top() - offset_to_animate, GetAppListCurrentTop());
  923. EXPECT_EQ(shown_shelf_top(), GetAppListTargetTop());
  924. // Start showing the app list. Verify the new animation starts at the same
  925. // point the show animation ended.
  926. ShowAppListNow(AppListViewState::kPeeking);
  927. EXPECT_EQ(PeekingHeightTop(), GetAppListTargetTop());
  928. }
  929. // Tests that how search box opacity is animated when the app list is shown and
  930. // closed.
  931. TEST_P(AppListAnimationTest, SearchBoxOpacityDuringShowAndClose) {
  932. // Set a transition duration that prevents the app list view from snapping to
  933. // the final position.
  934. ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
  935. ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
  936. ShowAppListNow(AppListViewState::kPeeking);
  937. SearchBoxView* const search_box = GetSearchBoxView();
  938. // The search box opacity should start at 0, and animate to 1.
  939. EXPECT_EQ(0.0f, search_box->layer()->opacity());
  940. EXPECT_EQ(1.0f, search_box->layer()->GetTargetOpacity());
  941. // If the app list is closed while the animation is still in progress, the
  942. // search box opacity should animate from the current opacity.
  943. DismissAppListNow();
  944. EXPECT_EQ(0.0f, search_box->layer()->opacity());
  945. EXPECT_EQ(0.0f, search_box->layer()->GetTargetOpacity());
  946. search_box->layer()->GetAnimator()->StopAnimating();
  947. // When show again, verify the app list animates from 0 opacity again.
  948. ShowAppListNow(AppListViewState::kPeeking);
  949. EXPECT_EQ(0.0f, search_box->layer()->opacity());
  950. EXPECT_EQ(1.0f, search_box->layer()->GetTargetOpacity());
  951. search_box->layer()->GetAnimator()->StopAnimating();
  952. EXPECT_EQ(1.0f, search_box->layer()->opacity());
  953. // Search box opacity animates from the current (full opacity) when closed
  954. // from shown state.
  955. DismissAppListNow();
  956. EXPECT_EQ(1.0f, search_box->layer()->opacity());
  957. EXPECT_EQ(0.0f, search_box->layer()->GetTargetOpacity());
  958. // If the app list is show again during close animation, the search box
  959. // opacity should animate from the current value.
  960. ShowAppListNow(AppListViewState::kPeeking);
  961. EXPECT_EQ(1.0f, search_box->layer()->opacity());
  962. EXPECT_EQ(1.0f, search_box->layer()->GetTargetOpacity());
  963. }
  964. class AppListControllerImplMetricsTest : public AshTestBase {
  965. public:
  966. AppListControllerImplMetricsTest() = default;
  967. AppListControllerImplMetricsTest(const AppListControllerImplMetricsTest&) =
  968. delete;
  969. AppListControllerImplMetricsTest& operator=(
  970. const AppListControllerImplMetricsTest&) = delete;
  971. ~AppListControllerImplMetricsTest() override = default;
  972. void SetUp() override {
  973. AshTestBase::SetUp();
  974. controller_ = Shell::Get()->app_list_controller();
  975. ui::PresentationTimeRecorder::SetReportPresentationTimeImmediatelyForTest(
  976. true);
  977. }
  978. void TearDown() override {
  979. ui::PresentationTimeRecorder::SetReportPresentationTimeImmediatelyForTest(
  980. false);
  981. AshTestBase::TearDown();
  982. }
  983. AppListControllerImpl* controller_;
  984. const base::HistogramTester histogram_tester_;
  985. };
  986. // One edge case may do harm to the presentation metrics reporter for tablet
  987. // mode: the user may keep pressing on launcher while exiting the tablet mode by
  988. // rotating the lid. In this situation, OnHomeLauncherDragEnd is not triggered.
  989. // It is handled correctly now because the AppListView is always closed after
  990. // exiting the tablet mode. But it still has potential risk to break in future.
  991. // Write this test case for precaution (https://crbug.com/947105).
  992. TEST_F(AppListControllerImplMetricsTest,
  993. PresentationMetricsForTabletNotRecordedInClamshell) {
  994. // ProductivityLauncher does not support app list dragging. This test can be
  995. // deleted when ProductivityLauncher is the default.
  996. if (features::IsProductivityLauncherEnabled())
  997. return;
  998. // Wait until the construction of TabletModeController finishes.
  999. base::RunLoop().RunUntilIdle();
  1000. // Turn on the tablet mode.
  1001. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  1002. EXPECT_TRUE(IsTabletMode());
  1003. // Create a window then press the home launcher button. Expect that |w| is
  1004. // hidden.
  1005. std::unique_ptr<aura::Window> w(
  1006. AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400)));
  1007. Shell::Get()->app_list_controller()->GoHome(
  1008. display::Screen::GetScreen()->GetPrimaryDisplay().id());
  1009. EXPECT_FALSE(w->IsVisible());
  1010. EXPECT_EQ(AppListViewState::kFullscreenAllApps,
  1011. GetAppListView()->app_list_state());
  1012. gfx::Point start =
  1013. GetAppListView()->GetWidget()->GetWindowBoundsInScreen().top_right();
  1014. base::TimeTicks timestamp = base::TimeTicks::Now();
  1015. // Emulate to drag the launcher downward.
  1016. // Send SCROLL_START event. Check the presentation metrics values.
  1017. ui::GestureEvent start_event = ui::GestureEvent(
  1018. start.x(), start.y(), ui::EF_NONE, timestamp,
  1019. ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, 1));
  1020. GetAppListView()->OnGestureEvent(&start_event);
  1021. // Turn off the tablet mode before scrolling is finished.
  1022. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
  1023. EXPECT_FALSE(IsTabletMode());
  1024. base::RunLoop().RunUntilIdle();
  1025. EXPECT_EQ(AppListViewState::kClosed, GetAppListView()->app_list_state());
  1026. GetAppListTestHelper()->CheckVisibility(false);
  1027. // Check metrics initial values.
  1028. histogram_tester_.ExpectTotalCount(
  1029. "Apps.StateTransition.Drag.PresentationTime.TabletMode", 0);
  1030. histogram_tester_.ExpectTotalCount(
  1031. "Apps.StateTransition.Drag.PresentationTime.MaxLatency.TabletMode", 0);
  1032. // Emulate to drag launcher from shelf. Then verifies the following things:
  1033. // (1) Metrics values for tablet mode are not recorded.
  1034. // (2) Metrics values for clamshell mode are recorded correctly.
  1035. gfx::Rect shelf_bounds =
  1036. GetPrimaryShelf()->shelf_widget()->GetWindowBoundsInScreen();
  1037. shelf_bounds.Intersect(
  1038. display::Screen::GetScreen()->GetPrimaryDisplay().bounds());
  1039. gfx::Point shelf_center = shelf_bounds.CenterPoint();
  1040. gfx::Point target_point =
  1041. display::Screen::GetScreen()->GetPrimaryDisplay().bounds().CenterPoint();
  1042. ui::test::EventGenerator* generator = GetEventGenerator();
  1043. generator->GestureScrollSequence(shelf_center, target_point,
  1044. base::Microseconds(500), 1);
  1045. EXPECT_EQ(AppListViewState::kFullscreenAllApps,
  1046. GetAppListView()->app_list_state());
  1047. histogram_tester_.ExpectTotalCount(
  1048. "Apps.StateTransition.Drag.PresentationTime.TabletMode", 0);
  1049. histogram_tester_.ExpectTotalCount(
  1050. "Apps.StateTransition.Drag.PresentationTime.MaxLatency.TabletMode", 0);
  1051. // AppListView::UpdateYPositionAndOpacity is triggered by
  1052. // ShelfLayoutManager::StartGestureDrag and
  1053. // ShelfLayoutManager::UpdateGestureDrag. Note that scrolling step of event
  1054. // generator is 1. So the expected value is 2.
  1055. histogram_tester_.ExpectTotalCount(
  1056. "Apps.StateTransition.Drag.PresentationTime.ClamshellMode", 2);
  1057. histogram_tester_.ExpectTotalCount(
  1058. "Apps.StateTransition.Drag.PresentationTime.MaxLatency.ClamshellMode", 1);
  1059. }
  1060. // Tests with the bubble launcher enabled. This is a separate test suite
  1061. // because the feature must be enabled before ash::Shell constructs the
  1062. // AppListControllerImpl.
  1063. class AppListControllerImplAppListBubbleTest : public AshTestBase {
  1064. public:
  1065. AppListControllerImplAppListBubbleTest() {
  1066. scoped_features_.InitAndEnableFeature(features::kProductivityLauncher);
  1067. }
  1068. ~AppListControllerImplAppListBubbleTest() override = default;
  1069. base::test::ScopedFeatureList scoped_features_;
  1070. };
  1071. TEST_F(AppListControllerImplAppListBubbleTest, ShowAppListOpensBubble) {
  1072. auto* controller = Shell::Get()->app_list_controller();
  1073. controller->ShowAppList();
  1074. EXPECT_TRUE(controller->bubble_presenter_for_test()->IsShowing());
  1075. EXPECT_TRUE(controller->IsVisible());
  1076. }
  1077. TEST_F(AppListControllerImplAppListBubbleTest, ToggleAppListOpensBubble) {
  1078. auto* controller = Shell::Get()->app_list_controller();
  1079. controller->ToggleAppList(GetPrimaryDisplay().id(),
  1080. AppListShowSource::kShelfButton,
  1081. /*event_time_stamp=*/{});
  1082. EXPECT_TRUE(controller->bubble_presenter_for_test()->IsShowing());
  1083. EXPECT_TRUE(controller->IsVisible());
  1084. }
  1085. TEST_F(AppListControllerImplAppListBubbleTest, DismissAppListClosesBubble) {
  1086. auto* controller = Shell::Get()->app_list_controller();
  1087. controller->ShowAppList();
  1088. controller->DismissAppList();
  1089. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1090. EXPECT_FALSE(controller->IsVisible());
  1091. }
  1092. TEST_F(AppListControllerImplAppListBubbleTest,
  1093. ShowAppListDoesNotOpenBubbleInTabletMode) {
  1094. EnableTabletMode();
  1095. auto* controller = Shell::Get()->app_list_controller();
  1096. controller->ShowAppList();
  1097. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1098. EXPECT_TRUE(controller->IsVisible());
  1099. }
  1100. TEST_F(AppListControllerImplAppListBubbleTest,
  1101. ToggleAppListDoesNotOpenBubbleInTabletMode) {
  1102. EnableTabletMode();
  1103. auto* controller = Shell::Get()->app_list_controller();
  1104. controller->ToggleAppList(GetPrimaryDisplay().id(),
  1105. AppListShowSource::kShelfButton,
  1106. /*event_time_stamp=*/{});
  1107. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1108. EXPECT_TRUE(controller->IsVisible());
  1109. }
  1110. TEST_F(AppListControllerImplAppListBubbleTest, EnteringTabletModeClosesBubble) {
  1111. auto* controller = Shell::Get()->app_list_controller();
  1112. controller->ShowAppList();
  1113. EnableTabletMode();
  1114. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1115. }
  1116. TEST_F(AppListControllerImplAppListBubbleTest,
  1117. WallpaperColorChangeDoesNotCrash) {
  1118. auto* controller = Shell::Get()->app_list_controller();
  1119. controller->ShowAppList();
  1120. // Simulate synced wallpaper update while bubble is open.
  1121. controller->OnWallpaperColorsChanged();
  1122. // No crash.
  1123. }
  1124. TEST_F(AppListControllerImplAppListBubbleTest, HideContinueSectionUpdatesPref) {
  1125. base::test::ScopedFeatureList feature_list(
  1126. features::kLauncherHideContinueSection);
  1127. auto* controller = Shell::Get()->app_list_controller();
  1128. PrefService* prefs =
  1129. Shell::Get()->session_controller()->GetLastActiveUserPrefService();
  1130. // Continue section defaults to not hidden.
  1131. EXPECT_FALSE(prefs->GetBoolean(prefs::kLauncherContinueSectionHidden));
  1132. EXPECT_FALSE(controller->ShouldHideContinueSection());
  1133. // Hiding continue section is reflected in prefs.
  1134. controller->SetHideContinueSection(true);
  1135. EXPECT_TRUE(controller->ShouldHideContinueSection());
  1136. EXPECT_TRUE(prefs->GetBoolean(prefs::kLauncherContinueSectionHidden));
  1137. // Showing continue section is reflected in prefs.
  1138. controller->SetHideContinueSection(false);
  1139. EXPECT_FALSE(controller->ShouldHideContinueSection());
  1140. EXPECT_FALSE(prefs->GetBoolean(prefs::kLauncherContinueSectionHidden));
  1141. }
  1142. // AppListControllerImpl test that start in inactive session.
  1143. class AppListControllerImplNotLoggedInTest
  1144. : public AppListControllerImplAppListBubbleTest {
  1145. public:
  1146. AppListControllerImplNotLoggedInTest() = default;
  1147. ~AppListControllerImplNotLoggedInTest() override = default;
  1148. void SetUp() override {
  1149. AppListControllerImplAppListBubbleTest::SetUp();
  1150. SetSessionState(session_manager::SessionState::LOGIN_PRIMARY);
  1151. }
  1152. void SetSessionState(session_manager::SessionState state) {
  1153. SessionInfo info;
  1154. info.state = state;
  1155. Shell::Get()->session_controller()->SetSessionInfo(info);
  1156. }
  1157. };
  1158. TEST_F(AppListControllerImplNotLoggedInTest, ToggleAppListOnLoginScreen) {
  1159. auto* controller = Shell::Get()->app_list_controller();
  1160. controller->ToggleAppList(GetPrimaryDisplay().id(),
  1161. AppListShowSource::kSearchKey,
  1162. /*event_time_stamp=*/{});
  1163. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1164. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1165. EXPECT_FALSE(controller->IsVisible());
  1166. // Verify app list cannot be toggled in logged in but inactive state.
  1167. SetSessionState(session_manager::SessionState::LOGGED_IN_NOT_ACTIVE);
  1168. controller->ToggleAppList(GetPrimaryDisplay().id(),
  1169. AppListShowSource::kSearchKey,
  1170. /*event_time_stamp=*/{});
  1171. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1172. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1173. EXPECT_FALSE(controller->IsVisible());
  1174. // Toggle app list works when session is active.
  1175. SetSessionState(session_manager::SessionState::ACTIVE);
  1176. controller->ToggleAppList(GetPrimaryDisplay().id(),
  1177. AppListShowSource::kSearchKey,
  1178. /*event_time_stamp=*/{});
  1179. EXPECT_TRUE(controller->bubble_presenter_for_test()->IsShowing());
  1180. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1181. EXPECT_TRUE(controller->IsVisible());
  1182. }
  1183. TEST_F(AppListControllerImplNotLoggedInTest, ShowAppListOnLoginScreen) {
  1184. auto* controller = Shell::Get()->app_list_controller();
  1185. controller->ShowAppList();
  1186. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1187. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1188. EXPECT_FALSE(controller->IsVisible());
  1189. // Verify app list cannot be toggled in logged in but inactive state.
  1190. SetSessionState(session_manager::SessionState::LOGGED_IN_NOT_ACTIVE);
  1191. controller->ShowAppList();
  1192. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1193. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1194. EXPECT_FALSE(controller->IsVisible());
  1195. // Toggle app list works when session is active.
  1196. SetSessionState(session_manager::SessionState::ACTIVE);
  1197. controller->ShowAppList();
  1198. EXPECT_TRUE(controller->bubble_presenter_for_test()->IsShowing());
  1199. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1200. EXPECT_TRUE(controller->IsVisible());
  1201. }
  1202. TEST_F(AppListControllerImplNotLoggedInTest, ToggleAppListInOobe) {
  1203. SetSessionState(session_manager::SessionState::OOBE);
  1204. auto* controller = Shell::Get()->app_list_controller();
  1205. controller->ToggleAppList(GetPrimaryDisplay().id(),
  1206. AppListShowSource::kSearchKey,
  1207. /*event_time_stamp=*/{});
  1208. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1209. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1210. EXPECT_FALSE(controller->IsVisible());
  1211. SetSessionState(session_manager::SessionState::LOGGED_IN_NOT_ACTIVE);
  1212. controller->ToggleAppList(GetPrimaryDisplay().id(),
  1213. AppListShowSource::kSearchKey,
  1214. /*event_time_stamp=*/{});
  1215. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1216. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1217. EXPECT_FALSE(controller->IsVisible());
  1218. // Toggle app list works when session is active.
  1219. SetSessionState(session_manager::SessionState::ACTIVE);
  1220. controller->ToggleAppList(GetPrimaryDisplay().id(),
  1221. AppListShowSource::kSearchKey,
  1222. /*event_time_stamp=*/{});
  1223. EXPECT_TRUE(controller->bubble_presenter_for_test()->IsShowing());
  1224. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1225. EXPECT_TRUE(controller->IsVisible());
  1226. }
  1227. TEST_F(AppListControllerImplNotLoggedInTest, ShowAppListInOobe) {
  1228. SetSessionState(session_manager::SessionState::OOBE);
  1229. auto* controller = Shell::Get()->app_list_controller();
  1230. controller->ShowAppList();
  1231. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1232. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1233. EXPECT_FALSE(controller->IsVisible());
  1234. // Verify app list cannot be toggled in logged in but inactive state.
  1235. SetSessionState(session_manager::SessionState::LOGGED_IN_NOT_ACTIVE);
  1236. controller->ShowAppList();
  1237. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1238. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1239. EXPECT_FALSE(controller->IsVisible());
  1240. // Toggle app list works when session is active.
  1241. SetSessionState(session_manager::SessionState::ACTIVE);
  1242. controller->ShowAppList();
  1243. EXPECT_TRUE(controller->bubble_presenter_for_test()->IsShowing());
  1244. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1245. EXPECT_TRUE(controller->IsVisible());
  1246. }
  1247. TEST_F(AppListControllerImplNotLoggedInTest, ToggleAppListOnLockScreen) {
  1248. SetSessionState(session_manager::SessionState::ACTIVE);
  1249. auto* controller = Shell::Get()->app_list_controller();
  1250. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1251. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1252. EXPECT_FALSE(controller->IsVisible());
  1253. // Lock screen - toggling app list should fail.
  1254. SetSessionState(session_manager::SessionState::LOCKED);
  1255. controller->ToggleAppList(GetPrimaryDisplay().id(),
  1256. AppListShowSource::kSearchKey,
  1257. /*event_time_stamp=*/{});
  1258. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1259. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1260. EXPECT_FALSE(controller->IsVisible());
  1261. // Unlock and verify toggling app list works.
  1262. SetSessionState(session_manager::SessionState::ACTIVE);
  1263. controller->ToggleAppList(GetPrimaryDisplay().id(),
  1264. AppListShowSource::kSearchKey,
  1265. /*event_time_stamp=*/{});
  1266. EXPECT_TRUE(controller->bubble_presenter_for_test()->IsShowing());
  1267. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1268. EXPECT_TRUE(controller->IsVisible());
  1269. // Locking the session hides the app list.
  1270. SetSessionState(session_manager::SessionState::LOCKED);
  1271. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1272. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1273. EXPECT_FALSE(controller->IsVisible());
  1274. }
  1275. TEST_F(AppListControllerImplNotLoggedInTest, ShowAppListOnLockScreen) {
  1276. SetSessionState(session_manager::SessionState::ACTIVE);
  1277. auto* controller = Shell::Get()->app_list_controller();
  1278. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1279. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1280. EXPECT_FALSE(controller->IsVisible());
  1281. // Lock screen - toggling app list should fail.
  1282. SetSessionState(session_manager::SessionState::LOCKED);
  1283. controller->ShowAppList();
  1284. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1285. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1286. EXPECT_FALSE(controller->IsVisible());
  1287. // Unlock and verify toggling app list works.
  1288. SetSessionState(session_manager::SessionState::ACTIVE);
  1289. controller->ShowAppList();
  1290. EXPECT_TRUE(controller->bubble_presenter_for_test()->IsShowing());
  1291. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1292. EXPECT_TRUE(controller->IsVisible());
  1293. // Locking the session hides the app list.
  1294. SetSessionState(session_manager::SessionState::LOCKED);
  1295. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1296. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1297. EXPECT_FALSE(controller->IsVisible());
  1298. controller->ShowAppList();
  1299. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1300. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1301. EXPECT_FALSE(controller->IsVisible());
  1302. }
  1303. TEST_F(AppListControllerImplNotLoggedInTest, ShowAppListWhenInTabletMode) {
  1304. // Enable tablet mode while on login screen.
  1305. EnableTabletMode();
  1306. auto* controller = Shell::Get()->app_list_controller();
  1307. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1308. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1309. EXPECT_FALSE(controller->IsVisible());
  1310. SetSessionState(session_manager::SessionState::LOGGED_IN_NOT_ACTIVE);
  1311. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1312. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1313. EXPECT_FALSE(controller->IsVisible());
  1314. // Fullscreen app list should be shown upon login.
  1315. SetSessionState(session_manager::SessionState::ACTIVE);
  1316. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1317. EXPECT_TRUE(controller->fullscreen_presenter()->GetTargetVisibility());
  1318. EXPECT_TRUE(controller->IsVisible());
  1319. }
  1320. TEST_F(AppListControllerImplNotLoggedInTest,
  1321. FullscreenLauncherInTabletModeWhenLocked) {
  1322. auto* controller = Shell::Get()->app_list_controller();
  1323. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1324. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1325. EXPECT_FALSE(controller->IsVisible());
  1326. SetSessionState(session_manager::SessionState::ACTIVE);
  1327. // Enable tablet mode and lock screen - fullscreen launcher should be shown
  1328. // (behind the lock screen).
  1329. EnableTabletMode();
  1330. SetSessionState(session_manager::SessionState::LOCKED);
  1331. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1332. EXPECT_TRUE(controller->fullscreen_presenter()->GetTargetVisibility());
  1333. EXPECT_TRUE(controller->IsVisible());
  1334. SetSessionState(session_manager::SessionState::ACTIVE);
  1335. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1336. EXPECT_TRUE(controller->fullscreen_presenter()->GetTargetVisibility());
  1337. EXPECT_TRUE(controller->IsVisible());
  1338. }
  1339. TEST_F(AppListControllerImplNotLoggedInTest,
  1340. FullscreenLauncherShownWhenEnteringTabletModeOnLockScreen) {
  1341. auto* controller = Shell::Get()->app_list_controller();
  1342. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1343. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1344. EXPECT_FALSE(controller->IsVisible());
  1345. SetSessionState(session_manager::SessionState::ACTIVE);
  1346. SetSessionState(session_manager::SessionState::LOCKED);
  1347. // Enable tablet mode and lock screen - fullscreen launcher should be shown
  1348. // (behind the lock screen).
  1349. EnableTabletMode();
  1350. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1351. EXPECT_FALSE(controller->fullscreen_presenter()->GetTargetVisibility());
  1352. EXPECT_FALSE(controller->IsVisible());
  1353. SetSessionState(session_manager::SessionState::ACTIVE);
  1354. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1355. EXPECT_TRUE(controller->fullscreen_presenter()->GetTargetVisibility());
  1356. EXPECT_TRUE(controller->IsVisible());
  1357. }
  1358. // Kiosk tests with the bubble launcher enabled.
  1359. class AppListControllerImplKioskTest
  1360. : public AppListControllerImplAppListBubbleTest {
  1361. public:
  1362. AppListControllerImplKioskTest() = default;
  1363. ~AppListControllerImplKioskTest() override = default;
  1364. void SetUp() override {
  1365. AppListControllerImplAppListBubbleTest::SetUp();
  1366. SessionInfo info;
  1367. info.is_running_in_app_mode = true;
  1368. info.state = session_manager::SessionState::ACTIVE;
  1369. Shell::Get()->session_controller()->SetSessionInfo(info);
  1370. }
  1371. };
  1372. TEST_F(AppListControllerImplKioskTest, ShouldNotShowLauncherInTabletMode) {
  1373. EnableTabletMode();
  1374. auto* controller = Shell::Get()->app_list_controller();
  1375. EXPECT_FALSE(controller->ShouldHomeLauncherBeVisible());
  1376. }
  1377. TEST_F(AppListControllerImplKioskTest,
  1378. DoNotShowAnyAppListInClamshellModeWhenShowAppListCalled) {
  1379. auto* controller = Shell::Get()->app_list_controller();
  1380. controller->ShowAppList();
  1381. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1382. EXPECT_FALSE(controller->IsVisible());
  1383. }
  1384. TEST_F(AppListControllerImplKioskTest,
  1385. DoNotShowAnyAppListInTabletModeWhenShowAppListCalled) {
  1386. EnableTabletMode();
  1387. auto* controller = Shell::Get()->app_list_controller();
  1388. controller->ShowAppList();
  1389. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1390. EXPECT_FALSE(controller->IsVisible());
  1391. }
  1392. TEST_F(AppListControllerImplKioskTest,
  1393. DoNotShowHomeLauncherInTabletModeWhenOnSessionStateChangedCalled) {
  1394. EnableTabletMode();
  1395. auto* controller = Shell::Get()->app_list_controller();
  1396. controller->OnSessionStateChanged(session_manager::SessionState::ACTIVE);
  1397. EXPECT_FALSE(controller->ShouldHomeLauncherBeVisible());
  1398. }
  1399. TEST_F(AppListControllerImplKioskTest,
  1400. DoNotMinimizeAppWindowInTabletModeWhenGoHomeCalled) {
  1401. // Emulation of a Kiosk app window.
  1402. std::unique_ptr<aura::Window> w(CreateTestWindow(gfx::Rect(0, 0, 400, 400)));
  1403. EnableTabletMode();
  1404. Shell::Get()->app_list_controller()->GoHome(GetPrimaryDisplay().id());
  1405. EXPECT_FALSE(WindowState::Get(w.get())->IsMinimized());
  1406. EXPECT_TRUE(w->IsVisible());
  1407. }
  1408. TEST_F(AppListControllerImplKioskTest,
  1409. DoNotShowAppListInTabletModeWhenPressHomeButton) {
  1410. // Emulation of a Kiosk app window.
  1411. std::unique_ptr<aura::Window> w(CreateTestWindow(gfx::Rect(0, 0, 400, 400)));
  1412. EnableTabletMode();
  1413. PressHomeButton();
  1414. EXPECT_FALSE(WindowState::Get(w.get())->IsMinimized());
  1415. EXPECT_TRUE(w->IsVisible());
  1416. EXPECT_FALSE(Shell::Get()->app_list_controller()->IsVisible());
  1417. }
  1418. TEST_F(AppListControllerImplKioskTest,
  1419. DoNotOpenAnyAppListAfterSwitchingFromTabletMode) {
  1420. auto* controller = Shell::Get()->app_list_controller();
  1421. EnableTabletMode();
  1422. controller->OnTabletModeStarted();
  1423. EXPECT_FALSE(controller->IsVisible());
  1424. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
  1425. controller->OnTabletModeEnded();
  1426. EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing());
  1427. EXPECT_FALSE(controller->IsVisible());
  1428. }
  1429. // App list assistant tests, parameterized by ProductivityLauncher.
  1430. class AppListControllerWithAssistantTest
  1431. : public AppListControllerImplTest,
  1432. public testing::WithParamInterface<bool> {
  1433. public:
  1434. AppListControllerWithAssistantTest()
  1435. : assistant_test_api_(AssistantTestApi::Create()) {
  1436. feature_list_.InitWithFeatureState(features::kProductivityLauncher,
  1437. GetParam());
  1438. }
  1439. AppListControllerWithAssistantTest(
  1440. const AppListControllerWithAssistantTest&) = delete;
  1441. AppListControllerWithAssistantTest& operator=(
  1442. const AppListControllerWithAssistantTest&) = delete;
  1443. ~AppListControllerWithAssistantTest() override = default;
  1444. // AppListControllerImplTest:
  1445. void SetUp() override {
  1446. AppListControllerImplTest::SetUp();
  1447. assistant_test_api_->SetAssistantEnabled(true);
  1448. assistant_test_api_->GetAssistantState()->NotifyFeatureAllowed(
  1449. assistant::AssistantAllowedState::ALLOWED);
  1450. assistant_test_api_->GetAssistantState()->NotifyStatusChanged(
  1451. assistant::AssistantStatus::READY);
  1452. assistant_test_api_->WaitUntilIdle();
  1453. }
  1454. protected:
  1455. void ToggleAssistantUiWithAccelerator() {
  1456. PressAndReleaseKey(ui::KeyboardCode::VKEY_A, ui::EF_COMMAND_DOWN);
  1457. EXPECT_TRUE(assistant_test_api_->IsVisible());
  1458. }
  1459. AssistantVisibility GetAssistantVisibility() const {
  1460. return AssistantUiController::Get()->GetModel()->visibility();
  1461. }
  1462. std::unique_ptr<AssistantTestApi> assistant_test_api_;
  1463. base::test::ScopedFeatureList feature_list_;
  1464. };
  1465. INSTANTIATE_TEST_SUITE_P(ProductivityLauncher,
  1466. AppListControllerWithAssistantTest,
  1467. testing::Bool());
  1468. // Verifies the scenario that the Assistant shortcut is triggered when the the
  1469. // app list close animation is running.
  1470. TEST_P(AppListControllerWithAssistantTest,
  1471. TriggerAssistantKeyWhenAppListClosing) {
  1472. // Show the Assistant and verify the app list state.
  1473. ToggleAssistantUiWithAccelerator();
  1474. auto* app_list_controller = Shell::Get()->app_list_controller();
  1475. EXPECT_TRUE(app_list_controller->IsVisible());
  1476. EXPECT_TRUE(AssistantUiController::Get()->HasShownOnboarding());
  1477. EXPECT_EQ(AssistantVisibility::kVisible, GetAssistantVisibility());
  1478. assistant_test_api_->input_text_field()->SetText(u"xyz");
  1479. EXPECT_EQ(u"xyz", assistant_test_api_->input_text_field()->GetText());
  1480. {
  1481. // Enable animation with non-zero duration.
  1482. ui::ScopedAnimationDurationScaleMode non_zero_duration(
  1483. ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
  1484. // Press the search key. The launcher starts to close.
  1485. PressAndReleaseKey(ui::KeyboardCode::VKEY_COMMAND);
  1486. EXPECT_EQ(AssistantVisibility::kClosing, GetAssistantVisibility());
  1487. // Toggle the Assistant ui and wait for app list animation to finish.
  1488. if (features::IsProductivityLauncherEnabled()) {
  1489. AppListBubbleView* bubble_view =
  1490. app_list_controller->bubble_presenter_for_test()
  1491. ->bubble_view_for_test();
  1492. ToggleAssistantUiWithAccelerator();
  1493. LayerAnimationStoppedWaiter().Wait(bubble_view->layer());
  1494. } else {
  1495. views::WidgetAnimationWaiter waiter(GetAppListView()->GetWidget());
  1496. ToggleAssistantUiWithAccelerator();
  1497. waiter.WaitForAnimation();
  1498. }
  1499. }
  1500. // Verify that the Assistant ui is visible. In addition, the text in the
  1501. // textfield does not change.
  1502. EXPECT_TRUE(assistant_test_api_->IsVisible());
  1503. EXPECT_EQ(u"xyz", assistant_test_api_->input_text_field()->GetText());
  1504. EXPECT_TRUE(app_list_controller->IsVisible());
  1505. EXPECT_EQ(AssistantVisibility::kVisible, GetAssistantVisibility());
  1506. // Press the search key to close the app list.
  1507. PressAndReleaseKey(ui::KeyboardCode::VKEY_COMMAND);
  1508. EXPECT_FALSE(app_list_controller->IsVisible());
  1509. // Toggle the Assistant ui. The text input field should be cleared.
  1510. ToggleAssistantUiWithAccelerator();
  1511. EXPECT_TRUE(app_list_controller->IsVisible());
  1512. // TODO(jamescook): Decide if we want this behavior for ProductivityLauncher.
  1513. if (!features::IsProductivityLauncherEnabled())
  1514. EXPECT_TRUE(assistant_test_api_->input_text_field()->GetText().empty());
  1515. }
  1516. // Verifies the scenario that the search key is triggered when the the app list
  1517. // close animation is running.
  1518. TEST_P(AppListControllerWithAssistantTest, TriggerSearchKeyWhenAppListClosing) {
  1519. ToggleAssistantUiWithAccelerator();
  1520. auto* app_list_controller = Shell::Get()->app_list_controller();
  1521. EXPECT_TRUE(app_list_controller->IsVisible());
  1522. // Enable animation with non-zero duration.
  1523. ui::ScopedAnimationDurationScaleMode non_zero_duration(
  1524. ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
  1525. // Press the search key to close the app list.
  1526. PressAndReleaseKey(ui::KeyboardCode::VKEY_COMMAND);
  1527. EXPECT_EQ(AssistantVisibility::kClosing, GetAssistantVisibility());
  1528. // Press the search key to reshow the app list.
  1529. if (features::IsProductivityLauncherEnabled()) {
  1530. AppListBubbleView* bubble_view =
  1531. app_list_controller->bubble_presenter_for_test()
  1532. ->bubble_view_for_test();
  1533. PressAndReleaseKey(ui::KeyboardCode::VKEY_COMMAND);
  1534. LayerAnimationStoppedWaiter().Wait(bubble_view->layer());
  1535. } else {
  1536. views::WidgetAnimationWaiter waiter(GetAppListView()->GetWidget());
  1537. PressAndReleaseKey(ui::KeyboardCode::VKEY_COMMAND);
  1538. waiter.WaitForAnimation();
  1539. }
  1540. // The Assistant should be closed.
  1541. EXPECT_EQ(AssistantVisibility::kClosed, GetAssistantVisibility());
  1542. }
  1543. } // namespace ash