1 // Copyright 2018 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 #ifndef CC_INPUT_SNAP_FLING_CONTROLLER_H_ 6 #define CC_INPUT_SNAP_FLING_CONTROLLER_H_ 7 8 #include <memory> 9 10 #include "base/time/time.h" 11 #include "cc/cc_export.h" 12 #include "ui/gfx/geometry/vector2d_f.h" 13 14 namespace cc { 15 namespace test { 16 class SnapFlingControllerTest; 17 } 18 19 class SnapFlingCurve; 20 21 // A client that provides information to the controller. It also executes the 22 // scroll operations and requests animation frames. All the inputs and outputs 23 // are in the same coordinate space. 24 class SnapFlingClient { 25 public: 26 virtual bool GetSnapFlingInfoAndSetAnimatingSnapTarget( 27 const gfx::Vector2dF& natural_displacement, 28 gfx::Vector2dF* out_initial_position, 29 gfx::Vector2dF* out_target_position) const = 0; 30 virtual gfx::Vector2dF ScrollByForSnapFling(const gfx::Vector2dF& delta) = 0; 31 virtual void ScrollEndForSnapFling(bool did_finish) = 0; 32 virtual void RequestAnimationForSnapFling() = 0; 33 }; 34 35 // SnapFlingController ensures that an incoming fling event (or inertial-phase 36 // scroll event) would land on a snap position if there is a valid one nearby. 37 // It takes an input event, filters it if it conflicts with the current fling, 38 // or generates a curve if the SnapFlingClient finds a valid snap position. 39 // It also animates the curve by notifying the client to scroll when clock 40 // ticks. 41 class CC_EXPORT SnapFlingController { 42 public: 43 enum class GestureScrollType { kBegin, kUpdate, kEnd }; 44 45 struct GestureScrollUpdateInfo { 46 gfx::Vector2dF delta; 47 bool is_in_inertial_phase; 48 base::TimeTicks event_time; 49 }; 50 51 explicit SnapFlingController(SnapFlingClient* client); 52 53 static std::unique_ptr<SnapFlingController> CreateForTests( 54 SnapFlingClient* client, 55 std::unique_ptr<SnapFlingCurve> curve); 56 57 SnapFlingController(const SnapFlingController&) = delete; 58 ~SnapFlingController(); 59 60 SnapFlingController& operator=(const SnapFlingController&) = delete; 61 62 // Returns true if the event should be consumed for snapping and should not be 63 // processed further. 64 bool FilterEventForSnap(GestureScrollType gesture_scroll_type); 65 66 // Creates the snap fling curve from the first inertial GSU. Returns true if 67 // the event if a snap fling curve has been created and the event should not 68 // be processed further. 69 bool HandleGestureScrollUpdate(const GestureScrollUpdateInfo& info); 70 71 // Notifies the snap fling controller to update or end the scroll animation. 72 void Animate(base::TimeTicks time); 73 74 private: 75 friend class test::SnapFlingControllerTest; 76 77 enum class State { 78 // We haven't received an inertial GSU in this scroll sequence. 79 kIdle, 80 // We have received an inertial GSU but decided not to snap for this scroll 81 // sequence. 82 kIgnored, 83 // We have received an inertial GSU and decided to snap and animate it for 84 // this scroll sequence. So subsequent GSUs and GSE in the scroll sequence 85 // are consumed for snapping. 86 kActive, 87 // The animation of the snap fling has finished for this scroll sequence. 88 // Subsequent GSUs and GSE in the scroll sequence are ignored. 89 kFinished, 90 }; 91 92 SnapFlingController(SnapFlingClient* client, 93 std::unique_ptr<SnapFlingCurve> curve); 94 void ClearSnapFling(); 95 96 // Sets the |curve_| to |curve| and the |state| to |kActive|. 97 void SetCurveForTest(std::unique_ptr<SnapFlingCurve> curve); 98 SetActiveStateForTest()99 void SetActiveStateForTest() { state_ = State::kActive; } 100 101 SnapFlingClient* client_; 102 State state_ = State::kIdle; 103 std::unique_ptr<SnapFlingCurve> curve_; 104 }; 105 106 } // namespace cc 107 108 #endif // CC_INPUT_SNAP_FLING_CONTROLLER_H_ 109