1 // Copyright 2014 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 UI_EVENTS_GESTURE_DETECTION_VELOCITY_TRACKER_H_ 6 #define UI_EVENTS_GESTURE_DETECTION_VELOCITY_TRACKER_H_ 7 8 #include "base/basictypes.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/time/time.h" 11 #include "ui/events/gesture_detection/bitset_32.h" 12 13 namespace ui { 14 15 class MotionEvent; 16 class VelocityTrackerStrategy; 17 18 namespace { 19 struct Estimator; 20 struct Position; 21 } 22 23 // Port of VelocityTracker from Android 24 // * platform/frameworks/native/include/input/VelocityTracker.h 25 // * Change-Id: I4983db61b53e28479fc90d9211fafff68f7f49a6 26 // * Please update the Change-Id as upstream Android changes are pulled. 27 class VelocityTracker { 28 public: 29 enum { 30 // The maximum number of pointers to use when computing the velocity. 31 // Note that the supplied MotionEvent may expose more than 16 pointers, but 32 // at most |MAX_POINTERS| will be used. 33 MAX_POINTERS = 16, 34 }; 35 36 enum Strategy { 37 // 1st order least squares. Quality: POOR. 38 // Frequently underfits the touch data especially when the finger 39 // accelerates or changes direction. Often underestimates velocity. The 40 // direction is overly influenced by historical touch points. 41 LSQ1, 42 43 // 2nd order least squares. Quality: VERY GOOD. 44 // Pretty much ideal, but can be confused by certain kinds of touch data, 45 // particularly if the panel has a tendency to generate delayed, 46 // duplicate or jittery touch coordinates when the finger is released. 47 LSQ2, 48 49 // 3rd order least squares. Quality: UNUSABLE. 50 // Frequently overfits the touch data yielding wildly divergent estimates 51 // of the velocity when the finger is released. 52 LSQ3, 53 54 // 2nd order weighted least squares, delta weighting. 55 // Quality: EXPERIMENTAL 56 WLSQ2_DELTA, 57 58 // 2nd order weighted least squares, central weighting. 59 // Quality: EXPERIMENTAL 60 WLSQ2_CENTRAL, 61 62 // 2nd order weighted least squares, recent weighting. 63 // Quality: EXPERIMENTAL 64 WLSQ2_RECENT, 65 66 // 1st order integrating filter. Quality: GOOD. 67 // Not as good as 'lsq2' because it cannot estimate acceleration but it is 68 // more tolerant of errors. Like 'lsq1', this strategy tends to 69 // underestimate 70 // the velocity of a fling but this strategy tends to respond to changes in 71 // direction more quickly and accurately. 72 INT1, 73 74 // 2nd order integrating filter. Quality: EXPERIMENTAL. 75 // For comparison purposes only. Unlike 'int1' this strategy can compensate 76 // for acceleration but it typically overestimates the effect. 77 INT2, 78 STRATEGY_MAX = INT2, 79 80 // The default velocity tracker strategy. 81 // Although other strategies are available for testing and comparison 82 // purposes, this is the strategy that applications will actually use. Be 83 // very careful when adjusting the default strategy because it can 84 // dramatically affect (often in a bad way) the user experience. 85 STRATEGY_DEFAULT = LSQ2, 86 }; 87 88 // Creates a velocity tracker using the default strategy for the platform. 89 VelocityTracker(); 90 91 // Creates a velocity tracker using the specified strategy. 92 // If strategy is NULL, uses the default strategy for the platform. 93 explicit VelocityTracker(Strategy strategy); 94 95 ~VelocityTracker(); 96 97 // Resets the velocity tracker state. 98 void Clear(); 99 100 // Adds movement information for all pointers in a MotionEvent, including 101 // historical samples. 102 void AddMovement(const MotionEvent& event); 103 104 // Gets the velocity of the specified pointer id in position units per second. 105 // Returns false and sets the velocity components to zero if there is 106 // insufficient movement information for the pointer. 107 bool GetVelocity(uint32_t id, float* outVx, float* outVy) const; 108 109 // Gets the active pointer id, or -1 if none. 110 inline int32_t GetActivePointerId() const { return active_pointer_id_; } 111 112 // Gets a bitset containing all pointer ids from the most recent movement. 113 inline BitSet32 GetCurrentPointerIdBits() const { 114 return current_pointer_id_bits_; 115 } 116 117 private: 118 // Resets the velocity tracker state for specific pointers. 119 // Call this method when some pointers have changed and may be reusing 120 // an id that was assigned to a different pointer earlier. 121 void ClearPointers(BitSet32 id_bits); 122 123 // Adds movement information for a set of pointers. 124 // The id_bits bitfield specifies the pointer ids of the pointers whose 125 // positions 126 // are included in the movement. 127 // The positions array contains position information for each pointer in order 128 // by 129 // increasing id. Its size should be equal to the number of one bits in 130 // id_bits. 131 void AddMovement(const base::TimeTicks& event_time, 132 BitSet32 id_bits, 133 const Position* positions); 134 135 // Gets an estimator for the recent movements of the specified pointer id. 136 // Returns false and clears the estimator if there is no information available 137 // about the pointer. 138 bool GetEstimator(uint32_t id, Estimator* out_estimator) const; 139 140 base::TimeTicks last_event_time_; 141 BitSet32 current_pointer_id_bits_; 142 int32_t active_pointer_id_; 143 scoped_ptr<VelocityTrackerStrategy> strategy_; 144 145 DISALLOW_COPY_AND_ASSIGN(VelocityTracker); 146 }; 147 148 } // namespace ui 149 150 #endif // UI_EVENTS_GESTURE_DETECTION_VELOCITY_TRACKER_H_ 151