xref: /aosp_15_r20/external/libchrome-gestures/include/mouse_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 <gtest/gtest.h>  // For FRIEND_TEST
6 
7 #include "include/gestures.h"
8 #include "include/interpreter.h"
9 #include "include/prop_registry.h"
10 #include "include/tracer.h"
11 
12 #ifndef GESTURES_MOUSE_INTERPRETER_H_
13 #define GESTURES_MOUSE_INTERPRETER_H_
14 
15 namespace gestures {
16 
17 class MouseInterpreter : public Interpreter, public PropertyDelegate {
18   FRIEND_TEST(MouseInterpreterTest, SimpleTest);
19   FRIEND_TEST(MouseInterpreterTest, HighResolutionVerticalScrollTest);
20   FRIEND_TEST(MouseInterpreterTest, ScrollAccelerationOnAndOffTest);
21   FRIEND_TEST(MouseInterpreterTest, JankyScrollTest);
22   FRIEND_TEST(MouseInterpreterTest, WheelTickReportingHighResTest);
23   FRIEND_TEST(MouseInterpreterTest, WheelTickReportingLowResTest);
24   FRIEND_TEST(MouseInterpreterTest, EmulateScrollWheelTest);
25  public:
26   MouseInterpreter(PropRegistry* prop_reg, Tracer* tracer);
~MouseInterpreter()27   virtual ~MouseInterpreter() {};
28 
29  protected:
30   virtual void SyncInterpretImpl(HardwareState& hwstate, stime_t* timeout);
31   // These functions interpret mouse events, which include button clicking and
32   // mouse movement. This function needs two consecutive HardwareState. If no
33   // mouse events are presented, result object is not modified. Scroll wheel
34   // events are not interpreted as they are handled differently for normal
35   // mice and multi-touch mice (ignored for multi-touch mice and accelerated
36   // for normal mice).
37   void InterpretMouseButtonEvent(const HardwareState& prev_state,
38                                  const HardwareState& hwstate);
39 
40   void InterpretMouseMotionEvent(const HardwareState& prev_state,
41                                  const HardwareState& hwstate);
42   // Check for scroll wheel events and produce scroll gestures.
43   void InterpretScrollWheelEvent(const HardwareState& hwstate,
44                                  bool is_vertical);
45   bool EmulateScrollWheel(const HardwareState& hwstate);
46  private:
47   struct WheelRecord {
WheelRecordWheelRecord48     WheelRecord(float v, stime_t t): change(v), timestamp(t) {}
WheelRecordWheelRecord49     WheelRecord(): change(0), timestamp(0) {}
50     float change;
51     stime_t timestamp;
52   };
53 
54   // Accelerate mouse scroll offsets so that it is larger when the user scroll
55   // the mouse wheel faster.
56   double ComputeScrollAccelFactor(double input_speed);
57 
58   Gesture CreateWheelGesture(stime_t start, stime_t end, float dx, float dy,
59                              int tick_120ths_dx, int tick_120ths_dy);
60 
61   HardwareState prev_state_;
62 
63   // Records last scroll wheel events.
64   std::vector<WheelRecord> last_vertical_wheels_, last_horizontal_wheels_;
65 
66   // Accumulators to measure scroll distance while doing scroll wheel emulation
67   double wheel_emulation_accu_x_;
68   double wheel_emulation_accu_y_;
69 
70   // True while wheel emulation is locked in.
71   bool wheel_emulation_active_;
72 
73   // f_approximated = a0 + a1*v + a2*v^2 + a3*v^3 + a4*v^4
74   double scroll_accel_curve_[5];
75 
76   // Reverse wheel scrolling.
77   BoolProperty reverse_scrolling_;
78 
79   // Mouse scroll acceleration.
80   BoolProperty scroll_acceleration_;
81 
82   // Mouse scroll sensitivity 1..5.
83   IntProperty scroll_sensitivity_;
84 
85   // Enable high-resolution scrolling.
86   BoolProperty hi_res_scrolling_;
87 
88   // When calculating scroll velocity for the purpose of acceleration, we
89   // use the average of this many events in the same direction. This is to avoid
90   // over-accelerating if we receive batched events with timestamps that are
91   // artificially close. If we don't have enough events, we won't accelerate at
92   // all.
93   IntProperty scroll_velocity_buffer_size_;
94 
95   // We use normal CDF to simulate scroll wheel acceleration curve. Use the
96   // following method to generate the coefficients of a degree-4 polynomial
97   // regression for a specific normal cdf in Python.
98   //
99   // Note: x for wheel value, v for velocity, y for scroll pixels (offset),
100   // and v = x / dt.
101   //
102   // The offset is computed as x * f(v) where f() outputs the acceleration
103   // factor for the given input speed. The formula allows us to produce similar
104   // offsets regardless of the mouse scrolling resolution. Since we want y to
105   // follow the normal CDF, we need to attenuate the case where x >= 1. This can
106   // happen when the user scrolls really fast, e.g., more than 1 unit within 8ms
107   // for a common, low-resolution mouse.
108   //
109   // In reality, v ranges from 1 to 120+ for an Apple Mighty Mouse, use range
110   // greater than that to minimize approximation error at the end points.
111   // In our case, the range is [-50, 200].
112   //
113   // Python (3) code:
114   // import numpy as np
115   // from scipy.stats import norm
116   // v = np.arange(-50, 201)
117   // f = (580 * norm.cdf(v, 100, 40) + 20) / np.maximum(v / 125.0, 1)
118   // coeff = np.flip(np.polyfit(v, f, 4), 0)
119   // Adjust the scroll acceleration curve
120   DoubleArrayProperty scroll_accel_curve_prop_;
121 
122   // when x is 177, the polynomial curve gives 450, the max pixels to scroll.
123   DoubleProperty scroll_max_allowed_input_speed_;
124 
125   // Force scroll wheel emulation for any devices
126   BoolProperty force_scroll_wheel_emulation_;
127 
128   // Multiplication factor to translate cursor motion into scrolling
129   DoubleProperty scroll_wheel_emulation_speed_;
130 
131   // Movement distance after which to start scroll wheel emulation [in mm]
132   DoubleProperty scroll_wheel_emulation_thresh_;
133 
134   // Whether to output GestureMouseWheel or GestureScroll structs from scrolls.
135   // TODO(chromium:1077644): remove once Chrome is migrated to the new structs.
136   BoolProperty output_mouse_wheel_gestures_;
137 };
138 
139 }  // namespace gestures
140 
141 #endif  // GESTURES_MOUSE_INTERPRETER_H_
142