| // Copyright 2020 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/app_list/test/app_list_test_helper.h" |
| #include "ash/home_screen/drag_window_from_shelf_controller.h" |
| #include "ash/home_screen/drag_window_from_shelf_controller_test_api.h" |
| #include "ash/public/cpp/ash_features.h" |
| #include "ash/public/cpp/ash_pref_names.h" |
| #include "ash/public/cpp/shelf_types.h" |
| #include "ash/session/session_controller_impl.h" |
| #include "ash/shelf/contextual_tooltip.h" |
| #include "ash/shelf/drag_handle.h" |
| #include "ash/shelf/shelf_layout_manager.h" |
| #include "ash/shelf/test/shelf_layout_manager_test_base.h" |
| #include "ash/shell.h" |
| #include "ash/test/ash_test_base.h" |
| #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/simple_test_clock.h" |
| #include "ui/compositor/scoped_animation_duration_scale_mode.h" |
| #include "ui/wm/core/window_util.h" |
| |
| namespace ash { |
| namespace { |
| |
| ShelfWidget* GetShelfWidget() { |
| return AshTestBase::GetPrimaryShelf()->shelf_widget(); |
| } |
| |
| ShelfLayoutManager* GetShelfLayoutManager() { |
| return AshTestBase::GetPrimaryShelf()->shelf_layout_manager(); |
| } |
| |
| } // namespace |
| |
| // Test base for unit test related to drag handle contextual nudges. |
| class DragHandleContextualNudgeTest : public ShelfLayoutManagerTestBase { |
| public: |
| DragHandleContextualNudgeTest() { |
| scoped_feature_list_.InitWithFeatures( |
| {ash::features::kContextualNudges, |
| ash::features::kHideShelfControlsInTabletMode}, |
| {}); |
| } |
| ~DragHandleContextualNudgeTest() override = default; |
| |
| DragHandleContextualNudgeTest(const DragHandleContextualNudgeTest& other) = |
| delete; |
| DragHandleContextualNudgeTest& operator=( |
| const DragHandleContextualNudgeTest& other) = delete; |
| |
| // ShelfLayoutManagerTestBase: |
| void SetUp() override { |
| ShelfLayoutManagerTestBase::SetUp(); |
| test_clock_.Advance(base::TimeDelta::FromHours(2)); |
| contextual_tooltip::OverrideClockForTesting(&test_clock_); |
| } |
| void TearDown() override { |
| contextual_tooltip::ClearClockOverrideForTesting(); |
| AshTestBase::TearDown(); |
| } |
| |
| base::SimpleTestClock test_clock_; |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| class DragHandleContextualNudgeTestA11yPrefs |
| : public DragHandleContextualNudgeTest, |
| public ::testing::WithParamInterface<std::string> {}; |
| |
| INSTANTIATE_TEST_SUITE_P( |
| All, |
| DragHandleContextualNudgeTestA11yPrefs, |
| testing::Values(prefs::kAccessibilityAutoclickEnabled, |
| prefs::kAccessibilitySpokenFeedbackEnabled, |
| prefs::kAccessibilitySwitchAccessEnabled)); |
| |
| TEST_F(DragHandleContextualNudgeTest, ShowDragHandleNudgeWithTimer) { |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_EQ(ShelfBackgroundType::kInApp, GetShelfWidget()->GetBackgroundType()); |
| |
| // The drag handle should be showing but the nudge should not. A timer to show |
| // the nudge should be initialized. |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| // Firing the timer should show the drag handle nudge. |
| GetShelfWidget()->GetDragHandle()->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_TRUE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| } |
| |
| TEST_F(DragHandleContextualNudgeTest, HideDragHandleNudgeHiddenOnMinimize) { |
| base::HistogramTester histogram_tester; |
| |
| // Creates a test window to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_EQ(ShelfBackgroundType::kInApp, GetShelfWidget()->GetBackgroundType()); |
| |
| // The drag handle and nudge should be showing after the timer fires. |
| GetShelfWidget()->GetDragHandle()->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_TRUE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| |
| // Minimizing the widget should hide the drag handle and nudge. |
| widget->Minimize(); |
| EXPECT_FALSE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| |
| histogram_tester.ExpectBucketCount( |
| "Ash.ContextualNudgeDismissContext.InAppToHome", |
| contextual_tooltip::DismissNudgeReason::kExitToHomeScreen, 1); |
| } |
| |
| // Tests that the drag handle nudge nudge is hidden when closing the widget and |
| // setting the ShelfBackgroundType to kHomeLauncher. |
| TEST_F(DragHandleContextualNudgeTest, DragHandleNudgeHiddenOnClose) { |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_EQ(ShelfBackgroundType::kInApp, GetShelfWidget()->GetBackgroundType()); |
| |
| DragHandle* const drag_handle = GetShelfWidget()->GetDragHandle(); |
| |
| ASSERT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| drag_handle->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility()); |
| |
| // Close the widget. |
| widget->CloseWithReason(views::Widget::ClosedReason::kCloseButtonClicked); |
| EXPECT_FALSE(drag_handle->GetVisible()); |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| } |
| |
| // Checks that the shelf cannot be auto hidden while animating shelf drag handle |
| // nudge. |
| TEST_F(DragHandleContextualNudgeTest, |
| HideDragHandleDoesNotInteruptShowNudgeAnimation) { |
| GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways); |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_EQ(ShelfBackgroundType::kInApp, GetShelfWidget()->GetBackgroundType()); |
| |
| ui::ScopedAnimationDurationScaleMode normal_animation_duration( |
| ui::ScopedAnimationDurationScaleMode::SLOW_DURATION); |
| GetShelfWidget()->GetDragHandle()->MaybeShowDragHandleNudge(); |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_TRUE( |
| GetShelfWidget()->GetDragHandle()->show_nudge_animation_in_progress()); |
| GetShelfLayoutManager()->UpdateAutoHideState(); |
| // Shelf auto hide should not interrupt animations to show drag handle nudge. |
| // Showing the nudge while hiding the shelf is not intended behavior. |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_TRUE( |
| GetShelfWidget()->GetDragHandle()->show_nudge_animation_in_progress()); |
| } |
| |
| // Checks that the drag handle nudge is not shown when entering kInApp with |
| // shelf autohide turned on. |
| TEST_F(DragHandleContextualNudgeTest, DragHandleNotShownForAutoHideShelf) { |
| GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways); |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->show_nudge_animation_in_progress()); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| } |
| |
| TEST_F(DragHandleContextualNudgeTest, DoNotShowNudgeWithoutDragHandle) { |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_EQ(ShelfBackgroundType::kInApp, GetShelfWidget()->GetBackgroundType()); |
| |
| // Minimizing the widget should hide the drag handle and nudge. |
| widget->Minimize(); |
| EXPECT_FALSE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| } |
| |
| TEST_F(DragHandleContextualNudgeTest, |
| ContinueShowingDragHandleNudgeOnActiveWidgetChanged) { |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_EQ(ShelfBackgroundType::kInApp, GetShelfWidget()->GetBackgroundType()); |
| GetShelfWidget()->GetDragHandle()->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_TRUE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| |
| // Maximizing and showing a different widget should not hide the drag handle |
| // or nudge. |
| views::Widget* new_widget = CreateTestWidget(); |
| new_widget->Maximize(); |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_TRUE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| } |
| |
| TEST_F(DragHandleContextualNudgeTest, DragHandleNudgeShownInAppShelf) { |
| base::HistogramTester histogram_tester; |
| |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| |
| // Drag handle and nudge should not be shown in clamshell mode. |
| EXPECT_FALSE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| |
| // Test that the first time a user transitions into tablet mode with a |
| // maximized window will show the drag nudge immedietly. The drag handle nudge |
| // should not be visible yet and the timer to show it should be set. |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_EQ(ShelfBackgroundType::kInApp, GetShelfWidget()->GetBackgroundType()); |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| EXPECT_TRUE(GetShelfWidget() |
| ->GetDragHandle() |
| ->has_show_drag_handle_timer_for_testing()); |
| |
| // Firing the timer should show the nudge for the first time. The nudge should |
| // remain visible until the shelf state changes so the timer to hide it should |
| // not be set. |
| GetShelfWidget()->GetDragHandle()->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| EXPECT_FALSE(GetShelfWidget() |
| ->GetDragHandle() |
| ->has_hide_drag_handle_timer_for_testing()); |
| |
| // Leaving tablet mode should hide the nudge. |
| TabletModeControllerTestApi().LeaveTabletMode(); |
| EXPECT_FALSE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| |
| histogram_tester.ExpectBucketCount( |
| "Ash.ContextualNudgeDismissContext.InAppToHome", |
| contextual_tooltip::DismissNudgeReason::kSwitchToClamshell, 1); |
| |
| // Reentering tablet mode should show the drag handle but the nudge should |
| // not. No timer should be set to show the nudge. |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| EXPECT_FALSE(GetShelfWidget() |
| ->GetDragHandle() |
| ->has_show_drag_handle_timer_for_testing()); |
| |
| // Advance time for more than a day (which should enable the nudge again). |
| test_clock_.Advance(base::TimeDelta::FromHours(25)); |
| |
| // Reentering tablet mode with a maximized widget should immedietly show the |
| // drag handle and set a timer to show the nudge. |
| TabletModeControllerTestApi().LeaveTabletMode(); |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| // Firing the timer should show the nudge. |
| EXPECT_TRUE(GetShelfWidget() |
| ->GetDragHandle() |
| ->has_show_drag_handle_timer_for_testing()); |
| GetShelfWidget()->GetDragHandle()->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| EXPECT_FALSE(GetShelfWidget() |
| ->GetDragHandle() |
| ->has_show_drag_handle_timer_for_testing()); |
| // On subsequent shows, the nudge should be hidden after a timeout. |
| EXPECT_TRUE(GetShelfWidget() |
| ->GetDragHandle() |
| ->has_hide_drag_handle_timer_for_testing()); |
| } |
| |
| TEST_F(DragHandleContextualNudgeTest, DragHandleNudgeShownOnTap) { |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_EQ(ShelfBackgroundType::kInApp, GetShelfWidget()->GetBackgroundType()); |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| EXPECT_TRUE(GetShelfWidget() |
| ->GetDragHandle() |
| ->has_show_drag_handle_timer_for_testing()); |
| GetShelfWidget()->GetDragHandle()->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| |
| // Exiting and re-entering tablet should hide the nudge and put the shelf into |
| // the default kInApp shelf state. |
| TabletModeControllerTestApi().LeaveTabletMode(); |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| |
| // Tapping the drag handle should show the drag handle nudge immedietly and |
| // the show nudge timer should be set. |
| GetEventGenerator()->GestureTapAt( |
| GetShelfWidget()->GetDragHandle()->GetBoundsInScreen().CenterPoint()); |
| EXPECT_FALSE(GetShelfWidget() |
| ->GetDragHandle() |
| ->has_show_drag_handle_timer_for_testing()); |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_TRUE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| EXPECT_TRUE(GetShelfWidget() |
| ->GetDragHandle() |
| ->has_hide_drag_handle_timer_for_testing()); |
| } |
| |
| TEST_F(DragHandleContextualNudgeTest, DragHandleNudgeNotShownForHiddenShelf) { |
| GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways); |
| |
| TabletModeControllerTestApi().EnterTabletMode(); |
| |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| |
| ShelfWidget* const shelf_widget = GetShelfWidget(); |
| DragHandle* const drag_handle = shelf_widget->GetDragHandle(); |
| |
| // The shelf is hidden, so the drag handle nudge should not be shown. |
| EXPECT_TRUE(drag_handle->GetVisible()); |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| EXPECT_FALSE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| |
| PrefService* const prefs = |
| Shell::Get()->session_controller()->GetLastActiveUserPrefService(); |
| // Back gesture nudge should be allowed if the shelf is hidden. |
| EXPECT_TRUE(contextual_tooltip::ShouldShowNudge( |
| prefs, contextual_tooltip::TooltipType::kBackGesture, nullptr)); |
| |
| // Swipe up to show the shelf - this should schedule the drag handle nudge. |
| SwipeUpOnShelf(); |
| |
| // Back gesture nudge should be disallowed at this time, given that the drag |
| // handle nudge can be shown. |
| EXPECT_FALSE(contextual_tooltip::ShouldShowNudge( |
| prefs, contextual_tooltip::TooltipType::kBackGesture, nullptr)); |
| |
| ASSERT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| drag_handle->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility()); |
| } |
| |
| // Tapping the drag handle nudge when auto hide shelf is enabled should hide the |
| // drag handle nudge but should not hide the shelf or hotseat. |
| TEST_F(DragHandleContextualNudgeTest, |
| DragHandleNudgeTapDoesNotHideAutoHiddenShelf) { |
| // Sets shelf auto hide behavior. |
| GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways); |
| |
| TabletModeControllerTestApi().EnterTabletMode(); |
| |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| |
| ShelfWidget* const shelf_widget = GetShelfWidget(); |
| DragHandle* const drag_handle = shelf_widget->GetDragHandle(); |
| |
| // The shelf and drag handle should be hidden and the nudge should not be |
| // scheduled because shelf auto hide is set. |
| EXPECT_TRUE(GetPrimaryShelf()->GetAutoHideState() == |
| ShelfAutoHideState::SHELF_AUTO_HIDE_HIDDEN); |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| EXPECT_FALSE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| |
| // Swipe up to show the shelf. This should show the shelf, extend the hotseat, |
| // and schedule the drag handle nudge. |
| SwipeUpOnShelf(); |
| EXPECT_TRUE(GetPrimaryShelf()->GetAutoHideState() == |
| ShelfAutoHideState::SHELF_AUTO_HIDE_SHOWN); |
| EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state()); |
| ASSERT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| // Firing the show timer should create the nudge set the target visibility for |
| // animations.. |
| drag_handle->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility()); |
| EXPECT_TRUE(drag_handle->drag_handle_nudge() != nullptr); |
| |
| // Tapping the drag handle nudge should hide the nudge but not affect the |
| // visibility of the shelf or hotseat. |
| GetEventGenerator()->GestureTapAt( |
| drag_handle->drag_handle_nudge()->GetBoundsInScreen().CenterPoint()); |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| EXPECT_TRUE(GetPrimaryShelf()->GetAutoHideState() == |
| ShelfAutoHideState::SHELF_AUTO_HIDE_SHOWN); |
| EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state()); |
| |
| // Swiping down on shelf should hide the shelf and hotseat. |
| SwipeDownOnShelf(); |
| EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state()); |
| EXPECT_TRUE(GetPrimaryShelf()->GetAutoHideState() == |
| ShelfAutoHideState::SHELF_AUTO_HIDE_HIDDEN); |
| |
| // Swiping up on shelf should show the shelf and drag handle but not the |
| // nudge or hotseat. |
| SwipeUpOnShelf(); |
| EXPECT_TRUE(GetPrimaryShelf()->GetAutoHideState() == |
| ShelfAutoHideState::SHELF_AUTO_HIDE_SHOWN); |
| EXPECT_FALSE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| EXPECT_TRUE(drag_handle->drag_handle_nudge() == nullptr); |
| EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state()); |
| } |
| |
| // Tests that drag handle show is canceled when the shelf is hidden while the |
| // drag handle is scheduled to be shown. |
| TEST_F(DragHandleContextualNudgeTest, HidingShelfCancelsDragHandleShow) { |
| GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways); |
| |
| TabletModeControllerTestApi().EnterTabletMode(); |
| |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| |
| ShelfWidget* const shelf_widget = GetShelfWidget(); |
| DragHandle* const drag_handle = shelf_widget->GetDragHandle(); |
| |
| // The shelf is hidden, so the drag handle nudge should not be shown. |
| EXPECT_TRUE(drag_handle->GetVisible()); |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| EXPECT_FALSE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| |
| // Swipe up to show the shelf - this should schedule the drag handle nudge. |
| SwipeUpOnShelf(); |
| |
| EXPECT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| |
| // Hide the shelf, and verify the drag handle show is canceled. |
| SwipeDownOnShelf(); |
| EXPECT_FALSE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| |
| PrefService* const prefs = |
| Shell::Get()->session_controller()->GetLastActiveUserPrefService(); |
| // Back gesture nudge should be allowed if the shelf is hidden. |
| EXPECT_TRUE(contextual_tooltip::ShouldShowNudge( |
| prefs, contextual_tooltip::TooltipType::kBackGesture, nullptr)); |
| } |
| |
| // Tests that the drag handle nudge is not hidden when the user extends the |
| // hotseat. |
| TEST_F(DragHandleContextualNudgeTest, |
| DragHandleNudgeNotHiddenByExtendingHotseat) { |
| TabletModeControllerTestApi().EnterTabletMode(); |
| |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| |
| ShelfWidget* const shelf_widget = GetShelfWidget(); |
| DragHandle* const drag_handle = shelf_widget->GetDragHandle(); |
| |
| ASSERT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| drag_handle->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility()); |
| |
| // Swipe up to extend the hotseat - verify that the drag handle remain |
| // visible. |
| SwipeUpOnShelf(); |
| EXPECT_TRUE(drag_handle->GetVisible()); |
| EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility()); |
| } |
| |
| // Tests that the drag handle nudge is horizontally centered in screen, and |
| // drawn above the shelf drag handle, even after display bounds are updated. |
| TEST_F(DragHandleContextualNudgeTest, DragHandleNudgeBoundsInScreen) { |
| UpdateDisplay("675x1200"); |
| TabletModeControllerTestApi().EnterTabletMode(); |
| |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| |
| ShelfWidget* const shelf_widget = GetShelfWidget(); |
| DragHandle* const drag_handle = shelf_widget->GetDragHandle(); |
| |
| EXPECT_TRUE(drag_handle->GetVisible()); |
| ASSERT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| drag_handle->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility()); |
| |
| // Calculates absolute difference between horizontal margins of |inner| rect |
| // within |outer| rect. |
| auto margin_diff = [](const gfx::Rect& inner, const gfx::Rect& outer) -> int { |
| const int left = inner.x() - outer.x(); |
| EXPECT_GE(left, 0); |
| |
| const int right = outer.right() - inner.right(); |
| EXPECT_GE(right, 0); |
| |
| return std::abs(left - right); |
| }; |
| |
| // Verify that nudge widget is centered in shelf. |
| gfx::Rect shelf_bounds = shelf_widget->GetWindowBoundsInScreen(); |
| gfx::Rect nudge_bounds = |
| drag_handle->drag_handle_nudge()->label()->GetBoundsInScreen(); |
| EXPECT_LE(margin_diff(nudge_bounds, shelf_bounds), 1); |
| |
| // Verify that the nudge vertical bounds - within the shelf bounds, and above |
| // the drag handle. |
| gfx::Rect drag_handle_bounds = drag_handle->GetBoundsInScreen(); |
| EXPECT_LE(shelf_bounds.y(), nudge_bounds.y()); |
| EXPECT_LE(nudge_bounds.bottom(), drag_handle_bounds.y()); |
| |
| // Change the display bounds, and verify the updated drag handle bounds. |
| UpdateDisplay("1200x675"); |
| EXPECT_TRUE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| |
| // Verify that nudge widget is centered in shelf. |
| shelf_bounds = shelf_widget->GetWindowBoundsInScreen(); |
| nudge_bounds = drag_handle->drag_handle_nudge()->label()->GetBoundsInScreen(); |
| EXPECT_LE(margin_diff(nudge_bounds, shelf_bounds), 1); |
| |
| // Verify that the nudge vertical bounds - within the shelf bounds, and above |
| // the drag handle. |
| drag_handle_bounds = drag_handle->GetBoundsInScreen(); |
| EXPECT_LE(shelf_bounds.y(), nudge_bounds.y()); |
| EXPECT_LE(nudge_bounds.bottom(), drag_handle_bounds.y()); |
| } |
| |
| // Tests that drag handle does not hide during the window drag from shelf |
| // gesture. |
| TEST_F(DragHandleContextualNudgeTest, |
| DragHandleNudgeNotHiddenDuringWindowDragFromShelf) { |
| TabletModeControllerTestApi().EnterTabletMode(); |
| |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| |
| ShelfWidget* const shelf_widget = GetShelfWidget(); |
| DragHandle* const drag_handle = shelf_widget->GetDragHandle(); |
| |
| ASSERT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| drag_handle->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility()); |
| |
| TabletModeControllerTestApi().LeaveTabletMode(); |
| // Advance time for more than a day (which should enable the nudge again). |
| test_clock_.Advance(base::TimeDelta::FromHours(25)); |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| drag_handle->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(drag_handle->has_hide_drag_handle_timer_for_testing()); |
| |
| const gfx::Point start = drag_handle->GetBoundsInScreen().CenterPoint(); |
| // Simulates window drag from shelf gesture, and verifies that the timer to |
| // hide the drag handle nudge is canceled when the window drag from shelf |
| // starts. |
| GetEventGenerator()->GestureScrollSequenceWithCallback( |
| start, start + gfx::Vector2d(0, -200), |
| base::TimeDelta::FromMilliseconds(50), |
| /*num_steps = */ 6, |
| base::BindRepeating( |
| [](DragHandle* drag_handle, ui::EventType type, |
| const gfx::Vector2dF& offset) { |
| DragWindowFromShelfController* window_drag_controller = |
| GetShelfLayoutManager()->window_drag_controller_for_testing(); |
| if (window_drag_controller && |
| window_drag_controller->dragged_window()) { |
| EXPECT_FALSE( |
| drag_handle->has_hide_drag_handle_timer_for_testing()); |
| } |
| const bool scroll_end = type == ui::ET_GESTURE_SCROLL_END; |
| EXPECT_EQ(!scroll_end, |
| drag_handle->gesture_nudge_target_visibility()); |
| }, |
| drag_handle)); |
| |
| // The nudge should be hidden when the gesture completes. |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| } |
| |
| // Tests that window drag from shelf cancels drag handle contextual nudge from |
| // showing. |
| TEST_F(DragHandleContextualNudgeTest, |
| DragHandleNudgeNotShownDuringWindowDragFromShelf) { |
| TabletModeControllerTestApi().EnterTabletMode(); |
| |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| |
| ShelfWidget* const shelf_widget = GetShelfWidget(); |
| DragHandle* const drag_handle = shelf_widget->GetDragHandle(); |
| |
| EXPECT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| |
| const gfx::Point start = |
| GetShelfWidget()->GetWindowBoundsInScreen().CenterPoint(); |
| // Simulates window drag from shelf gesture, and verifies that the timer to |
| // show the drag handle nudge is canceled when the window drag from shelf |
| // starts. |
| GetEventGenerator()->GestureScrollSequenceWithCallback( |
| start, start + gfx::Vector2d(0, -200), |
| base::TimeDelta::FromMilliseconds(50), |
| /*num_steps = */ 6, |
| base::BindRepeating( |
| [](DragHandle* drag_handle, ui::EventType type, |
| const gfx::Vector2dF& offset) { |
| DragWindowFromShelfController* window_drag_controller = |
| GetShelfLayoutManager()->window_drag_controller_for_testing(); |
| if (window_drag_controller && |
| window_drag_controller->dragged_window()) { |
| EXPECT_FALSE( |
| drag_handle->has_show_drag_handle_timer_for_testing()); |
| |
| // Attempt to schedule the nudge should fail. |
| if (type != ui::ET_GESTURE_SCROLL_END) { |
| drag_handle->ScheduleShowDragHandleNudge(); |
| EXPECT_FALSE( |
| drag_handle->has_show_drag_handle_timer_for_testing()); |
| } |
| } |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| }, |
| drag_handle)); |
| |
| // The nudge should be hidden when the gesture completes. |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| } |
| |
| TEST_F(DragHandleContextualNudgeTest, GestureSwipeHidesDragHandleNudge) { |
| base::HistogramTester histogram_tester; |
| |
| TabletModeControllerTestApi().EnterTabletMode(); |
| |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| |
| ShelfWidget* const shelf_widget = GetShelfWidget(); |
| DragHandle* const drag_handle = shelf_widget->GetDragHandle(); |
| |
| ASSERT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| drag_handle->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility()); |
| |
| const gfx::Point start = drag_handle->GetBoundsInScreen().CenterPoint(); |
| // Simulates a swipe up from the drag handle to perform the in app to home |
| // gesture. |
| GetEventGenerator()->GestureScrollSequence( |
| start, start + gfx::Vector2d(0, -300), |
| base::TimeDelta::FromMilliseconds(10), |
| /*num_steps = */ 5); |
| |
| // The nudge should be hidden when the gesture completes. |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| GetAppListTestHelper()->CheckVisibility(true); |
| |
| histogram_tester.ExpectBucketCount( |
| "Ash.ContextualNudgeDismissContext.InAppToHome", |
| contextual_tooltip::DismissNudgeReason::kPerformedGesture, 1); |
| histogram_tester.ExpectTimeBucketCount( |
| "Ash.ContextualNudgeDismissTime.InAppToHome", |
| base::TimeDelta::FromSeconds(0), 1); |
| } |
| |
| // Tests that drag handle nudge gets hidden when the user performs window drag |
| // from shelf to home. |
| TEST_F(DragHandleContextualNudgeTest, FlingFromShelfToHomeHidesTheNudge) { |
| TabletModeControllerTestApi().EnterTabletMode(); |
| |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| |
| ShelfWidget* const shelf_widget = GetShelfWidget(); |
| DragHandle* const drag_handle = shelf_widget->GetDragHandle(); |
| |
| ASSERT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| drag_handle->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility()); |
| |
| const gfx::Point start = drag_handle->GetBoundsInScreen().CenterPoint(); |
| // Simulates window drag from shelf gesture, and verifies that the timer to |
| // hide the drag handle nudge is canceled when the window drag from shelf |
| // starts. |
| GetEventGenerator()->GestureScrollSequenceWithCallback( |
| start, start + gfx::Vector2d(0, -300), |
| base::TimeDelta::FromMilliseconds(10), |
| /*num_steps = */ 6, |
| base::BindRepeating( |
| [](DragHandle* drag_handle, ui::EventType type, |
| const gfx::Vector2dF& offset) { |
| const bool scroll_end = type == ui::ET_GESTURE_SCROLL_END; |
| EXPECT_EQ(!scroll_end, |
| drag_handle->gesture_nudge_target_visibility()); |
| }, |
| drag_handle)); |
| |
| // The nudge should be hidden when the gesture completes. |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| GetAppListTestHelper()->CheckVisibility(true); |
| } |
| |
| // Tests that drag handle nudge gets hidden when the user performs window drag |
| // from shelf, even if the gesture does not end up going home. |
| TEST_F(DragHandleContextualNudgeTest, DragFromShelfToHomeHidesTheNudge) { |
| TabletModeControllerTestApi().EnterTabletMode(); |
| |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| |
| ShelfWidget* const shelf_widget = GetShelfWidget(); |
| DragHandle* const drag_handle = shelf_widget->GetDragHandle(); |
| |
| ASSERT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| drag_handle->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility()); |
| |
| const gfx::Point start = drag_handle->GetBoundsInScreen().CenterPoint(); |
| // Simulates window drag from shelf gesture, and verifies that the timer to |
| // hide the drag handle nudge is canceled when the window drag from shelf |
| // starts. |
| GetEventGenerator()->GestureScrollSequenceWithCallback( |
| start, start + gfx::Vector2d(0, -150), |
| base::TimeDelta::FromMilliseconds(500), |
| /*num_steps = */ 20, |
| base::BindRepeating( |
| [](DragHandle* drag_handle, ui::EventType type, |
| const gfx::Vector2dF& offset) { |
| DragWindowFromShelfController* window_drag_controller = |
| GetShelfLayoutManager()->window_drag_controller_for_testing(); |
| if (window_drag_controller && |
| window_drag_controller->dragged_window()) { |
| DragWindowFromShelfControllerTestApi().WaitUntilOverviewIsShown( |
| window_drag_controller); |
| } |
| const bool scroll_end = type == ui::ET_GESTURE_SCROLL_END; |
| EXPECT_EQ(!scroll_end, |
| drag_handle->gesture_nudge_target_visibility()); |
| }, |
| drag_handle)); |
| |
| // The nudge should be hidden when the gesture completes. |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| |
| GetAppListTestHelper()->CheckVisibility(false); |
| EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession()); |
| } |
| |
| // Tests that scheduled drag handle nudge show is canceled when overview starts. |
| TEST_F(DragHandleContextualNudgeTest, OverviewCancelsNudgeShow) { |
| TabletModeControllerTestApi().EnterTabletMode(); |
| |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| |
| ShelfWidget* const shelf_widget = GetShelfWidget(); |
| DragHandle* const drag_handle = shelf_widget->GetDragHandle(); |
| |
| ASSERT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| Shell::Get()->overview_controller()->StartOverview(); |
| ASSERT_FALSE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| } |
| |
| // Tests that tapping the drag handle can shown drag handle nudge in overview. |
| TEST_F(DragHandleContextualNudgeTest, DragHandleTapShowNudgeInOverview) { |
| TabletModeControllerTestApi().EnterTabletMode(); |
| |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| |
| ShelfWidget* const shelf_widget = GetShelfWidget(); |
| DragHandle* const drag_handle = shelf_widget->GetDragHandle(); |
| |
| ASSERT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| drag_handle->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility()); |
| |
| TabletModeControllerTestApi().LeaveTabletMode(); |
| TabletModeControllerTestApi().EnterTabletMode(); |
| |
| Shell::Get()->overview_controller()->StartOverview(); |
| ASSERT_FALSE(drag_handle->has_show_drag_handle_timer_for_testing()); |
| |
| GetEventGenerator()->GestureTapAt( |
| drag_handle->GetBoundsInScreen().CenterPoint()); |
| |
| EXPECT_TRUE(drag_handle->GetVisible()); |
| EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility()); |
| |
| EXPECT_TRUE(drag_handle->has_hide_drag_handle_timer_for_testing()); |
| drag_handle->fire_hide_drag_handle_timer_for_testing(); |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| |
| // Tapping the drag handle again will show the nudge again. |
| GetEventGenerator()->GestureTapAt( |
| drag_handle->GetBoundsInScreen().CenterPoint()); |
| EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility()); |
| } |
| |
| // Tests that tapping the drag handle in split screen does not show nudge. |
| TEST_F(DragHandleContextualNudgeTest, |
| DragHandleTapDoesNotShowNudgeForSplitScreen) { |
| TabletModeControllerTestApi().EnterTabletMode(); |
| std::unique_ptr<aura::Window> window = |
| AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400)); |
| wm::ActivateWindow(window.get()); |
| |
| ShelfWidget* const shelf_widget = GetShelfWidget(); |
| DragHandle* const drag_handle = shelf_widget->GetDragHandle(); |
| |
| // Go into split view mode by first going into overview, and then snapping |
| // the open window on one side. |
| OverviewController* overview_controller = Shell::Get()->overview_controller(); |
| overview_controller->StartOverview(); |
| SplitViewController* split_view_controller = |
| SplitViewController::Get(shelf_widget->GetNativeWindow()); |
| split_view_controller->SnapWindow(window.get(), SplitViewController::LEFT); |
| EXPECT_TRUE(split_view_controller->InSplitViewMode()); |
| |
| // Tapping the drag handle will not show the drag handle. |
| GetEventGenerator()->GestureTapAt( |
| drag_handle->GetBoundsInScreen().CenterPoint()); |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| } |
| |
| // Tests that entering split screen hides the drag handle nudge. |
| TEST_F(DragHandleContextualNudgeTest, DragHandleNudgeHiddenOnSplitScreen) { |
| TabletModeControllerTestApi().EnterTabletMode(); |
| |
| std::unique_ptr<aura::Window> window = |
| AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400)); |
| wm::ActivateWindow(window.get()); |
| |
| ShelfWidget* const shelf_widget = GetShelfWidget(); |
| DragHandle* const drag_handle = shelf_widget->GetDragHandle(); |
| |
| // Tapping the drag handle should show the drag handle. |
| GetEventGenerator()->GestureTapAt( |
| drag_handle->GetBoundsInScreen().CenterPoint()); |
| EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility()); |
| |
| // Go into split view mode by first going into overview, and then snapping |
| // the open window on one side. |
| OverviewController* overview_controller = Shell::Get()->overview_controller(); |
| overview_controller->StartOverview(); |
| SplitViewController* split_view_controller = |
| SplitViewController::Get(shelf_widget->GetNativeWindow()); |
| split_view_controller->SnapWindow(window.get(), SplitViewController::LEFT); |
| EXPECT_TRUE(split_view_controller->InSplitViewMode()); |
| |
| // The drag handle nudge should no longer be visible. |
| EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility()); |
| } |
| |
| TEST_P(DragHandleContextualNudgeTestA11yPrefs, HideNudgesForShelfControls) { |
| SCOPED_TRACE(testing::Message() << "Pref=" << GetParam()); |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_EQ(ShelfBackgroundType::kInApp, GetShelfWidget()->GetBackgroundType()); |
| |
| // The drag handle should be showing but the nudge should not. A timer to show |
| // the nudge should be initialized. |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| // Firing the timer should show the drag handle nudge. |
| GetShelfWidget()->GetDragHandle()->fire_show_drag_handle_timer_for_testing(); |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_TRUE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| |
| // Enabling accessibility auto click disables gestures and enables shelf |
| // control buttons. In app to home nudge should be hidden. |
| Shell::Get() |
| ->session_controller() |
| ->GetLastActiveUserPrefService() |
| ->SetBoolean(GetParam(), true); |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| } |
| |
| TEST_P(DragHandleContextualNudgeTestA11yPrefs, DisableNudgesForShelfControls) { |
| SCOPED_TRACE(testing::Message() << "Pref=" << GetParam()); |
| // Turn on accessibility settings to enable shelf controls. |
| Shell::Get() |
| ->session_controller() |
| ->GetLastActiveUserPrefService() |
| ->SetBoolean(GetParam(), true); |
| |
| // Creates a widget to put shelf into in-app state. |
| views::Widget* widget = CreateTestWidget(); |
| widget->Maximize(); |
| TabletModeControllerTestApi().EnterTabletMode(); |
| EXPECT_EQ(ShelfBackgroundType::kInApp, GetShelfWidget()->GetBackgroundType()); |
| // The drag handle should be showing but the nudge should not. A timer to show |
| // the nudge should not be initialized because shelf controls are on. |
| EXPECT_TRUE(GetShelfWidget()->GetDragHandle()->GetVisible()); |
| EXPECT_FALSE( |
| GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility()); |
| EXPECT_FALSE(GetShelfWidget() |
| ->GetDragHandle() |
| ->has_show_drag_handle_timer_for_testing()); |
| } |
| |
| } // namespace ash |