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