123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- // Copyright 2019 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/shelf/swipe_home_to_overview_controller.h"
- #include "ash/app_list/app_list_controller_impl.h"
- #include "ash/constants/ash_features.h"
- #include "ash/controls/contextual_tooltip.h"
- #include "ash/public/cpp/app_list/app_list_config.h"
- #include "ash/public/cpp/shelf_config.h"
- #include "ash/session/session_controller_impl.h"
- #include "ash/shelf/drag_window_from_shelf_controller.h"
- #include "ash/shelf/shelf_metrics.h"
- #include "ash/shell.h"
- #include "ash/wm/overview/overview_controller.h"
- #include "ash/wm/overview/overview_session.h"
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/cxx17_backports.h"
- #include "base/metrics/histogram_macros.h"
- #include "base/time/default_tick_clock.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "ui/compositor/layer_animation_element.h"
- #include "ui/compositor/scoped_layer_animation_settings.h"
- #include "ui/display/display.h"
- #include "ui/display/screen.h"
- #include "ui/gfx/animation/tween.h"
- namespace ash {
- namespace {
- // The target/min home launcher view scale.
- constexpr float kTargetHomeScale = 0.92f;
- // The home UI will be scaled down towards center of the screen as drag location
- // moves upwards. The target threshold for scaling is extended above the actual
- // threshold for transition so the UI keeps changing even when the gesture goes
- // over the threshold. This is the target home screen scaling threshold in terms
- // of ratio of the display height.
- constexpr float kHomeScalingThresholdDisplayHeightRatio = 0.5f;
- // The amount of time the drag has to remain bellow velocity threshold before
- // the transition to the overview starts.
- constexpr base::TimeDelta kOverviewTransitionDelay = base::Milliseconds(150);
- // The duration of transition from the home screen current scaled state to the
- // initial (unscaled) state when the gesture is canceled.
- constexpr base::TimeDelta kGestureCancelationDuration = base::Milliseconds(350);
- // The duration of transition from the home screen current scaled state to the
- // initial (unscaled) state when the gesture is canceled due to a back gesture.
- constexpr base::TimeDelta kGestureCancelationForBackDuration =
- base::Milliseconds(250);
- void UpdateHomeAnimationForGestureCancel(
- bool going_back,
- ui::ScopedLayerAnimationSettings* settings) {
- settings->SetTransitionDuration(going_back
- ? kGestureCancelationForBackDuration
- : kGestureCancelationDuration);
- settings->SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
- settings->SetPreemptionStrategy(
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- }
- } // namespace
- SwipeHomeToOverviewController::SwipeHomeToOverviewController(int64_t display_id)
- : SwipeHomeToOverviewController(display_id,
- base::DefaultTickClock::GetInstance()) {}
- SwipeHomeToOverviewController::SwipeHomeToOverviewController(
- int64_t display_id,
- const base::TickClock* tick_clock)
- : display_id_(display_id), overview_transition_timer_(tick_clock) {}
- SwipeHomeToOverviewController::~SwipeHomeToOverviewController() {
- CancelDrag();
- }
- void SwipeHomeToOverviewController::Drag(const gfx::PointF& location_in_screen,
- float scroll_x,
- float scroll_y) {
- if (state_ == State::kFinished)
- return;
- display::Display display;
- if (!display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id_,
- &display)) {
- CancelDrag();
- return;
- }
- const int shelf_top =
- display.bounds().bottom() - ShelfConfig::Get()->shelf_size();
- if (state_ == State::kInitial) {
- // Do not start drag until the drag goes above the shelf.
- if (location_in_screen.y() > shelf_top)
- return;
- overview_transition_threshold_y_ =
- shelf_top - kVerticalThresholdForOverviewTransition;
- scaling_threshold_y_ =
- display.bounds().y() +
- display.bounds().height() * kHomeScalingThresholdDisplayHeightRatio;
- state_ = State::kTrackingDrag;
- home_screen_blur_disabler_ =
- Shell::Get()->app_list_controller()->DisableHomeScreenBackgroundBlur();
- } else {
- if (location_in_screen.y() <= overview_transition_threshold_y_ &&
- std::abs(scroll_x) + std::abs(scroll_y) <= kMovementVelocityThreshold) {
- ScheduleFinalizeDragAndShowOverview();
- } else {
- overview_transition_timer_.Stop();
- }
- }
- // Update the home screen scale to match progress during the drag.
- // Use extended threshold as the projected final transition position - UI
- // changing even after the user gets over the threshold should make the user
- // more likely to keep dragging up when they get really close to the threshold
- // for transition to overview (and reduce false negatives for detecting
- // transition to overview).
- const float distance = location_in_screen.y() - scaling_threshold_y_;
- const float target_distance = overview_transition_threshold_y_ -
- scaling_threshold_y_ +
- kVerticalThresholdForOverviewTransition;
- const float progress = gfx::Tween::CalculateValue(
- gfx::Tween::FAST_OUT_SLOW_IN,
- base::clamp(1.f - distance / target_distance, 0.0f, 1.0f));
- float scale = gfx::Tween::FloatValueBetween(progress, 1.0f, kTargetHomeScale);
- Shell::Get()->app_list_controller()->UpdateScaleAndOpacityForHomeLauncher(
- scale, 1.0f /*opacity*/, absl::nullopt /*animation_info*/,
- base::NullCallback());
- }
- void SwipeHomeToOverviewController::EndDrag(
- const gfx::PointF& location_in_screen,
- absl::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 result of the gesture should be
- // staying on the home screen.
- FinalizeDragAndStayOnHomeScreen(go_back);
- }
- void SwipeHomeToOverviewController::CancelDrag() {
- if (state_ != State::kTrackingDrag) {
- state_ = State::kFinished;
- return;
- }
- FinalizeDragAndStayOnHomeScreen(/*go_back=*/false);
- }
- void SwipeHomeToOverviewController::ScheduleFinalizeDragAndShowOverview() {
- if (overview_transition_timer_.IsRunning())
- return;
- overview_transition_timer_.Start(
- FROM_HERE, kOverviewTransitionDelay,
- base::BindOnce(
- &SwipeHomeToOverviewController::FinalizeDragAndShowOverview,
- base::Unretained(this)));
- }
- void SwipeHomeToOverviewController::FinalizeDragAndShowOverview() {
- state_ = State::kFinished;
- overview_transition_threshold_y_ = 0;
- if (features::AreContextualNudgesEnabled()) {
- contextual_tooltip::HandleGesturePerformed(
- Shell::Get()->session_controller()->GetActivePrefService(),
- contextual_tooltip::TooltipType::kHomeToOverview);
- }
- UMA_HISTOGRAM_ENUMERATION(kEnterOverviewHistogramName,
- EnterOverviewFromHomeLauncher::kOverview);
- // NOTE: No need to update the home launcher opacity and scale here - the
- // AppListControllerImpl will update the home launcher state when it detects
- // that the overview is starting.
- Shell::Get()->overview_controller()->StartOverview(
- OverviewStartAction::kExitHomeLauncher);
- // No need to keep blur disabled for the drag - note that blur might remain
- // disabled at this point due to the started overview transition (which
- // triggers home screen scale animation).
- 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()->app_list_controller()->UpdateScaleAndOpacityForHomeLauncher(
- 1.0f /*scale*/, 1.0f /*opacity*/, absl::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
|