xref: /aosp_15_r20/external/libchrome-gestures/include/accel_filter_interpreter.h (revision aed3e5085e770be5b69ce25295ecf6ddf906af95)
1 // Copyright 2012 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <math.h>
6 
7 #include <memory>
8 #include <gtest/gtest.h>  // for FRIEND_TEST
9 
10 #include "include/filter_interpreter.h"
11 #include "include/gestures.h"
12 #include "include/prop_registry.h"
13 #include "include/tracer.h"
14 
15 #ifndef GESTURES_ACCEL_FILTER_INTERPRETER_H_
16 #define GESTURES_ACCEL_FILTER_INTERPRETER_H_
17 
18 namespace gestures {
19 
20 // This interpreter provides pointer and scroll acceleration based on
21 // an acceleration curve and the user's sensitivity setting.
22 //
23 // For additional documentation, see ../docs/accel_filter_interpreter.md.
24 
25 class AccelFilterInterpreter : public FilterInterpreter {
26   FRIEND_TEST(AccelFilterInterpreterTest, CurveSegmentInitializerTest);
27   FRIEND_TEST(AccelFilterInterpreterTest, CustomAccelTest);
28   FRIEND_TEST(AccelFilterInterpreterTest, SimpleTest);
29   FRIEND_TEST(AccelFilterInterpreterTest, TimingTest);
30   FRIEND_TEST(AccelFilterInterpreterTest, NotSmoothingTest);
31   FRIEND_TEST(AccelFilterInterpreterTest, SmoothingTest);
32   FRIEND_TEST(AccelFilterInterpreterTest, TinyMoveTest);
33   FRIEND_TEST(AccelFilterInterpreterTest, BadGestureTest);
34   FRIEND_TEST(AccelFilterInterpreterTest, BadDeltaTTest);
35   FRIEND_TEST(AccelFilterInterpreterTest, BadSpeedFlingTest);
36   FRIEND_TEST(AccelFilterInterpreterTest, BadSpeedMoveTest);
37   FRIEND_TEST(AccelFilterInterpreterTest, UnacceleratedMouseTest);
38   FRIEND_TEST(AccelFilterInterpreterTest, UnacceleratedTouchpadTest);
39   FRIEND_TEST(AccelFilterInterpreterTest, TouchpadPointAccelCurveTest);
40   FRIEND_TEST(AccelFilterInterpreterTest, TouchpadScrollAccelCurveTest);
41   FRIEND_TEST(AccelFilterInterpreterTest, AccelDebugDataTest);
42  public:
43   // Takes ownership of |next|:
44   AccelFilterInterpreter(PropRegistry* prop_reg, Interpreter* next,
45                          Tracer* tracer);
~AccelFilterInterpreter()46   virtual ~AccelFilterInterpreter() {}
47 
48   virtual void ConsumeGesture(const Gesture& gs);
49 
50  private:
51   struct CurveSegment {
CurveSegmentCurveSegment52     CurveSegment() : x_(INFINITY), sqr_(0.0), mul_(1.0), int_(0.0) {}
CurveSegmentCurveSegment53     CurveSegment(float x, float s, float m, float b)
54         : x_(x), sqr_(s), mul_(m), int_(b) {}
CurveSegmentCurveSegment55     CurveSegment(const CurveSegment& that)
56         : x_(that.x_), sqr_(that.sqr_), mul_(that.mul_), int_(that.int_) {}
57     // Be careful adding new members: We currently cast arrays of CurveSegment
58     // to arrays of float (to expose to the properties system)
59     double x_;  // Max X value of segment. User's point will be less than this.
60     double sqr_;  // x^2 multiplier
61     double mul_;  // Slope of line (x multiplier)
62     double int_;  // Intercept of line
63   };
64 
65   //**************************************************************************
66   // Worker Funnctions that are used internal to this class as well
67   // as giving internal information for testing/research purposes.
68 
69   // Calculate the Delta Time for a given gesture.
70   //    in:     gs, provided Gesture
71   //    ret:    delta time
72   float get_dt(const Gesture& gs);
73 
74   // Calculate the Delta Time and adjust the value if the calculation gives
75   // an out of bounds value.
76   //    in:     gs, provided Gesture
77   //    ret:    Reasonable Delta Time
78   float get_adjusted_dt(const Gesture& gs);
79 
80   // The calculations in the ConsumeGestures is generic but works on
81   // different fields based on what the gesture is.  This worker will
82   // gather the correct values for the ConsumeGestures process.
83   //    in:     gs, provided Gesture
84   //    out:    dx, address of delta X
85   //    out:    dy, address of delta Y
86   //    out:    x_scale, value of X scaling factor
87   //    out:    y_scale, value of Y scaling factor
88   //    out:    scale_out_x, address of X value to adjust
89   //    out:    scale_out_y, address of Y value to adjust
90   //    out:    scale_out_x_ordinal, address of X orginal value to adjust
91   //    out:    scale_out_y_ordinal, address of Y orginal value to adjust
92   //    out:    segs, address of CurveSegment array to use
93   //    out:    max_segs, number of array entries of segs
94   //    ret:    true, acceleration expected
95   //            false, acceleration not expected
96   bool get_accel_parameters(
97       Gesture& gs,
98       float*& dx, float*& dy,
99       float& x_scale, float& y_scale,
100       float*& scale_out_x, float*& scale_out_y,
101       float*& scale_out_x_ordinal, float*& scale_out_y_ordinal,
102       CurveSegment*& segs, size_t& max_segs);
103 
104   // Given a dx/dy/dt (non-fling motion) or, if dx and dy are nullptr,
105   // vx/vy (fling velocity) calculate the speed.
106   //    in:     dx, address of delta X
107   //    in:     dy, address of delta Y
108   //    in:     vx, value of X velocity (only valid if dx/dy are nullptr)
109   //    in:     vy, value of Y velocity (only valid if dx/dy are nullptr)
110   //    in:     dt, value of delta time (assumed 1 if dx/dy are nullptr)
111   //    out:    speed, actual distance/delta time
112   //    ret:    true, acceleration expected
113   //            false, acceleration not expected
114   bool get_actual_speed(
115       float* dx, float* dy,
116       float vx, float vy,
117       float dt,
118       float& speed);
119 
120   // Speed smoothing, this is currently disabled but can be enabled by
121   // means of the smooth_accel_ Property.
122   //    in:     gs, provided Gesture
123   //    inout:  speed, actual speed on input and smoothed on output
124   void smooth_speed(const Gesture& gs, float& speed);
125 
126   // Map a speed on a given CurveSegment array to a ratio multiplier.
127   //    in:     segs, address of CurveSegment array being used
128   //    in:     max_segs, number of array entries in segs
129   //    in:     speed, actual distance/delta time value
130   //    ret:    determined gain to apply
131   float RatioFromAccelCurve(const CurveSegment* segs,
132                             const size_t max_segs,
133                             const float speed);
134 
135   template<typename T>
LogDebugData(const T & debug_data)136   void LogDebugData(const T& debug_data) {
137     using EventDebug = ActivityLog::EventDebug;
138     if (EventDebugLoggingIsEnabled(EventDebug::Accel))
139       log_->LogDebugData(debug_data);
140   }
141 
142   //**************************************************************************
143 
144   static const size_t kMaxCurveSegs = 3;
145   static const size_t kMaxCustomCurveSegs = 20;
146   static const size_t kMaxUnaccelCurveSegs = 1;
147 
148   static const size_t kMaxAccelCurves = 5;
149 
150   // curves for sensitivity 1..5
151   CurveSegment point_curves_[kMaxAccelCurves][kMaxCurveSegs];
152   CurveSegment old_mouse_point_curves_[kMaxAccelCurves][kMaxCurveSegs];
153   CurveSegment mouse_point_curves_[kMaxAccelCurves][kMaxCurveSegs];
154   CurveSegment scroll_curves_[kMaxAccelCurves][kMaxCurveSegs];
155 
156   // curves when acceleration is disabled.
157   CurveSegment unaccel_point_curves_[kMaxAccelCurves];
158   CurveSegment unaccel_mouse_curves_[kMaxAccelCurves];
159   // TODO(zentaro): Add unaccelerated scroll curves.
160 
161   // Custom curves
162   CurveSegment tp_custom_point_[kMaxCustomCurveSegs];
163   CurveSegment tp_custom_scroll_[kMaxCustomCurveSegs];
164   CurveSegment mouse_custom_point_[kMaxCustomCurveSegs];
165   // Note: there is no mouse_custom_scroll_ b/c mouse wheel accel is
166   // handled in the MouseInterpreter class.
167 
168   // See max* and min_reasonable_dt_ properties
169   stime_t last_reasonable_dt_ = 0.05;
170 
171   // These are used to calculate acceleration, see smooth_accel_
172   stime_t last_end_time_ = -1.0;
173 
174   std::vector<float> last_mags_;
175   static const size_t kMaxLastMagsSize = 2;
176 
177   // These properties expose the custom curves (just above) to the
178   // property system.
179   DoubleArrayProperty tp_custom_point_prop_;
180   DoubleArrayProperty tp_custom_scroll_prop_;
181   DoubleArrayProperty mouse_custom_point_prop_;
182 
183   // These properties enable use of custom curves (just above).
184   BoolProperty use_custom_tp_point_curve_;
185   BoolProperty use_custom_tp_scroll_curve_;
186   BoolProperty use_custom_mouse_curve_;
187 
188   IntProperty pointer_sensitivity_;  // [1..5]
189   IntProperty scroll_sensitivity_;  // [1..5]
190 
191   DoubleProperty point_x_out_scale_;
192   DoubleProperty point_y_out_scale_;
193   DoubleProperty scroll_x_out_scale_;
194   DoubleProperty scroll_y_out_scale_;
195 
196   // These properties are automatically set on mice-like devices:
197   BoolProperty use_mouse_point_curves_;  // set on {touch,nontouch} mice
198   BoolProperty use_mouse_scroll_curves_;  // set on nontouch mice
199   // If use_mouse_point_curves_ is true, this is consulted to see which
200   // curves to use:
201   BoolProperty use_old_mouse_point_curves_;
202   // Flag for disabling mouse/touchpad acceleration.
203   BoolProperty pointer_acceleration_;
204 
205   // Sometimes on wireless hardware (e.g. Bluetooth), packets need to be
206   // resent. This can lead to a time between packets that very large followed
207   // by a very small one. Very small periods especially cause problems b/c they
208   // make the velocity seem very fast, which leads to an exaggeration of
209   // movement.
210   // To compensate, we have bounds on what we expect a reasonable period to be.
211   // Events that have too large or small a period get reassigned the last
212   // reasonable period.
213   DoubleProperty min_reasonable_dt_;
214   DoubleProperty max_reasonable_dt_;
215 
216   // If we enable smooth accel, the past few magnitudes are used to compute the
217   // multiplication factor.
218   BoolProperty smooth_accel_;
219 };
220 
221 }  // namespace gestures
222 
223 #endif  // GESTURES_SCALING_FILTER_INTERPRETER_H_
224