xref: /aosp_15_r20/external/libchrome-gestures/src/gestures.cc (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 "include/gestures.h"
6 
7 #include <cstring>
8 #include <sys/time.h>
9 
10 #include "include/accel_filter_interpreter.h"
11 #include "include/box_filter_interpreter.h"
12 #include "include/click_wiggle_filter_interpreter.h"
13 #include "include/finger_merge_filter_interpreter.h"
14 #include "include/finger_metrics.h"
15 #include "include/fling_stop_filter_interpreter.h"
16 #include "include/haptic_button_generator_filter_interpreter.h"
17 #include "include/iir_filter_interpreter.h"
18 #include "include/immediate_interpreter.h"
19 #include "include/integral_gesture_filter_interpreter.h"
20 #include "include/logging.h"
21 #include "include/logging_filter_interpreter.h"
22 #include "include/lookahead_filter_interpreter.h"
23 #include "include/metrics_filter_interpreter.h"
24 #include "include/mouse_interpreter.h"
25 #include "include/multitouch_mouse_interpreter.h"
26 #include "include/non_linearity_filter_interpreter.h"
27 #include "include/palm_classifying_filter_interpreter.h"
28 #include "include/prop_registry.h"
29 #include "include/scaling_filter_interpreter.h"
30 #include "include/sensor_jump_filter_interpreter.h"
31 #include "include/split_correcting_filter_interpreter.h"
32 #include "include/stationary_wiggle_filter_interpreter.h"
33 #include "include/string_util.h"
34 #include "include/stuck_button_inhibitor_filter_interpreter.h"
35 #include "include/t5r2_correcting_filter_interpreter.h"
36 #include "include/timestamp_filter_interpreter.h"
37 #include "include/trace_marker.h"
38 #include "include/tracer.h"
39 #include "include/trend_classifying_filter_interpreter.h"
40 #include "include/util.h"
41 
42 using std::string;
43 using std::min;
44 using gestures::StringPrintf;
45 
46 // C API:
47 
48 static const int kMinSupportedVersion = 1;
49 static const int kMaxSupportedVersion = 1;
50 
StimeFromTimeval(const struct timeval * tv)51 stime_t StimeFromTimeval(const struct timeval* tv) {
52   return static_cast<stime_t>(tv->tv_sec) +
53       static_cast<stime_t>(tv->tv_usec) / 1000000.0;
54 }
55 
StimeFromTimespec(const struct timespec * ts)56 stime_t StimeFromTimespec(const struct timespec* ts) {
57   return static_cast<stime_t>(ts->tv_sec) +
58       static_cast<stime_t>(ts->tv_nsec) / 1000000000.0;
59 }
60 
String() const61 std::string HardwareProperties::String() const {
62   return StringPrintf("%f,  // left edge\n"
63                       "%f,  // top edge\n"
64                       "%f,  // right edge\n"
65                       "%f,  // bottom edge\n"
66                       "%f,  // x pixels/TP width\n"
67                       "%f,  // y pixels/TP height\n"
68                       "%f,  // orientation minimum\n"
69                       "%f,  // orientation maximum\n"
70                       "%u,  // max fingers\n"
71                       "%u,  // max touch\n"
72                       "%u,  // t5r2\n"
73                       "%u,  // semi-mt\n"
74                       "%u   // is button pad\n",
75                       left, top, right, bottom,
76                       res_x,
77                       res_y,
78                       orientation_minimum,
79                       orientation_maximum,
80                       max_finger_cnt,
81                       max_touch_cnt,
82                       supports_t5r2,
83                       support_semi_mt,
84                       is_button_pad);
85 }
86 
87 namespace {
NameForFingerStateFlag(unsigned flag)88 string NameForFingerStateFlag(unsigned flag) {
89 #define CASERET(name)                           \
90   case GESTURES_FINGER_##name: return #name
91   switch (flag) {
92     CASERET(WARP_X_NON_MOVE);
93     CASERET(WARP_Y_NON_MOVE);
94     CASERET(NO_TAP);
95     CASERET(POSSIBLE_PALM);
96     CASERET(PALM);
97     CASERET(WARP_X_MOVE);
98     CASERET(WARP_Y_MOVE);
99     CASERET(WARP_X_TAP_MOVE);
100     CASERET(WARP_Y_TAP_MOVE);
101     CASERET(MERGE);
102     CASERET(TREND_INC_X);
103     CASERET(TREND_DEC_X);
104     CASERET(TREND_INC_Y);
105     CASERET(TREND_DEC_Y);
106     CASERET(TREND_INC_PRESSURE);
107     CASERET(TREND_DEC_PRESSURE);
108     CASERET(TREND_INC_TOUCH_MAJOR);
109     CASERET(TREND_DEC_TOUCH_MAJOR);
110     CASERET(INSTANTANEOUS_MOVING);
111     CASERET(WARP_TELEPORTATION);
112   }
113 #undef CASERET
114   return "";
115 }
116 }  // namespace {}
117 
FlagsString(unsigned flags)118 string FingerState::FlagsString(unsigned flags) {
119   string ret;
120   const char kPipeSeparator[] = " | ";
121   for (unsigned i = 0; i < 8 * sizeof(flags); i++) {
122     const unsigned flag = 1 << i;
123     const string name = NameForFingerStateFlag(flag);
124     if ((flags & flag) && !name.empty()) {
125       ret += kPipeSeparator;
126       ret += name;
127       flags &= ~flag;
128     }
129   }
130   if (flags) {
131     // prepend remaining number
132     ret = StringPrintf("%u%s", flags, ret.c_str());
133   } else if (ret.rfind(kPipeSeparator, 0) == 0) {
134     // strip extra pipe
135     ret = ret.substr(strlen(kPipeSeparator));
136   } else {
137     ret = "no flags";
138   }
139   return ret;
140 }
141 
String() const142 string FingerState::String() const {
143   return StringPrintf("{ %d: (%.2f, %.2f), touch %.2fx%.2f, width %.2fx%.2f, "
144                       "pressure %.2f, orient %.2f%s }",
145                       tracking_id,
146                       position_x, position_y,
147                       touch_major, touch_minor,
148                       width_major, width_minor,
149                       pressure,
150                       orientation,
151                       flags ? (", " + FlagsString(flags)).c_str() : "");
152 }
153 
GetFingerState(short tracking_id)154 FingerState* HardwareState::GetFingerState(short tracking_id) {
155   return const_cast<FingerState*>(
156       const_cast<const HardwareState*>(this)->GetFingerState(tracking_id));
157 }
158 
GetFingerState(short tracking_id) const159 const FingerState* HardwareState::GetFingerState(short tracking_id) const {
160   for (short i = 0; i < finger_cnt; i++) {
161     if (fingers[i].tracking_id == tracking_id)
162       return &fingers[i];
163   }
164   return nullptr;
165 }
166 
String() const167 string HardwareState::String() const {
168   string ret = StringPrintf("{ %f, buttons 0x%x, %d f, %d t, {",
169                             timestamp,
170                             buttons_down,
171                             finger_cnt,
172                             touch_cnt);
173   for (size_t i = 0; i < finger_cnt; i++) {
174     if (i != 0)
175       ret += ",";
176     ret += " ";
177     ret += fingers[i].String();
178   }
179   if (finger_cnt > 0)
180     ret += " ";
181   ret += "} }";
182   return ret;
183 }
184 
SameFingersAs(const HardwareState & that) const185 bool HardwareState::SameFingersAs(const HardwareState& that) const {
186   if (finger_cnt != that.finger_cnt || touch_cnt != that.touch_cnt)
187     return false;
188   // For now, require fingers to be in the same slots
189   for (size_t i = 0; i < finger_cnt; i++)
190     if (fingers[i].tracking_id != that.fingers[i].tracking_id)
191       return false;
192   return true;
193 }
194 
DeepCopy(const HardwareState & that,unsigned short max_finger_cnt)195 void HardwareState::DeepCopy(const HardwareState& that,
196                              unsigned short max_finger_cnt) {
197   timestamp = that.timestamp;
198   buttons_down = that.buttons_down;
199   touch_cnt = that.touch_cnt;
200   finger_cnt = min(that.finger_cnt, max_finger_cnt);
201   if(that.fingers != nullptr) {
202     memcpy(fingers, that.fingers, finger_cnt * sizeof(FingerState));
203   } else if (finger_cnt > 0) {
204     Err("HardwareState with no finger data but %d finger count", finger_cnt);
205   }
206   rel_x = that.rel_x;
207   rel_y = that.rel_y;
208   rel_wheel = that.rel_wheel;
209   rel_wheel_hi_res = that.rel_wheel_hi_res;
210   rel_hwheel = that.rel_hwheel;
211   msc_timestamp = that.msc_timestamp;
212 }
213 
String() const214 string Gesture::String() const {
215   switch (type) {
216     case kGestureTypeNull:
217       return "(Gesture type: null)";
218     case kGestureTypeContactInitiated:
219       return StringPrintf("(Gesture type: contactInitiated "
220                           "start: %f stop: %f)", start_time, end_time);
221     case kGestureTypeMove:
222       return StringPrintf("(Gesture type: move start: %f stop: %f "
223                           "dx: %f dy: %f ordinal_dx: %f ordinal_dy: %f)",
224                           start_time, end_time,
225                           details.move.dx, details.move.dy,
226                           details.move.ordinal_dx, details.move.ordinal_dy);
227     case kGestureTypeScroll:
228       return StringPrintf("(Gesture type: scroll start: %f stop: %f "
229                           "dx: %f dy: %f ordinal_dx: %f ordinal_dy: %f)",
230                           start_time, end_time,
231                           details.scroll.dx, details.scroll.dy,
232                           details.scroll.ordinal_dx, details.scroll.ordinal_dy);
233     case kGestureTypeMouseWheel:
234       return StringPrintf("(Gesture type: wheel start: %f stop %f "
235                           "dx: %f dy: %f "
236                           "tick_120ths_dx: %d tick_120ths_dy: %d)",
237                           start_time, end_time,
238                           details.wheel.dx, details.wheel.dy,
239                           details.wheel.tick_120ths_dx,
240                           details.wheel.tick_120ths_dy);
241     case kGestureTypePinch:
242       return StringPrintf("(Gesture type: pinch start: %f stop: %f "
243                           "dz: %f ordinal_dz: %f, state: %d)", start_time,
244                           end_time, details.pinch.dz, details.pinch.ordinal_dz,
245                           details.pinch.zoom_state);
246     case kGestureTypeButtonsChange:
247       return StringPrintf("(Gesture type: buttons start: %f stop: "
248                           "%f down: %d up: %d is_tap: %s)", start_time, end_time,
249                           details.buttons.down, details.buttons.up,
250                           details.buttons.is_tap ? "true" : "false");
251     case kGestureTypeFling:
252       return StringPrintf("(Gesture type: fling start: %f stop: "
253                           "%f vx: %f vy: %f ordinal_dx: %f ordinal_dy: %f "
254                           "state: %s)", start_time, end_time,
255                           details.fling.vx, details.fling.vy,
256                           details.fling.ordinal_vx, details.fling.ordinal_vy,
257                           details.fling.fling_state == GESTURES_FLING_START ?
258                           "start" : "tapdown");
259     case kGestureTypeSwipe:
260       return StringPrintf("(Gesture type: swipe start: %f stop: %f "
261                           "dx: %f dy: %f ordinal_dx: %f ordinal_dy: %f)",
262                           start_time, end_time,
263                           details.swipe.dx, details.swipe.dy,
264                           details.swipe.ordinal_dx, details.swipe.ordinal_dy);
265     case kGestureTypeSwipeLift:
266       return StringPrintf("(Gesture type: swipeLift start: %f stop: %f)",
267                           start_time, end_time);
268     case kGestureTypeFourFingerSwipe:
269       return StringPrintf("(Gesture type: fourFingerSwipe start: %f stop: %f "
270                           "dx: %f dy: %f ordinal_dx: %f ordinal_dy: %f)",
271                           start_time, end_time,
272                           details.four_finger_swipe.dx,
273                           details.four_finger_swipe.dy,
274                           details.four_finger_swipe.ordinal_dx,
275                           details.four_finger_swipe.ordinal_dy);
276     case kGestureTypeFourFingerSwipeLift:
277       return StringPrintf("(Gesture type: fourFingerSwipeLift start: %f "
278                           "stop: %f)", start_time, end_time);
279     case kGestureTypeMetrics:
280       return StringPrintf("(Gesture type: metrics start: %f stop: %f "
281                           "type: %d d1: %f d2: %f)", start_time, end_time,
282                           details.metrics.type,
283                           details.metrics.data[0], details.metrics.data[1]);
284   }
285   return "(Gesture type: unknown)";
286 }
287 
operator ==(const Gesture & that) const288 bool Gesture::operator==(const Gesture& that) const {
289   if (type != that.type)
290     return false;
291   bool times_equal = gestures::DoubleEq(start_time, that.start_time) &&
292                      gestures::DoubleEq(end_time, that.end_time);
293   switch (type) {
294     case kGestureTypeNull:  // fall through
295     case kGestureTypeContactInitiated:
296       return true;
297     case kGestureTypeMove:
298       return times_equal &&
299           gestures::FloatEq(details.move.dx, that.details.move.dx) &&
300           gestures::FloatEq(details.move.dy, that.details.move.dy);
301     case kGestureTypeScroll:
302       return times_equal &&
303           gestures::FloatEq(details.scroll.dx, that.details.scroll.dx) &&
304           gestures::FloatEq(details.scroll.dy, that.details.scroll.dy);
305     case kGestureTypeMouseWheel:
306       return times_equal &&
307           gestures::FloatEq(details.wheel.dx, that.details.wheel.dx) &&
308           gestures::FloatEq(details.wheel.dy, that.details.wheel.dy) &&
309           details.wheel.tick_120ths_dx == that.details.wheel.tick_120ths_dx &&
310           details.wheel.tick_120ths_dy == that.details.wheel.tick_120ths_dy;
311     case kGestureTypePinch:
312       return times_equal &&
313           gestures::FloatEq(details.pinch.dz, that.details.pinch.dz);
314     case kGestureTypeButtonsChange:
315       return times_equal &&
316           details.buttons.down == that.details.buttons.down &&
317           details.buttons.up == that.details.buttons.up;
318     case kGestureTypeFling:
319       return times_equal &&
320           gestures::FloatEq(details.fling.vx, that.details.fling.vx) &&
321           gestures::FloatEq(details.fling.vy, that.details.fling.vy);
322     case kGestureTypeSwipe:
323       return times_equal &&
324           gestures::FloatEq(details.swipe.dx, that.details.swipe.dx);
325     case kGestureTypeSwipeLift:
326       return times_equal;
327     case kGestureTypeFourFingerSwipe:
328       return times_equal &&
329           gestures::FloatEq(details.four_finger_swipe.dx,
330               that.details.four_finger_swipe.dx);
331     case kGestureTypeFourFingerSwipeLift:
332       return times_equal;
333     case kGestureTypeMetrics:
334       return times_equal &&
335           details.metrics.type == that.details.metrics.type &&
336           gestures::FloatEq(details.metrics.data[0],
337               that.details.metrics.data[0]) &&
338           gestures::FloatEq(details.metrics.data[1],
339               that.details.metrics.data[1]);
340   }
341   return true;
342 }
343 
NewGestureInterpreterImpl(int version)344 GestureInterpreter* NewGestureInterpreterImpl(int version) {
345   if (version < kMinSupportedVersion) {
346     Err("Client too old. It's using version %d"
347         ", but library has min supported version %d",
348         version,
349         kMinSupportedVersion);
350     return nullptr;
351   }
352   if (version > kMaxSupportedVersion) {
353     Err("Client too new. It's using version %d"
354         ", but library has max supported version %d",
355         version,
356         kMaxSupportedVersion);
357     return nullptr;
358   }
359   return new gestures::GestureInterpreter(version);
360 }
361 
DeleteGestureInterpreter(GestureInterpreter * obj)362 void DeleteGestureInterpreter(GestureInterpreter* obj) {
363   delete obj;
364 }
365 
GestureInterpreterPushHardwareState(GestureInterpreter * obj,struct HardwareState * hwstate)366 void GestureInterpreterPushHardwareState(GestureInterpreter* obj,
367                                          struct HardwareState* hwstate) {
368   obj->PushHardwareState(hwstate);
369 }
370 
GestureInterpreterSetHardwareProperties(GestureInterpreter * obj,const struct HardwareProperties * hwprops)371 void GestureInterpreterSetHardwareProperties(
372     GestureInterpreter* obj,
373     const struct HardwareProperties* hwprops) {
374   obj->SetHardwareProperties(*hwprops);
375 }
376 
GestureInterpreterSetCallback(GestureInterpreter * obj,GestureReadyFunction fn,void * user_data)377 void GestureInterpreterSetCallback(GestureInterpreter* obj,
378                                    GestureReadyFunction fn,
379                                    void* user_data) {
380   obj->SetCallback(fn, user_data);
381 }
382 
GestureInterpreterSetTimerProvider(GestureInterpreter * obj,GesturesTimerProvider * tp,void * data)383 void GestureInterpreterSetTimerProvider(GestureInterpreter* obj,
384                                         GesturesTimerProvider* tp,
385                                         void* data) {
386   obj->SetTimerProvider(tp, data);
387 }
388 
GestureInterpreterSetPropProvider(GestureInterpreter * obj,GesturesPropProvider * pp,void * data)389 void GestureInterpreterSetPropProvider(GestureInterpreter* obj,
390                                        GesturesPropProvider* pp,
391                                        void* data) {
392   obj->SetPropProvider(pp, data);
393 }
394 
GestureInterpreterInitialize(GestureInterpreter * obj,enum GestureInterpreterDeviceClass cls)395 void GestureInterpreterInitialize(GestureInterpreter* obj,
396                                   enum GestureInterpreterDeviceClass cls) {
397   obj->Initialize(cls);
398 }
399 
400 // C++ API:
401 namespace gestures {
402 class GestureInterpreterConsumer : public GestureConsumer {
403  public:
GestureInterpreterConsumer(GestureReadyFunction callback,void * callback_data)404   GestureInterpreterConsumer(GestureReadyFunction callback,
405                              void* callback_data)
406       : callback_(callback),
407         callback_data_(callback_data) {}
408 
SetCallback(GestureReadyFunction callback,void * callback_data)409   void SetCallback(GestureReadyFunction callback, void* callback_data) {
410     callback_ = callback;
411     callback_data_ = callback_data;
412   }
413 
ConsumeGesture(const Gesture & gesture)414   void ConsumeGesture(const Gesture& gesture) {
415     AssertWithReturn(gesture.type != kGestureTypeNull);
416     if (callback_)
417       callback_(callback_data_, &gesture);
418   }
419 
420  private:
421   GestureReadyFunction callback_;
422   void* callback_data_;
423 };
424 }
425 
GestureInterpreter(int version)426 GestureInterpreter::GestureInterpreter(int version)
427     : callback_(nullptr),
428       callback_data_(nullptr),
429       timer_provider_(nullptr),
430       timer_provider_data_(nullptr),
431       interpret_timer_(nullptr),
432       loggingFilter_(nullptr) {
433   prop_reg_.reset(new PropRegistry);
434   tracer_.reset(new Tracer(prop_reg_.get(), TraceMarker::StaticTraceWrite));
435   TraceMarker::CreateTraceMarker();
436 }
437 
~GestureInterpreter()438 GestureInterpreter::~GestureInterpreter() {
439   SetTimerProvider(nullptr, nullptr);
440   SetPropProvider(nullptr, nullptr);
441   TraceMarker::DeleteTraceMarker();
442 }
443 
444 namespace {
InternalTimerCallback(stime_t now,void * callback_data)445 stime_t InternalTimerCallback(stime_t now, void* callback_data) {
446   Log("TimerCallback called");
447   GestureInterpreter* gi = reinterpret_cast<GestureInterpreter*>(callback_data);
448   stime_t next = NO_DEADLINE;
449   gi->TimerCallback(now, &next);
450   return next;
451 }
452 }
453 
PushHardwareState(HardwareState * hwstate)454 void GestureInterpreter::PushHardwareState(HardwareState* hwstate) {
455   if (!interpreter_.get()) {
456     Err("Filters are not composed yet!");
457     return;
458   }
459   stime_t timeout = NO_DEADLINE;
460   interpreter_->SyncInterpret(*hwstate, &timeout);
461   if (timer_provider_ && interpret_timer_) {
462     if (timeout == NO_DEADLINE) {
463       timer_provider_->cancel_fn(timer_provider_data_, interpret_timer_);
464     } else {
465       timer_provider_->set_fn(timer_provider_data_,
466                               interpret_timer_,
467                               timeout,
468                               InternalTimerCallback,
469                               this);
470       Log("Setting timer for %f s out.", timeout);
471     }
472   } else {
473     ErrOnce("No timer provider has been set, so some features won't work.");
474   }
475 }
476 
SetHardwareProperties(const HardwareProperties & hwprops)477 void GestureInterpreter::SetHardwareProperties(
478     const HardwareProperties& hwprops) {
479   if (!interpreter_.get()) {
480     Err("Filters are not composed yet!");
481     return;
482   }
483   hwprops_ = hwprops;
484   if (consumer_)
485     interpreter_->Initialize(&hwprops_, nullptr, mprops_.get(),
486                              consumer_.get());
487 }
488 
TimerCallback(stime_t now,stime_t * timeout)489 void GestureInterpreter::TimerCallback(stime_t now, stime_t* timeout) {
490   if (!interpreter_.get()) {
491     Err("Filters are not composed yet!");
492     return;
493   }
494   interpreter_->HandleTimer(now, timeout);
495 }
496 
SetTimerProvider(GesturesTimerProvider * tp,void * data)497 void GestureInterpreter::SetTimerProvider(GesturesTimerProvider* tp,
498                                           void* data) {
499   if (timer_provider_ == tp && timer_provider_data_ == data)
500     return;
501   if (timer_provider_ && interpret_timer_) {
502     timer_provider_->free_fn(timer_provider_data_, interpret_timer_);
503     interpret_timer_ = nullptr;
504   }
505   if (interpret_timer_)
506     Err("How was interpret_timer_ not null?!");
507   timer_provider_ = tp;
508   timer_provider_data_ = data;
509   if (timer_provider_)
510     interpret_timer_ = timer_provider_->create_fn(timer_provider_data_);
511 }
512 
SetPropProvider(GesturesPropProvider * pp,void * data)513 void GestureInterpreter::SetPropProvider(GesturesPropProvider* pp,
514                                          void* data) {
515   prop_reg_->SetPropProvider(pp, data);
516 }
517 
SetCallback(GestureReadyFunction callback,void * client_data)518 void GestureInterpreter::SetCallback(GestureReadyFunction callback,
519                                      void* client_data) {
520   callback_ = callback;
521   callback_data_ = client_data;
522 
523   if (consumer_)
524     consumer_->SetCallback(callback, client_data);
525 }
526 
set_callback(GestureReadyFunction callback,void * client_data)527 void GestureInterpreter::set_callback(GestureReadyFunction callback,
528                                       void* client_data) {
529   SetCallback(callback, client_data);
530 }
531 
InitializeTouchpad(void)532 void GestureInterpreter::InitializeTouchpad(void) {
533   if (prop_reg_.get()) {
534     stack_version_ = std::make_unique<IntProperty>(prop_reg_.get(),
535                                                    "Touchpad Stack Version", 2);
536     if (stack_version_->val_ == 2) {
537       InitializeTouchpad2();
538       return;
539     }
540   }
541 
542   Interpreter* temp = new ImmediateInterpreter(prop_reg_.get(), tracer_.get());
543   temp = new FlingStopFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
544                                         GESTURES_DEVCLASS_TOUCHPAD);
545   temp = new ClickWiggleFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
546   temp = new PalmClassifyingFilterInterpreter(prop_reg_.get(), temp,
547                                               tracer_.get());
548   temp = new IirFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
549   temp = new LookaheadFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
550   temp = new BoxFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
551   temp = new StationaryWiggleFilterInterpreter(prop_reg_.get(), temp,
552                                                tracer_.get());
553   temp = new SensorJumpFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
554   temp = new AccelFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
555   temp = new SplitCorrectingFilterInterpreter(prop_reg_.get(), temp,
556                                               tracer_.get());
557   temp = new TrendClassifyingFilterInterpreter(prop_reg_.get(), temp,
558                                                tracer_.get());
559   temp = new MetricsFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
560                                       GESTURES_DEVCLASS_TOUCHPAD);
561   temp = new ScalingFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
562                                       GESTURES_DEVCLASS_TOUCHPAD);
563   temp = new FingerMergeFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
564   temp = new StuckButtonInhibitorFilterInterpreter(temp, tracer_.get());
565   temp = new HapticButtonGeneratorFilterInterpreter(prop_reg_.get(), temp,
566                                                     tracer_.get());
567   temp = new T5R2CorrectingFilterInterpreter(prop_reg_.get(), temp,
568                                              tracer_.get());
569   temp = new NonLinearityFilterInterpreter(prop_reg_.get(), temp,
570                                            tracer_.get());
571   temp = new TimestampFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
572   temp = loggingFilter_ = new LoggingFilterInterpreter(prop_reg_.get(), temp,
573                                                        tracer_.get());
574   interpreter_.reset(temp);
575   temp = nullptr;
576 }
577 
InitializeTouchpad2(void)578 void GestureInterpreter::InitializeTouchpad2(void) {
579   Interpreter* temp = new ImmediateInterpreter(prop_reg_.get(), tracer_.get());
580   temp = new FlingStopFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
581                                         GESTURES_DEVCLASS_TOUCHPAD);
582   temp = new ClickWiggleFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
583   temp = new PalmClassifyingFilterInterpreter(prop_reg_.get(), temp,
584                                               tracer_.get());
585   temp = new LookaheadFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
586   temp = new BoxFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
587   temp = new StationaryWiggleFilterInterpreter(prop_reg_.get(), temp,
588                                                tracer_.get());
589   temp = new AccelFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
590   temp = new TrendClassifyingFilterInterpreter(prop_reg_.get(), temp,
591                                                tracer_.get());
592   temp = new MetricsFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
593                                       GESTURES_DEVCLASS_TOUCHPAD);
594   temp = new ScalingFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
595                                       GESTURES_DEVCLASS_TOUCHPAD);
596   temp = new FingerMergeFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
597   temp = new StuckButtonInhibitorFilterInterpreter(temp, tracer_.get());
598   temp = new HapticButtonGeneratorFilterInterpreter(prop_reg_.get(), temp,
599                                                     tracer_.get());
600   temp = new TimestampFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
601   temp = loggingFilter_ = new LoggingFilterInterpreter(prop_reg_.get(), temp,
602                                                        tracer_.get());
603   interpreter_.reset(temp);
604   temp = nullptr;
605 }
606 
InitializeMouse(GestureInterpreterDeviceClass cls)607 void GestureInterpreter::InitializeMouse(GestureInterpreterDeviceClass cls) {
608   Interpreter* temp = new MouseInterpreter(prop_reg_.get(), tracer_.get());
609   // TODO(clchiou;chromium-os:36321): Use mouse acceleration algorithm for mice
610   temp = new AccelFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
611   temp = new ScalingFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
612                                       cls);
613   temp = new MetricsFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
614                                       cls);
615   temp = new IntegralGestureFilterInterpreter(temp, tracer_.get());
616   temp = loggingFilter_ = new LoggingFilterInterpreter(prop_reg_.get(), temp,
617                                                        tracer_.get());
618   interpreter_.reset(temp);
619   temp = nullptr;
620 }
621 
InitializeMultitouchMouse(void)622 void GestureInterpreter::InitializeMultitouchMouse(void) {
623   Interpreter* temp = new MultitouchMouseInterpreter(prop_reg_.get(),
624                                                      tracer_.get());
625   temp = new FlingStopFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
626                                         GESTURES_DEVCLASS_MULTITOUCH_MOUSE);
627   temp = new ClickWiggleFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
628   temp = new LookaheadFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
629   temp = new BoxFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
630   // TODO(clchiou;chromium-os:36321): Use mouse acceleration algorithm for mice
631   temp = new AccelFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
632   temp = new ScalingFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
633                                       GESTURES_DEVCLASS_MULTITOUCH_MOUSE);
634   temp = new MetricsFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
635                                       GESTURES_DEVCLASS_MULTITOUCH_MOUSE);
636   temp = new IntegralGestureFilterInterpreter(temp, tracer_.get());
637   temp = new StuckButtonInhibitorFilterInterpreter(temp, tracer_.get());
638   temp = new NonLinearityFilterInterpreter(prop_reg_.get(), temp,
639                                            tracer_.get());
640   temp = loggingFilter_ = new LoggingFilterInterpreter(prop_reg_.get(), temp,
641                                                        tracer_.get());
642   interpreter_.reset(temp);
643   temp = nullptr;
644 }
645 
Initialize(GestureInterpreterDeviceClass cls)646 void GestureInterpreter::Initialize(GestureInterpreterDeviceClass cls) {
647   if (cls == GESTURES_DEVCLASS_TOUCHPAD ||
648       cls == GESTURES_DEVCLASS_TOUCHSCREEN)
649     InitializeTouchpad();
650   else if (cls == GESTURES_DEVCLASS_MOUSE ||
651            cls == GESTURES_DEVCLASS_POINTING_STICK)
652     InitializeMouse(cls);
653   else if (cls == GESTURES_DEVCLASS_MULTITOUCH_MOUSE)
654     InitializeMultitouchMouse();
655   else
656     Err("Couldn't recognize device class: %d", cls);
657 
658   mprops_.reset(new MetricsProperties(prop_reg_.get()));
659   consumer_.reset(new GestureInterpreterConsumer(callback_,
660                                                    callback_data_));
661 }
662 
EncodeActivityLog()663 std::string GestureInterpreter::EncodeActivityLog() {
664   return loggingFilter_->EncodeActivityLog();
665 }
666 
667 const GestureMove kGestureMove = { 0, 0, 0, 0 };
668 const GestureScroll kGestureScroll = { 0, 0, 0, 0, 0 };
669 const GestureMouseWheel kGestureMouseWheel = { 0, 0, 0, 0 };
670 const GestureButtonsChange kGestureButtonsChange = { 0, 0, 0 };
671 const GestureFling kGestureFling = { 0, 0, 0, 0, 0 };
672 const GestureSwipe kGestureSwipe = { 0, 0, 0, 0 };
673 const GestureFourFingerSwipe kGestureFourFingerSwipe = { 0, 0, 0, 0 };
674 const GesturePinch kGesturePinch = { 0, 0, 0 };
675 const GestureSwipeLift kGestureSwipeLift = { };
676 const GestureFourFingerSwipeLift kGestureFourFingerSwipeLift = { };
677 const GestureMetrics kGestureMetrics = { kGestureMetricsTypeUnknown, {0, 0} };
678