1*aed3e508SAndroid Build Coastguard Worker // Copyright 2012 The ChromiumOS Authors
2*aed3e508SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*aed3e508SAndroid Build Coastguard Worker // found in the LICENSE file.
4*aed3e508SAndroid Build Coastguard Worker
5*aed3e508SAndroid Build Coastguard Worker #include "include/mouse_interpreter.h"
6*aed3e508SAndroid Build Coastguard Worker
7*aed3e508SAndroid Build Coastguard Worker #include <math.h>
8*aed3e508SAndroid Build Coastguard Worker
9*aed3e508SAndroid Build Coastguard Worker #include "include/logging.h"
10*aed3e508SAndroid Build Coastguard Worker #include "include/macros.h"
11*aed3e508SAndroid Build Coastguard Worker #include "include/tracer.h"
12*aed3e508SAndroid Build Coastguard Worker
13*aed3e508SAndroid Build Coastguard Worker namespace gestures {
14*aed3e508SAndroid Build Coastguard Worker
15*aed3e508SAndroid Build Coastguard Worker /*
16*aed3e508SAndroid Build Coastguard Worker * The number of subdivisions that `REL_WHEEL_HI_RES` and `REL_HWHEEL_HI_RES`
17*aed3e508SAndroid Build Coastguard Worker * have relative to `REL_WHEEL` and `REL_HWHEEL` respectively.
18*aed3e508SAndroid Build Coastguard Worker */
19*aed3e508SAndroid Build Coastguard Worker const static int REL_WHEEL_HI_RES_UNITS_PER_NOTCH = 120;
20*aed3e508SAndroid Build Coastguard Worker
21*aed3e508SAndroid Build Coastguard Worker // Default value for mouse scroll sensitivity.
22*aed3e508SAndroid Build Coastguard Worker const static int kMouseScrollSensitivityDefaultValue = 3;
23*aed3e508SAndroid Build Coastguard Worker
MouseInterpreter(PropRegistry * prop_reg,Tracer * tracer)24*aed3e508SAndroid Build Coastguard Worker MouseInterpreter::MouseInterpreter(PropRegistry* prop_reg, Tracer* tracer)
25*aed3e508SAndroid Build Coastguard Worker : Interpreter(nullptr, tracer, false),
26*aed3e508SAndroid Build Coastguard Worker wheel_emulation_accu_x_(0.0),
27*aed3e508SAndroid Build Coastguard Worker wheel_emulation_accu_y_(0.0),
28*aed3e508SAndroid Build Coastguard Worker wheel_emulation_active_(false),
29*aed3e508SAndroid Build Coastguard Worker reverse_scrolling_(prop_reg, "Mouse Reverse Scrolling", false),
30*aed3e508SAndroid Build Coastguard Worker scroll_acceleration_(prop_reg, "Mouse Scroll Acceleration", true),
31*aed3e508SAndroid Build Coastguard Worker scroll_sensitivity_(prop_reg,"Mouse Scroll Sensitivity",
32*aed3e508SAndroid Build Coastguard Worker kMouseScrollSensitivityDefaultValue),
33*aed3e508SAndroid Build Coastguard Worker hi_res_scrolling_(prop_reg, "Mouse High Resolution Scrolling", true),
34*aed3e508SAndroid Build Coastguard Worker scroll_velocity_buffer_size_(prop_reg, "Scroll Wheel Velocity Buffer", 3),
35*aed3e508SAndroid Build Coastguard Worker scroll_accel_curve_prop_(prop_reg, "Mouse Scroll Accel Curve",
36*aed3e508SAndroid Build Coastguard Worker scroll_accel_curve_, sizeof(scroll_accel_curve_) / sizeof(double)),
37*aed3e508SAndroid Build Coastguard Worker scroll_max_allowed_input_speed_(prop_reg,
38*aed3e508SAndroid Build Coastguard Worker "Mouse Scroll Max Input Speed",
39*aed3e508SAndroid Build Coastguard Worker 177.0),
40*aed3e508SAndroid Build Coastguard Worker force_scroll_wheel_emulation_(prop_reg,
41*aed3e508SAndroid Build Coastguard Worker "Force Scroll Wheel Emulation",
42*aed3e508SAndroid Build Coastguard Worker false),
43*aed3e508SAndroid Build Coastguard Worker scroll_wheel_emulation_speed_(prop_reg,
44*aed3e508SAndroid Build Coastguard Worker "Scroll Wheel Emulation Speed",
45*aed3e508SAndroid Build Coastguard Worker 100.0),
46*aed3e508SAndroid Build Coastguard Worker scroll_wheel_emulation_thresh_(prop_reg,
47*aed3e508SAndroid Build Coastguard Worker "Scroll Wheel Emulation Threshold",
48*aed3e508SAndroid Build Coastguard Worker 1.0),
49*aed3e508SAndroid Build Coastguard Worker output_mouse_wheel_gestures_(prop_reg,
50*aed3e508SAndroid Build Coastguard Worker "Output Mouse Wheel Gestures", false) {
51*aed3e508SAndroid Build Coastguard Worker InitName();
52*aed3e508SAndroid Build Coastguard Worker memset(&prev_state_, 0, sizeof(prev_state_));
53*aed3e508SAndroid Build Coastguard Worker // Scroll acceleration curve coefficients. See the definition for more
54*aed3e508SAndroid Build Coastguard Worker // details on how to generate them.
55*aed3e508SAndroid Build Coastguard Worker scroll_accel_curve_[0] = 1.0374e+01;
56*aed3e508SAndroid Build Coastguard Worker scroll_accel_curve_[1] = 4.1773e-01;
57*aed3e508SAndroid Build Coastguard Worker scroll_accel_curve_[2] = 2.5737e-02;
58*aed3e508SAndroid Build Coastguard Worker scroll_accel_curve_[3] = 8.0428e-05;
59*aed3e508SAndroid Build Coastguard Worker scroll_accel_curve_[4] = -9.1149e-07;
60*aed3e508SAndroid Build Coastguard Worker scroll_max_allowed_input_speed_.SetDelegate(this);
61*aed3e508SAndroid Build Coastguard Worker }
62*aed3e508SAndroid Build Coastguard Worker
SyncInterpretImpl(HardwareState & hwstate,stime_t * timeout)63*aed3e508SAndroid Build Coastguard Worker void MouseInterpreter::SyncInterpretImpl(HardwareState& hwstate,
64*aed3e508SAndroid Build Coastguard Worker stime_t* timeout) {
65*aed3e508SAndroid Build Coastguard Worker const char name[] = "MouseInterpreter::SyncInterpretImpl";
66*aed3e508SAndroid Build Coastguard Worker LogHardwareStatePre(name, hwstate);
67*aed3e508SAndroid Build Coastguard Worker
68*aed3e508SAndroid Build Coastguard Worker if(!EmulateScrollWheel(hwstate)) {
69*aed3e508SAndroid Build Coastguard Worker // Interpret mouse events in the order of pointer moves, scroll wheels and
70*aed3e508SAndroid Build Coastguard Worker // button clicks.
71*aed3e508SAndroid Build Coastguard Worker InterpretMouseMotionEvent(prev_state_, hwstate);
72*aed3e508SAndroid Build Coastguard Worker // Note that unlike touchpad scrolls, we interpret and send separate events
73*aed3e508SAndroid Build Coastguard Worker // for horizontal/vertical mouse wheel scrolls. This is partly to match what
74*aed3e508SAndroid Build Coastguard Worker // the xf86-input-evdev driver does and is partly because not all code in
75*aed3e508SAndroid Build Coastguard Worker // Chrome honors MouseWheelEvent that has both X and Y offsets.
76*aed3e508SAndroid Build Coastguard Worker InterpretScrollWheelEvent(hwstate, true);
77*aed3e508SAndroid Build Coastguard Worker InterpretScrollWheelEvent(hwstate, false);
78*aed3e508SAndroid Build Coastguard Worker InterpretMouseButtonEvent(prev_state_, hwstate);
79*aed3e508SAndroid Build Coastguard Worker }
80*aed3e508SAndroid Build Coastguard Worker // Pass max_finger_cnt = 0 to DeepCopy() since we don't care fingers and
81*aed3e508SAndroid Build Coastguard Worker // did not allocate any space for fingers.
82*aed3e508SAndroid Build Coastguard Worker prev_state_.DeepCopy(hwstate, 0);
83*aed3e508SAndroid Build Coastguard Worker
84*aed3e508SAndroid Build Coastguard Worker LogHardwareStatePost(name, hwstate);
85*aed3e508SAndroid Build Coastguard Worker }
86*aed3e508SAndroid Build Coastguard Worker
ComputeScrollAccelFactor(double input_speed)87*aed3e508SAndroid Build Coastguard Worker double MouseInterpreter::ComputeScrollAccelFactor(double input_speed) {
88*aed3e508SAndroid Build Coastguard Worker double result = 0.0;
89*aed3e508SAndroid Build Coastguard Worker double term = 1.0;
90*aed3e508SAndroid Build Coastguard Worker double allowed_speed = fabs(input_speed);
91*aed3e508SAndroid Build Coastguard Worker if (allowed_speed > scroll_max_allowed_input_speed_.val_)
92*aed3e508SAndroid Build Coastguard Worker allowed_speed = scroll_max_allowed_input_speed_.val_;
93*aed3e508SAndroid Build Coastguard Worker
94*aed3e508SAndroid Build Coastguard Worker // Compute the scroll acceleration factor.
95*aed3e508SAndroid Build Coastguard Worker for (size_t i = 0; i < arraysize(scroll_accel_curve_); i++) {
96*aed3e508SAndroid Build Coastguard Worker result += term * scroll_accel_curve_[i];
97*aed3e508SAndroid Build Coastguard Worker term *= allowed_speed;
98*aed3e508SAndroid Build Coastguard Worker }
99*aed3e508SAndroid Build Coastguard Worker return result;
100*aed3e508SAndroid Build Coastguard Worker }
101*aed3e508SAndroid Build Coastguard Worker
EmulateScrollWheel(const HardwareState & hwstate)102*aed3e508SAndroid Build Coastguard Worker bool MouseInterpreter::EmulateScrollWheel(const HardwareState& hwstate) {
103*aed3e508SAndroid Build Coastguard Worker const char name[] = "MouseInterpreter::EmulateScrollWheel";
104*aed3e508SAndroid Build Coastguard Worker
105*aed3e508SAndroid Build Coastguard Worker if (!force_scroll_wheel_emulation_.val_ && hwprops_->has_wheel)
106*aed3e508SAndroid Build Coastguard Worker return false;
107*aed3e508SAndroid Build Coastguard Worker bool down = hwstate.buttons_down & GESTURES_BUTTON_MIDDLE ||
108*aed3e508SAndroid Build Coastguard Worker (hwstate.buttons_down & GESTURES_BUTTON_LEFT &&
109*aed3e508SAndroid Build Coastguard Worker hwstate.buttons_down & GESTURES_BUTTON_RIGHT);
110*aed3e508SAndroid Build Coastguard Worker bool prev_down = prev_state_.buttons_down & GESTURES_BUTTON_MIDDLE ||
111*aed3e508SAndroid Build Coastguard Worker (prev_state_.buttons_down & GESTURES_BUTTON_LEFT &&
112*aed3e508SAndroid Build Coastguard Worker prev_state_.buttons_down & GESTURES_BUTTON_RIGHT);
113*aed3e508SAndroid Build Coastguard Worker bool raising = down && !prev_down;
114*aed3e508SAndroid Build Coastguard Worker bool falling = !down && prev_down;
115*aed3e508SAndroid Build Coastguard Worker
116*aed3e508SAndroid Build Coastguard Worker // Reset scroll emulation detection on button down.
117*aed3e508SAndroid Build Coastguard Worker if (raising) {
118*aed3e508SAndroid Build Coastguard Worker wheel_emulation_accu_x_ = 0;
119*aed3e508SAndroid Build Coastguard Worker wheel_emulation_accu_y_ = 0;
120*aed3e508SAndroid Build Coastguard Worker wheel_emulation_active_ = false;
121*aed3e508SAndroid Build Coastguard Worker }
122*aed3e508SAndroid Build Coastguard Worker
123*aed3e508SAndroid Build Coastguard Worker // Send button event if button has been released without scrolling.
124*aed3e508SAndroid Build Coastguard Worker if (falling && !wheel_emulation_active_) {
125*aed3e508SAndroid Build Coastguard Worker auto button_change = Gesture(kGestureButtonsChange,
126*aed3e508SAndroid Build Coastguard Worker prev_state_.timestamp,
127*aed3e508SAndroid Build Coastguard Worker hwstate.timestamp,
128*aed3e508SAndroid Build Coastguard Worker prev_state_.buttons_down,
129*aed3e508SAndroid Build Coastguard Worker prev_state_.buttons_down,
130*aed3e508SAndroid Build Coastguard Worker false); // is_tap
131*aed3e508SAndroid Build Coastguard Worker LogGestureProduce(name, button_change);
132*aed3e508SAndroid Build Coastguard Worker ProduceGesture(button_change);
133*aed3e508SAndroid Build Coastguard Worker }
134*aed3e508SAndroid Build Coastguard Worker
135*aed3e508SAndroid Build Coastguard Worker if (down) {
136*aed3e508SAndroid Build Coastguard Worker // Detect scroll emulation
137*aed3e508SAndroid Build Coastguard Worker if (!wheel_emulation_active_) {
138*aed3e508SAndroid Build Coastguard Worker wheel_emulation_accu_x_ += hwstate.rel_x;
139*aed3e508SAndroid Build Coastguard Worker wheel_emulation_accu_y_ += hwstate.rel_y;
140*aed3e508SAndroid Build Coastguard Worker double dist_sq = wheel_emulation_accu_x_ * wheel_emulation_accu_x_ +
141*aed3e508SAndroid Build Coastguard Worker wheel_emulation_accu_y_ * wheel_emulation_accu_y_;
142*aed3e508SAndroid Build Coastguard Worker double thresh_sq = scroll_wheel_emulation_thresh_.val_ *
143*aed3e508SAndroid Build Coastguard Worker scroll_wheel_emulation_thresh_.val_;
144*aed3e508SAndroid Build Coastguard Worker if (dist_sq > thresh_sq) {
145*aed3e508SAndroid Build Coastguard Worker // Lock into scroll emulation until button is released.
146*aed3e508SAndroid Build Coastguard Worker wheel_emulation_active_ = true;
147*aed3e508SAndroid Build Coastguard Worker }
148*aed3e508SAndroid Build Coastguard Worker }
149*aed3e508SAndroid Build Coastguard Worker
150*aed3e508SAndroid Build Coastguard Worker // Transform motion into scrolling.
151*aed3e508SAndroid Build Coastguard Worker if (wheel_emulation_active_) {
152*aed3e508SAndroid Build Coastguard Worker double scroll_x = hwstate.rel_x * scroll_wheel_emulation_speed_.val_;
153*aed3e508SAndroid Build Coastguard Worker double scroll_y = hwstate.rel_y * scroll_wheel_emulation_speed_.val_;
154*aed3e508SAndroid Build Coastguard Worker
155*aed3e508SAndroid Build Coastguard Worker auto scroll = Gesture(kGestureScroll, hwstate.timestamp,
156*aed3e508SAndroid Build Coastguard Worker hwstate.timestamp, scroll_x, scroll_y);
157*aed3e508SAndroid Build Coastguard Worker LogGestureProduce(name, scroll);
158*aed3e508SAndroid Build Coastguard Worker ProduceGesture(scroll);
159*aed3e508SAndroid Build Coastguard Worker }
160*aed3e508SAndroid Build Coastguard Worker return true;
161*aed3e508SAndroid Build Coastguard Worker }
162*aed3e508SAndroid Build Coastguard Worker
163*aed3e508SAndroid Build Coastguard Worker return false;
164*aed3e508SAndroid Build Coastguard Worker }
165*aed3e508SAndroid Build Coastguard Worker
InterpretScrollWheelEvent(const HardwareState & hwstate,bool is_vertical)166*aed3e508SAndroid Build Coastguard Worker void MouseInterpreter::InterpretScrollWheelEvent(const HardwareState& hwstate,
167*aed3e508SAndroid Build Coastguard Worker bool is_vertical) {
168*aed3e508SAndroid Build Coastguard Worker const char name[] = "MouseInterpreter::InterpretScrollWheelEvent";
169*aed3e508SAndroid Build Coastguard Worker
170*aed3e508SAndroid Build Coastguard Worker const size_t max_buffer_size = scroll_velocity_buffer_size_.val_;
171*aed3e508SAndroid Build Coastguard Worker const float scroll_wheel_event_time_delta_min = 0.008 * max_buffer_size;
172*aed3e508SAndroid Build Coastguard Worker bool use_high_resolution =
173*aed3e508SAndroid Build Coastguard Worker is_vertical && hwprops_->wheel_is_hi_res
174*aed3e508SAndroid Build Coastguard Worker && hi_res_scrolling_.val_;
175*aed3e508SAndroid Build Coastguard Worker // Vertical wheel or horizontal wheel.
176*aed3e508SAndroid Build Coastguard Worker WheelRecord current_wheel;
177*aed3e508SAndroid Build Coastguard Worker current_wheel.timestamp = hwstate.timestamp;
178*aed3e508SAndroid Build Coastguard Worker int ticks;
179*aed3e508SAndroid Build Coastguard Worker std::vector<WheelRecord>* last_wheels;
180*aed3e508SAndroid Build Coastguard Worker if (is_vertical) {
181*aed3e508SAndroid Build Coastguard Worker // Only vertical high-res scrolling is supported for now.
182*aed3e508SAndroid Build Coastguard Worker if (use_high_resolution) {
183*aed3e508SAndroid Build Coastguard Worker current_wheel.change = hwstate.rel_wheel_hi_res
184*aed3e508SAndroid Build Coastguard Worker / REL_WHEEL_HI_RES_UNITS_PER_NOTCH;
185*aed3e508SAndroid Build Coastguard Worker ticks = hwstate.rel_wheel_hi_res;
186*aed3e508SAndroid Build Coastguard Worker } else {
187*aed3e508SAndroid Build Coastguard Worker current_wheel.change = hwstate.rel_wheel;
188*aed3e508SAndroid Build Coastguard Worker ticks = hwstate.rel_wheel * REL_WHEEL_HI_RES_UNITS_PER_NOTCH;
189*aed3e508SAndroid Build Coastguard Worker }
190*aed3e508SAndroid Build Coastguard Worker last_wheels = &last_vertical_wheels_;
191*aed3e508SAndroid Build Coastguard Worker } else {
192*aed3e508SAndroid Build Coastguard Worker last_wheels = &last_horizontal_wheels_;
193*aed3e508SAndroid Build Coastguard Worker current_wheel.change = hwstate.rel_hwheel;
194*aed3e508SAndroid Build Coastguard Worker ticks = hwstate.rel_hwheel * REL_WHEEL_HI_RES_UNITS_PER_NOTCH;
195*aed3e508SAndroid Build Coastguard Worker }
196*aed3e508SAndroid Build Coastguard Worker
197*aed3e508SAndroid Build Coastguard Worker // Check if the wheel is scrolled.
198*aed3e508SAndroid Build Coastguard Worker if (current_wheel.change) {
199*aed3e508SAndroid Build Coastguard Worker stime_t start_time, end_time = hwstate.timestamp;
200*aed3e508SAndroid Build Coastguard Worker // Check if this scroll is in same direction as previous scroll event.
201*aed3e508SAndroid Build Coastguard Worker if (!last_wheels->empty() &&
202*aed3e508SAndroid Build Coastguard Worker ((current_wheel.change < 0 && last_wheels->back().change < 0) ||
203*aed3e508SAndroid Build Coastguard Worker (current_wheel.change > 0 && last_wheels->back().change > 0))) {
204*aed3e508SAndroid Build Coastguard Worker start_time = last_wheels->begin()->timestamp;
205*aed3e508SAndroid Build Coastguard Worker } else {
206*aed3e508SAndroid Build Coastguard Worker last_wheels->clear();
207*aed3e508SAndroid Build Coastguard Worker start_time = end_time;
208*aed3e508SAndroid Build Coastguard Worker }
209*aed3e508SAndroid Build Coastguard Worker
210*aed3e508SAndroid Build Coastguard Worker // We will only accelerate scrolls if we have filled our buffer of scroll
211*aed3e508SAndroid Build Coastguard Worker // events all in the same direction. If the buffer is full, then calculate
212*aed3e508SAndroid Build Coastguard Worker // scroll velocity using the average velocity of the entire buffer.
213*aed3e508SAndroid Build Coastguard Worker float velocity;
214*aed3e508SAndroid Build Coastguard Worker if (last_wheels->size() < max_buffer_size) {
215*aed3e508SAndroid Build Coastguard Worker velocity = 0.0;
216*aed3e508SAndroid Build Coastguard Worker } else {
217*aed3e508SAndroid Build Coastguard Worker stime_t dt = end_time - last_wheels->back().timestamp;
218*aed3e508SAndroid Build Coastguard Worker if (dt < scroll_wheel_event_time_delta_min) {
219*aed3e508SAndroid Build Coastguard Worker // The first packets received after BT wakeup may be delayed, causing
220*aed3e508SAndroid Build Coastguard Worker // the time delta between that and the subsequent packets to be
221*aed3e508SAndroid Build Coastguard Worker // artificially very small.
222*aed3e508SAndroid Build Coastguard Worker // Prevent small time deltas from triggering large amounts of
223*aed3e508SAndroid Build Coastguard Worker // acceleration by enforcing a minimum time delta.
224*aed3e508SAndroid Build Coastguard Worker dt = scroll_wheel_event_time_delta_min;
225*aed3e508SAndroid Build Coastguard Worker }
226*aed3e508SAndroid Build Coastguard Worker
227*aed3e508SAndroid Build Coastguard Worker last_wheels->pop_back();
228*aed3e508SAndroid Build Coastguard Worker float buffer_scroll_distance = current_wheel.change;
229*aed3e508SAndroid Build Coastguard Worker for (auto wheel : *last_wheels) {
230*aed3e508SAndroid Build Coastguard Worker buffer_scroll_distance += wheel.change;
231*aed3e508SAndroid Build Coastguard Worker }
232*aed3e508SAndroid Build Coastguard Worker
233*aed3e508SAndroid Build Coastguard Worker velocity = buffer_scroll_distance / dt;
234*aed3e508SAndroid Build Coastguard Worker }
235*aed3e508SAndroid Build Coastguard Worker last_wheels->insert(last_wheels->begin(), current_wheel);
236*aed3e508SAndroid Build Coastguard Worker
237*aed3e508SAndroid Build Coastguard Worker // When scroll acceleration is off, the scroll factor does not relate to
238*aed3e508SAndroid Build Coastguard Worker // scroll velocity. It's simply a constant multiplier to the wheel value.
239*aed3e508SAndroid Build Coastguard Worker const double unaccel_scroll_factors[] = { 20.0, 36.0, 72.0, 112.0, 164.0 };
240*aed3e508SAndroid Build Coastguard Worker
241*aed3e508SAndroid Build Coastguard Worker float offset = current_wheel.change * (
242*aed3e508SAndroid Build Coastguard Worker scroll_acceleration_.val_?
243*aed3e508SAndroid Build Coastguard Worker ComputeScrollAccelFactor(velocity) :
244*aed3e508SAndroid Build Coastguard Worker unaccel_scroll_factors[scroll_sensitivity_.val_ - 1]);
245*aed3e508SAndroid Build Coastguard Worker
246*aed3e508SAndroid Build Coastguard Worker if (is_vertical) {
247*aed3e508SAndroid Build Coastguard Worker // For historical reasons the vertical wheel (REL_WHEEL) is inverted
248*aed3e508SAndroid Build Coastguard Worker if (!reverse_scrolling_.val_) {
249*aed3e508SAndroid Build Coastguard Worker offset = -offset;
250*aed3e508SAndroid Build Coastguard Worker ticks = -ticks;
251*aed3e508SAndroid Build Coastguard Worker }
252*aed3e508SAndroid Build Coastguard Worker auto scroll_wheel = CreateWheelGesture(start_time, end_time,
253*aed3e508SAndroid Build Coastguard Worker 0, offset, 0, ticks);
254*aed3e508SAndroid Build Coastguard Worker LogGestureProduce(name, scroll_wheel);
255*aed3e508SAndroid Build Coastguard Worker ProduceGesture(scroll_wheel);
256*aed3e508SAndroid Build Coastguard Worker } else {
257*aed3e508SAndroid Build Coastguard Worker auto scroll_wheel = CreateWheelGesture(start_time, end_time,
258*aed3e508SAndroid Build Coastguard Worker offset, 0, ticks, 0);
259*aed3e508SAndroid Build Coastguard Worker LogGestureProduce(name, scroll_wheel);
260*aed3e508SAndroid Build Coastguard Worker ProduceGesture(scroll_wheel);
261*aed3e508SAndroid Build Coastguard Worker }
262*aed3e508SAndroid Build Coastguard Worker }
263*aed3e508SAndroid Build Coastguard Worker }
264*aed3e508SAndroid Build Coastguard Worker
CreateWheelGesture(stime_t start_time,stime_t end_time,float dx,float dy,int tick_120ths_dx,int tick_120ths_dy)265*aed3e508SAndroid Build Coastguard Worker Gesture MouseInterpreter::CreateWheelGesture(
266*aed3e508SAndroid Build Coastguard Worker stime_t start_time, stime_t end_time, float dx, float dy,
267*aed3e508SAndroid Build Coastguard Worker int tick_120ths_dx, int tick_120ths_dy) {
268*aed3e508SAndroid Build Coastguard Worker if (output_mouse_wheel_gestures_.val_) {
269*aed3e508SAndroid Build Coastguard Worker return Gesture(kGestureMouseWheel, start_time, end_time, dx, dy,
270*aed3e508SAndroid Build Coastguard Worker tick_120ths_dx, tick_120ths_dy);
271*aed3e508SAndroid Build Coastguard Worker } else {
272*aed3e508SAndroid Build Coastguard Worker return Gesture(kGestureScroll, start_time, end_time, dx, dy);
273*aed3e508SAndroid Build Coastguard Worker }
274*aed3e508SAndroid Build Coastguard Worker }
275*aed3e508SAndroid Build Coastguard Worker
InterpretMouseButtonEvent(const HardwareState & prev_state,const HardwareState & hwstate)276*aed3e508SAndroid Build Coastguard Worker void MouseInterpreter::InterpretMouseButtonEvent(
277*aed3e508SAndroid Build Coastguard Worker const HardwareState& prev_state, const HardwareState& hwstate) {
278*aed3e508SAndroid Build Coastguard Worker const char name[] = "MouseInterpreter::InterpretMouseButtonEvent";
279*aed3e508SAndroid Build Coastguard Worker
280*aed3e508SAndroid Build Coastguard Worker const unsigned buttons[] = {
281*aed3e508SAndroid Build Coastguard Worker GESTURES_BUTTON_LEFT,
282*aed3e508SAndroid Build Coastguard Worker GESTURES_BUTTON_MIDDLE,
283*aed3e508SAndroid Build Coastguard Worker GESTURES_BUTTON_RIGHT,
284*aed3e508SAndroid Build Coastguard Worker GESTURES_BUTTON_BACK,
285*aed3e508SAndroid Build Coastguard Worker GESTURES_BUTTON_FORWARD,
286*aed3e508SAndroid Build Coastguard Worker GESTURES_BUTTON_SIDE,
287*aed3e508SAndroid Build Coastguard Worker GESTURES_BUTTON_EXTRA,
288*aed3e508SAndroid Build Coastguard Worker };
289*aed3e508SAndroid Build Coastguard Worker unsigned down = 0, up = 0;
290*aed3e508SAndroid Build Coastguard Worker
291*aed3e508SAndroid Build Coastguard Worker for (unsigned i = 0; i < arraysize(buttons); i++) {
292*aed3e508SAndroid Build Coastguard Worker if (!(prev_state.buttons_down & buttons[i]) &&
293*aed3e508SAndroid Build Coastguard Worker (hwstate.buttons_down & buttons[i]))
294*aed3e508SAndroid Build Coastguard Worker down |= buttons[i];
295*aed3e508SAndroid Build Coastguard Worker if ((prev_state.buttons_down & buttons[i]) &&
296*aed3e508SAndroid Build Coastguard Worker !(hwstate.buttons_down & buttons[i]))
297*aed3e508SAndroid Build Coastguard Worker up |= buttons[i];
298*aed3e508SAndroid Build Coastguard Worker }
299*aed3e508SAndroid Build Coastguard Worker
300*aed3e508SAndroid Build Coastguard Worker if (down || up) {
301*aed3e508SAndroid Build Coastguard Worker auto button_change = Gesture(kGestureButtonsChange,
302*aed3e508SAndroid Build Coastguard Worker prev_state.timestamp,
303*aed3e508SAndroid Build Coastguard Worker hwstate.timestamp,
304*aed3e508SAndroid Build Coastguard Worker down,
305*aed3e508SAndroid Build Coastguard Worker up,
306*aed3e508SAndroid Build Coastguard Worker false); // is_tap
307*aed3e508SAndroid Build Coastguard Worker LogGestureProduce(name, button_change);
308*aed3e508SAndroid Build Coastguard Worker ProduceGesture(button_change);
309*aed3e508SAndroid Build Coastguard Worker }
310*aed3e508SAndroid Build Coastguard Worker }
311*aed3e508SAndroid Build Coastguard Worker
InterpretMouseMotionEvent(const HardwareState & prev_state,const HardwareState & hwstate)312*aed3e508SAndroid Build Coastguard Worker void MouseInterpreter::InterpretMouseMotionEvent(
313*aed3e508SAndroid Build Coastguard Worker const HardwareState& prev_state,
314*aed3e508SAndroid Build Coastguard Worker const HardwareState& hwstate) {
315*aed3e508SAndroid Build Coastguard Worker const char name[] = "MouseInterpreter::InterpretMouseMotionEvent";
316*aed3e508SAndroid Build Coastguard Worker
317*aed3e508SAndroid Build Coastguard Worker if (hwstate.rel_x || hwstate.rel_y) {
318*aed3e508SAndroid Build Coastguard Worker auto move = Gesture(kGestureMove,
319*aed3e508SAndroid Build Coastguard Worker prev_state.timestamp,
320*aed3e508SAndroid Build Coastguard Worker hwstate.timestamp,
321*aed3e508SAndroid Build Coastguard Worker hwstate.rel_x,
322*aed3e508SAndroid Build Coastguard Worker hwstate.rel_y);
323*aed3e508SAndroid Build Coastguard Worker LogGestureProduce(name, move);
324*aed3e508SAndroid Build Coastguard Worker ProduceGesture(move);
325*aed3e508SAndroid Build Coastguard Worker }
326*aed3e508SAndroid Build Coastguard Worker }
327*aed3e508SAndroid Build Coastguard Worker
328*aed3e508SAndroid Build Coastguard Worker } // namespace gestures
329