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
13namespace ui {
14
15class MotionEvent;
16class VelocityTrackerStrategy;
17
18namespace {
19struct Estimator;
20struct 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.
27class 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