swipe_home_to_overview_controller.cc 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright 2019 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. #include "ash/shelf/swipe_home_to_overview_controller.h"
  5. #include "ash/app_list/app_list_controller_impl.h"
  6. #include "ash/constants/ash_features.h"
  7. #include "ash/controls/contextual_tooltip.h"
  8. #include "ash/public/cpp/app_list/app_list_config.h"
  9. #include "ash/public/cpp/shelf_config.h"
  10. #include "ash/session/session_controller_impl.h"
  11. #include "ash/shelf/drag_window_from_shelf_controller.h"
  12. #include "ash/shelf/shelf_metrics.h"
  13. #include "ash/shell.h"
  14. #include "ash/wm/overview/overview_controller.h"
  15. #include "ash/wm/overview/overview_session.h"
  16. #include "base/bind.h"
  17. #include "base/callback_helpers.h"
  18. #include "base/cxx17_backports.h"
  19. #include "base/metrics/histogram_macros.h"
  20. #include "base/time/default_tick_clock.h"
  21. #include "third_party/abseil-cpp/absl/types/optional.h"
  22. #include "ui/compositor/layer_animation_element.h"
  23. #include "ui/compositor/scoped_layer_animation_settings.h"
  24. #include "ui/display/display.h"
  25. #include "ui/display/screen.h"
  26. #include "ui/gfx/animation/tween.h"
  27. namespace ash {
  28. namespace {
  29. // The target/min home launcher view scale.
  30. constexpr float kTargetHomeScale = 0.92f;
  31. // The home UI will be scaled down towards center of the screen as drag location
  32. // moves upwards. The target threshold for scaling is extended above the actual
  33. // threshold for transition so the UI keeps changing even when the gesture goes
  34. // over the threshold. This is the target home screen scaling threshold in terms
  35. // of ratio of the display height.
  36. constexpr float kHomeScalingThresholdDisplayHeightRatio = 0.5f;
  37. // The amount of time the drag has to remain bellow velocity threshold before
  38. // the transition to the overview starts.
  39. constexpr base::TimeDelta kOverviewTransitionDelay = base::Milliseconds(150);
  40. // The duration of transition from the home screen current scaled state to the
  41. // initial (unscaled) state when the gesture is canceled.
  42. constexpr base::TimeDelta kGestureCancelationDuration = base::Milliseconds(350);
  43. // The duration of transition from the home screen current scaled state to the
  44. // initial (unscaled) state when the gesture is canceled due to a back gesture.
  45. constexpr base::TimeDelta kGestureCancelationForBackDuration =
  46. base::Milliseconds(250);
  47. void UpdateHomeAnimationForGestureCancel(
  48. bool going_back,
  49. ui::ScopedLayerAnimationSettings* settings) {
  50. settings->SetTransitionDuration(going_back
  51. ? kGestureCancelationForBackDuration
  52. : kGestureCancelationDuration);
  53. settings->SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
  54. settings->SetPreemptionStrategy(
  55. ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
  56. }
  57. } // namespace
  58. SwipeHomeToOverviewController::SwipeHomeToOverviewController(int64_t display_id)
  59. : SwipeHomeToOverviewController(display_id,
  60. base::DefaultTickClock::GetInstance()) {}
  61. SwipeHomeToOverviewController::SwipeHomeToOverviewController(
  62. int64_t display_id,
  63. const base::TickClock* tick_clock)
  64. : display_id_(display_id), overview_transition_timer_(tick_clock) {}
  65. SwipeHomeToOverviewController::~SwipeHomeToOverviewController() {
  66. CancelDrag();
  67. }
  68. void SwipeHomeToOverviewController::Drag(const gfx::PointF& location_in_screen,
  69. float scroll_x,
  70. float scroll_y) {
  71. if (state_ == State::kFinished)
  72. return;
  73. display::Display display;
  74. if (!display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id_,
  75. &display)) {
  76. CancelDrag();
  77. return;
  78. }
  79. const int shelf_top =
  80. display.bounds().bottom() - ShelfConfig::Get()->shelf_size();
  81. if (state_ == State::kInitial) {
  82. // Do not start drag until the drag goes above the shelf.
  83. if (location_in_screen.y() > shelf_top)
  84. return;
  85. overview_transition_threshold_y_ =
  86. shelf_top - kVerticalThresholdForOverviewTransition;
  87. scaling_threshold_y_ =
  88. display.bounds().y() +
  89. display.bounds().height() * kHomeScalingThresholdDisplayHeightRatio;
  90. state_ = State::kTrackingDrag;
  91. home_screen_blur_disabler_ =
  92. Shell::Get()->app_list_controller()->DisableHomeScreenBackgroundBlur();
  93. } else {
  94. if (location_in_screen.y() <= overview_transition_threshold_y_ &&
  95. std::abs(scroll_x) + std::abs(scroll_y) <= kMovementVelocityThreshold) {
  96. ScheduleFinalizeDragAndShowOverview();
  97. } else {
  98. overview_transition_timer_.Stop();
  99. }
  100. }
  101. // Update the home screen scale to match progress during the drag.
  102. // Use extended threshold as the projected final transition position - UI
  103. // changing even after the user gets over the threshold should make the user
  104. // more likely to keep dragging up when they get really close to the threshold
  105. // for transition to overview (and reduce false negatives for detecting
  106. // transition to overview).
  107. const float distance = location_in_screen.y() - scaling_threshold_y_;
  108. const float target_distance = overview_transition_threshold_y_ -
  109. scaling_threshold_y_ +
  110. kVerticalThresholdForOverviewTransition;
  111. const float progress = gfx::Tween::CalculateValue(
  112. gfx::Tween::FAST_OUT_SLOW_IN,
  113. base::clamp(1.f - distance / target_distance, 0.0f, 1.0f));
  114. float scale = gfx::Tween::FloatValueBetween(progress, 1.0f, kTargetHomeScale);
  115. Shell::Get()->app_list_controller()->UpdateScaleAndOpacityForHomeLauncher(
  116. scale, 1.0f /*opacity*/, absl::nullopt /*animation_info*/,
  117. base::NullCallback());
  118. }
  119. void SwipeHomeToOverviewController::EndDrag(
  120. const gfx::PointF& location_in_screen,
  121. absl::optional<float> velocity_y) {
  122. if (state_ != State::kTrackingDrag) {
  123. state_ = State::kFinished;
  124. return;
  125. }
  126. // Upward swipe should return to the home screen's initial state.
  127. const bool go_back =
  128. velocity_y &&
  129. *velocity_y <
  130. -DragWindowFromShelfController::kVelocityToHomeScreenThreshold;
  131. // Overview is triggered by |overview_transition_timer_|. If EndDrag()
  132. // is called before the timer fires, the result of the gesture should be
  133. // staying on the home screen.
  134. FinalizeDragAndStayOnHomeScreen(go_back);
  135. }
  136. void SwipeHomeToOverviewController::CancelDrag() {
  137. if (state_ != State::kTrackingDrag) {
  138. state_ = State::kFinished;
  139. return;
  140. }
  141. FinalizeDragAndStayOnHomeScreen(/*go_back=*/false);
  142. }
  143. void SwipeHomeToOverviewController::ScheduleFinalizeDragAndShowOverview() {
  144. if (overview_transition_timer_.IsRunning())
  145. return;
  146. overview_transition_timer_.Start(
  147. FROM_HERE, kOverviewTransitionDelay,
  148. base::BindOnce(
  149. &SwipeHomeToOverviewController::FinalizeDragAndShowOverview,
  150. base::Unretained(this)));
  151. }
  152. void SwipeHomeToOverviewController::FinalizeDragAndShowOverview() {
  153. state_ = State::kFinished;
  154. overview_transition_threshold_y_ = 0;
  155. if (features::AreContextualNudgesEnabled()) {
  156. contextual_tooltip::HandleGesturePerformed(
  157. Shell::Get()->session_controller()->GetActivePrefService(),
  158. contextual_tooltip::TooltipType::kHomeToOverview);
  159. }
  160. UMA_HISTOGRAM_ENUMERATION(kEnterOverviewHistogramName,
  161. EnterOverviewFromHomeLauncher::kOverview);
  162. // NOTE: No need to update the home launcher opacity and scale here - the
  163. // AppListControllerImpl will update the home launcher state when it detects
  164. // that the overview is starting.
  165. Shell::Get()->overview_controller()->StartOverview(
  166. OverviewStartAction::kExitHomeLauncher);
  167. // No need to keep blur disabled for the drag - note that blur might remain
  168. // disabled at this point due to the started overview transition (which
  169. // triggers home screen scale animation).
  170. home_screen_blur_disabler_.reset();
  171. }
  172. void SwipeHomeToOverviewController::FinalizeDragAndStayOnHomeScreen(
  173. bool go_back) {
  174. overview_transition_timer_.Stop();
  175. overview_transition_threshold_y_ = 0;
  176. state_ = State::kFinished;
  177. if (go_back) {
  178. Shell::Get()->app_list_controller()->Back();
  179. UMA_HISTOGRAM_ENUMERATION(kEnterOverviewHistogramName,
  180. EnterOverviewFromHomeLauncher::kBack);
  181. } else {
  182. UMA_HISTOGRAM_ENUMERATION(kEnterOverviewHistogramName,
  183. EnterOverviewFromHomeLauncher::kCanceled);
  184. }
  185. // Make sure the home launcher scale and opacity return to the initial state.
  186. // Note that this is needed even if the gesture ended up in a fling, as early
  187. // gesture handling might have updated the launcher scale.
  188. Shell::Get()->app_list_controller()->UpdateScaleAndOpacityForHomeLauncher(
  189. 1.0f /*scale*/, 1.0f /*opacity*/, absl::nullopt /*animation_info*/,
  190. base::BindRepeating(&UpdateHomeAnimationForGestureCancel, go_back));
  191. // No need to keep blur disabled for the drag - note that blur might remain
  192. // disabled at this point due to the started home screen scale animation.
  193. home_screen_blur_disabler_.reset();
  194. }
  195. } // namespace ash