diff --git a/ash/home_screen/swipe_home_to_overview_controller.cc b/ash/home_screen/swipe_home_to_overview_controller.cc index d2d2e9657c59f..e72457a8ffa5e 100644 --- a/ash/home_screen/swipe_home_to_overview_controller.cc +++ b/ash/home_screen/swipe_home_to_overview_controller.cc @@ -4,8 +4,11 @@ #include "ash/home_screen/swipe_home_to_overview_controller.h" +#include "ash/app_list/app_list_controller_impl.h" +#include "ash/home_screen/drag_window_from_shelf_controller.h" #include "ash/home_screen/home_screen_controller.h" #include "ash/home_screen/home_screen_delegate.h" +#include "ash/public/cpp/app_list/app_list_config.h" #include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/shelf_config.h" #include "ash/session/session_controller_impl.h" @@ -50,8 +53,11 @@ constexpr base::TimeDelta kGestureCancelationDuration = base::TimeDelta::FromMilliseconds(350); void UpdateHomeAnimationForGestureCancel( + bool going_back, ui::ScopedLayerAnimationSettings* settings) { - settings->SetTransitionDuration(kGestureCancelationDuration); + settings->SetTransitionDuration( + going_back ? AppListConfig::instance().page_transition_duration() + : kGestureCancelationDuration); settings->SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN); settings->SetPreemptionStrategy( ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); @@ -139,9 +145,21 @@ void SwipeHomeToOverviewController::Drag(const gfx::PointF& location_in_screen, void SwipeHomeToOverviewController::EndDrag( const gfx::PointF& location_in_screen, base::Optional<float> velocity_y) { + if (state_ != State::kTrackingDrag) { + state_ = State::kFinished; + return; + } + + // Upward swipe should return to the home screen's initial state. + const bool go_back = + velocity_y && + *velocity_y < + -DragWindowFromShelfController::kVelocityToHomeScreenThreshold; + // Overview is triggered by |overview_transition_timer_|. If EndDrag() - // is called before the timer fires, the gesture is canceled. - CancelDrag(); + // is called before the timer fires, the result of the gesture should be + // staying on the home screen. + FinalizeDragAndStayOnHomeScreen(go_back); } void SwipeHomeToOverviewController::CancelDrag() { @@ -150,22 +168,7 @@ void SwipeHomeToOverviewController::CancelDrag() { return; } - overview_transition_timer_.Stop(); - overview_transition_threshold_y_ = 0; - state_ = State::kFinished; - - UMA_HISTOGRAM_ENUMERATION(kEnterOverviewHistogramName, - EnterOverviewFromHomeLauncher::kCanceled); - Shell::Get() - ->home_screen_controller() - ->delegate() - ->UpdateScaleAndOpacityForHomeLauncher( - 1.0f /*scale*/, 1.0f /*opacity*/, base::nullopt /*animation_info*/, - base::BindRepeating(&UpdateHomeAnimationForGestureCancel)); - - // No need to keep blur disabled for the drag - note that blur might remain - // disabled at this point due to the started home screen scale animation. - home_screen_blur_disabler_.reset(); + FinalizeDragAndStayOnHomeScreen(/*go_back=*/false); } void SwipeHomeToOverviewController::ScheduleFinalizeDragAndShowOverview() { @@ -190,7 +193,11 @@ void SwipeHomeToOverviewController::FinalizeDragAndShowOverview() { } UMA_HISTOGRAM_ENUMERATION(kEnterOverviewHistogramName, - EnterOverviewFromHomeLauncher::kSuccess); + EnterOverviewFromHomeLauncher::kOverview); + + // NOTE: No need to update the home launcher opacity and scale here - the + // HomeScreenController will update the home launcher state when it detects + // that the overview is starting. Shell::Get()->overview_controller()->StartOverview(); // No need to keep blur disabled for the drag - note that blur might remain @@ -199,4 +206,34 @@ void SwipeHomeToOverviewController::FinalizeDragAndShowOverview() { home_screen_blur_disabler_.reset(); } +void SwipeHomeToOverviewController::FinalizeDragAndStayOnHomeScreen( + bool go_back) { + overview_transition_timer_.Stop(); + overview_transition_threshold_y_ = 0; + state_ = State::kFinished; + + if (go_back) { + Shell::Get()->app_list_controller()->Back(); + UMA_HISTOGRAM_ENUMERATION(kEnterOverviewHistogramName, + EnterOverviewFromHomeLauncher::kBack); + } else { + UMA_HISTOGRAM_ENUMERATION(kEnterOverviewHistogramName, + EnterOverviewFromHomeLauncher::kCanceled); + } + + // Make sure the home launcher scale and opacity return to the initial state. + // Note that this is needed even if the gesture ended up in a fling, as early + // gesture handling might have updated the launcher scale. + Shell::Get() + ->home_screen_controller() + ->delegate() + ->UpdateScaleAndOpacityForHomeLauncher( + 1.0f /*scale*/, 1.0f /*opacity*/, base::nullopt /*animation_info*/, + base::BindRepeating(&UpdateHomeAnimationForGestureCancel, go_back)); + + // No need to keep blur disabled for the drag - note that blur might remain + // disabled at this point due to the started home screen scale animation. + home_screen_blur_disabler_.reset(); +} + } // namespace ash diff --git a/ash/home_screen/swipe_home_to_overview_controller.h b/ash/home_screen/swipe_home_to_overview_controller.h index 0d264261f93f4..6c870d06a54b9 100644 --- a/ash/home_screen/swipe_home_to_overview_controller.h +++ b/ash/home_screen/swipe_home_to_overview_controller.h @@ -64,6 +64,10 @@ class ASH_EXPORT SwipeHomeToOverviewController { // moving the pointer - those events will be ignored. void FinalizeDragAndShowOverview(); + // Finalizes the drag sequence by staying on the home screen. + // |go_back| - if the gesture should invoke home screen back action. + void FinalizeDragAndStayOnHomeScreen(bool go_back); + const int64_t display_id_; State state_ = State::kInitial; diff --git a/ash/home_screen/swipe_home_to_overview_controller_unittest.cc b/ash/home_screen/swipe_home_to_overview_controller_unittest.cc index 31759c33b4eb3..a24f9a364df2f 100644 --- a/ash/home_screen/swipe_home_to_overview_controller_unittest.cc +++ b/ash/home_screen/swipe_home_to_overview_controller_unittest.cc @@ -6,6 +6,7 @@ #include "ash/app_list/test/app_list_test_helper.h" #include "ash/app_list/views/app_list_view.h" +#include "ash/app_list/views/search_box_view.h" #include "ash/home_screen/home_screen_controller.h" #include "ash/home_screen/home_screen_delegate.h" #include "ash/public/cpp/ash_features.h" @@ -112,6 +113,14 @@ class SwipeHomeToOverviewControllerTest : public AshTestBase { } } + void TapOnHomeLauncherSearchBox() { + GetEventGenerator()->GestureTapAt(GetAppListTestHelper() + ->GetAppListView() + ->search_box_view() + ->GetBoundsInScreen() + .CenterPoint()); + } + base::TimeTicks GetTimerDesiredRunTime() const { return home_to_overview_controller_->overview_transition_timer_for_testing() ->desired_run_time(); @@ -191,7 +200,7 @@ TEST_F(SwipeHomeToOverviewControllerTest, BasicFlow) { base::HistogramTester histogram_tester; histogram_tester.ExpectBucketCount( - kEnterOverviewHistogramName, EnterOverviewFromHomeLauncher::kSuccess, 0); + kEnterOverviewHistogramName, EnterOverviewFromHomeLauncher::kOverview, 0); StartDrag(); // Drag to a point within shelf bounds - verify that app list has not been @@ -207,7 +216,7 @@ TEST_F(SwipeHomeToOverviewControllerTest, BasicFlow) { EXPECT_FALSE(OverviewTransitionTimerRunning()); EXPECT_FALSE(OverviewStarted()); histogram_tester.ExpectBucketCount( - kEnterOverviewHistogramName, EnterOverviewFromHomeLauncher::kSuccess, 0); + kEnterOverviewHistogramName, EnterOverviewFromHomeLauncher::kOverview, 0); const int transition_threshold = SwipeHomeToOverviewController::kVerticalThresholdForOverviewTransition; @@ -224,7 +233,7 @@ TEST_F(SwipeHomeToOverviewControllerTest, BasicFlow) { EXPECT_FALSE(home_screen_window->transform().IsIdentityOrTranslation()); EXPECT_EQ(1.f, home_screen_window->layer()->opacity()); histogram_tester.ExpectBucketCount( - kEnterOverviewHistogramName, EnterOverviewFromHomeLauncher::kSuccess, 0); + kEnterOverviewHistogramName, EnterOverviewFromHomeLauncher::kOverview, 0); // Move above the transition threshold - verify the overview transition timer // has started. @@ -239,14 +248,14 @@ TEST_F(SwipeHomeToOverviewControllerTest, BasicFlow) { EXPECT_TRUE(OverviewTransitionTimerRunning()); EXPECT_FALSE(OverviewStarted()); histogram_tester.ExpectBucketCount( - kEnterOverviewHistogramName, EnterOverviewFromHomeLauncher::kSuccess, 0); + kEnterOverviewHistogramName, EnterOverviewFromHomeLauncher::kOverview, 0); // Fire overview transition timer, and verify the overview has started. FireOverviewTransitionTimer(); EXPECT_TRUE(OverviewStarted()); histogram_tester.ExpectBucketCount( - kEnterOverviewHistogramName, EnterOverviewFromHomeLauncher::kSuccess, 1); + kEnterOverviewHistogramName, EnterOverviewFromHomeLauncher::kOverview, 1); // Home screen is still scaled down, and not visible. EXPECT_EQ(home_screen_window->transform(), @@ -262,7 +271,7 @@ TEST_F(SwipeHomeToOverviewControllerTest, BasicFlow) { EXPECT_TRUE(OverviewStarted()); histogram_tester.ExpectBucketCount( - kEnterOverviewHistogramName, EnterOverviewFromHomeLauncher::kSuccess, 1); + kEnterOverviewHistogramName, EnterOverviewFromHomeLauncher::kOverview, 1); // Home screen is still scaled down, and not visible. EXPECT_EQ(home_screen_window->transform(), @@ -313,7 +322,108 @@ TEST_F(SwipeHomeToOverviewControllerTest, EndDragBeforeTimeout) { EXPECT_FALSE(OverviewStarted()); } +TEST_F(SwipeHomeToOverviewControllerTest, GoBackOnHomeLauncher) { + // Show home screen search results page. + GetAppListTestHelper()->CheckVisibility(true); + TapOnHomeLauncherSearchBox(); + GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch); + + const gfx::RectF shelf_bounds = GetShelfBoundsInFloat(); + + StartDrag(); + + aura::Window* home_screen_window = + home_screen_delegate()->GetHomeScreenWindow(); + ASSERT_TRUE(home_screen_window); + + const int transition_threshold = + SwipeHomeToOverviewController::kVerticalThresholdForOverviewTransition; + + // Move above the transition threshold - verify the overview transition timer + // has started. + Drag(shelf_bounds.top_center() - gfx::Vector2d(0, transition_threshold / 2), + 0.f, 1.f); + Drag(shelf_bounds.top_center() - gfx::Vector2d(0, transition_threshold + 10), + 0.f, 1.f); + + EXPECT_EQ(home_screen_window->transform(), + home_screen_window->layer()->GetTargetTransform()); + EXPECT_TRUE(home_screen_window->transform().IsScaleOrTranslation()); + EXPECT_FALSE(home_screen_window->transform().IsIdentityOrTranslation()); + + EXPECT_TRUE(OverviewTransitionTimerRunning()); + EXPECT_FALSE(OverviewStarted()); + + // The user ending drag with a fling should move home to the initial state - + // fullscreen all apps. + EndDrag( + shelf_bounds.top_center() - gfx::Vector2d(0, transition_threshold + 10), + -1500.f); + + EXPECT_EQ(home_screen_window->transform(), + home_screen_window->layer()->GetTargetTransform()); + EXPECT_EQ(gfx::Transform(), home_screen_window->transform()); + EXPECT_EQ(1.f, home_screen_window->layer()->opacity()); + + EXPECT_FALSE(OverviewTransitionTimerRunning()); + EXPECT_FALSE(OverviewStarted()); + GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps); +} + +TEST_F(SwipeHomeToOverviewControllerTest, FlingOnAppsPage) { + // Show home screen search results page. + GetAppListTestHelper()->CheckVisibility(true); + GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps); + + const gfx::RectF shelf_bounds = GetShelfBoundsInFloat(); + + StartDrag(); + + aura::Window* home_screen_window = + home_screen_delegate()->GetHomeScreenWindow(); + ASSERT_TRUE(home_screen_window); + + const int transition_threshold = + SwipeHomeToOverviewController::kVerticalThresholdForOverviewTransition; + + // Move above the transition threshold - verify the overview transition timer + // has started. + Drag(shelf_bounds.top_center() - gfx::Vector2d(0, transition_threshold / 2), + 0.f, 1.f); + Drag(shelf_bounds.top_center() - gfx::Vector2d(0, transition_threshold + 10), + 0.f, 1.f); + + EXPECT_EQ(home_screen_window->transform(), + home_screen_window->layer()->GetTargetTransform()); + EXPECT_TRUE(home_screen_window->transform().IsScaleOrTranslation()); + EXPECT_FALSE(home_screen_window->transform().IsIdentityOrTranslation()); + + EXPECT_TRUE(OverviewTransitionTimerRunning()); + EXPECT_FALSE(OverviewStarted()); + + // The user ending drag with a fling should move home to the initial state - + // fullscreen all apps. + EndDrag( + shelf_bounds.top_center() - gfx::Vector2d(0, transition_threshold + 10), + -1500.f); + + EXPECT_EQ(home_screen_window->transform(), + home_screen_window->layer()->GetTargetTransform()); + EXPECT_EQ(gfx::Transform(), home_screen_window->transform()); + EXPECT_EQ(1.f, home_screen_window->layer()->opacity()); + + EXPECT_FALSE(OverviewTransitionTimerRunning()); + EXPECT_FALSE(OverviewStarted()); + + GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps); +} + TEST_F(SwipeHomeToOverviewControllerTest, CancelDragBeforeTimeout) { + // Show home screen search results page. + GetAppListTestHelper()->CheckVisibility(true); + TapOnHomeLauncherSearchBox(); + GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch); + const gfx::RectF shelf_bounds = GetShelfBoundsInFloat(); StartDrag(); @@ -350,6 +460,10 @@ TEST_F(SwipeHomeToOverviewControllerTest, CancelDragBeforeTimeout) { EXPECT_FALSE(OverviewTransitionTimerRunning()); EXPECT_FALSE(OverviewStarted()); + + // The gesture was not a fling - the home screen should have stayed in the + // fullscreen search state. + GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch); } TEST_F(SwipeHomeToOverviewControllerTest, DragMovementRestartsTimeout) { diff --git a/ash/shelf/shelf_metrics.h b/ash/shelf/shelf_metrics.h index b253abc1a9428..e5de1be90be9a 100644 --- a/ash/shelf/shelf_metrics.h +++ b/ash/shelf/shelf_metrics.h @@ -50,10 +50,13 @@ enum class EnterOverviewFromHomeLauncher { kCanceled = 0, // Succeed to enter overview mode from home launcher. - kSuccess = 1, + kOverview = 1, + + // The gesture was detected as a swipe to the home screen initial state. + kBack = 2, // New items should be added before to keep this one always the last. - kMaxState = 2, + kMaxState = 3, kMaxValue = kMaxState }; diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 88cbc23081b2f..a5c76a18171e9 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml @@ -65128,6 +65128,7 @@ would be helpful to identify which type is being sent. <enum name="SwipeHomeToOverviewResult"> <int value="0" label="Remained on the home screen"/> <int value="1" label="Transitioned to overview"/> + <int value="2" label="Went back on the home screen"/> </enum> <enum name="SwReporterRunningTimeRegistryError">