1 // Copyright (c) 2020 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 <memory>
6 #include <tuple>
7 #include <vector>
8 
9 #include "ash/app_list/app_list_controller_impl.h"
10 #include "ash/app_list/test/app_list_test_helper.h"
11 #include "ash/assistant/assistant_controller_impl.h"
12 #include "ash/focus_cycler.h"
13 #include "ash/home_screen/drag_window_from_shelf_controller_test_api.h"
14 #include "ash/home_screen/home_screen_controller.h"
15 #include "ash/public/cpp/ash_features.h"
16 #include "ash/public/cpp/assistant/controller/assistant_ui_controller.h"
17 #include "ash/public/cpp/presentation_time_recorder.h"
18 #include "ash/public/cpp/test/assistant_test_api.h"
19 #include "ash/public/cpp/test/shell_test_api.h"
20 #include "ash/shelf/home_button.h"
21 #include "ash/shelf/hotseat_widget.h"
22 #include "ash/shelf/shelf.h"
23 #include "ash/shelf/shelf_app_button.h"
24 #include "ash/shelf/shelf_focus_cycler.h"
25 #include "ash/shelf/shelf_layout_manager.h"
26 #include "ash/shelf/shelf_metrics.h"
27 #include "ash/shelf/shelf_navigation_widget.h"
28 #include "ash/shelf/shelf_test_util.h"
29 #include "ash/shelf/shelf_view.h"
30 #include "ash/shelf/shelf_view_test_api.h"
31 #include "ash/shelf/test/hotseat_state_watcher.h"
32 #include "ash/shelf/test/shelf_layout_manager_test_base.h"
33 #include "ash/shelf/test/widget_animation_smoothness_inspector.h"
34 #include "ash/shelf/test/widget_animation_waiter.h"
35 #include "ash/shell.h"
36 #include "ash/system/overview/overview_button_tray.h"
37 #include "ash/system/status_area_widget.h"
38 #include "ash/system/unified/unified_system_tray.h"
39 #include "ash/test/ash_test_base.h"
40 #include "ash/wm/overview/overview_controller.h"
41 #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
42 #include "ash/wm/window_state.h"
43 #include "ash/wm/wm_event.h"
44 #include "ash/wm/work_area_insets.h"
45 #include "base/test/metrics/histogram_tester.h"
46 #include "base/test/scoped_feature_list.h"
47 #include "chromeos/services/assistant/public/cpp/assistant_service.h"
48 #include "testing/gtest/include/gtest/gtest.h"
49 #include "ui/aura/client/aura_constants.h"
50 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
51 #include "ui/events/gesture_detection/gesture_configuration.h"
52 #include "ui/events/test/event_generator.h"
53 #include "ui/wm/core/window_util.h"
54 
55 namespace ash {
56 
57 namespace {
GetShelfWidget()58 ShelfWidget* GetShelfWidget() {
59   return AshTestBase::GetPrimaryShelf()->shelf_widget();
60 }
61 
GetShelfLayoutManager()62 ShelfLayoutManager* GetShelfLayoutManager() {
63   return AshTestBase::GetPrimaryShelf()->shelf_layout_manager();
64 }
65 }  // namespace
66 
67 class HotseatWidgetTest
68     : public ShelfLayoutManagerTestBase,
69       public testing::WithParamInterface<
70           std::tuple<ShelfAutoHideBehavior,
71                      /*is_assistant_enabled*/ bool,
72                      /*navigation_buttons_shown_in_tablet_mode*/ bool>> {
73  public:
HotseatWidgetTest()74   HotseatWidgetTest()
75       : ShelfLayoutManagerTestBase(
76             base::test::TaskEnvironment::TimeSource::MOCK_TIME),
77         shelf_auto_hide_behavior_(std::get<0>(GetParam())),
78         is_assistant_enabled_(std::get<1>(GetParam())),
79         navigation_buttons_shown_in_tablet_mode_(std::get<2>(GetParam())) {
80     if (is_assistant_enabled_)
81       assistant_test_api_ = AssistantTestApi::Create();
82 
83     std::vector<base::Feature> enabled_features;
84     std::vector<base::Feature> disabled_features;
85 
86     if (navigation_buttons_shown_in_tablet_mode_) {
87       disabled_features.push_back(features::kHideShelfControlsInTabletMode);
88     } else {
89       enabled_features.push_back(features::kHideShelfControlsInTabletMode);
90     }
91     scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
92   }
93 
94   // testing::Test:
SetUp()95   void SetUp() override {
96     ShelfLayoutManagerTestBase::SetUp();
97 
98     if (is_assistant_enabled_) {
99       assistant_test_api_->SetAssistantEnabled(true);
100       assistant_test_api_->GetAssistantState()->NotifyFeatureAllowed(
101           chromeos::assistant::AssistantAllowedState::ALLOWED);
102       assistant_test_api_->GetAssistantState()->NotifyStatusChanged(
103           chromeos::assistant::AssistantStatus::READY);
104 
105       assistant_test_api_->WaitUntilIdle();
106     }
107   }
108 
TearDown()109   void TearDown() override {
110     // Some tests may override this value, make sure it's reset.
111     PresentationTimeRecorder::SetReportPresentationTimeImmediatelyForTest(
112         false);
113     ShelfLayoutManagerTestBase::TearDown();
114   }
115 
shelf_auto_hide_behavior() const116   ShelfAutoHideBehavior shelf_auto_hide_behavior() const {
117     return shelf_auto_hide_behavior_;
118   }
is_assistant_enabled() const119   bool is_assistant_enabled() const { return is_assistant_enabled_; }
assistant_test_api()120   AssistantTestApi* assistant_test_api() { return assistant_test_api_.get(); }
121 
ShowShelfAndActivateAssistant()122   void ShowShelfAndActivateAssistant() {
123     if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways)
124       SwipeUpOnShelf();
125 
126     // If the launcher button is not expected to be shown, show the assistant UI
127     // directly; otherwise, simulate the long press on the home button,
128     if (!navigation_buttons_shown_in_tablet_mode_ &&
129         Shell::Get()->tablet_mode_controller()->InTabletMode()) {
130       AssistantUiController::Get()->ShowUi(
131           chromeos::assistant::AssistantEntryPoint::kLongPressLauncher);
132       return;
133     }
134 
135     views::View* home_button =
136         GetPrimaryShelf()->navigation_widget()->GetHomeButton();
137     auto center_point = home_button->GetBoundsInScreen().CenterPoint();
138 
139     GetEventGenerator()->set_current_screen_location(center_point);
140     GetEventGenerator()->PressTouch();
141     GetAppListTestHelper()->WaitUntilIdle();
142 
143     // Advance clock to make sure long press gesture is triggered.
144     task_environment()->AdvanceClock(base::TimeDelta::FromSeconds(5));
145     GetAppListTestHelper()->WaitUntilIdle();
146 
147     GetEventGenerator()->ReleaseTouch();
148     GetAppListTestHelper()->WaitUntilIdle();
149   }
150 
ShowShelfAndGoHome()151   void ShowShelfAndGoHome() {
152     // If the launcher button is not expected to be shown, go home directly;
153     // otherwise, simulate tap on the home button,
154     if (!navigation_buttons_shown_in_tablet_mode_ &&
155         Shell::Get()->tablet_mode_controller()->InTabletMode()) {
156       Shell::Get()->home_screen_controller()->GoHome(GetPrimaryDisplay().id());
157       return;
158     }
159 
160     // Ensure the shelf, and the home button, are visible.
161     if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways)
162       SwipeUpOnShelf();
163     views::View* home_button =
164         GetPrimaryShelf()->navigation_widget()->GetHomeButton();
165     GetEventGenerator()->GestureTapAt(
166         home_button->GetBoundsInScreen().CenterPoint());
167   }
168 
StartOverview()169   void StartOverview() {
170     ASSERT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
171 
172     // If the overview button is not expected to be shown, start overview
173     // directly; otherwise, simulate tap on the overview button, which should
174     // toggle overview.
175     if (!navigation_buttons_shown_in_tablet_mode_ &&
176         Shell::Get()->tablet_mode_controller()->InTabletMode()) {
177       Shell::Get()->overview_controller()->StartOverview();
178       return;
179     }
180 
181     const gfx::Point overview_button_center = GetPrimaryShelf()
182                                                   ->status_area_widget()
183                                                   ->overview_button_tray()
184                                                   ->GetBoundsInScreen()
185                                                   .CenterPoint();
186     GetEventGenerator()->GestureTapAt(overview_button_center);
187   }
188 
EndOverview()189   void EndOverview() {
190     ASSERT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
191 
192     // If the overview button is not expected to be shown, end overview
193     // directly; otherwise, simulate tap on the overview button, which should
194     // toggle overview.
195     if (!navigation_buttons_shown_in_tablet_mode_ &&
196         Shell::Get()->tablet_mode_controller()->InTabletMode()) {
197       Shell::Get()->overview_controller()->EndOverview();
198       return;
199     }
200 
201     const gfx::Point overview_button_center = GetPrimaryShelf()
202                                                   ->status_area_widget()
203                                                   ->overview_button_tray()
204                                                   ->GetBoundsInScreen()
205                                                   .CenterPoint();
206     GetEventGenerator()->GestureTapAt(overview_button_center);
207   }
208 
209  private:
210   const ShelfAutoHideBehavior shelf_auto_hide_behavior_;
211   const bool is_assistant_enabled_;
212   const bool navigation_buttons_shown_in_tablet_mode_;
213   std::unique_ptr<AssistantTestApi> assistant_test_api_;
214   base::test::ScopedFeatureList scoped_feature_list_;
215 };
216 
217 // Counts the number of times the work area changes.
218 class DisplayWorkAreaChangeCounter : public display::DisplayObserver {
219  public:
DisplayWorkAreaChangeCounter()220   DisplayWorkAreaChangeCounter() {
221     Shell::Get()->display_manager()->AddObserver(this);
222   }
~DisplayWorkAreaChangeCounter()223   ~DisplayWorkAreaChangeCounter() override {
224     Shell::Get()->display_manager()->RemoveObserver(this);
225   }
226 
OnDisplayMetricsChanged(const display::Display & display,uint32_t metrics)227   void OnDisplayMetricsChanged(const display::Display& display,
228                                uint32_t metrics) override {
229     if (metrics & display::DisplayObserver::DISPLAY_METRIC_WORK_AREA)
230       work_area_change_count_++;
231   }
232 
count() const233   int count() const { return work_area_change_count_; }
234 
235  private:
236   int work_area_change_count_ = 0;
237 
238   DISALLOW_COPY_AND_ASSIGN(DisplayWorkAreaChangeCounter);
239 };
240 
241 // Watches the shelf for state changes.
242 class ShelfStateWatcher : public ShelfObserver {
243  public:
ShelfStateWatcher()244   ShelfStateWatcher() { AshTestBase::GetPrimaryShelf()->AddObserver(this); }
~ShelfStateWatcher()245   ~ShelfStateWatcher() override {
246     AshTestBase::GetPrimaryShelf()->RemoveObserver(this);
247   }
WillChangeVisibilityState(ShelfVisibilityState new_state)248   void WillChangeVisibilityState(ShelfVisibilityState new_state) override {
249     state_change_count_++;
250   }
state_change_count() const251   int state_change_count() const { return state_change_count_; }
252 
253  private:
254   int state_change_count_ = 0;
255 };
256 
257 // Watches the Hotseat transition animation states.
258 class HotseatTransitionAnimationObserver
259     : public HotseatTransitionAnimator::Observer {
260  public:
HotseatTransitionAnimationObserver(HotseatTransitionAnimator * hotseat_transition_animator)261   explicit HotseatTransitionAnimationObserver(
262       HotseatTransitionAnimator* hotseat_transition_animator)
263       : hotseat_transition_animator_(hotseat_transition_animator) {
264     hotseat_transition_animator_->AddObserver(this);
265   }
~HotseatTransitionAnimationObserver()266   ~HotseatTransitionAnimationObserver() override {
267     hotseat_transition_animator_->RemoveObserver(this);
268   }
269 
270   // HotseatTransitionAnimtor::Observer:
OnHotseatTransitionAnimationWillStart(HotseatState from_state,HotseatState to_start)271   void OnHotseatTransitionAnimationWillStart(HotseatState from_state,
272                                              HotseatState to_start) override {
273     ++observer_counts_.started;
274   }
OnHotseatTransitionAnimationEnded(HotseatState from_state,HotseatState to_start)275   void OnHotseatTransitionAnimationEnded(HotseatState from_state,
276                                          HotseatState to_start) override {
277     ++observer_counts_.ended;
278     if (run_loop_)
279       run_loop_->Quit();
280   }
OnHotseatTransitionAnimationAborted()281   void OnHotseatTransitionAnimationAborted() override {
282     ++observer_counts_.aborted;
283   }
284 
Wait()285   void Wait() {
286     run_loop_ = std::make_unique<base::RunLoop>();
287     run_loop_->Run();
288   }
289 
Reset()290   void Reset() {
291     if (run_loop_)
292       run_loop_->Quit();
293     observer_counts_ = {0};
294   }
295 
296   // Checks that the started and ending/aborting methods have fired the same
297   // amount of times.
ObserverCountsEqual() const298   bool ObserverCountsEqual() const {
299     return observer_counts_.started ==
300            (observer_counts_.ended + observer_counts_.aborted);
301   }
302 
AnimationAbortedCalls() const303   int AnimationAbortedCalls() const { return observer_counts_.aborted; }
304 
305  private:
306   // Struct which keeps track of the counts of the Observer method has fired.
307   // These are used to verify that started calls = ended calls + aborted calls.
308   struct ObserverCounts {
309     int started;
310     int ended;
311     int aborted;
312   } observer_counts_ = {0};
313   std::unique_ptr<base::RunLoop> run_loop_;
314   HotseatTransitionAnimator* hotseat_transition_animator_;
315 };
316 
317 // Used to test the Hotseat, ScrollabeShelf, and DenseShelf features.
318 INSTANTIATE_TEST_SUITE_P(
319     All,
320     HotseatWidgetTest,
321     testing::Combine(testing::Values(ShelfAutoHideBehavior::kNever,
322                                      ShelfAutoHideBehavior::kAlways),
323                      testing::Bool(),
324                      testing::Bool()));
325 
TEST_P(HotseatWidgetTest,LongPressHomeWithoutAppWindow)326 TEST_P(HotseatWidgetTest, LongPressHomeWithoutAppWindow) {
327   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
328   TabletModeControllerTestApi().EnterTabletMode();
329   GetAppListTestHelper()->CheckVisibility(true);
330 
331   HotseatStateWatcher watcher(GetShelfLayoutManager());
332 
333   ShowShelfAndActivateAssistant();
334   GetAppListTestHelper()->CheckVisibility(true);
335 
336   EXPECT_EQ(
337       is_assistant_enabled(),
338       GetAppListTestHelper()->GetAppListView()->IsShowingEmbeddedAssistantUI());
339 
340   // Hotseat should not change when showing Assistant.
341   watcher.CheckEqual({});
342 }
343 
TEST_P(HotseatWidgetTest,LongPressHomeWithAppWindow)344 TEST_P(HotseatWidgetTest, LongPressHomeWithAppWindow) {
345   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
346   TabletModeControllerTestApi().EnterTabletMode();
347   GetAppListTestHelper()->CheckVisibility(true);
348 
349   std::unique_ptr<aura::Window> window =
350       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
351   wm::ActivateWindow(window.get());
352 
353   GetAppListTestHelper()->CheckVisibility(false);
354 
355   HotseatStateWatcher watcher(GetShelfLayoutManager());
356 
357   ShowShelfAndActivateAssistant();
358   GetAppListTestHelper()->CheckVisibility(false);
359 
360   EXPECT_EQ(
361       is_assistant_enabled(),
362       GetAppListTestHelper()->GetAppListView()->IsShowingEmbeddedAssistantUI());
363 
364   std::vector<HotseatState> expected_state;
365   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways) {
366     // |ShowShelfAndActivateAssistant()| will bring up shelf so it will trigger
367     // one hotseat state change.
368     expected_state.push_back(HotseatState::kExtended);
369   }
370   watcher.CheckEqual(expected_state);
371 }
372 
373 // Tests that closing a window which was opened prior to entering tablet mode
374 // results in a kShownHomeLauncher hotseat.
TEST_P(HotseatWidgetTest,ClosingLastWindowInTabletMode)375 TEST_P(HotseatWidgetTest, ClosingLastWindowInTabletMode) {
376   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
377   std::unique_ptr<aura::Window> window =
378       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
379   // Activate the window and go to tablet mode.
380   wm::ActivateWindow(window.get());
381   TabletModeControllerTestApi().EnterTabletMode();
382 
383   // Close the window, the AppListView should be shown, and the hotseat should
384   // be kShownHomeLauncher.
385   window->Hide();
386 
387   EXPECT_EQ(HotseatState::kShownHomeLauncher,
388             GetShelfLayoutManager()->hotseat_state());
389   GetAppListTestHelper()->CheckVisibility(true);
390 }
391 
392 // Tests that the hotseat is kShownHomeLauncher when entering tablet mode with
393 // no windows.
TEST_P(HotseatWidgetTest,GoingToTabletModeNoWindows)394 TEST_P(HotseatWidgetTest, GoingToTabletModeNoWindows) {
395   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
396   TabletModeControllerTestApi().EnterTabletMode();
397 
398   GetAppListTestHelper()->CheckVisibility(true);
399   EXPECT_EQ(HotseatState::kShownHomeLauncher,
400             GetShelfLayoutManager()->hotseat_state());
401 }
402 
403 // Tests that the hotseat is kHidden when entering tablet mode with a window.
TEST_P(HotseatWidgetTest,GoingToTabletModeWithWindows)404 TEST_P(HotseatWidgetTest, GoingToTabletModeWithWindows) {
405   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
406 
407   std::unique_ptr<aura::Window> window =
408       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
409   // Activate the window and go to tablet mode.
410   wm::ActivateWindow(window.get());
411   TabletModeControllerTestApi().EnterTabletMode();
412 
413   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
414   GetAppListTestHelper()->CheckVisibility(false);
415 }
416 
417 // The in-app Hotseat should not be hidden automatically when the shelf context
418 // menu shows (https://crbug.com/1020388).
TEST_P(HotseatWidgetTest,InAppShelfShowingContextMenu)419 TEST_P(HotseatWidgetTest, InAppShelfShowingContextMenu) {
420   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
421   TabletModeControllerTestApi().EnterTabletMode();
422   std::unique_ptr<aura::Window> window =
423       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
424   wm::ActivateWindow(window.get());
425   EXPECT_FALSE(Shell::Get()->app_list_controller()->IsVisible(
426       display::Screen::GetScreen()->GetPrimaryDisplay().id()));
427 
428   ShelfTestUtil::AddAppShortcut("app_id", TYPE_PINNED_APP);
429 
430   // Swipe up on the shelf to show the hotseat.
431   SwipeUpOnShelf();
432   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
433 
434   ShelfViewTestAPI shelf_view_test_api(
435       GetPrimaryShelf()->shelf_widget()->shelf_view_for_testing());
436   ShelfAppButton* app_icon = shelf_view_test_api.GetButton(0);
437 
438   // Accelerate the generation of the long press event.
439   ui::GestureConfiguration::GetInstance()->set_show_press_delay_in_ms(1);
440   ui::GestureConfiguration::GetInstance()->set_long_press_time_in_ms(1);
441 
442   // Press the icon enough long time to generate the long press event.
443   GetEventGenerator()->MoveTouch(app_icon->GetBoundsInScreen().CenterPoint());
444   GetEventGenerator()->PressTouch();
445   ui::GestureConfiguration* gesture_config =
446       ui::GestureConfiguration::GetInstance();
447   const int long_press_delay_ms = gesture_config->long_press_time_in_ms() +
448                                   gesture_config->show_press_delay_in_ms();
449   base::RunLoop run_loop;
450   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
451       FROM_HERE, run_loop.QuitClosure(),
452       base::TimeDelta::FromMilliseconds(long_press_delay_ms));
453   run_loop.Run();
454   GetEventGenerator()->ReleaseTouch();
455 
456   // Expects that the hotseat's state is kExntended.
457   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
458 
459   // Ensures that the ink drop state is InkDropState::ACTIVATED before closing
460   // the menu.
461   app_icon->FireRippleActivationTimerForTest();
462 }
463 
464 // Tests that a window that is created after going to tablet mode, then closed,
465 // results in a kShownHomeLauncher hotseat.
TEST_P(HotseatWidgetTest,CloseLastWindowOpenedInTabletMode)466 TEST_P(HotseatWidgetTest, CloseLastWindowOpenedInTabletMode) {
467   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
468   TabletModeControllerTestApi().EnterTabletMode();
469 
470   std::unique_ptr<aura::Window> window =
471       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
472   // Activate the window after entering tablet mode.
473   wm::ActivateWindow(window.get());
474 
475   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
476   GetAppListTestHelper()->CheckVisibility(false);
477 
478   // Hide the window, the hotseat should be kShownHomeLauncher, and the home
479   // launcher should be visible.
480   window->Hide();
481 
482   EXPECT_EQ(HotseatState::kShownHomeLauncher,
483             GetShelfLayoutManager()->hotseat_state());
484   GetAppListTestHelper()->CheckVisibility(true);
485 }
486 
487 // Tests that swiping up on an autohidden shelf shows the hotseat, and swiping
488 // down hides it.
TEST_P(HotseatWidgetTest,ShowingAndHidingAutohiddenShelf)489 TEST_P(HotseatWidgetTest, ShowingAndHidingAutohiddenShelf) {
490   if (shelf_auto_hide_behavior() != ShelfAutoHideBehavior::kAlways)
491     return;
492 
493   GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
494   TabletModeControllerTestApi().EnterTabletMode();
495   std::unique_ptr<aura::Window> window =
496       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
497   wm::ActivateWindow(window.get());
498 
499   SwipeUpOnShelf();
500 
501   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
502   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
503 
504   SwipeDownOnShelf();
505 
506   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
507   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, GetPrimaryShelf()->GetAutoHideState());
508 
509   // Swipe down again, nothing should change.
510   SwipeDownOnShelf();
511 
512   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
513   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, GetPrimaryShelf()->GetAutoHideState());
514 }
515 
516 // Tests that swiping up on several places in the in-app shelf shows the
517 // hotseat (crbug.com/1016931).
TEST_P(HotseatWidgetTest,SwipeUpInAppShelfShowsHotseat)518 TEST_P(HotseatWidgetTest, SwipeUpInAppShelfShowsHotseat) {
519   TabletModeControllerTestApi().EnterTabletMode();
520   std::unique_ptr<aura::Window> window =
521       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
522   wm::ActivateWindow(window.get());
523 
524   base::HistogramTester histogram_tester;
525   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
526                                      InAppShelfGestures::kSwipeDownToHide, 0);
527   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
528                                      InAppShelfGestures::kSwipeUpToShow, 0);
529 
530   // Swipe up from the center of the shelf.
531   SwipeUpOnShelf();
532   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
533   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
534                                      InAppShelfGestures::kSwipeDownToHide, 0);
535   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
536                                      InAppShelfGestures::kSwipeUpToShow, 1);
537 
538   // Swipe down from the hotseat to hide it.
539   gfx::Rect hotseat_bounds =
540       GetPrimaryShelf()->hotseat_widget()->GetWindowBoundsInScreen();
541   gfx::Point start = hotseat_bounds.top_center();
542   gfx::Point end = start + gfx::Vector2d(0, 80);
543   const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(100);
544   const int kNumScrollSteps = 4;
545 
546   GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
547                                              kNumScrollSteps);
548   ASSERT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
549 
550   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
551                                      InAppShelfGestures::kSwipeDownToHide, 1);
552   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
553                                      InAppShelfGestures::kSwipeUpToShow, 1);
554 
555   // Swipe up from the right part of the shelf (the system tray).
556   start = GetShelfWidget()
557               ->status_area_widget()
558               ->GetWindowBoundsInScreen()
559               .CenterPoint();
560   end = start + gfx::Vector2d(0, -80);
561 
562   GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
563                                              kNumScrollSteps);
564   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
565 
566   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
567                                      InAppShelfGestures::kSwipeDownToHide, 1);
568   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
569                                      InAppShelfGestures::kSwipeUpToShow, 2);
570 
571   // Swipe down from the hotseat to hide it.
572   start = hotseat_bounds.top_center();
573   end = start + gfx::Vector2d(0, 80);
574 
575   GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
576                                              kNumScrollSteps);
577   ASSERT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
578 
579   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
580                                      InAppShelfGestures::kSwipeDownToHide, 2);
581   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
582                                      InAppShelfGestures::kSwipeUpToShow, 2);
583 
584   // Swipe up from the left part of the shelf (the home/back button).
585   start = GetShelfWidget()
586               ->navigation_widget()
587               ->GetWindowBoundsInScreen()
588               .CenterPoint();
589   end = start + gfx::Vector2d(0, -80);
590 
591   GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
592                                              kNumScrollSteps);
593   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
594 
595   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
596                                      InAppShelfGestures::kSwipeDownToHide, 2);
597   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
598                                      InAppShelfGestures::kSwipeUpToShow, 3);
599 }
600 
601 // Tests that swiping up on the hotseat does nothing.
TEST_P(HotseatWidgetTest,SwipeUpOnHotseatBackgroundDoesNothing)602 TEST_P(HotseatWidgetTest, SwipeUpOnHotseatBackgroundDoesNothing) {
603   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
604   TabletModeControllerTestApi().EnterTabletMode();
605   std::unique_ptr<aura::Window> window =
606       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
607   wm::ActivateWindow(window.get());
608 
609   base::HistogramTester histogram_tester;
610   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
611                                      InAppShelfGestures::kSwipeDownToHide, 0);
612   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
613                                      InAppShelfGestures::kSwipeUpToShow, 0);
614 
615   // Swipe up on the shelf to show the hotseat.
616   EXPECT_FALSE(Shell::Get()->app_list_controller()->IsVisible(
617       display::Screen::GetScreen()->GetPrimaryDisplay().id()));
618 
619   SwipeUpOnShelf();
620 
621   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
622   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
623                                      InAppShelfGestures::kSwipeDownToHide, 0);
624   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
625                                      InAppShelfGestures::kSwipeUpToShow, 1);
626   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways)
627     EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
628 
629   // Swipe up on the Hotseat (parent of ShelfView) does nothing.
630   gfx::Point start(GetPrimaryShelf()
631                        ->shelf_widget()
632                        ->hotseat_widget()
633                        ->GetWindowBoundsInScreen()
634                        .top_center());
635   const gfx::Point end(start + gfx::Vector2d(0, -300));
636   const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(100);
637   const int kNumScrollSteps = 4;
638   GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
639                                              kNumScrollSteps);
640 
641   EXPECT_FALSE(Shell::Get()->app_list_controller()->IsVisible(
642       display::Screen::GetScreen()->GetPrimaryDisplay().id()));
643   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
644   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways)
645     EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
646   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
647                                      InAppShelfGestures::kSwipeDownToHide, 0);
648   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
649                                      InAppShelfGestures::kSwipeUpToShow, 1);
650 }
651 
652 // Tests that tapping an active window with an extended hotseat results in a
653 // hidden hotseat.
TEST_P(HotseatWidgetTest,TappingActiveWindowHidesHotseat)654 TEST_P(HotseatWidgetTest, TappingActiveWindowHidesHotseat) {
655   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
656   TabletModeControllerTestApi().EnterTabletMode();
657   std::unique_ptr<aura::Window> window =
658       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
659   wm::ActivateWindow(window.get());
660 
661   base::HistogramTester histogram_tester;
662   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
663                                      InAppShelfGestures::kSwipeDownToHide, 0);
664   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
665                                      InAppShelfGestures::kSwipeUpToShow, 0);
666   histogram_tester.ExpectBucketCount(
667       kHotseatGestureHistogramName,
668       InAppShelfGestures::kHotseatHiddenDueToInteractionOutsideOfShelf, 0);
669 
670   // Swipe up on the shelf to show the hotseat.
671   SwipeUpOnShelf();
672 
673   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
674                                      InAppShelfGestures::kSwipeDownToHide, 0);
675   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
676                                      InAppShelfGestures::kSwipeUpToShow, 1);
677   histogram_tester.ExpectBucketCount(
678       kHotseatGestureHistogramName,
679       InAppShelfGestures::kHotseatHiddenDueToInteractionOutsideOfShelf, 0);
680 
681   // Tap the shelf background, nothing should happen.
682   gfx::Rect display_bounds =
683       display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
684   gfx::Point tap_point = display_bounds.bottom_center();
685   GetEventGenerator()->GestureTapAt(tap_point);
686 
687   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
688   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways)
689     EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
690 
691   // Tap the active window, the hotseat should hide.
692   tap_point.Offset(0, -200);
693   GetEventGenerator()->GestureTapAt(tap_point);
694 
695   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
696   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways)
697     EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, GetPrimaryShelf()->GetAutoHideState());
698 
699   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
700                                      InAppShelfGestures::kSwipeDownToHide, 0);
701   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
702                                      InAppShelfGestures::kSwipeUpToShow, 1);
703   histogram_tester.ExpectBucketCount(
704       kHotseatGestureHistogramName,
705       InAppShelfGestures::kHotseatHiddenDueToInteractionOutsideOfShelf, 1);
706 }
707 
708 // Tests that gesture dragging an active window hides the hotseat.
TEST_P(HotseatWidgetTest,GestureDraggingActiveWindowHidesHotseat)709 TEST_P(HotseatWidgetTest, GestureDraggingActiveWindowHidesHotseat) {
710   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
711   TabletModeControllerTestApi().EnterTabletMode();
712   std::unique_ptr<aura::Window> window =
713       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
714   wm::ActivateWindow(window.get());
715 
716   base::HistogramTester histogram_tester;
717   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
718                                      InAppShelfGestures::kSwipeDownToHide, 0);
719   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
720                                      InAppShelfGestures::kSwipeUpToShow, 0);
721 
722   // Swipe up on the shelf to show the hotseat.
723   SwipeUpOnShelf();
724 
725   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
726                                      InAppShelfGestures::kSwipeDownToHide, 0);
727   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
728                                      InAppShelfGestures::kSwipeUpToShow, 1);
729 
730   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways)
731     EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
732 
733   // Gesture drag on the active window, the hotseat should hide.
734   gfx::Rect display_bounds =
735       display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
736   gfx::Point start = display_bounds.bottom_center();
737   start.Offset(0, -200);
738   gfx::Point end = start;
739   end.Offset(0, -200);
740   GetEventGenerator()->GestureScrollSequence(
741       start, end, base::TimeDelta::FromMilliseconds(10), 4);
742 
743   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
744   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways)
745     EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, GetPrimaryShelf()->GetAutoHideState());
746 
747   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
748                                      InAppShelfGestures::kSwipeDownToHide, 0);
749   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
750                                      InAppShelfGestures::kSwipeUpToShow, 1);
751 }
752 
753 // Tests that a swipe up on the shelf shows the hotseat while in split view.
TEST_P(HotseatWidgetTest,SwipeUpOnShelfShowsHotseatInSplitView)754 TEST_P(HotseatWidgetTest, SwipeUpOnShelfShowsHotseatInSplitView) {
755   TabletModeControllerTestApi().EnterTabletMode();
756   std::unique_ptr<aura::Window> window =
757       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
758   wm::ActivateWindow(window.get());
759 
760   base::HistogramTester histogram_tester;
761   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
762                                      InAppShelfGestures::kSwipeDownToHide, 0);
763   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
764                                      InAppShelfGestures::kSwipeUpToShow, 0);
765 
766   // Go into split view mode by first going into overview, and then snapping
767   // the open window on one side.
768   OverviewController* overview_controller = Shell::Get()->overview_controller();
769   overview_controller->StartOverview();
770   SplitViewController* split_view_controller =
771       SplitViewController::Get(Shell::GetPrimaryRootWindow());
772   split_view_controller->SnapWindow(window.get(), SplitViewController::LEFT);
773   EXPECT_TRUE(split_view_controller->InSplitViewMode());
774 
775   // We should still be able to drag up the hotseat.
776   SwipeUpOnShelf();
777   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
778   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
779                                      InAppShelfGestures::kSwipeDownToHide, 0);
780   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
781                                      InAppShelfGestures::kSwipeUpToShow, 1);
782 }
783 
784 // Tests that HotseatTransitionAimationObserver starting and ending calls have a
785 // 1:1 relation. This test verifies that behavior.
TEST_P(HotseatWidgetTest,ObserverCallsMatch)786 TEST_P(HotseatWidgetTest, ObserverCallsMatch) {
787   ui::ScopedAnimationDurationScaleMode non_zero(
788       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
789   // Enter tablet mode to show the home launcher. Hotseat state should be
790   // kShownHomeLauncher.
791   TabletModeControllerTestApi().EnterTabletMode();
792   ASSERT_EQ(HotseatState::kShownHomeLauncher,
793             GetShelfLayoutManager()->hotseat_state());
794 
795   // Create a window to transition to the in-app shelf. Hotseat state should be
796   // kHidden.
797   HotseatTransitionAnimationObserver observer(
798       GetPrimaryShelf()->shelf_widget()->hotseat_transition_animator());
799   std::unique_ptr<aura::Window> window =
800       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 800, 800));
801   observer.Wait();
802   EXPECT_TRUE(observer.ObserverCountsEqual());
803   ASSERT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
804 
805   observer.Reset();
806   // Go to home launcher again. Hotseat state should be kShownHomeLauncher.
807   ShowShelfAndGoHome();
808   observer.Wait();
809   EXPECT_TRUE(observer.ObserverCountsEqual());
810   ASSERT_EQ(HotseatState::kShownHomeLauncher,
811             GetShelfLayoutManager()->hotseat_state());
812 
813   observer.Reset();
814   // Go to overview and cancel immediately. Hotseat state should be
815   // kShownHomeLauncher.
816   StartOverview();
817   EXPECT_TRUE(Shell::Get()->overview_controller()->IsInStartAnimation());
818   // No animations should have been started so no animations are in progress
819   // or aborted.
820   EXPECT_TRUE(observer.ObserverCountsEqual());
821   EXPECT_EQ(0, observer.AnimationAbortedCalls());
822 
823   EndOverview();
824 
825   // No animations should have been started or aborted.
826   EXPECT_EQ(0, observer.AnimationAbortedCalls());
827   EXPECT_TRUE(observer.ObserverCountsEqual());
828   ASSERT_EQ(HotseatState::kShownHomeLauncher,
829             GetShelfLayoutManager()->hotseat_state());
830 
831   observer.Reset();
832   // Go to overview. Hotseat state should be kExtended.
833   StartOverview();
834 
835   ASSERT_EQ(HotseatState::kShownHomeLauncher,
836             GetShelfLayoutManager()->hotseat_state());
837   EXPECT_TRUE(observer.ObserverCountsEqual());
838 }
839 
840 // Tests that a swipe up on the shelf shows the hotseat while in split view.
TEST_P(HotseatWidgetTest,DisableBlurDuringOverviewMode)841 TEST_P(HotseatWidgetTest, DisableBlurDuringOverviewMode) {
842   TabletModeControllerTestApi().EnterTabletMode();
843 
844   ASSERT_EQ(
845       ShelfConfig::Get()->shelf_blur_radius(),
846       GetShelfWidget()->hotseat_widget()->GetHotseatBackgroundBlurForTest());
847 
848   // Go into overview and check that at the end of the animation, background
849   // blur is disabled.
850   StartOverview();
851   WaitForOverviewAnimation(/*enter=*/true);
852   EXPECT_EQ(
853       0, GetShelfWidget()->hotseat_widget()->GetHotseatBackgroundBlurForTest());
854 
855   // Exit overview and check that at the end of the animation, background
856   // blur is enabled again.
857   EndOverview();
858   WaitForOverviewAnimation(/*enter=*/false);
859   EXPECT_EQ(
860       ShelfConfig::Get()->shelf_blur_radius(),
861       GetShelfWidget()->hotseat_widget()->GetHotseatBackgroundBlurForTest());
862 }
863 
864 // Tests that releasing the hotseat gesture below the threshold results in a
865 // kHidden hotseat when the shelf is shown.
TEST_P(HotseatWidgetTest,ReleasingSlowDragBelowThreshold)866 TEST_P(HotseatWidgetTest, ReleasingSlowDragBelowThreshold) {
867   GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kNever);
868   TabletModeControllerTestApi().EnterTabletMode();
869   std::unique_ptr<aura::Window> window =
870       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
871   wm::ActivateWindow(window.get());
872 
873   base::HistogramTester histogram_tester;
874   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
875                                      InAppShelfGestures::kSwipeDownToHide, 0);
876   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
877                                      InAppShelfGestures::kSwipeUpToShow, 0);
878 
879   gfx::Rect display_bounds =
880       display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
881   const gfx::Point start(display_bounds.bottom_center());
882   const int hotseat_size = GetPrimaryShelf()
883                                ->shelf_widget()
884                                ->hotseat_widget()
885                                ->GetWindowBoundsInScreen()
886                                .height();
887   const gfx::Point end(start + gfx::Vector2d(0, -hotseat_size / 2 + 1));
888   const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(1000);
889   const int kNumScrollSteps = 4;
890   GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
891                                              kNumScrollSteps);
892 
893   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
894   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
895                                      InAppShelfGestures::kSwipeDownToHide, 0);
896   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
897                                      InAppShelfGestures::kSwipeUpToShow, 0);
898 }
899 
900 // Tests that releasing the hotseat gesture above the threshold results in a
901 // kExtended hotseat.
TEST_P(HotseatWidgetTest,ReleasingSlowDragAboveThreshold)902 TEST_P(HotseatWidgetTest, ReleasingSlowDragAboveThreshold) {
903   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
904   TabletModeControllerTestApi().EnterTabletMode();
905   std::unique_ptr<aura::Window> window =
906       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
907   wm::ActivateWindow(window.get());
908 
909   base::HistogramTester histogram_tester;
910   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
911                                      InAppShelfGestures::kSwipeDownToHide, 0);
912   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
913                                      InAppShelfGestures::kSwipeUpToShow, 0);
914 
915   gfx::Rect display_bounds =
916       display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
917   const gfx::Point start(display_bounds.bottom_center());
918   const int hotseat_size = GetPrimaryShelf()
919                                ->shelf_widget()
920                                ->hotseat_widget()
921                                ->GetWindowBoundsInScreen()
922                                .height();
923   const gfx::Point end(start + gfx::Vector2d(0, -hotseat_size * 3.0f / 2.0f));
924   const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(1000);
925   const int kNumScrollSteps = 4;
926   GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
927                                              kNumScrollSteps);
928 
929   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
930   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways)
931     EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
932   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
933                                      InAppShelfGestures::kSwipeDownToHide, 0);
934   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
935                                      InAppShelfGestures::kSwipeUpToShow, 1);
936 }
937 
938 // Tests that showing overview after showing the hotseat results in only one
939 // animation, to |kExtended|.
TEST_P(HotseatWidgetTest,ShowingOverviewFromShownAnimatesOnce)940 TEST_P(HotseatWidgetTest, ShowingOverviewFromShownAnimatesOnce) {
941   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
942   TabletModeControllerTestApi().EnterTabletMode();
943   std::unique_ptr<aura::Window> window =
944       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
945   wm::ActivateWindow(window.get());
946 
947   std::unique_ptr<HotseatStateWatcher> state_watcher_ =
948       std::make_unique<HotseatStateWatcher>(GetShelfLayoutManager());
949   SwipeUpOnShelf();
950   ASSERT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
951 
952   StartOverview();
953   state_watcher_->CheckEqual({HotseatState::kExtended});
954 }
955 
956 // Tests that the hotseat is not flush with the bottom of the screen when home
957 // launcher is showing.
TEST_P(HotseatWidgetTest,HotseatNotFlushWhenHomeLauncherShowing)958 TEST_P(HotseatWidgetTest, HotseatNotFlushWhenHomeLauncherShowing) {
959   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
960   TabletModeControllerTestApi().EnterTabletMode();
961   const int display_height =
962       display::Screen::GetScreen()->GetPrimaryDisplay().bounds().height();
963   const int hotseat_bottom = GetPrimaryShelf()
964                                  ->shelf_widget()
965                                  ->hotseat_widget()
966                                  ->GetWindowBoundsInScreen()
967                                  .bottom();
968   EXPECT_LT(hotseat_bottom, display_height);
969 }
970 
971 // Tests that home -> overview results in only one hotseat state change.
TEST_P(HotseatWidgetTest,HomeToOverviewChangesStateOnce)972 TEST_P(HotseatWidgetTest, HomeToOverviewChangesStateOnce) {
973   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
974   TabletModeControllerTestApi().EnterTabletMode();
975 
976   // First, try with no windows open.
977   {
978     HotseatStateWatcher watcher(GetShelfLayoutManager());
979     StartOverview();
980     WaitForOverviewAnimation(/*enter=*/true);
981     watcher.CheckEqual({/* shelf state should not change*/});
982   }
983 
984   // Open a window, then open the home launcher.
985   std::unique_ptr<aura::Window> window =
986       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
987   wm::ActivateWindow(window.get());
988   ShowShelfAndGoHome();
989   GetAppListTestHelper()->CheckVisibility(true);
990 
991   // Activate overview and expect the hotseat only changes state to extended.
992   {
993     HotseatStateWatcher watcher(GetShelfLayoutManager());
994     StartOverview();
995     WaitForOverviewAnimation(/*enter=*/true);
996 
997     watcher.CheckEqual({/* shelf state should not change*/});
998   }
999 }
1000 
1001 // Verifies that the hotseat widget and the status area widget are animated to
1002 // the target location when entering overview mode in home launcher
1003 // (https://crbug.com/1079347).
TEST_P(HotseatWidgetTest,VerifyShelfAnimationWhenEnteringOverview)1004 TEST_P(HotseatWidgetTest, VerifyShelfAnimationWhenEnteringOverview) {
1005   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
1006   TabletModeControllerTestApi().EnterTabletMode();
1007 
1008   ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
1009       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1010 
1011   HotseatWidget* hotseat_widget = GetPrimaryShelf()->hotseat_widget();
1012   ASSERT_EQ(HotseatState::kShownHomeLauncher, hotseat_widget->state());
1013 
1014   ui::LayerAnimator* hotseat_layer_animator =
1015       hotseat_widget->GetNativeView()->layer()->GetAnimator();
1016   ui::LayerAnimator* status_area_layer_animator = GetShelfWidget()
1017                                                       ->status_area_widget()
1018                                                       ->GetNativeView()
1019                                                       ->layer()
1020                                                       ->GetAnimator();
1021   ASSERT_FALSE(hotseat_layer_animator->is_animating());
1022   ASSERT_FALSE(status_area_layer_animator->is_animating());
1023 
1024   StartOverview();
1025   EXPECT_FALSE(hotseat_layer_animator->is_animating());
1026   EXPECT_FALSE(status_area_layer_animator->is_animating());
1027   ASSERT_EQ(HotseatState::kShownHomeLauncher, hotseat_widget->state());
1028 }
1029 
1030 // Tests that home -> in-app results in only one state change.
TEST_P(HotseatWidgetTest,HomeToInAppChangesStateOnce)1031 TEST_P(HotseatWidgetTest, HomeToInAppChangesStateOnce) {
1032   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
1033   TabletModeControllerTestApi().EnterTabletMode();
1034 
1035   // Go to in-app, the hotseat should hide.
1036   HotseatStateWatcher watcher(GetShelfLayoutManager());
1037   std::unique_ptr<aura::Window> window =
1038       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1039   wm::ActivateWindow(window.get());
1040 
1041   watcher.CheckEqual({HotseatState::kHidden});
1042 }
1043 
1044 // Tests that in-app -> home via closing the only window, swiping from the
1045 // bottom of the shelf, and tapping the home launcher button results in only one
1046 // state change.
TEST_P(HotseatWidgetTest,InAppToHomeChangesStateOnce)1047 TEST_P(HotseatWidgetTest, InAppToHomeChangesStateOnce) {
1048   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
1049   TabletModeControllerTestApi().EnterTabletMode();
1050 
1051   // Go to in-app with an extended hotseat.
1052   std::unique_ptr<aura::Window> window =
1053       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1054   wm::ActivateWindow(window.get());
1055   SwipeUpOnShelf();
1056 
1057   // Press the home button, the hotseat should transition directly to
1058   // kShownHomeLauncher.
1059   {
1060     HotseatStateWatcher watcher(GetShelfLayoutManager());
1061     ShowShelfAndGoHome();
1062     watcher.CheckEqual({HotseatState::kShownHomeLauncher});
1063   }
1064   // Go to in-app.
1065   window->Show();
1066   wm::ActivateWindow(window.get());
1067 
1068   // Extend the hotseat, then Swipe up to go home, the hotseat should transition
1069   // directly to kShownHomeLauncher.
1070   SwipeUpOnShelf();
1071   {
1072     ui::ScopedAnimationDurationScaleMode regular_animations(
1073         ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1074     HotseatStateWatcher watcher(GetShelfLayoutManager());
1075     FlingUpOnShelf();
1076     watcher.CheckEqual({HotseatState::kShownHomeLauncher});
1077 
1078     // Wait for the window animation to complete, and verify the hotseat state
1079     // remained kShownHomeLauncher.
1080     ShellTestApi().WaitForWindowFinishAnimating(window.get());
1081     watcher.CheckEqual({HotseatState::kShownHomeLauncher});
1082   }
1083 
1084   // Nothing left to test for autohidden shelf.
1085   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways)
1086     return;
1087 
1088   // Go to in-app and do not extend the hotseat.
1089   window->Show();
1090   wm::ActivateWindow(window.get());
1091 
1092   // TODO(manucornet): This is flaky when the shelf is always auto-hidden.
1093   // Investigate and fix (sometimes fails when the assistant is enabled,
1094   // sometimes not).
1095   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kNever)
1096     return;
1097 
1098   // Press the home button, the hotseat should transition directly to
1099   // kShownHomeLauncher.
1100   {
1101     HotseatStateWatcher watcher(GetShelfLayoutManager());
1102     ShowShelfAndGoHome();
1103     watcher.CheckEqual({HotseatState::kShownHomeLauncher});
1104   }
1105 }
1106 
1107 // Tests that transitioning from overview to home while a transition from home
1108 // to overview is still in progress ends up with hotseat in kShownHomeLauncher
1109 // state (and in app shelf not visible).
TEST_P(HotseatWidgetTest,HomeToOverviewAndBack)1110 TEST_P(HotseatWidgetTest, HomeToOverviewAndBack) {
1111   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
1112   TabletModeControllerTestApi().EnterTabletMode();
1113 
1114   std::unique_ptr<aura::Window> window =
1115       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1116   WindowState::Get(window.get())->Minimize();
1117 
1118   HotseatStateWatcher watcher(GetShelfLayoutManager());
1119 
1120   // Start going to overview.
1121   {
1122     ui::ScopedAnimationDurationScaleMode regular_animations(
1123         ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1124     StartOverview();
1125 
1126     watcher.CheckEqual({/*Hotseat state should not change*/});
1127   }
1128 
1129   OverviewController* overview_controller = Shell::Get()->overview_controller();
1130   EXPECT_TRUE(overview_controller->InOverviewSession());
1131 
1132   ShowShelfAndGoHome();
1133 
1134   GetAppListTestHelper()->CheckVisibility(true);
1135   EXPECT_FALSE(overview_controller->InOverviewSession());
1136   EXPECT_FALSE(ShelfConfig::Get()->is_in_app());
1137 
1138   watcher.CheckEqual({/*Hotseat state should not change*/});
1139 }
1140 
TEST_P(HotseatWidgetTest,InAppToOverviewAndBack)1141 TEST_P(HotseatWidgetTest, InAppToOverviewAndBack) {
1142   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
1143   TabletModeControllerTestApi().EnterTabletMode();
1144 
1145   std::unique_ptr<aura::Window> window =
1146       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1147   wm::ActivateWindow(window.get());
1148 
1149   // Start watching hotseat state before swipping up the shelf, so hotseat
1150   // change expectation match for both auto-hidden and always-shown shelf.
1151   HotseatStateWatcher watcher(GetShelfLayoutManager());
1152 
1153   // Make sure shelf (and overview button) are visible - this is moves the
1154   // hotseat into kExtended state.
1155   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways)
1156     SwipeUpOnShelf();
1157 
1158   // Start going to overview - use non zero animation so transition is not
1159   // immediate.
1160   {
1161     ui::ScopedAnimationDurationScaleMode regular_animations(
1162         ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1163     StartOverview();
1164   }
1165 
1166   OverviewController* overview_controller = Shell::Get()->overview_controller();
1167   EXPECT_TRUE(overview_controller->InOverviewSession());
1168   GetAppListTestHelper()->CheckVisibility(false);
1169 
1170   // Hotseat should be extended as overview is starting.
1171   watcher.CheckEqual({HotseatState::kExtended});
1172 
1173   // Exit overview to go back to the app window.
1174   EndOverview();
1175   EXPECT_FALSE(overview_controller->InOverviewSession());
1176   EXPECT_TRUE(ShelfConfig::Get()->is_in_app());
1177 
1178   // The hotseat is expected to be hidden.
1179   watcher.CheckEqual({HotseatState::kExtended, HotseatState::kHidden});
1180 }
1181 
1182 // Tests transition to home screen initiated while transition from app window to
1183 // overview is in progress.
TEST_P(HotseatWidgetTest,ShowShelfAndGoHomeDuringInAppToOverviewTransition)1184 TEST_P(HotseatWidgetTest, ShowShelfAndGoHomeDuringInAppToOverviewTransition) {
1185   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
1186   TabletModeControllerTestApi().EnterTabletMode();
1187 
1188   std::unique_ptr<aura::Window> window =
1189       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1190   wm::ActivateWindow(window.get());
1191 
1192   // Start watching hotseat state before swipping up the shelf, so hotseat
1193   // change expectation match for both auto-hidden and always-shown shelf.
1194   HotseatStateWatcher watcher(GetShelfLayoutManager());
1195 
1196   // Make sure shelf (and overview button) are visible - this is moves the
1197   // hotseat into kExtended state.
1198   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways)
1199     SwipeUpOnShelf();
1200 
1201   // Start going to overview - use non zero animation so transition is not
1202   // immediate.
1203   {
1204     ui::ScopedAnimationDurationScaleMode regular_animations(
1205         ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1206     StartOverview();
1207   }
1208 
1209   OverviewController* overview_controller = Shell::Get()->overview_controller();
1210   EXPECT_TRUE(overview_controller->InOverviewSession());
1211   GetAppListTestHelper()->CheckVisibility(false);
1212 
1213   // Hotseat should be extended as overview is starting.
1214   watcher.CheckEqual({HotseatState::kExtended});
1215 
1216   // Go home - expect transition to home (with hotseat in kShownHomeLauncher
1217   // state, and in app shelf hidden).
1218   ShowShelfAndGoHome();
1219 
1220   GetAppListTestHelper()->CheckVisibility(true);
1221   EXPECT_FALSE(overview_controller->InOverviewSession());
1222   EXPECT_FALSE(ShelfConfig::Get()->is_in_app());
1223 
1224   watcher.CheckEqual(
1225       {HotseatState::kExtended, HotseatState::kShownHomeLauncher});
1226 }
1227 
1228 // Tests that in-app -> overview results in only one state change with an
1229 // autohidden shelf.
TEST_P(HotseatWidgetTest,InAppToOverviewChangesStateOnceAutohiddenShelf)1230 TEST_P(HotseatWidgetTest, InAppToOverviewChangesStateOnceAutohiddenShelf) {
1231   GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
1232   TabletModeControllerTestApi().EnterTabletMode();
1233 
1234   // Test going to overview mode using the controller from an autohide hidden
1235   // shelf. Go to in-app.
1236   std::unique_ptr<aura::Window> window =
1237       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1238   wm::ActivateWindow(window.get());
1239   {
1240     HotseatStateWatcher watcher(GetShelfLayoutManager());
1241     // Enter overview by using the controller.
1242     Shell::Get()->overview_controller()->StartOverview();
1243     WaitForOverviewAnimation(/*enter=*/true);
1244 
1245     watcher.CheckEqual({HotseatState::kExtended});
1246   }
1247 
1248   Shell::Get()->overview_controller()->EndOverview();
1249   WaitForOverviewAnimation(/*enter=*/false);
1250 
1251   // Test in-app -> overview again with the autohide shown shelf.
1252   EXPECT_TRUE(ShelfConfig::Get()->is_in_app());
1253   EXPECT_EQ(ShelfAutoHideState::SHELF_AUTO_HIDE_HIDDEN,
1254             GetShelfLayoutManager()->auto_hide_state());
1255   SwipeUpOnShelf();
1256   {
1257     HotseatStateWatcher watcher(GetShelfLayoutManager());
1258     // Enter overview by using the controller.
1259     Shell::Get()->overview_controller()->StartOverview();
1260     WaitForOverviewAnimation(/*enter=*/true);
1261 
1262     watcher.CheckEqual({});
1263     EXPECT_EQ(HotseatState::kExtended,
1264               GetShelfLayoutManager()->hotseat_state());
1265   }
1266 }
1267 
1268 // Tests that going between Applist and overview in tablet mode with no windows
1269 // results in no work area change.
TEST_P(HotseatWidgetTest,WorkAreaDoesNotUpdateAppListToFromOverviewWithNoWindow)1270 TEST_P(HotseatWidgetTest,
1271        WorkAreaDoesNotUpdateAppListToFromOverviewWithNoWindow) {
1272   TabletModeControllerTestApi().EnterTabletMode();
1273   DisplayWorkAreaChangeCounter counter;
1274 
1275   Shell::Get()->overview_controller()->StartOverview();
1276   WaitForOverviewAnimation(/*enter=*/true);
1277   EXPECT_EQ(0, counter.count());
1278 
1279   Shell::Get()->overview_controller()->StartOverview();
1280   WaitForOverviewAnimation(/*enter=*/true);
1281   EXPECT_EQ(0, counter.count());
1282 }
1283 
1284 // Tests that switching between AppList and overview with a window results in no
1285 // work area change.
TEST_P(HotseatWidgetTest,WorkAreaDoesNotUpdateAppListToFromOverviewWithWindow)1286 TEST_P(HotseatWidgetTest,
1287        WorkAreaDoesNotUpdateAppListToFromOverviewWithWindow) {
1288   DisplayWorkAreaChangeCounter counter;
1289   TabletModeControllerTestApi().EnterTabletMode();
1290   std::unique_ptr<aura::Window> window =
1291       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1292   wm::ActivateWindow(window.get());
1293   ASSERT_EQ(1, counter.count());
1294   ShowShelfAndGoHome();
1295 
1296   StartOverview();
1297   WaitForOverviewAnimation(/*enter=*/true);
1298   EXPECT_EQ(1, counter.count());
1299 
1300   EndOverview();
1301   WaitForOverviewAnimation(/*enter=*/false);
1302   EXPECT_EQ(1, counter.count());
1303 }
1304 
1305 // Tests that switching between AppList and an active window does not update the
1306 // work area.
TEST_P(HotseatWidgetTest,WorkAreaDoesNotUpdateOpenWindowToFromAppList)1307 TEST_P(HotseatWidgetTest, WorkAreaDoesNotUpdateOpenWindowToFromAppList) {
1308   TabletModeControllerTestApi().EnterTabletMode();
1309   std::unique_ptr<aura::Window> window =
1310       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1311   wm::ActivateWindow(window.get());
1312   ASSERT_TRUE(ShelfConfig::Get()->is_in_app());
1313 
1314   // Go to the home launcher, work area should not update.
1315   DisplayWorkAreaChangeCounter counter;
1316   ShowShelfAndGoHome();
1317 
1318   GetAppListTestHelper()->CheckVisibility(true);
1319   EXPECT_EQ(0, counter.count());
1320 
1321   // Go back to the window, work area should not update.
1322   wm::ActivateWindow(window.get());
1323 
1324   EXPECT_TRUE(ShelfConfig::Get()->is_in_app());
1325   EXPECT_EQ(0, counter.count());
1326 }
1327 
1328 // Tests that switching between overview and an active window does not update
1329 // the work area.
TEST_P(HotseatWidgetTest,WorkAreaDoesNotUpdateOpenWindowToFromOverview)1330 TEST_P(HotseatWidgetTest, WorkAreaDoesNotUpdateOpenWindowToFromOverview) {
1331   TabletModeControllerTestApi().EnterTabletMode();
1332   std::unique_ptr<aura::Window> window =
1333       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1334   wm::ActivateWindow(window.get());
1335   ASSERT_TRUE(ShelfConfig::Get()->is_in_app());
1336 
1337   // Go to overview, there should not be a work area update.
1338   DisplayWorkAreaChangeCounter counter;
1339   StartOverview();
1340   WaitForOverviewAnimation(/*enter=*/true);
1341   EXPECT_EQ(0, counter.count());
1342 
1343   // Go back to the app, there should not be a work area update.
1344   wm::ActivateWindow(window.get());
1345 
1346   EXPECT_TRUE(ShelfConfig::Get()->is_in_app());
1347   EXPECT_EQ(0, counter.count());
1348 }
1349 
1350 // Tests that the shelf opaque background is properly updated after a tablet
1351 // mode transition with no apps.
TEST_P(HotseatWidgetTest,ShelfBackgroundNotVisibleInTabletModeNoApps)1352 TEST_P(HotseatWidgetTest, ShelfBackgroundNotVisibleInTabletModeNoApps) {
1353   TabletModeControllerTestApi().EnterTabletMode();
1354 
1355   EXPECT_FALSE(GetShelfWidget()->GetOpaqueBackground()->visible());
1356 }
1357 
1358 // Tests that the shelf opaque background is properly updated after a tablet
1359 // mode transition with no apps with dense shelf.
TEST_P(HotseatWidgetTest,DenseShelfBackgroundNotVisibleInTabletModeNoApps)1360 TEST_P(HotseatWidgetTest, DenseShelfBackgroundNotVisibleInTabletModeNoApps) {
1361   UpdateDisplay("300x1000");
1362   TabletModeControllerTestApi().EnterTabletMode();
1363 
1364   EXPECT_FALSE(GetShelfWidget()->GetOpaqueBackground()->visible());
1365 }
1366 
1367 // Tests that the hotseat is extended if focused with a keyboard.
TEST_P(HotseatWidgetTest,ExtendHotseatIfFocusedWithKeyboard)1368 TEST_P(HotseatWidgetTest, ExtendHotseatIfFocusedWithKeyboard) {
1369   TabletModeControllerTestApi().EnterTabletMode();
1370   std::unique_ptr<aura::Window> window =
1371       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1372   wm::ActivateWindow(window.get());
1373   ASSERT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
1374 
1375   // Focus the shelf. Hotseat should now show extended.
1376   GetPrimaryShelf()->shelf_focus_cycler()->FocusShelf(false /* last_element */);
1377   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1378 
1379   // Focus the status area. Hotseat should now hide, as it was
1380   // automatically extended by focusing it.
1381   GetPrimaryShelf()->shelf_focus_cycler()->FocusStatusArea(
1382       false /* last_element */);
1383   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
1384 
1385   // Now swipe up to show the shelf and then focus it with the keyboard. Hotseat
1386   // should keep extended.
1387   SwipeUpOnShelf();
1388   GetPrimaryShelf()->shelf_focus_cycler()->FocusShelf(false /* last_element */);
1389   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1390 
1391   // Now focus the status area widget again. Hotseat should remain shown, as it
1392   // was manually extended.
1393   GetPrimaryShelf()->shelf_focus_cycler()->FocusStatusArea(
1394       false /* last_element */);
1395   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1396 }
1397 
1398 // Tests that if the hotseat was hidden while being focused, doing a traversal
1399 // focus on the next element brings it up again.
TEST_P(HotseatWidgetTest,SwipeDownOnFocusedHotseat)1400 TEST_P(HotseatWidgetTest, SwipeDownOnFocusedHotseat) {
1401   TabletModeControllerTestApi().EnterTabletMode();
1402   std::unique_ptr<aura::Window> window =
1403       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1404   wm::ActivateWindow(window.get());
1405   ShelfTestUtil::AddAppShortcut("app_id_1", TYPE_APP);
1406   ShelfTestUtil::AddAppShortcut("app_id_2", TYPE_APP);
1407   ASSERT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
1408 
1409   // Focus the shelf, then swipe down on the shelf to hide it. Hotseat should be
1410   // hidden.
1411   GetPrimaryShelf()->shelf_focus_cycler()->FocusShelf(false /* last_element */);
1412   gfx::Rect hotseat_bounds =
1413       GetPrimaryShelf()->hotseat_widget()->GetWindowBoundsInScreen();
1414   gfx::Point start = hotseat_bounds.top_center();
1415   gfx::Point end = start + gfx::Vector2d(0, 80);
1416   GetEventGenerator()->GestureScrollSequence(
1417       start, end, base::TimeDelta::FromMilliseconds(100), 4 /*scroll_steps*/);
1418   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
1419 
1420   // Focus to the next element in the hotseat. The hotseat should show again.
1421   GetEventGenerator()->PressKey(ui::VKEY_TAB, 0);
1422   GetEventGenerator()->ReleaseKey(ui::VKEY_TAB, 0);
1423   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1424 }
1425 
1426 // Tests that in overview, we can still exit by clicking on the hotseat if the
1427 // point is not on the visible area.
TEST_P(HotseatWidgetTest,ExitOverviewWithClickOnHotseat)1428 TEST_P(HotseatWidgetTest, ExitOverviewWithClickOnHotseat) {
1429   std::unique_ptr<aura::Window> window1 = AshTestBase::CreateTestWindow();
1430   ShelfTestUtil::AddAppShortcut("app_id_1", TYPE_APP);
1431 
1432   TabletModeControllerTestApi().EnterTabletMode();
1433   ASSERT_TRUE(TabletModeControllerTestApi().IsTabletModeStarted());
1434   ASSERT_FALSE(WindowState::Get(window1.get())->IsMinimized());
1435 
1436   // Enter overview, hotseat is visible. Choose the point to the farthest left.
1437   // This point will not be visible.
1438   auto* overview_controller = Shell::Get()->overview_controller();
1439   auto* hotseat_widget = GetPrimaryShelf()->hotseat_widget();
1440   overview_controller->StartOverview();
1441   ASSERT_TRUE(overview_controller->InOverviewSession());
1442   ASSERT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1443   gfx::Point far_left_point =
1444       hotseat_widget->GetWindowBoundsInScreen().left_center();
1445 
1446   // Tests that on clicking, we exit overview and all windows are minimized.
1447   GetEventGenerator()->set_current_screen_location(far_left_point);
1448   GetEventGenerator()->ClickLeftButton();
1449   EXPECT_EQ(HotseatState::kShownHomeLauncher,
1450             GetShelfLayoutManager()->hotseat_state());
1451   EXPECT_TRUE(WindowState::Get(window1.get())->IsMinimized());
1452   EXPECT_FALSE(overview_controller->InOverviewSession());
1453 }
1454 
1455 // Hides the hotseat if the hotseat is in kExtendedMode and the system tray
1456 // is about to show (see https://crbug.com/1028321).
TEST_P(HotseatWidgetTest,DismissHotseatWhenSystemTrayShows)1457 TEST_P(HotseatWidgetTest, DismissHotseatWhenSystemTrayShows) {
1458   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
1459 
1460   TabletModeControllerTestApi().EnterTabletMode();
1461   std::unique_ptr<aura::Window> window =
1462       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1463   wm::ActivateWindow(window.get());
1464 
1465   SwipeUpOnShelf();
1466   ASSERT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1467 
1468   // Activates the system tray when hotseat is in kExtended mode and waits for
1469   // the update in system tray to finish.
1470   StatusAreaWidget* status_area_widget = GetShelfWidget()->status_area_widget();
1471   const gfx::Point status_area_widget_center =
1472       status_area_widget->GetNativeView()->GetBoundsInScreen().CenterPoint();
1473   GetEventGenerator()->GestureTapAt(status_area_widget_center);
1474   base::RunLoop().RunUntilIdle();
1475 
1476   // Expects that the system tray shows and the hotseat is hidden.
1477   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
1478   EXPECT_TRUE(status_area_widget->unified_system_tray()->IsBubbleShown());
1479 
1480   // Early out since the remaining code is only meaningful for auto-hide shelf.
1481   if (GetPrimaryShelf()->auto_hide_behavior() !=
1482       ShelfAutoHideBehavior::kAlways) {
1483     return;
1484   }
1485 
1486   // Auto-hide shelf should show when opening the system tray.
1487   EXPECT_EQ(ShelfAutoHideState::SHELF_AUTO_HIDE_SHOWN,
1488             GetShelfLayoutManager()->auto_hide_state());
1489 
1490   // Auto-hide shelf should hide when closing the system tray.
1491   GetEventGenerator()->GestureTapAt(status_area_widget_center);
1492 
1493   // Waits for the system tray to be closed.
1494   base::RunLoop().RunUntilIdle();
1495 
1496   EXPECT_EQ(ShelfAutoHideState::SHELF_AUTO_HIDE_HIDDEN,
1497             GetShelfLayoutManager()->auto_hide_state());
1498 }
1499 
1500 // Tests that the work area updates once each when going to/from tablet mode
1501 // with no windows open.
TEST_P(HotseatWidgetTest,WorkAreaUpdatesClamshellToFromHomeLauncherNoWindows)1502 TEST_P(HotseatWidgetTest, WorkAreaUpdatesClamshellToFromHomeLauncherNoWindows) {
1503   DisplayWorkAreaChangeCounter counter;
1504   TabletModeControllerTestApi().EnterTabletMode();
1505 
1506   EXPECT_EQ(1, counter.count());
1507 
1508   TabletModeControllerTestApi().LeaveTabletMode();
1509 
1510   EXPECT_EQ(2, counter.count());
1511 }
1512 
1513 // Tests that the work area changes just once when opening a window in tablet
1514 // mode.
TEST_P(HotseatWidgetTest,OpenWindowInTabletModeChangesWorkArea)1515 TEST_P(HotseatWidgetTest, OpenWindowInTabletModeChangesWorkArea) {
1516   DisplayWorkAreaChangeCounter counter;
1517   TabletModeControllerTestApi().EnterTabletMode();
1518   ASSERT_EQ(1, counter.count());
1519 
1520   std::unique_ptr<aura::Window> window =
1521       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1522   wm::ActivateWindow(window.get());
1523 
1524   EXPECT_EQ(1, counter.count());
1525 }
1526 
1527 // Tests that going to and from tablet mode with an open window results in a
1528 // work area change.
TEST_P(HotseatWidgetTest,ToFromTabletModeWithWindowChangesWorkArea)1529 TEST_P(HotseatWidgetTest, ToFromTabletModeWithWindowChangesWorkArea) {
1530   DisplayWorkAreaChangeCounter counter;
1531   std::unique_ptr<aura::Window> window =
1532       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1533   wm::ActivateWindow(window.get());
1534 
1535   TabletModeControllerTestApi().EnterTabletMode();
1536   EXPECT_EQ(1, counter.count());
1537 
1538   TabletModeControllerTestApi().LeaveTabletMode();
1539   EXPECT_EQ(2, counter.count());
1540 }
1541 
1542 // Tests that the work area changes when fullscreening the active window or
1543 // autohiding the shelf.
TEST_P(HotseatWidgetTest,ShelfVisibilityChangeChangesWorkArea)1544 TEST_P(HotseatWidgetTest, ShelfVisibilityChangeChangesWorkArea) {
1545   UpdateDisplay("800x603");
1546 
1547   TabletModeControllerTestApi().EnterTabletMode();
1548   auto window = AshTestBase::CreateTestWindow(gfx::Rect(400, 400));
1549 
1550   // The expected work area is 3 pixels smaller to leave space to swipe the auto
1551   // hide shelf up.
1552   const gfx::Rect expected_auto_hide_work_area(800, 600);
1553   const gfx::Rect expected_in_app_work_area(
1554       800, 603 - ShelfConfig::Get()->in_app_shelf_size());
1555   auto get_work_area = []() -> gfx::Rect {
1556     return WorkAreaInsets::ForWindow(Shell::GetPrimaryRootWindow())
1557         ->user_work_area_bounds();
1558   };
1559 
1560   DisplayWorkAreaChangeCounter counter;
1561   WMEvent toggle_fullscreen(WM_EVENT_TOGGLE_FULLSCREEN);
1562   WindowState::Get(window.get())->OnWMEvent(&toggle_fullscreen);
1563   EXPECT_EQ(expected_auto_hide_work_area, get_work_area());
1564   EXPECT_EQ(1, counter.count());
1565 
1566   WindowState::Get(window.get())->OnWMEvent(&toggle_fullscreen);
1567   EXPECT_EQ(expected_in_app_work_area, get_work_area());
1568   EXPECT_EQ(2, counter.count());
1569 
1570   GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
1571   EXPECT_EQ(expected_auto_hide_work_area, get_work_area());
1572   EXPECT_EQ(3, counter.count());
1573 
1574   GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kNever);
1575   EXPECT_EQ(expected_in_app_work_area, get_work_area());
1576   EXPECT_EQ(4, counter.count());
1577 }
1578 
1579 // Tests that the hotseat is flush with the bottom of the screen when in
1580 // clamshell mode and the shelf is oriented on the bottom.
TEST_P(HotseatWidgetTest,HotseatFlushWithScreenBottomInClamshell)1581 TEST_P(HotseatWidgetTest, HotseatFlushWithScreenBottomInClamshell) {
1582   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
1583   const int display_height =
1584       display::Screen::GetScreen()->GetPrimaryDisplay().bounds().height();
1585   const int hotseat_bottom = GetPrimaryShelf()
1586                                  ->shelf_widget()
1587                                  ->hotseat_widget()
1588                                  ->GetWindowBoundsInScreen()
1589                                  .bottom();
1590   EXPECT_EQ(hotseat_bottom, display_height);
1591 }
1592 
1593 // Tests that when hotseat and drag-window-to-overview features are both
1594 // enabled, HomeLauncherGestureHandler can receive and process events properly.
TEST_P(HotseatWidgetTest,DragActiveWindowInTabletMode)1595 TEST_P(HotseatWidgetTest, DragActiveWindowInTabletMode) {
1596   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
1597   TabletModeControllerTestApi().EnterTabletMode();
1598   std::unique_ptr<aura::Window> window =
1599       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1600   wm::ActivateWindow(window.get());
1601 
1602   // Swipe up to bring up the hotseat first.
1603   SwipeUpOnShelf();
1604   ASSERT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1605 
1606   // Now swipe up again to start drag the active window.
1607   ui::test::EventGenerator* generator = GetEventGenerator();
1608   const gfx::Rect bottom_shelf_bounds =
1609       GetShelfWidget()->GetWindowBoundsInScreen();
1610   generator->MoveMouseTo(bottom_shelf_bounds.CenterPoint());
1611   generator->PressTouch();
1612   EXPECT_TRUE(window->layer()->transform().IsIdentity());
1613 
1614   // Drag upward, test the window transform changes.
1615   const gfx::Rect display_bounds =
1616       display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
1617   generator->MoveTouch(display_bounds.CenterPoint());
1618   const gfx::Transform upward_transform = window->layer()->transform();
1619   EXPECT_FALSE(upward_transform.IsIdentity());
1620   // Drag downwad, test the window tranfrom changes.
1621   generator->MoveTouch(display_bounds.bottom_center());
1622   const gfx::Transform downward_transform = window->layer()->transform();
1623   EXPECT_NE(upward_transform, downward_transform);
1624 
1625   generator->ReleaseTouch();
1626   EXPECT_TRUE(window->layer()->transform().IsIdentity());
1627 }
1628 
1629 // Tests that when hotseat and drag-window-to-overview features are both
1630 // enabled, hotseat is not extended after dragging a window to overview, and
1631 // then activating the window.
TEST_P(HotseatWidgetTest,ExitingOverviewHidesHotseat)1632 TEST_P(HotseatWidgetTest, ExitingOverviewHidesHotseat) {
1633   const ShelfAutoHideBehavior auto_hide_behavior = shelf_auto_hide_behavior();
1634   GetPrimaryShelf()->SetAutoHideBehavior(auto_hide_behavior);
1635   TabletModeControllerTestApi().EnterTabletMode();
1636 
1637   std::unique_ptr<aura::Window> window =
1638       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1639   wm::ActivateWindow(window.get());
1640 
1641   // If the shelf is auto-hidden, swipe up to bring up shelf and hotseat first
1642   // (otherwise, the window drag to overview will not be handled).
1643   if (auto_hide_behavior == ShelfAutoHideBehavior::kAlways) {
1644     SwipeUpOnShelf();
1645     ASSERT_EQ(HotseatState::kExtended,
1646               GetShelfLayoutManager()->hotseat_state());
1647   }
1648 
1649   // Swipe up to start dragging the active window.
1650   const gfx::Rect bottom_shelf_bounds =
1651       GetShelfWidget()->GetWindowBoundsInScreen();
1652   StartScroll(bottom_shelf_bounds.CenterPoint());
1653   // Ensure swipe goes past the top of the hotseat first to activate the window
1654   // drag controller.
1655   UpdateScroll(
1656       -GetPrimaryShelf()->hotseat_widget()->GetHotseatFullDragAmount());
1657   // Drag upward, to the center of the screen, and release (this should enter
1658   // the overview).
1659   const gfx::Rect display_bounds =
1660       display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
1661   UpdateScroll(display_bounds.CenterPoint().y() -
1662                bottom_shelf_bounds.CenterPoint().y());
1663   // Small scroll update, to simulate the user holding the pointer.
1664   UpdateScroll(2);
1665   DragWindowFromShelfController* window_drag_controller =
1666       GetShelfLayoutManager()->window_drag_controller_for_testing();
1667   ASSERT_TRUE(window_drag_controller);
1668   DragWindowFromShelfControllerTestApi test_api;
1669   test_api.WaitUntilOverviewIsShown(window_drag_controller);
1670   EndScroll(/*is_fling=*/false, 0.f);
1671 
1672   OverviewController* overview_controller = Shell::Get()->overview_controller();
1673   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1674   EXPECT_TRUE(overview_controller->InOverviewSession());
1675 
1676   // Activate the window - the overview session should exit, and hotseat should
1677   // be hidden.
1678   wm::ActivateWindow(window.get());
1679   EXPECT_FALSE(overview_controller->InOverviewSession());
1680   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
1681 }
1682 
1683 // Tests that failing to drag the maximized window to overview mode results in
1684 // an extended hotseat.
TEST_P(HotseatWidgetTest,FailingOverviewDragResultsInExtendedHotseat)1685 TEST_P(HotseatWidgetTest, FailingOverviewDragResultsInExtendedHotseat) {
1686   const ShelfAutoHideBehavior auto_hide_behavior = shelf_auto_hide_behavior();
1687   GetPrimaryShelf()->SetAutoHideBehavior(auto_hide_behavior);
1688   TabletModeControllerTestApi().EnterTabletMode();
1689 
1690   std::unique_ptr<aura::Window> window =
1691       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1692   wm::ActivateWindow(window.get());
1693 
1694   // If the shelf is auto-hidden, swipe up to bring up shelf and hotseat first
1695   // (otherwise, the window drag to overview will not be handled).
1696   if (auto_hide_behavior == ShelfAutoHideBehavior::kAlways) {
1697     SwipeUpOnShelf();
1698     ASSERT_EQ(HotseatState::kExtended,
1699               GetShelfLayoutManager()->hotseat_state());
1700   }
1701 
1702   // Swipe up to start dragging the active window.
1703   const gfx::Rect bottom_shelf_bounds =
1704       GetShelfWidget()->GetWindowBoundsInScreen();
1705   StartScroll(bottom_shelf_bounds.top_center());
1706 
1707   const int extended_hotseat_distance_from_top_of_shelf =
1708       ShelfConfig::Get()->hotseat_bottom_padding() +
1709       GetPrimaryShelf()->hotseat_widget()->GetHotseatSize();
1710   // Overview is triggered when the bottom of the dragged window goes past the
1711   // top of the hotseat. The window scaling and translation are handled slightly
1712   // differently for if the hotseat is extended or not.
1713   if (HotseatState::kExtended == GetShelfLayoutManager()->hotseat_state()) {
1714     // Drag upward, a bit below the hotseat extended height, to ensure that the
1715     // bottom of the dragged window doesn't go past the top of the hotseat, so
1716     // that it doesn't go into overview.
1717     UpdateScroll(-extended_hotseat_distance_from_top_of_shelf + 20);
1718   } else {
1719     // Drag upward, a bit past the hotseat extended height so that the window
1720     // drag controller is activated, but not enough to go to overview.
1721     UpdateScroll(-extended_hotseat_distance_from_top_of_shelf - 30);
1722   }
1723   EndScroll(/*is_fling=*/false, 0.f);
1724 
1725   ASSERT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
1726   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1727 }
1728 
1729 // Tests that hotseat remains in extended state while in overview mode when
1730 // flinging the shelf up or down.
TEST_P(HotseatWidgetTest,SwipeOnHotseatInOverview)1731 TEST_P(HotseatWidgetTest, SwipeOnHotseatInOverview) {
1732   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
1733   TabletModeControllerTestApi().EnterTabletMode();
1734 
1735   std::unique_ptr<aura::Window> window =
1736       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1737   wm::ActivateWindow(window.get());
1738 
1739   OverviewController* overview_controller = Shell::Get()->overview_controller();
1740   overview_controller->StartOverview();
1741 
1742   Shelf* const shelf = GetPrimaryShelf();
1743 
1744   SwipeUpOnShelf();
1745 
1746   EXPECT_TRUE(overview_controller->InOverviewSession());
1747   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1748   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways) {
1749     EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
1750     EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
1751   } else {
1752     EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
1753   }
1754 
1755   // Drag from the hotseat to the bezel, the hotseat should remain in extended
1756   // state.
1757   DragHotseatDownToBezel();
1758 
1759   EXPECT_TRUE(overview_controller->InOverviewSession());
1760   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1761   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways) {
1762     EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
1763     EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
1764   } else {
1765     EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
1766   }
1767 
1768   SwipeUpOnShelf();
1769 
1770   EXPECT_TRUE(overview_controller->InOverviewSession());
1771   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1772   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways) {
1773     EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
1774     EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
1775   } else {
1776     EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
1777   }
1778 }
1779 
TEST_P(HotseatWidgetTest,SwipeOnHotseatInSplitViewWithOverview)1780 TEST_P(HotseatWidgetTest, SwipeOnHotseatInSplitViewWithOverview) {
1781   Shelf* const shelf = GetPrimaryShelf();
1782   shelf->SetAutoHideBehavior(shelf_auto_hide_behavior());
1783   TabletModeControllerTestApi().EnterTabletMode();
1784 
1785   std::unique_ptr<aura::Window> window =
1786       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1787   wm::ActivateWindow(window.get());
1788 
1789   OverviewController* overview_controller = Shell::Get()->overview_controller();
1790   overview_controller->StartOverview();
1791 
1792   SplitViewController* split_view_controller =
1793       SplitViewController::Get(Shell::GetPrimaryRootWindow());
1794   split_view_controller->SnapWindow(window.get(), SplitViewController::LEFT);
1795 
1796   SwipeUpOnShelf();
1797 
1798   EXPECT_TRUE(split_view_controller->InSplitViewMode());
1799   EXPECT_TRUE(overview_controller->InOverviewSession());
1800   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1801   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways) {
1802     EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
1803     EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
1804   } else {
1805     EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
1806   }
1807 
1808   DragHotseatDownToBezel();
1809 
1810   EXPECT_TRUE(split_view_controller->InSplitViewMode());
1811   EXPECT_TRUE(overview_controller->InOverviewSession());
1812   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
1813   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways) {
1814     EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
1815     EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
1816   } else {
1817     EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
1818   }
1819 
1820   SwipeUpOnShelf();
1821 
1822   EXPECT_TRUE(split_view_controller->InSplitViewMode());
1823   EXPECT_TRUE(overview_controller->InOverviewSession());
1824   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1825   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways) {
1826     EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
1827     EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
1828   } else {
1829     EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
1830   }
1831 }
1832 
TEST_P(HotseatWidgetTest,SwipeOnHotseatInSplitView)1833 TEST_P(HotseatWidgetTest, SwipeOnHotseatInSplitView) {
1834   Shelf* const shelf = GetPrimaryShelf();
1835   shelf->SetAutoHideBehavior(shelf_auto_hide_behavior());
1836   TabletModeControllerTestApi().EnterTabletMode();
1837 
1838   std::unique_ptr<aura::Window> window1 =
1839       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1840   std::unique_ptr<aura::Window> window2 =
1841       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1842   wm::ActivateWindow(window1.get());
1843 
1844   SplitViewController* split_view_controller =
1845       SplitViewController::Get(Shell::GetPrimaryRootWindow());
1846   split_view_controller->SnapWindow(window1.get(), SplitViewController::LEFT);
1847   split_view_controller->SnapWindow(window2.get(), SplitViewController::RIGHT);
1848   EXPECT_TRUE(split_view_controller->InSplitViewMode());
1849 
1850   SwipeUpOnShelf();
1851 
1852   EXPECT_TRUE(split_view_controller->InSplitViewMode());
1853   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1854   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways) {
1855     EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
1856     EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
1857   } else {
1858     EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
1859   }
1860 
1861   DragHotseatDownToBezel();
1862 
1863   EXPECT_TRUE(split_view_controller->InSplitViewMode());
1864   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
1865   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways) {
1866     EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
1867     EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
1868   } else {
1869     EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
1870   }
1871 
1872   SwipeUpOnShelf();
1873 
1874   EXPECT_TRUE(split_view_controller->InSplitViewMode());
1875   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1876   if (shelf_auto_hide_behavior() == ShelfAutoHideBehavior::kAlways) {
1877     EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
1878     EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
1879   } else {
1880     EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
1881   }
1882 }
1883 
1884 // Tests that swiping downward, towards the bezel, from a variety of points
1885 // results in hiding the hotseat.
TEST_P(HotseatWidgetTest,HotseatHidesWhenSwipedToBezel)1886 TEST_P(HotseatWidgetTest, HotseatHidesWhenSwipedToBezel) {
1887   // Go to in-app shelf and extend the hotseat.
1888   TabletModeControllerTestApi().EnterTabletMode();
1889   std::unique_ptr<aura::Window> window =
1890       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1891   wm::ActivateWindow(window.get());
1892   SwipeUpOnShelf();
1893 
1894   // Drag from the hotseat to the bezel, the hotseat should hide.
1895   DragHotseatDownToBezel();
1896   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
1897 
1898   // Reset the hotseat and swipe from the center of the hotseat, it should hide.
1899   SwipeUpOnShelf();
1900 
1901   gfx::Rect shelf_widget_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
1902   gfx::Rect hotseat_bounds =
1903       GetPrimaryShelf()->hotseat_widget()->GetWindowBoundsInScreen();
1904   gfx::Point start = hotseat_bounds.CenterPoint();
1905   const gfx::Point end =
1906       gfx::Point(shelf_widget_bounds.x() + shelf_widget_bounds.width() / 2,
1907                  shelf_widget_bounds.bottom() + 1);
1908   const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(100);
1909   const int kNumScrollSteps = 4;
1910 
1911   GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
1912                                              kNumScrollSteps);
1913 
1914   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
1915 
1916   // Reset the hotseat and swipe from the bottom of the hotseat, it should hide.
1917   SwipeUpOnShelf();
1918 
1919   start = hotseat_bounds.bottom_center();
1920   start.Offset(0, -1);
1921   GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
1922                                              kNumScrollSteps);
1923 
1924   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
1925 
1926   // Reset the hotseat and swipe from the center of the in-app shelf, it should
1927   // hide.
1928   SwipeUpOnShelf();
1929 
1930   start = shelf_widget_bounds.CenterPoint();
1931 
1932   GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
1933                                              kNumScrollSteps);
1934 
1935   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
1936 
1937   // Reset the hotseat and swipe from the bottom of the in-app shelf, it should
1938   // hide.
1939   SwipeUpOnShelf();
1940 
1941   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1942   start = shelf_widget_bounds.bottom_center();
1943   // The first few events which get sent to ShelfLayoutManager are
1944   // ui::ET_TAP_DOWN, and ui::ET_GESTURE_START. After a few px we get
1945   // ui::ET_GESTURE_SCROLL_UPDATE. Add 6 px of slop to get the first events out
1946   // of the way, and 1 extra px to ensure we are not on the bottom edge of the
1947   // display.
1948   start.Offset(0, -7);
1949 
1950   GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
1951                                              kNumScrollSteps);
1952 
1953   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
1954 }
1955 
1956 // Tests that flinging up the in-app shelf should show the hotseat.
TEST_P(HotseatWidgetTest,FlingUpHotseatWithShortFling)1957 TEST_P(HotseatWidgetTest, FlingUpHotseatWithShortFling) {
1958   TabletModeControllerTestApi().EnterTabletMode();
1959   std::unique_ptr<aura::Window> window =
1960       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1961   wm::ActivateWindow(window.get());
1962   GetAppListTestHelper()->CheckVisibility(false);
1963 
1964   base::HistogramTester histogram_tester;
1965   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
1966                                      InAppShelfGestures::kSwipeUpToShow, 0);
1967 
1968   // Scrolls the hotseat by a distance not sufficuent to trigger the action of
1969   // entering home screen from the in-app shelf.
1970   gfx::Rect display_bounds =
1971       display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
1972   const gfx::Point start(display_bounds.bottom_center());
1973   const gfx::Point end(start + gfx::Vector2d(0, -20));
1974 
1975   const int fling_speed =
1976       DragWindowFromShelfController::kVelocityToHomeScreenThreshold + 1;
1977   const int scroll_steps = 20;
1978   base::TimeDelta scroll_time =
1979       GetEventGenerator()->CalculateScrollDurationForFlingVelocity(
1980           start, end, fling_speed, scroll_steps);
1981   GetEventGenerator()->GestureScrollSequence(start, end, scroll_time,
1982                                              scroll_steps);
1983   base::RunLoop().RunUntilIdle();
1984 
1985   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
1986   GetAppListTestHelper()->CheckVisibility(false);
1987   histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
1988                                      InAppShelfGestures::kSwipeUpToShow, 1);
1989 }
1990 
1991 // Tests that flinging up the in-app shelf should show the home launcher if the
1992 // gesture distance is long enough.
TEST_P(HotseatWidgetTest,FlingUpHotseatWithLongFling)1993 TEST_P(HotseatWidgetTest, FlingUpHotseatWithLongFling) {
1994   TabletModeControllerTestApi().EnterTabletMode();
1995   std::unique_ptr<aura::Window> window =
1996       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
1997   wm::ActivateWindow(window.get());
1998   GetAppListTestHelper()->CheckVisibility(false);
1999 
2000   base::HistogramTester histogram_tester;
2001   histogram_tester.ExpectBucketCount(
2002       kHotseatGestureHistogramName,
2003       InAppShelfGestures::kFlingUpToShowHomeScreen, 0);
2004 
2005   // Scrolls the hotseat by the sufficient distance to trigger the action of
2006   // entering home screen from the in-app shelf.
2007   gfx::Rect display_bounds =
2008       display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
2009   const gfx::Point start(display_bounds.bottom_center());
2010   const gfx::Point end(start + gfx::Vector2d(0, -200));
2011 
2012   const int fling_speed =
2013       DragWindowFromShelfController::kVelocityToHomeScreenThreshold + 1;
2014   const int scroll_steps = 20;
2015   base::TimeDelta scroll_time =
2016       GetEventGenerator()->CalculateScrollDurationForFlingVelocity(
2017           start, end, fling_speed, scroll_steps);
2018   GetEventGenerator()->GestureScrollSequence(start, end, scroll_time,
2019                                              scroll_steps);
2020   base::RunLoop().RunUntilIdle();
2021 
2022   EXPECT_EQ(HotseatState::kShownHomeLauncher,
2023             GetShelfLayoutManager()->hotseat_state());
2024   GetAppListTestHelper()->CheckVisibility(true);
2025   histogram_tester.ExpectBucketCount(
2026       kHotseatGestureHistogramName,
2027       InAppShelfGestures::kFlingUpToShowHomeScreen, 1);
2028 }
2029 
2030 // Tests that UpdateVisibilityState is ignored during a shelf drag. This
2031 // prevents drag from getting interrupted.
TEST_P(HotseatWidgetTest,NoVisibilityStateUpdateDuringDrag)2032 TEST_P(HotseatWidgetTest, NoVisibilityStateUpdateDuringDrag) {
2033   // Autohide the shelf, then start a shelf drag.
2034   GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
2035   std::unique_ptr<aura::Window> window1 =
2036       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
2037   wm::ActivateWindow(window1.get());
2038   ASSERT_EQ(SHELF_AUTO_HIDE_HIDDEN, GetPrimaryShelf()->GetAutoHideState());
2039 
2040   // Drag the autohidden shelf up a bit, then open a new window and activate it
2041   // during the drag. The shelf state should not change.
2042   gfx::Point start_drag = GetVisibleShelfWidgetBoundsInScreen().top_center();
2043   GetEventGenerator()->set_current_screen_location(start_drag);
2044   GetEventGenerator()->PressTouch();
2045   GetEventGenerator()->MoveTouchBy(0, -2);
2046   auto shelf_state_watcher = std::make_unique<ShelfStateWatcher>();
2047   std::unique_ptr<aura::Window> window2 =
2048       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
2049 
2050   wm::ActivateWindow(window2.get());
2051   window2->SetBounds(gfx::Rect(0, 0, 200, 200));
2052 
2053   EXPECT_EQ(0, shelf_state_watcher->state_change_count());
2054 }
2055 
2056 // Tests that when tablet mode has ended, the hotseat background is no longer
2057 // visible. See crbug/1050383
TEST_P(HotseatWidgetTest,HotseatBackgroundDisappearsAfterTabletModeEnd)2058 TEST_P(HotseatWidgetTest, HotseatBackgroundDisappearsAfterTabletModeEnd) {
2059   HotseatWidget* hotseat = GetPrimaryShelf()->hotseat_widget();
2060   EXPECT_FALSE(hotseat->GetIsTranslucentBackgroundVisibleForTest());
2061 
2062   TabletModeControllerTestApi().EnterTabletMode();
2063   EXPECT_TRUE(hotseat->GetIsTranslucentBackgroundVisibleForTest());
2064 
2065   TabletModeControllerTestApi().LeaveTabletMode();
2066   EXPECT_FALSE(hotseat->GetIsTranslucentBackgroundVisibleForTest());
2067 }
2068 
2069 // Tests that popups don't activate the hotseat. (crbug.com/1018266)
TEST_P(HotseatWidgetTest,HotseatRemainsHiddenIfPopupLaunched)2070 TEST_P(HotseatWidgetTest, HotseatRemainsHiddenIfPopupLaunched) {
2071   // Go to in-app shelf and extend the hotseat.
2072   TabletModeControllerTestApi().EnterTabletMode();
2073   std::unique_ptr<aura::Window> window =
2074       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
2075   wm::ActivateWindow(window.get());
2076   SwipeUpOnShelf();
2077   EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
2078 
2079   // Hide hotseat by clicking outside its bounds.
2080   gfx::Rect hotseat_bounds =
2081       GetPrimaryShelf()->hotseat_widget()->GetWindowBoundsInScreen();
2082   gfx::Point start = hotseat_bounds.top_center();
2083   GetEventGenerator()->GestureTapAt(gfx::Point(start.x() + 1, start.y() - 1));
2084   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
2085 
2086   // Create a popup window and wait until all actions finish. The hotseat should
2087   // remain hidden.
2088   aura::Window* window_2 = CreateTestWindowInParent(window.get());
2089   window_2->SetBounds(gfx::Rect(201, 0, 100, 100));
2090   window_2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
2091   window_2->Show();
2092   GetAppListTestHelper()->WaitUntilIdle();
2093   EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
2094 }
2095 
2096 // Tests that blur is not showing during animations.
TEST_P(HotseatWidgetTest,NoBlurDuringAnimations)2097 TEST_P(HotseatWidgetTest, NoBlurDuringAnimations) {
2098   TabletModeControllerTestApi().EnterTabletMode();
2099   ASSERT_EQ(
2100       ShelfConfig::Get()->shelf_blur_radius(),
2101       GetShelfWidget()->hotseat_widget()->GetHotseatBackgroundBlurForTest());
2102   ui::ScopedAnimationDurationScaleMode regular_animations(
2103       ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2104 
2105   // Open a window, as the hotseat animates to kHidden, it should lose its blur.
2106   std::unique_ptr<aura::Window> window =
2107       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
2108   wm::ActivateWindow(window.get());
2109   EXPECT_EQ(
2110       0, GetShelfWidget()->hotseat_widget()->GetHotseatBackgroundBlurForTest());
2111 
2112   // Wait for the animation to finish, hotseat blur should return.
2113   ShellTestApi().WaitForWindowFinishAnimating(window.get());
2114   EXPECT_EQ(
2115       ShelfConfig::Get()->shelf_blur_radius(),
2116       GetShelfWidget()->hotseat_widget()->GetHotseatBackgroundBlurForTest());
2117 }
2118 
TEST_P(HotseatWidgetTest,PresentationTimeMetricDuringDrag)2119 TEST_P(HotseatWidgetTest, PresentationTimeMetricDuringDrag) {
2120   PresentationTimeRecorder::SetReportPresentationTimeImmediatelyForTest(true);
2121 
2122   std::unique_ptr<aura::Window> window =
2123       AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
2124   wm::ActivateWindow(window.get());
2125 
2126   GetPrimaryShelf()->SetAutoHideBehavior(shelf_auto_hide_behavior());
2127   TabletModeControllerTestApi().EnterTabletMode();
2128 
2129   ui::test::EventGenerator* generator = GetEventGenerator();
2130   const gfx::Rect display_bounds =
2131       display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
2132   // Drag upwards from the bottom of the screen to bring up hotseat - this
2133   // should request presentation time metric to be reported.
2134   generator->PressTouch(display_bounds.bottom_center());
2135 
2136   HotseatWidget* const hotseat_widget = GetPrimaryShelf()->hotseat_widget();
2137   int last_hotseat_y = hotseat_widget->GetWindowBoundsInScreen().y();
2138 
2139   // Returns whether the hotseat vertical position has changed comapred to
2140   // |last_hotseat_y|, and updates |last_hotseat_y| to match the current hotseat
2141   // position.
2142   auto hotseat_moved = [&last_hotseat_y, &hotseat_widget]() -> bool {
2143     const int hotseat_y = hotseat_widget->GetWindowBoundsInScreen().y();
2144     const bool y_changed = hotseat_y != last_hotseat_y;
2145     last_hotseat_y = hotseat_y;
2146     return y_changed;
2147   };
2148 
2149   base::HistogramTester histogram_tester;
2150 
2151   auto check_bucket_size = [&histogram_tester](int expected_size) {
2152     histogram_tester.ExpectTotalCount(
2153         "Ash.HotseatTransition.Drag.PresentationTime", expected_size);
2154     histogram_tester.ExpectTotalCount(
2155         "Ash.HotseatTransition.Drag.PresentationTime.MaxLatency", 0);
2156   };
2157 
2158   int expected_bucket_size = 0;
2159   {
2160     SCOPED_TRACE("Initial state");
2161     check_bucket_size(expected_bucket_size);
2162   }
2163 
2164   const int shelf_height = GetShelfWidget()->GetWindowBoundsInScreen().height();
2165 
2166   {
2167     SCOPED_TRACE("Upward drag with move - 1");
2168     generator->MoveTouchBy(0, -shelf_height / 2);
2169     ASSERT_TRUE(hotseat_moved());
2170     check_bucket_size(++expected_bucket_size);
2171   }
2172 
2173   {
2174     SCOPED_TRACE("Upward drag with move - 2");
2175     generator->MoveTouchBy(0, -shelf_height / 2);
2176     ASSERT_TRUE(hotseat_moved());
2177     check_bucket_size(++expected_bucket_size);
2178   }
2179 
2180   {
2181     SCOPED_TRACE("Downward drag with move");
2182     generator->MoveTouchBy(0, shelf_height / 2);
2183     ASSERT_TRUE(hotseat_moved());
2184     check_bucket_size(++expected_bucket_size);
2185   }
2186 
2187   {
2188     SCOPED_TRACE("Upward drag with move - 3");
2189     generator->MoveTouchBy(0, -shelf_height / 2);
2190     ASSERT_TRUE(hotseat_moved());
2191     check_bucket_size(++expected_bucket_size);
2192   }
2193 
2194   const int hotseat_height =
2195       GetPrimaryShelf()->hotseat_widget()->GetWindowBoundsInScreen().height();
2196   {
2197     SCOPED_TRACE("Upward drag with move above shelf - 1");
2198     generator->MoveTouchBy(0, -hotseat_height / 2);
2199     ASSERT_TRUE(hotseat_moved());
2200     check_bucket_size(++expected_bucket_size);
2201   }
2202 
2203   {
2204     SCOPED_TRACE("Upward drag with move above shelf - 2");
2205     generator->MoveTouchBy(0, -hotseat_height / 2);
2206     ASSERT_TRUE(hotseat_moved());
2207     check_bucket_size(++expected_bucket_size);
2208   }
2209 
2210   {
2211     SCOPED_TRACE("Downward drag with move above shelf");
2212     generator->MoveTouchBy(0, hotseat_height / 2);
2213     ASSERT_TRUE(hotseat_moved());
2214     check_bucket_size(++expected_bucket_size);
2215   }
2216 
2217   {
2218     SCOPED_TRACE("Upward drag with move above shelf - 3");
2219     generator->MoveTouchBy(0, -hotseat_height - hotseat_height / 2);
2220     ASSERT_TRUE(hotseat_moved());
2221     check_bucket_size(++expected_bucket_size);
2222   }
2223 
2224   // Once the hotseat has been fully extended, presentation time metric should
2225   // stop being reported, as the hotseat is expected to stop moving.
2226   {
2227     SCOPED_TRACE("Upward drag without moving - 1");
2228     generator->MoveTouchBy(0, -hotseat_height);
2229     ASSERT_FALSE(hotseat_moved());
2230     check_bucket_size(expected_bucket_size);
2231   }
2232 
2233   {
2234     SCOPED_TRACE("Upward drag without moving - 2");
2235     generator->MoveTouchBy(0, -hotseat_height / 2);
2236     ASSERT_FALSE(hotseat_moved());
2237     check_bucket_size(expected_bucket_size);
2238   }
2239 
2240   // Move hotseat downwards - the presentation time should not get reported
2241   // until the hotseat starts moving downwards.
2242   {
2243     SCOPED_TRACE("Downward drag without moving - 1");
2244     generator->MoveTouchBy(0, hotseat_height / 2);
2245     ASSERT_FALSE(hotseat_moved());
2246     check_bucket_size(expected_bucket_size);
2247   }
2248 
2249   {
2250     SCOPED_TRACE("Downward drag without moving - 2");
2251     generator->MoveTouchBy(0, hotseat_height);
2252     ASSERT_FALSE(hotseat_moved());
2253     check_bucket_size(expected_bucket_size);
2254   }
2255 
2256   generator->ReleaseTouch();
2257 
2258   window.reset();
2259 
2260   {
2261     SCOPED_TRACE("Drag ended.");
2262     histogram_tester.ExpectTotalCount(
2263         "Ash.HotseatTransition.Drag.PresentationTime", expected_bucket_size);
2264     histogram_tester.ExpectTotalCount(
2265         "Ash.HotseatTransition.Drag.PresentationTime.MaxLatency", 1);
2266   }
2267 }
2268 
2269 // TODO(manucornet): Enable this test once the new API for layer animation
2270 // sequence observers is available.
TEST_P(HotseatWidgetTest,DISABLED_OverviewToHomeAnimationAndBackIsSmooth)2271 TEST_P(HotseatWidgetTest, DISABLED_OverviewToHomeAnimationAndBackIsSmooth) {
2272   // Go into tablet mode and make sure animations are over.
2273   HotseatWidget* hotseat = GetPrimaryShelf()->hotseat_widget();
2274   WidgetAnimationWaiter waiter(hotseat);
2275   TabletModeControllerTestApi().EnterTabletMode();
2276   waiter.WaitForAnimation();
2277 
2278   ui::ScopedAnimationDurationScaleMode regular_animations(
2279       ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2280 
2281   // Go into overview and back to know what to expect in terms of bounds.
2282   const gfx::Rect shown_hotseat_bounds = hotseat->GetWindowBoundsInScreen();
2283   {
2284     WidgetAnimationWaiter waiter(hotseat);
2285     StartOverview();
2286     waiter.WaitForAnimation();
2287   }
2288 
2289   const gfx::Rect extended_hotseat_bounds = hotseat->GetWindowBoundsInScreen();
2290   {
2291     WidgetAnimationWaiter waiter(hotseat);
2292     EndOverview();
2293     waiter.WaitForAnimation();
2294   }
2295 
2296   // The extended hotseat should be higher (lower value of Y) than the
2297   // shown hotseat.
2298   EXPECT_GT(shown_hotseat_bounds.y(), extended_hotseat_bounds.y());
2299 
2300   // We should start with the hotseat in its shown position again.
2301   EXPECT_EQ(shown_hotseat_bounds, hotseat->GetWindowBoundsInScreen());
2302 
2303   {
2304     WidgetAnimationSmoothnessInspector inspector(hotseat);
2305     WidgetAnimationWaiter waiter(hotseat);
2306     StartOverview();
2307     waiter.WaitForAnimation();
2308     EXPECT_TRUE(inspector.CheckAnimation(4));
2309   }
2310 
2311   // The hotseat should now be extended.
2312   EXPECT_EQ(extended_hotseat_bounds, hotseat->GetWindowBoundsInScreen());
2313 
2314   {
2315     WidgetAnimationSmoothnessInspector inspector(hotseat);
2316     WidgetAnimationWaiter waiter(hotseat);
2317     EndOverview();
2318     waiter.WaitForAnimation();
2319     EXPECT_TRUE(inspector.CheckAnimation(4));
2320   }
2321 
2322   // And we should now be back where we started.
2323   EXPECT_EQ(shown_hotseat_bounds, hotseat->GetWindowBoundsInScreen());
2324 }
2325 
2326 }  // namespace ash
2327