• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stdio.h>
6 #include <vector>
7 
8 #include <gtest/gtest.h>
9 
10 #include "include/gestures.h"
11 #include "include/immediate_interpreter.h"
12 #include "include/string_util.h"
13 #include "include/unittest_util.h"
14 #include "include/util.h"
15 
16 namespace gestures {
17 
18 using std::string;
19 
20 class ImmediateInterpreterTest : public ::testing::Test {};
21 
TEST(ImmediateInterpreterTest,ScrollEventTest)22 TEST(ImmediateInterpreterTest, ScrollEventTest) {
23   ScrollEvent ev1 = {1.0, 2.0, 3.0};
24   ScrollEvent ev2 = {10.0, 20.0, 30.0};
25   ScrollEvent ev3 = ScrollEvent::Add(ev1, ev2);
26   EXPECT_EQ(11.0, ev3.dx);
27   EXPECT_EQ(22.0, ev3.dy);
28   EXPECT_EQ(33.0, ev3.dt);
29 
30   ScrollEventBuffer* evbuf = new ScrollEventBuffer(2);
31   evbuf->Insert(1.0, 2.0, 3.0);
32   ev1 = evbuf->Get(0);
33   EXPECT_EQ(1.0, ev1.dx);
34   EXPECT_EQ(2.0, ev1.dy);
35   EXPECT_EQ(3.0, ev1.dt);
36   ev1 = evbuf->Get(3);
37   EXPECT_EQ(0.0, ev1.dx);
38   EXPECT_EQ(0.0, ev1.dy);
39   EXPECT_EQ(0.0, ev1.dt);
40 }
41 
TEST(ImmediateInterpreterTest,HardwareStateBufferTest)42 TEST(ImmediateInterpreterTest, HardwareStateBufferTest) {
43   HardwareStateBuffer* hsb = new HardwareStateBuffer(10);
44   hsb->Reset(0);
45   EXPECT_EQ(hsb->Size(), 10);
46 }
47 
TEST(ImmediateInterpreterTest,ScrollManagerTest)48 TEST(ImmediateInterpreterTest, ScrollManagerTest) {
49   PropRegistry* my_prop_reg = new PropRegistry();
50   ScrollManager* sm = new ScrollManager(my_prop_reg);
51   ScrollEventBuffer* scroll_buffer = new ScrollEventBuffer(2);
52   ScrollEvent ev;
53 
54   sm->RegressScrollVelocity(*scroll_buffer, 1, &ev);
55   EXPECT_EQ(0.0, ev.dx);
56   EXPECT_EQ(0.0, ev.dy);
57   EXPECT_EQ(1.0, ev.dt);
58 }
59 
TEST(ImmediateInterpreterTest,MoveDownTest)60 TEST(ImmediateInterpreterTest, MoveDownTest) {
61   ImmediateInterpreter ii(NULL, NULL);
62 
63   HardwareProperties hwprops = {
64     0,  // left edge
65     0,  // top edge
66     1000,  // right edge
67     1000,  // bottom edge
68     500,  // pixels/TP width
69     500,  // pixels/TP height
70     96,  // screen DPI x
71     96,  // screen DPI y
72     -1,  // orientation minimum
73     2,   // orientation maximum
74     2,  // max fingers
75     5,  // max touch
76     0,  // tripletap
77     0,  // semi-mt
78     1,  // is button pad
79     0,  // has_wheel
80     0,  // wheel_is_hi_res
81     0,  // is haptic pad
82   };
83   TestInterpreterWrapper wrapper(&ii, &hwprops);
84 
85   FingerState finger_states[] = {
86     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
87     {0, 0, 0, 0, 1, 0, 10, 10, 1, 0},
88     {0, 0, 0, 0, 1, 0, 10, 20, 1, 0},
89     {0, 0, 0, 0, 1, 0, 20, 20, 1, 0}
90   };
91   HardwareState hardware_states[] = {
92     // time, buttons down, finger count, finger states pointer
93     make_hwstate(200000, 0, 1, 1, &finger_states[0]),
94     make_hwstate(210000, 0, 1, 1, &finger_states[1]),
95     make_hwstate(220000, 0, 1, 1, &finger_states[2]),
96     make_hwstate(230000, 0, 0, 0, NULL),
97     make_hwstate(240000, 0, 0, 0, NULL),
98   };
99 
100   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[0], NULL));
101 
102   Gesture* gs = wrapper.SyncInterpret(&hardware_states[1], NULL);
103   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
104   EXPECT_EQ(kGestureTypeMove, gs->type);
105   EXPECT_EQ(0, gs->details.move.dx);
106   EXPECT_EQ(10, gs->details.move.dy);
107   EXPECT_EQ(200000, gs->start_time);
108   EXPECT_EQ(210000, gs->end_time);
109 
110   gs = wrapper.SyncInterpret(&hardware_states[2], NULL);
111   EXPECT_NE(reinterpret_cast<Gesture*>(NULL), gs);
112   EXPECT_EQ(kGestureTypeMove, gs->type);
113   EXPECT_EQ(10, gs->details.move.dx);
114   EXPECT_EQ(0, gs->details.move.dy);
115   EXPECT_EQ(210000, gs->start_time);
116   EXPECT_EQ(220000, gs->end_time);
117 
118   EXPECT_EQ(reinterpret_cast<Gesture*>(NULL),
119             wrapper.SyncInterpret(&hardware_states[3], NULL));
120   EXPECT_EQ(reinterpret_cast<Gesture*>(NULL),
121             wrapper.SyncInterpret(&hardware_states[4], NULL));
122 }
123 
TEST(ImmediateInterpreterTest,MoveUpWithRestingThumbTest)124 TEST(ImmediateInterpreterTest, MoveUpWithRestingThumbTest) {
125   ImmediateInterpreter ii(NULL, NULL);
126 
127   HardwareProperties hwprops = {
128     0,  // left edge
129     0,  // top edge
130     1000,  // right edge
131     1000,  // bottom edge
132     50,  // pixels/TP width
133     50,  // pixels/TP height
134     96,  // screen DPI x
135     96,  // screen DPI y
136     -1,  // orientation minimum
137     2,   // orientation maximum
138     2,  // max fingers
139     5,  // max touch
140     0,  // tripletap
141     0,  // semi-mt
142     1,  // is button pad
143     0,  // has_wheel
144     0,  // wheel_is_hi_res
145     0,  // is haptic pad
146   };
147   TestInterpreterWrapper wrapper(&ii, &hwprops);
148 
149   FingerState finger_states[] = {
150     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
151     {0, 0, 0, 0, 10, 0, 500, 999, 1, 0},
152     {0, 0, 0, 0, 10, 0, 500, 950, 2, 0},
153     {0, 0, 0, 0, 10, 0, 500, 999, 1, 0},
154     {0, 0, 0, 0, 10, 0, 500, 940, 2, 0},
155     {0, 0, 0, 0, 10, 0, 500, 999, 1, 0},
156     {0, 0, 0, 0, 10, 0, 500, 930, 2, 0}
157   };
158   HardwareState hardware_states[] = {
159     // time, buttons down, finger count, finger states pointer
160     make_hwstate(200000, 0, 2, 2, &finger_states[0]),
161     make_hwstate(210000, 0, 2, 2, &finger_states[2]),
162     make_hwstate(220000, 0, 2, 2, &finger_states[4]),
163     make_hwstate(230000, 0, 0, 0, NULL),
164     make_hwstate(240000, 0, 0, 0, NULL),
165   };
166 
167   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[0], NULL));
168 
169   Gesture* gs = wrapper.SyncInterpret(&hardware_states[1], NULL);
170   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
171   EXPECT_EQ(kGestureTypeMove, gs->type);
172   EXPECT_EQ(0, gs->details.move.dx);
173   EXPECT_EQ(-10, gs->details.move.dy);
174   EXPECT_EQ(200000, gs->start_time);
175   EXPECT_EQ(210000, gs->end_time);
176 
177   gs = wrapper.SyncInterpret(&hardware_states[2], NULL);
178   EXPECT_NE(reinterpret_cast<Gesture*>(NULL), gs);
179   EXPECT_EQ(kGestureTypeMove, gs->type);
180   EXPECT_EQ(0, gs->details.move.dx);
181   EXPECT_EQ(-10, gs->details.move.dy);
182   EXPECT_EQ(210000, gs->start_time);
183   EXPECT_EQ(220000, gs->end_time);
184 
185   EXPECT_EQ(reinterpret_cast<Gesture*>(NULL),
186             wrapper.SyncInterpret(&hardware_states[3], NULL));
187   EXPECT_EQ(reinterpret_cast<Gesture*>(NULL),
188             wrapper.SyncInterpret(&hardware_states[4], NULL));
189 }
190 
TEST(ImmediateInterpreterTest,SemiMtScrollUpWithRestingThumbTest)191 TEST(ImmediateInterpreterTest, SemiMtScrollUpWithRestingThumbTest) {
192   ImmediateInterpreter ii(NULL, NULL);
193   HardwareProperties hwprops = {
194     0,  // left edge
195     0,  // top edge
196     1000,  // right edge
197     1000,  // bottom edge
198     20,  // pixels/TP width
199     20,  // pixels/TP height
200     96,  // x screen DPI
201     96,  // y screen DPI
202     -1,  // orientation minimum
203     2,   // orientation maximum
204     2,  // max fingers
205     3,  // max touch
206     0,  // tripletap
207     1,  // semi-mt
208     1,  // is button pad
209     0,  // has_wheel
210     0,  // wheel_is_hi_res
211     0,  // is haptic pad
212   };
213   TestInterpreterWrapper wrapper(&ii, &hwprops);
214 
215   FingerState finger_states[] = {
216     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
217     {0, 0, 0, 0, 100, 0, 50, 950, 1, 0},
218     {0, 0, 0, 0, 100, 0, 415, 900, 2, 0},
219 
220     {0, 0, 0, 0, 100, 0, 50, 950, 1, 0},
221     {0, 0, 0, 0, 100, 0, 415, 800, 2, 0},
222 
223     {0, 0, 0, 0, 100, 0, 50, 950, 1, 0},
224     {0, 0, 0, 0, 100, 0, 415, 700, 2, 0},
225   };
226   HardwareState hardware_states[] = {
227     // time, buttons, finger count, touch count, finger states pointer
228     make_hwstate(0.200000, 0, 2, 3, &finger_states[0]),
229     make_hwstate(0.250000, 0, 2, 3, &finger_states[2]),
230     make_hwstate(0.300000, 0, 2, 3, &finger_states[4]),
231   };
232 
233   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[0], NULL));
234 
235   Gesture* gs = wrapper.SyncInterpret(&hardware_states[1], NULL);
236   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
237   EXPECT_EQ(kGestureTypeScroll, gs->type);
238   EXPECT_FLOAT_EQ(0, gs->details.move.dx);
239   EXPECT_FLOAT_EQ(-100, gs->details.move.dy);
240   EXPECT_DOUBLE_EQ(0.200000, gs->start_time);
241   EXPECT_DOUBLE_EQ(0.250000, gs->end_time);
242 
243   gs = wrapper.SyncInterpret(&hardware_states[2], NULL);
244   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
245   EXPECT_EQ(kGestureTypeScroll, gs->type);
246   EXPECT_FLOAT_EQ(0, gs->details.move.dx);
247   EXPECT_FLOAT_EQ(-100, gs->details.move.dy);
248   EXPECT_DOUBLE_EQ(0.250000, gs->start_time);
249   EXPECT_DOUBLE_EQ(0.300000, gs->end_time);
250 }
251 
ScrollUpTest(float pressure_a,float pressure_b)252 void ScrollUpTest(float pressure_a, float pressure_b) {
253   ImmediateInterpreter ii(NULL, NULL);
254   HardwareProperties hwprops = {
255     0,  // left edge
256     0,  // top edge
257     1000,  // right edge
258     1000,  // bottom edge
259     20,  // pixels/TP width
260     20,  // pixels/TP height
261     96,  // x screen DPI
262     96,  // y screen DPI
263     -1,  // orientation minimum
264     2,   // orientation maximum
265     2,  // max fingers
266     5,  // max touch
267     0,  // tripletap
268     0,  // semi-mt
269     1,  // is button pad
270     0,  // has_wheel
271     0,  // wheel_is_hi_res
272     0,  // is haptic pad
273   };
274   TestInterpreterWrapper wrapper(&ii, &hwprops);
275 
276   float p_a = pressure_a;
277   float p_b = pressure_b;
278 
279   FingerState finger_states[] = {
280     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
281     {0, 0, 0, 0, p_a, 0, 400, 900, 1, 0},
282     {0, 0, 0, 0, p_b, 0, 415, 900, 2, 0},
283 
284     {0, 0, 0, 0, p_a, 0, 400, 800, 1, 0},
285     {0, 0, 0, 0, p_b, 0, 415, 800, 2, 0},
286 
287     {0, 0, 0, 0, p_a, 0, 400, 700, 1, 0},
288     {0, 0, 0, 0, p_b, 0, 415, 700, 2, 0},
289   };
290   HardwareState hardware_states[] = {
291     // time, buttons, finger count, touch count, finger states pointer
292     make_hwstate(0.200000, 0, 2, 2, &finger_states[0]),
293     make_hwstate(0.250000, 0, 2, 2, &finger_states[2]),
294     make_hwstate(0.300000, 0, 2, 2, &finger_states[4]),
295   };
296 
297   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[0], NULL));
298 
299   Gesture* gs = wrapper.SyncInterpret(&hardware_states[1], NULL);
300   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
301   EXPECT_EQ(kGestureTypeScroll, gs->type);
302   EXPECT_FLOAT_EQ(0, gs->details.move.dx);
303   EXPECT_FLOAT_EQ(-100, gs->details.move.dy);
304   EXPECT_DOUBLE_EQ(0.200000, gs->start_time);
305   EXPECT_DOUBLE_EQ(0.250000, gs->end_time);
306 
307   gs = wrapper.SyncInterpret(&hardware_states[2], NULL);
308   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
309   EXPECT_EQ(kGestureTypeScroll, gs->type);
310   EXPECT_FLOAT_EQ(0, gs->details.move.dx);
311   EXPECT_FLOAT_EQ(-100, gs->details.move.dy);
312   EXPECT_DOUBLE_EQ(0.250000, gs->start_time);
313   EXPECT_DOUBLE_EQ(0.300000, gs->end_time);
314 }
315 
TEST(ImmediateInterpreterTest,ScrollUpTest)316 TEST(ImmediateInterpreterTest, ScrollUpTest) {
317   ScrollUpTest(24, 92);
318 }
319 
TEST(ImmediateInterpreterTest,FatFingerScrollUpTest)320 TEST(ImmediateInterpreterTest, FatFingerScrollUpTest) {
321   ScrollUpTest(125, 185);
322 }
323 
324 // Tests that a tap immediately after a scroll doesn't generate a click.
325 // Such a tap would be unrealistic to come from a human.
TEST(ImmediateInterpreterTest,ScrollThenFalseTapTest)326 TEST(ImmediateInterpreterTest, ScrollThenFalseTapTest) {
327   ImmediateInterpreter ii(NULL, NULL);
328   HardwareProperties hwprops = {
329     0,  // left edge
330     0,  // top edge
331     1000,  // right edge
332     1000,  // bottom edge
333     20,  // pixels/TP width
334     20,  // pixels/TP height
335     96,  // x screen DPI
336     96,  // y screen DPI
337     -1,  // orientation minimum
338     2,   // orientation maximum
339     2,  // max fingers
340     5,  // max touch
341     0,  // tripletap
342     0,  // semi-mt
343     1,  // is button pad
344     0,  // has_wheel
345     0,  // wheel_is_hi_res
346     0,  // is haptic pad
347   };
348   TestInterpreterWrapper wrapper(&ii, &hwprops);
349 
350   FingerState finger_states[] = {
351     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
352     {0, 0, 0, 0, 20, 0, 400, 900, 1, 0},
353     {0, 0, 0, 0, 20, 0, 415, 900, 2, 0},
354 
355     {0, 0, 0, 0, 20, 0, 400, 800, 1, 0},
356     {0, 0, 0, 0, 20, 0, 415, 800, 2, 0},
357 
358     {0, 0, 0, 0, 20, 0, 400, 700, 1, 0},
359     {0, 0, 0, 0, 20, 0, 415, 700, 2, 0},
360 
361     {0, 0, 0, 0, 20, 0, 400, 600, 3, 0},
362   };
363   HardwareState hardware_states[] = {
364     // time, buttons, finger count, touch count, finger states pointer
365     make_hwstate(0.200000, 0, 2, 2, &finger_states[0]),
366     make_hwstate(0.250000, 0, 2, 2, &finger_states[2]),
367     make_hwstate(0.300000, 0, 2, 2, &finger_states[4]),
368     make_hwstate(0.310000, 0, 0, 0, NULL),
369     make_hwstate(0.320000, 0, 1, 1, &finger_states[6]),
370     make_hwstate(0.330000, 0, 0, 0, NULL),
371   };
372 
373   ii.tap_enable_.val_ = 1;
374   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[0], NULL));
375 
376   Gesture* gs = wrapper.SyncInterpret(&hardware_states[1], NULL);
377   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
378   EXPECT_EQ(kGestureTypeScroll, gs->type);
379   gs = wrapper.SyncInterpret(&hardware_states[2], NULL);
380   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
381   EXPECT_EQ(kGestureTypeScroll, gs->type);
382   gs = wrapper.SyncInterpret(&hardware_states[3], NULL);
383   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
384   EXPECT_EQ(kGestureTypeFling, gs->type);
385   gs = wrapper.SyncInterpret(&hardware_states[4], NULL);
386   ASSERT_EQ(reinterpret_cast<Gesture*>(NULL), gs);
387   stime_t timeout = NO_DEADLINE;
388   gs = wrapper.SyncInterpret(&hardware_states[5], &timeout);
389   ASSERT_EQ(reinterpret_cast<Gesture*>(NULL), gs);
390   // If it were a tap, timeout would be > 0, but this shouldn't be a tap,
391   // so timeout should be negative still.
392   EXPECT_LT(timeout, 0.0);
393 }
394 
395 // Tests that a consistent scroll has predictable fling, and that increasing
396 // scrolls have a fling as least as fast the second to last scroll.
TEST(ImmediateInterpreterTest,FlingTest)397 TEST(ImmediateInterpreterTest, FlingTest) {
398   ImmediateInterpreter ii(NULL, NULL);
399   HardwareProperties hwprops = {
400     0,  // left edge
401     0,  // top edge
402     100,  // right edge
403     100,  // bottom edge
404     1,  // pixels/TP width
405     1,  // pixels/TP height
406     96,  // x screen DPI
407     96,  // y screen DPI
408     -1,  // orientation minimum
409     2,   // orientation maximum
410     2,  // max fingers
411     5,  // max touch
412     0,  // tripletap
413     0,  // semi-mt
414     1,  // is button pad
415     0,  // has_wheel
416     0,  // wheel_is_hi_res
417     0,  // is haptic pad
418   };
419   TestInterpreterWrapper wrapper(&ii, &hwprops);
420 
421   FingerState finger_states[] = {
422     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
423     // Consistent movement for 4 frames
424     {0, 0, 0, 0, 20, 0, 40, 20, 1, 0},
425     {0, 0, 0, 0, 20, 0, 60, 20, 2, 0},
426 
427     {0, 0, 0, 0, 20, 0, 40, 30, 1, 0},
428     {0, 0, 0, 0, 20, 0, 60, 30, 2, 0},
429 
430     {0, 0, 0, 0, 20, 0, 40, 40, 1, 0},
431     {0, 0, 0, 0, 20, 0, 60, 40, 2, 0},
432 
433     {0, 0, 0, 0, 20, 0, 40, 50, 1, 0},
434     {0, 0, 0, 0, 20, 0, 60, 50, 2, 0},
435 
436     // Increasing movement for 4 frames
437     {0, 0, 0, 0, 20, 0, 40, 20, 3, 0},
438     {0, 0, 0, 0, 20, 0, 60, 20, 4, 0},
439 
440     {0, 0, 0, 0, 20, 0, 40, 25, 3, 0},
441     {0, 0, 0, 0, 20, 0, 60, 25, 4, 0},
442 
443     {0, 0, 0, 0, 20, 0, 40, 35, 3, 0},
444     {0, 0, 0, 0, 20, 0, 60, 35, 4, 0},
445 
446     {0, 0, 0, 0, 20, 0, 40, 50, 3, 0},
447     {0, 0, 0, 0, 20, 0, 60, 50, 4, 0},
448   };
449   HardwareState hardware_states[] = {
450     // time, buttons, finger count, touch count, finger states pointer
451     make_hwstate(0.00, 0, 2, 2, &finger_states[0]),
452     make_hwstate(1.00, 0, 2, 2, &finger_states[0]),
453     make_hwstate(1.01, 0, 2, 2, &finger_states[2]),
454     make_hwstate(1.02, 0, 2, 2, &finger_states[4]),
455     make_hwstate(1.03, 0, 2, 2, &finger_states[6]),
456     make_hwstate(1.04, 0, 0, 0, NULL),
457 
458     make_hwstate(3.00, 0, 2, 2, &finger_states[8]),
459     make_hwstate(4.00, 0, 2, 2, &finger_states[8]),
460     make_hwstate(4.01, 0, 2, 2, &finger_states[10]),
461     make_hwstate(4.02, 0, 2, 2, &finger_states[12]),
462     make_hwstate(4.03, 0, 2, 2, &finger_states[14]),
463     make_hwstate(4.04, 0, 0, 0, NULL),
464   };
465 
466   size_t idx = 0;
467 
468   // Consistent movement
469   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[idx++], NULL));
470   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[idx++], NULL));
471 
472   Gesture* gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
473   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
474   EXPECT_EQ(kGestureTypeScroll, gs->type);
475   gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
476   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
477   EXPECT_EQ(kGestureTypeScroll, gs->type);
478   gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
479   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
480   EXPECT_EQ(kGestureTypeScroll, gs->type);
481   gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
482   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
483   EXPECT_EQ(kGestureTypeFling, gs->type);
484   EXPECT_FLOAT_EQ(0, gs->details.fling.vx);
485   EXPECT_FLOAT_EQ(10 / 0.01, gs->details.fling.vy);
486 
487   // Increasing speed movement
488   gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
489   EXPECT_EQ(reinterpret_cast<Gesture*>(NULL), gs) << gs->String();
490   gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
491   EXPECT_EQ(reinterpret_cast<Gesture*>(NULL), gs) << gs->String();
492 
493   gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
494   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
495   EXPECT_EQ(kGestureTypeScroll, gs->type);
496   gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
497   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
498   EXPECT_EQ(kGestureTypeScroll, gs->type);
499   gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
500   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
501   EXPECT_EQ(kGestureTypeScroll, gs->type);
502   gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
503   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
504   EXPECT_EQ(kGestureTypeFling, gs->type);
505   EXPECT_FLOAT_EQ(0, gs->details.fling.vx);
506   EXPECT_FLOAT_EQ(1250, gs->details.fling.vy);
507 }
508 
509 // Tests that fingers that have been present a while, but are stationary,
510 // can be evaluated multiple times when they start moving.
TEST(ImmediateInterpreterTest,DelayedStartScrollTest)511 TEST(ImmediateInterpreterTest, DelayedStartScrollTest) {
512   ImmediateInterpreter ii(NULL, NULL);
513   HardwareProperties hwprops = {
514     0,  // left edge
515     0,  // top edge
516     100,  // right edge
517     100,  // bottom edge
518     1,  // pixels/TP width
519     1,  // pixels/TP height
520     96,  // x screen DPI
521     96,  // y screen DPI
522     -1,  // orientation minimum
523     2,   // orientation maximum
524     2,  // max fingers
525     5,  // max touch
526     0,  // tripletap
527     0,  // semi-mt
528     1,  // is button pad
529     0,  // has_wheel
530     0,  // wheel_is_hi_res
531     0,  // is haptic pad
532   };
533   TestInterpreterWrapper wrapper(&ii, &hwprops);
534 
535   FingerState finger_states[] = {
536     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
537     // Consistent movement for 4 frames
538     {0, 0, 0, 0, 20, 0, 40, 95, 1, 0},
539     {0, 0, 0, 0, 20, 0, 60, 95, 2, 0},
540 
541     {0, 0, 0, 0, 20, 0, 40, 95, 1, 0},
542     {0, 0, 0, 0, 20, 0, 60, 85, 2, 0},
543 
544     {0, 0, 0, 0, 20, 0, 40, 80, 1, 0},
545     {0, 0, 0, 0, 20, 0, 60, 75, 2, 0},
546   };
547   HardwareState hardware_states[] = {
548     // time, buttons, finger count, touch count, finger states pointer
549     make_hwstate(1.00, 0, 2, 2, &finger_states[0]),
550     make_hwstate(2.00, 0, 2, 2, &finger_states[0]),
551     make_hwstate(2.01, 0, 2, 2, &finger_states[2]),
552     make_hwstate(2.02, 0, 2, 2, &finger_states[4]),
553     make_hwstate(2.03, 0, 0, 0, NULL),
554   };
555 
556   size_t idx = 0;
557 
558   // Consistent movement
559   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[idx++], NULL));
560   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[idx++], NULL));
561 
562   Gesture* gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
563   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
564   EXPECT_EQ(kGestureTypeMove, gs->type);
565 
566   gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
567   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
568   EXPECT_EQ(kGestureTypeScroll, gs->type);
569 }
570 
571 // Tests that after a scroll is happening, if a finger lets go, scrolling stops.
TEST(ImmediateInterpreterTest,ScrollReevaluateTest)572 TEST(ImmediateInterpreterTest, ScrollReevaluateTest) {
573   ImmediateInterpreter ii(NULL, NULL);
574   HardwareProperties hwprops = {
575     0,  // left edge
576     0,  // top edge
577     100,  // right edge
578     100,  // bottom edge
579     1,  // pixels/TP width
580     1,  // pixels/TP height
581     96,  // x screen DPI
582     96,  // y screen DPI
583     -1,  // orientation minimum
584     2,   // orientation maximum
585     2,  // max fingers
586     5,  // max touch
587     0,  // tripletap
588     0,  // semi-mt
589     1,  // is button pad
590     0,  // has_wheel
591     0,  // wheel_is_hi_res
592     0,  // is haptic pad
593   };
594 
595   FingerState finger_states[] = {
596     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
597     // Consistent movement for 4 frames
598     {0, 0, 0, 0, 20, 0, 10, 95, 1, 0},
599     {0, 0, 0, 0, 20, 0, 59, 95, 2, 0},
600 
601     {0, 0, 0, 0, 20, 0, 10, 85, 1, 0},
602     {0, 0, 0, 0, 20, 0, 59, 85, 2, 0},
603 
604     {0, 0, 0, 0, 20, 0, 10, 75, 1, 0},
605     {0, 0, 0, 0, 20, 0, 59, 75, 2, 0},
606 
607     // Just too far apart to be scrolling
608     {0, 0, 0, 0, 20, 0, 10, 65, 1, 0},
609     {0, 0, 0, 0, 20, 0, 61, 65, 2, 0},
610   };
611   HardwareState hardware_states[] = {
612     // time, buttons, finger count, touch count, finger states pointer
613     make_hwstate(1.00, 0, 2, 2, &finger_states[0]),
614     make_hwstate(2.00, 0, 2, 2, &finger_states[0]),
615     make_hwstate(2.01, 0, 2, 2, &finger_states[2]),
616     make_hwstate(2.02, 0, 2, 2, &finger_states[4]),
617     make_hwstate(2.03, 0, 2, 2, &finger_states[6]),
618   };
619 
620   TestInterpreterWrapper wrapper(&ii, &hwprops);
621 
622   size_t idx = 0;
623 
624   // Consistent movement
625   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[idx++], NULL));
626   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[idx++], NULL));
627 
628   Gesture* gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
629   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
630   EXPECT_EQ(kGestureTypeScroll, gs->type);
631 
632   gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
633   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
634   EXPECT_EQ(kGestureTypeScroll, gs->type);
635 
636   gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
637   if (gs) {
638     fprintf(stderr, "gs:%si=%zd\n", gs->String().c_str(), idx);
639     EXPECT_NE(kGestureTypeScroll, gs->type);
640   }
641 }
642 
643 
644 // This is based on a log from Dave Moore. He put one finger down, which put
645 // it into move mode, then put a second finger down a bit later, but it was
646 // stuck in move mode. This tests that it does switch to scroll mode.
TEST(ImmediateInterpreterTest,OneFingerThenTwoDelayedStartScrollTest)647 TEST(ImmediateInterpreterTest, OneFingerThenTwoDelayedStartScrollTest) {
648   ImmediateInterpreter ii(NULL, NULL);
649   HardwareProperties hwprops = {
650     0,  // left edge
651     0,  // top edge
652     100,  // right edge
653     100,  // bottom edge
654     1,  // pixels/TP width
655     1,  // pixels/TP height
656     96,  // x screen DPI
657     96,  // y screen DPI
658     -1,  // orientation minimum
659     2,   // orientation maximum
660     2,  // max fingers
661     5,  // max touch
662     0,  // tripletap
663     0,  // semi-mt
664     1,  // is button pad
665     0,  // has_wheel
666     0,  // wheel_is_hi_res
667     0,  // is haptic pad
668   };
669 
670   FingerState finger_states[] = {
671     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
672     // Consistent movement for 4 frames
673     {0, 0, 0, 0, 20, 0, 40, 85, 2, 0},
674 
675     {0, 0, 0, 0, 20, 0, 40, 85, 1, 0},
676     {0, 0, 0, 0, 20, 0, 60, 83, 2, 0},
677 
678     {0, 0, 0, 0, 20, 0, 40, 77, 1, 0},
679     {0, 0, 0, 0, 20, 0, 60, 75, 2, 0},
680 
681   };
682   HardwareState hardware_states[] = {
683     // time, buttons, finger count, touch count, finger states pointer
684     make_hwstate(1.00, 0, 1, 1, &finger_states[0]),
685     make_hwstate(1.20, 0, 2, 2, &finger_states[1]),
686     make_hwstate(2.00, 0, 2, 2, &finger_states[1]),
687     make_hwstate(2.01, 0, 2, 2, &finger_states[3]),
688     make_hwstate(2.03, 0, 0, 0, NULL),
689   };
690 
691   TestInterpreterWrapper wrapper(&ii, &hwprops);
692 
693   size_t idx = 0;
694 
695   // Consistent movement
696   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[idx++], NULL));
697   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[idx++], NULL));
698 
699   Gesture* gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
700   EXPECT_EQ(reinterpret_cast<Gesture*>(NULL), gs);
701 
702   gs = wrapper.SyncInterpret(&hardware_states[idx++], NULL);
703   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
704   EXPECT_EQ(kGestureTypeScroll, gs->type);
705 }
706 
707 namespace {
708 
709 enum TestCaseStartOrContinueFlag {
710   kS,  // start
711   kC  // continue
712 };
713 
714 enum OneFatFingerScrollTestExpectation {
715   kAnything,
716   kScroll
717 };
718 
719 struct OneFatFingerScrollTestInputs {
720   TestCaseStartOrContinueFlag start;
721   stime_t now;
722   float x0, y0, p0, x1, y1, p1;  // (x, y) coordinate and pressure
723   OneFatFingerScrollTestExpectation expectation;
724 };
725 
726 }  // namespace {}
727 
728 // Tests two scroll operations with data from actual logs from Ryan Tabone.
TEST(ImmediateInterpreterTest,OneFatFingerScrollTest)729 TEST(ImmediateInterpreterTest, OneFatFingerScrollTest) {
730   std::unique_ptr<ImmediateInterpreter> ii;
731   HardwareProperties hwprops = {
732     0,  // left edge
733     0,  // top edge
734     106.666672,  // right edge
735     68.000000,  // bottom edge
736     1,  // pixels/TP width
737     1,  // pixels/TP height
738     25.4,  // screen DPI x
739     25.4,  // screen DPI y
740     -1,  // orientation minimum
741     2,   // orientation maximum
742     15,  // max fingers
743     5,  // max touch
744     0,  // t5r2
745     0,  // semi-mt
746     true,  // is button pad
747     0,  // has_wheel
748     0,  // wheel_is_hi_res
749     false,  // is haptic pad
750   };
751   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
752   // 4 runs that were failing, but now pass:
753   OneFatFingerScrollTestInputs inputs[] = {
754     { kS, 54.6787, 49.83, 33.20,  3.71, 73.25, 22.80, 32.82, kAnything },
755     { kC, 54.6904, 49.83, 33.20, 61.93, 73.25, 22.80, 40.58, kAnything },
756     { kC, 54.7022, 49.83, 33.20, 67.75, 73.25, 22.90, 40.58, kAnything },
757     { kC, 54.7140, 49.83, 33.20, 67.75, 73.25, 22.90, 42.52, kAnything },
758     { kC, 54.7256, 49.66, 33.20, 71.63, 73.25, 21.90, 38.64, kAnything },
759     { kC, 54.7373, 49.00, 32.90, 75.51, 72.91, 20.80, 40.58, kAnything },
760     { kC, 54.7492, 48.50, 31.70, 77.45, 72.75, 19.90, 40.58, kScroll },
761     { kC, 54.7613, 47.91, 30.30, 77.45, 73.08, 17.90, 44.46, kScroll },
762     { kC, 54.7734, 47.58, 26.80, 79.39, 73.08, 16.10, 46.40, kScroll },
763     { kC, 54.7855, 47.33, 24.30, 85.21, 73.08, 13.40, 42.52, kScroll },
764     { kC, 54.7976, 47.08, 21.30, 83.27, 73.25, 11.00, 46.40, kScroll },
765     { kC, 54.8099, 47.08, 18.30, 87.15, 73.16,  9.00, 44.46, kScroll },
766     { kC, 54.8222, 46.75, 15.90, 83.27, 73.16,  6.80, 42.52, kScroll },
767     { kC, 54.8344, 46.66, 13.50, 85.21, 73.33,  4.80, 46.40, kScroll },
768     { kC, 54.8469, 46.50, 11.80, 83.27, 73.33,  3.70, 44.46, kScroll },
769     { kC, 54.8598, 46.41, 10.80, 85.21, 73.33,  3.00, 46.40, kScroll },
770     { kC, 54.8726, 46.00,  9.50, 79.39, 73.33,  1.70, 40.58, kScroll },
771     { kC, 54.8851, 46.00,  8.60, 81.33, 73.33,  1.50, 40.58, kScroll },
772     { kC, 54.8975, 46.00,  7.90, 83.27, 73.33,  1.20, 38.64, kScroll },
773     { kC, 54.9099, 46.00,  7.20, 85.21, 73.33,  1.20, 38.64, kScroll },
774     { kC, 54.9224, 46.00,  7.00, 81.33, 73.33,  1.00, 34.76, kScroll },
775     { kC, 54.9350, 46.00,  7.00, 81.33, 73.66,  0.90, 34.76, kScroll },
776     { kC, 54.9473, 46.00,  6.80, 83.27, 73.66,  0.50, 34.76, kScroll },
777     { kC, 54.9597, 46.00,  6.70, 77.45, 73.66,  0.40, 32.82, kScroll },
778     { kC, 54.9721, 46.00,  6.60, 56.10, 73.50,  0.40, 28.94, kScroll },
779     { kC, 54.9844, 46.41,  6.20, 32.82, 73.16,  0.40, 19.24, kScroll },
780     { kC, 54.9967, 46.08,  6.20, 17.30, 72.41,  0.40,  7.60, kScroll },
781     { kC, 55.0067, 47.16,  6.30,  3.71,  0.00,  0.00,  0.00, kAnything },
782 
783     { kS, 91.6606, 48.08, 31.20,  9.54,  0.00,  0.00,  0.00, kAnything },
784     { kC, 91.6701, 48.08, 31.20, 23.12,  0.00,  0.00,  0.00, kAnything },
785     { kC, 91.6821, 48.25, 31.20, 38.64, 69.50, 23.20,  7.60, kAnything },
786     { kC, 91.6943, 48.25, 31.20, 50.28, 69.50, 23.20, 19.24, kAnything },
787     { kC, 91.7062, 48.25, 31.20, 58.04, 69.41, 23.00, 23.12, kAnything },
788     { kC, 91.7182, 48.25, 31.20, 63.87, 69.41, 23.00, 27.00, kAnything },
789     { kC, 91.7303, 48.25, 31.20, 65.81, 69.16, 23.00, 30.88, kAnything },
790     { kC, 91.7423, 48.25, 31.20, 65.81, 69.08, 23.00, 30.88, kAnything },
791     { kC, 91.7541, 48.25, 31.20, 67.75, 69.83, 21.90, 25.06, kAnything },
792     { kC, 91.7660, 48.25, 30.80, 67.75, 69.75, 21.90, 27.00, kAnything },
793     { kC, 91.7778, 48.25, 30.00, 63.87, 69.75, 21.60, 30.88, kAnything },
794     { kC, 91.7895, 48.25, 29.00, 63.87, 69.75, 21.30, 30.88, kAnything },
795     { kC, 91.8016, 48.25, 27.60, 65.81, 69.50, 19.90, 34.76, kAnything },
796     { kC, 91.8138, 48.16, 26.00, 67.75, 69.41, 18.70, 36.70, kScroll },
797     { kC, 91.8259, 47.83, 24.30, 69.69, 69.16, 17.50, 40.58, kScroll },
798     { kC, 91.8382, 47.66, 22.50, 69.69, 69.16, 15.50, 36.70, kScroll },
799     { kC, 91.8503, 47.58, 19.20, 71.63, 69.16, 13.20, 34.76, kScroll },
800     { kC, 91.8630, 47.41, 17.10, 71.63, 69.16, 10.80, 40.58, kScroll },
801     { kC, 91.8751, 47.16, 14.70, 73.57, 69.16,  8.40, 34.76, kScroll },
802     { kC, 91.8871, 47.16, 12.70, 73.57, 69.50,  7.10, 36.70, kScroll },
803     { kC, 91.8994, 47.16, 11.30, 71.63, 69.75,  5.90, 36.70, kScroll },
804     { kC, 91.9119, 47.16, 10.10, 67.75, 69.75,  4.40, 40.58, kScroll },
805     { kC, 91.9243, 47.58,  8.70, 69.69, 69.75,  3.50, 42.52, kScroll },
806     { kC, 91.9367, 48.00,  7.80, 63.87, 70.08,  2.70, 38.64, kScroll },
807     { kC, 91.9491, 48.33,  6.90, 59.99, 70.58,  2.10, 34.76, kScroll },
808     { kC, 91.9613, 48.66,  6.50, 56.10, 70.58,  1.50, 32.82, kScroll },
809     { kC, 91.9732, 48.91,  6.00, 48.34, 70.66,  1.10, 28.94, kScroll },
810     { kC, 91.9854, 49.00,  5.90, 38.64, 71.00,  1.10, 23.12, kScroll },
811     { kC, 91.9975, 49.41,  5.60, 27.00, 71.33,  1.10, 15.36, kScroll },
812     { kC, 92.0094, 49.41,  5.30, 13.42, 71.33,  0.90,  9.54, kScroll },
813     { kC, 92.0215, 49.33,  4.20,  7.60, 71.33,  0.50,  3.71, kScroll },
814 
815     { kS, 93.3635, 43.58, 31.40, 36.70, 60.75, 19.00, 11.48, kAnything },
816     { kC, 93.3757, 43.58, 31.40, 73.57, 60.58, 18.80, 27.00, kAnything },
817     { kC, 93.3880, 43.58, 31.40, 75.51, 60.41, 17.90, 32.82, kAnything },
818     { kC, 93.4004, 43.33, 31.20, 77.45, 60.33, 17.40, 38.64, kAnything },
819     { kC, 93.4126, 43.00, 30.70, 79.39, 60.33, 16.50, 42.52, kAnything },
820     { kC, 93.4245, 42.75, 28.90, 81.33, 60.33, 15.70, 46.40, kScroll },
821     { kC, 93.4364, 42.41, 27.00, 79.39, 60.33, 14.30, 48.34, kScroll },
822     { kC, 93.4485, 42.16, 25.80, 87.15, 60.33, 12.50, 50.28, kScroll },
823     { kC, 93.4609, 42.08, 24.20, 89.09, 60.33, 11.10, 56.10, kScroll },
824     { kC, 93.4733, 41.66, 21.70, 81.33, 60.33,  9.70, 52.22, kScroll },
825     { kC, 93.4855, 41.66, 18.50, 85.21, 60.33,  7.80, 52.22, kScroll },
826     { kC, 93.4978, 41.66, 16.29, 85.21, 60.66,  5.40, 54.16, kScroll },
827     { kC, 93.5104, 41.66, 13.20, 79.39, 60.75,  3.80, 54.16, kScroll },
828     { kC, 93.5227, 41.66, 11.80, 79.39, 62.33,  2.00, 42.52, kScroll },
829     { kC, 93.5350, 41.91, 10.60, 71.63, 61.58,  1.80, 42.52, kScroll },
830     { kC, 93.5476, 42.00,  9.10, 67.75, 61.83,  1.20, 38.64, kScroll },
831     { kC, 93.5597, 42.41,  7.70, 58.04, 61.83,  0.80, 32.82, kScroll },
832     { kC, 93.5718, 42.41,  7.20, 48.34, 61.83,  0.80, 27.00, kScroll },
833     { kC, 93.5837, 42.33,  6.80, 34.76, 62.08,  0.50, 19.24, kScroll },
834     { kC, 93.5957, 42.00,  6.10, 19.24, 62.08,  0.50, 15.36, kScroll },
835     { kC, 93.6078, 41.91,  6.30,  7.60, 62.08,  0.50,  5.65, kAnything },
836 
837     { kS, 95.4803, 65.66, 34.90, 13.42,  0.00,  0.00,  0.00, kAnything },
838     { kC, 95.4901, 66.00, 35.00, 36.70,  0.00,  0.00,  0.00, kAnything },
839     { kC, 95.5024, 66.00, 35.10, 40.58, 44.66, 45.29, 59.99, kAnything },
840     { kC, 95.5144, 66.00, 35.40, 38.64, 44.66, 45.29, 81.33, kAnything },
841     { kC, 95.5267, 66.00, 35.40, 38.64, 44.50, 45.29, 87.15, kAnything },
842     { kC, 95.5388, 66.00, 35.40, 40.58, 44.50, 45.29, 87.15, kAnything },
843     { kC, 95.5507, 66.00, 33.60, 38.64, 44.50, 45.29, 91.03, kAnything },
844     { kC, 95.5625, 65.75, 32.00, 34.76, 44.08, 43.60, 91.03, kScroll },
845     { kC, 95.5747, 66.75, 30.00, 42.52, 43.83, 42.00, 89.09, kScroll },
846     { kC, 95.5866, 66.75, 27.50, 38.64, 43.58, 38.90, 87.15, kScroll },
847     { kC, 95.5986, 66.75, 25.00, 44.46, 43.58, 36.50, 92.97, kScroll },
848     { kC, 95.6111, 66.75, 22.70, 42.52, 43.33, 33.70, 89.09, kScroll },
849     { kC, 95.6230, 67.16, 20.40, 42.52, 43.33, 31.30, 94.91, kScroll },
850     { kC, 95.6351, 67.33, 18.70, 44.46, 43.33, 28.90, 96.85, kScroll },
851     { kC, 95.6476, 67.50, 17.30, 48.34, 43.33, 26.10, 92.97, kScroll },
852     { kC, 95.6596, 67.83, 16.20, 46.40, 43.33, 25.00, 92.97, kScroll },
853     { kC, 95.6717, 67.83, 15.60, 42.52, 43.33, 24.20, 94.91, kScroll },
854     { kC, 95.6837, 68.00, 13.80, 46.40, 43.33, 23.90, 92.97, kScroll },
855     { kC, 95.6959, 68.00, 13.80, 44.46, 43.33, 23.70, 92.97, kScroll },
856     { kC, 95.7080, 68.00, 13.80, 44.46, 43.33, 23.50, 94.91, kScroll },
857     { kC, 95.7199, 68.00, 13.60, 44.46, 43.33, 23.10, 96.85, kScroll },
858     { kC, 95.7321, 68.00, 13.60, 44.46, 43.33, 23.00, 98.79, kScroll },
859     { kC, 95.7443, 68.25, 13.60, 44.46, 43.25, 23.00, 98.79, kScroll },
860   };
861   for (size_t i = 0; i < arraysize(inputs); i++) {
862     if (inputs[i].start == kS) {
863       ii.reset(new ImmediateInterpreter(NULL, NULL));
864       wrapper.Reset(ii.get());
865     }
866 
867     FingerState fs[] = {
868       { 0, 0, 0, 0, inputs[i].p0, 0.0, inputs[i].x0, inputs[i].y0, 1, 0 },
869       { 0, 0, 0, 0, inputs[i].p1, 0.0, inputs[i].x1, inputs[i].y1, 2, 0 },
870     };
871     unsigned short finger_cnt = inputs[i].p1 == 0.0 ? 1 : 2;
872     HardwareState hs =
873         make_hwstate(inputs[i].now, 0, finger_cnt, finger_cnt, fs);
874 
875     stime_t timeout = NO_DEADLINE;
876     Gesture* gs = wrapper.SyncInterpret(&hs, &timeout);
877     switch (inputs[i].expectation) {
878       case kAnything:
879         // Anything goes
880         break;
881       case kScroll:
882         EXPECT_NE(static_cast<Gesture*>(NULL), gs) << "i=" << i;
883         if (!gs)
884           break;
885         EXPECT_EQ(kGestureTypeScroll, gs->type);
886         break;
887     }
888   }
889 };
890 
891 struct NoLiftoffScrollTestInputs {
892   bool reset;
893   stime_t now;
894   float x0, y0, p0, x1, y1, p1;  // (x, y) coordinate and pressure per finger
895 };
896 
897 // Tests that if one scrolls backwards a bit before lifting fingers off, we
898 // don't scroll backwards. Based on an actual log
TEST(ImmediateInterpreterTest,NoLiftoffScrollTest)899 TEST(ImmediateInterpreterTest, NoLiftoffScrollTest) {
900   std::unique_ptr<ImmediateInterpreter> ii;
901   HardwareProperties hwprops = {
902     0,  // left edge
903     0,  // top edge
904     106.666672,  // right edge
905     68.000000,  // bottom edge
906     1,  // pixels/TP width
907     1,  // pixels/TP height
908     25.4,  // screen DPI x
909     25.4,  // screen DPI y
910     -1,  // orientation minimum
911     2,   // orientation maximum
912     15,  // max fingers
913     5,  // max touch
914     0,  // t5r2
915     0,  // semi-mt
916     true,  // is button pad
917     0,  // has_wheel
918     0,  // wheel_is_hi_res
919     false,  // is haptic pad
920   };
921   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
922 
923   NoLiftoffScrollTestInputs inputs[] = {
924     // These logs are examples of scrolling up that may have some accidental
925     // reverse-scroll when fingers lift-off
926     {  true, 4.9621, 59.5, 55.9, 17.30, 43.2, 62.5, 19.24 },
927     { false, 4.9745, 59.5, 55.9, 30.88, 43.2, 62.5, 25.06 },
928     { false, 4.9862, 59.3, 55.9, 34.76, 43.3, 61.7, 28.94 },
929     { false, 4.9974, 59.3, 55.4, 36.70, 43.0, 60.7, 32.82 },
930     { false, 5.0085, 59.0, 54.4, 40.58, 43.0, 58.7, 36.70 },
931     { false, 5.0194, 59.0, 50.9, 44.46, 42.5, 55.7, 42.52 },
932     { false, 5.0299, 59.0, 48.2, 46.40, 42.2, 52.7, 44.46 },
933     { false, 5.0412, 58.7, 44.5, 46.40, 41.6, 49.7, 48.34 },
934     { false, 5.0518, 57.3, 39.6, 48.34, 41.2, 45.7, 54.16 },
935     { false, 5.0626, 57.1, 35.2, 48.34, 41.0, 42.0, 61.93 },
936     { false, 5.0739, 56.7, 30.8, 56.10, 41.1, 36.6, 69.69 },
937     { false, 5.0848, 56.3, 26.4, 58.04, 39.7, 32.3, 63.87 },
938     { false, 5.0957, 56.3, 23.4, 61.93, 39.7, 27.8, 67.75 },
939     { false, 5.1068, 56.3, 19.9, 67.75, 39.7, 24.1, 71.63 },
940     { false, 5.1177, 56.7, 18.1, 71.63, 39.7, 20.4, 75.51 },
941     { false, 5.1287, 57.1, 15.9, 71.63, 39.7, 18.7, 75.51 },
942     { false, 5.1398, 57.5, 14.2, 77.45, 39.7, 17.3, 79.39 },
943     { false, 5.1508, 57.6, 13.3, 75.51, 39.7, 16.1, 77.45 },
944     { false, 5.1619, 57.7, 12.9, 79.39, 40.0, 15.5, 83.27 },
945     { false, 5.1734, 58.1, 12.8, 79.39, 40.0, 15.4, 83.27 },
946     { false, 5.1847, 58.1, 12.7, 79.39, 40.0, 15.3, 83.27 },
947     { false, 5.1963, 58.1, 12.7, 78.42, 40.0, 15.3, 83.27 },
948     { false, 5.2078, 58.1, 12.7, 77.45, 40.0, 15.3, 83.27 },
949     { false, 5.2191, 58.1, 12.7, 79.39, 40.0, 15.3, 83.27 },
950     { false, 5.2306, 58.1, 12.7, 78.42, 40.0, 15.3, 82.30 },
951     { false, 5.2421, 58.1, 12.7, 77.45, 40.0, 15.3, 81.33 },
952     { false, 5.2533, 58.1, 12.7, 77.45, 40.0, 15.3, 77.45 },
953     { false, 5.2642, 58.1, 12.7, 63.87, 40.0, 15.4, 58.04 },
954     { false, 5.2752, 57.9, 12.7, 34.76, 40.0, 15.8, 25.06 },
955 
956     {  true, 4.1501, 66.25, 19.10, 46.40, 83.50, 15.10, 46.40 },
957     { false, 4.1610, 66.25, 19.00, 48.34, 83.58, 15.10, 46.40 },
958     { false, 4.1721, 66.58, 18.50, 48.34, 83.58, 15.00, 44.46 },
959     { false, 4.1830, 67.00, 18.50, 48.34, 83.66, 14.90, 44.46 },
960     { false, 4.1943, 67.08, 18.40, 50.28, 83.66, 14.80, 46.40 },
961     { false, 4.2053, 67.08, 18.40, 50.28, 83.66, 14.80, 46.40 },
962     { false, 4.2163, 67.08, 18.40, 50.28, 83.66, 14.80, 46.40 },
963     { false, 4.2274, 67.08, 18.40, 48.34, 83.66, 14.80, 46.40 },
964     { false, 4.2385, 67.08, 18.30, 50.28, 83.83, 14.60, 46.40 },
965     { false, 4.2494, 67.08, 18.10, 48.34, 83.91, 14.30, 46.40 },
966     { false, 4.2602, 67.08, 17.60, 46.40, 84.08, 14.10, 44.46 },
967     { false, 4.2712, 67.08, 17.40, 48.34, 84.25, 13.70, 46.40 },
968     { false, 4.2822, 67.25, 17.20, 48.34, 84.50, 13.40, 48.34 },
969     { false, 4.2932, 67.33, 16.90, 46.40, 84.75, 13.20, 46.40 },
970     { false, 4.3044, 67.33, 16.60, 46.40, 84.91, 13.00, 48.34 },
971     { false, 4.3153, 67.41, 16.50, 46.40, 84.91, 12.90, 46.40 },
972     { false, 4.3264, 67.50, 16.29, 46.40, 84.91, 12.90, 46.40 },
973     { false, 4.3372, 67.58, 16.29, 46.40, 85.08, 12.90, 48.34 },
974     { false, 4.3481, 67.58, 16.10, 44.46, 85.08, 12.90, 48.34 },
975     { false, 4.3591, 67.58, 16.00, 44.46, 85.08, 12.90, 48.34 },
976     { false, 4.3699, 67.58, 15.95, 44.46, 85.08, 12.85, 48.34 },
977     { false, 4.3808, 67.58, 15.90, 44.46, 85.08, 12.80, 48.34 },
978     { false, 4.3922, 67.58, 15.90, 44.46, 85.25, 12.50, 48.34 },
979     { false, 4.4035, 67.75, 15.80, 46.40, 85.25, 12.40, 46.40 },
980     { false, 4.4146, 67.75, 15.30, 46.40, 85.33, 12.20, 48.34 },
981     { false, 4.4260, 67.91, 15.20, 48.34, 85.75, 12.20, 50.28 },
982     { false, 4.4373, 67.91, 15.20, 46.40, 85.75, 12.10, 48.34 },
983     { false, 4.4485, 67.91, 15.10, 46.40, 85.75, 12.10, 48.34 },
984     { false, 4.4712, 67.91, 15.05, 46.40, 85.75, 12.05, 48.34 },
985     { false, 4.4940, 67.91, 15.00, 46.40, 85.75, 12.00, 48.34 },
986     { false, 4.5052, 67.91, 14.80, 48.34, 85.75, 11.80, 48.34 },
987     { false, 4.5163, 68.00, 14.60, 48.34, 85.83, 11.70, 48.34 },
988     { false, 4.5276, 68.08, 14.50, 48.34, 85.91, 11.60, 50.28 },
989     { false, 4.5390, 68.08, 14.30, 46.40, 85.91, 11.50, 48.34 },
990     { false, 4.5499, 68.08, 14.30, 48.34, 85.91, 11.50, 48.34 },
991     { false, 4.5613, 68.08, 14.30, 47.37, 85.91, 11.45, 48.34 },
992     { false, 4.5726, 68.08, 14.30, 46.40, 85.91, 11.40, 48.34 },
993     { false, 4.5837, 68.08, 14.20, 46.40, 85.91, 11.40, 48.34 },
994     { false, 4.5949, 68.08, 14.10, 46.40, 85.91, 11.40, 48.34 },
995     { false, 4.6061, 68.16, 14.10, 46.40, 85.91, 11.40, 48.34 },
996     { false, 4.6172, 68.16, 14.00, 48.34, 86.00, 11.30, 48.34 },
997     { false, 4.6285, 68.25, 13.90, 48.34, 86.00, 11.20, 48.34 },
998     { false, 4.6399, 68.25, 13.90, 48.34, 86.00, 11.20, 48.34 },
999     { false, 4.6514, 68.33, 13.80, 48.34, 86.00, 11.10, 48.34 },
1000     { false, 4.6741, 68.33, 13.80, 47.37, 86.00, 11.05, 47.37 },
1001     { false, 4.6968, 68.33, 13.80, 46.40, 86.00, 11.00, 46.40 },
1002     { false, 4.7079, 68.33, 13.80, 42.52, 86.00, 11.00, 44.46 },
1003     { false, 4.7191, 68.33, 13.80, 38.64, 86.00, 11.00, 42.52 },
1004     { false, 4.7304, 68.33, 13.80, 34.76, 86.00, 11.00, 42.52 },
1005     { false, 4.7417, 68.41, 13.80, 27.00, 86.41, 11.00, 36.70 },
1006     { false, 4.7528, 68.83, 13.60, 21.18, 86.25, 10.90, 32.82 },
1007     { false, 4.7638, 68.83, 13.60, 13.42, 86.25, 10.80, 25.06 },
1008     { false, 4.7749, 68.83, 13.60,  5.65, 86.25, 10.50, 15.36 },
1009     { false, 4.7862, 68.75, 14.00,  1.77, 85.91, 10.50,  7.60 },
1010   };
1011   for (size_t i = 0; i < arraysize(inputs); i++) {
1012     if (inputs[i].reset) {
1013       ii.reset(new ImmediateInterpreter(NULL, NULL));
1014       wrapper.Reset(ii.get());
1015     }
1016     FingerState fs[] = {
1017       { 0, 0, 0, 0, inputs[i].p0, 0.0, inputs[i].x0, inputs[i].y0, 1, 0 },
1018       { 0, 0, 0, 0, inputs[i].p1, 0.0, inputs[i].x1, inputs[i].y1, 2, 0 },
1019     };
1020     HardwareState hs = make_hwstate(inputs[i].now, 0, 2, 2, fs);
1021 
1022     stime_t timeout = NO_DEADLINE;
1023     Gesture* gs = wrapper.SyncInterpret(&hs, &timeout);
1024     if (gs) {
1025       EXPECT_EQ(kGestureTypeScroll, gs->type);
1026       EXPECT_LE(gs->details.scroll.dy, 0.0);
1027     }
1028   }
1029 }
1030 
1031 struct HardwareStateAnScrollExpectations {
1032   HardwareState hs;
1033   float dx;
1034   float dy;
1035 };
1036 
TEST(ImmediateInterpreterTest,DiagonalSnapTest)1037 TEST(ImmediateInterpreterTest, DiagonalSnapTest) {
1038   std::unique_ptr<ImmediateInterpreter> ii;
1039   HardwareProperties hwprops = {
1040     0,  // left edge
1041     0,  // top edge
1042     100,  // right edge
1043     100,  // bottom edge
1044     1,  // pixels/TP width
1045     1,  // pixels/TP height
1046     96,  // x screen DPI
1047     96,  // y screen DPI
1048     -1,  // orientation minimum
1049     2,   // orientation maximum
1050     2,  // max fingers
1051     5,  // max touch
1052     0,  // t5r2
1053     0,  // semi-mt
1054     1,  // is button pad
1055     0,  // has_wheel
1056     0,  // wheel_is_hi_res
1057     0,  // is haptic pad
1058   };
1059   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
1060 
1061   const float kBig = 5;  // mm
1062   const float kSml = 1;  // mm
1063 
1064   const float kX0 = 40;
1065   const float kX1 = 60;
1066   const float kY = 50;  // heh
1067 
1068   short fid = 1;
1069 
1070   FingerState finger_states[] = {
1071     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1072 
1073     // Perfect diagonal movement - should scroll diagonally
1074     {0, 0, 0, 0, 50, 0, kX0, kY, fid++, 0},
1075     {0, 0, 0, 0, 50, 0, kX1, kY, fid--, 0},
1076 
1077     {0, 0, 0, 0, 50, 0, kX0 + kBig, kY + kBig, fid++, 0},
1078     {0, 0, 0, 0, 50, 0, kX1 + kBig, kY + kBig, fid++, 0},
1079 
1080     // Almost vertical movement - should snap to vertical
1081     {0, 0, 0, 0, 50, 0, kX0, kY, fid++, 0},
1082     {0, 0, 0, 0, 50, 0, kX1, kY, fid--, 0},
1083 
1084     {0, 0, 0, 0, 50, 0, kX0 + kSml, kY + kBig, fid++, 0},
1085     {0, 0, 0, 0, 50, 0, kX1 + kSml, kY + kBig, fid++, 0},
1086 
1087     // Almost horizontal movement - should snap to horizontal
1088     {0, 0, 0, 0, 50, 0, kX0, kY, fid++, 0},
1089     {0, 0, 0, 0, 50, 0, kX1, kY, fid--, 0},
1090 
1091     {0, 0, 0, 0, 50, 0, kX0 + kBig, kY + kSml, fid++, 0},
1092     {0, 0, 0, 0, 50, 0, kX1 + kBig, kY + kSml, fid++, 0},
1093 
1094     // Vertical movement with Warp - shouldn't scroll
1095     {0, 0, 0, 0, 50, 0, kX0, kY, fid++, 0},
1096     {0, 0, 0, 0, 50, 0, kX1, kY, fid--, 0},
1097 
1098     {0, 0, 0, 0, 50, 0, kX0, kY + kBig, fid++, GESTURES_FINGER_WARP_Y},
1099     {0, 0, 0, 0, 50, 0, kX1, kY + kBig, fid++, GESTURES_FINGER_WARP_Y},
1100   };
1101   ssize_t idx = 0;
1102   HardwareStateAnScrollExpectations hardware_states[] = {
1103     // time, buttons, finger count, touch count, finger states pointer
1104     { make_hwstate(0.000, 0, 2, 2, &finger_states[idx * 4 ]),
1105       0, 0 },
1106     { make_hwstate(1.000, 0, 2, 2, &finger_states[idx * 4 ]),
1107       0, 0 },
1108     { make_hwstate(1.010, 0, 2, 2, &finger_states[idx++ * 4 + 2]),
1109       kBig, kBig },
1110 
1111     { make_hwstate(0.000, 0, 2, 2, &finger_states[idx * 4 ]),
1112       0, 0 },
1113     { make_hwstate(1.000, 0, 2, 2, &finger_states[idx * 4 ]),
1114       0, 0 },
1115     { make_hwstate(1.010, 0, 2, 2, &finger_states[idx++ * 4 + 2]),
1116       0, kBig },
1117 
1118     { make_hwstate(0.000, 0, 2, 2, &finger_states[idx * 4 ]),
1119       0, 0 },
1120     { make_hwstate(1.000, 0, 2, 2, &finger_states[idx * 4 ]),
1121       0, 0 },
1122     { make_hwstate(1.010, 0, 2, 2, &finger_states[idx++ * 4 + 2]),
1123       kBig, 0 },
1124 
1125     { make_hwstate(0.000, 0, 2, 2, &finger_states[idx * 4 ]),
1126       0, 0 },
1127     { make_hwstate(1.000, 0, 2, 2, &finger_states[idx * 4 ]),
1128       0, 0 },
1129     { make_hwstate(1.010, 0, 2, 2, &finger_states[idx++ * 4 + 2]),
1130       0, 0 },
1131   };
1132 
1133   for (size_t i = 0; i < arraysize(hardware_states); i++) {
1134     HardwareStateAnScrollExpectations& hse = hardware_states[i];
1135     if (hse.hs.timestamp == 0.0) {
1136       ii.reset(new ImmediateInterpreter(NULL, NULL));
1137       wrapper.Reset(ii.get());
1138     }
1139     Gesture* gs = wrapper.SyncInterpret(&hse.hs, NULL);
1140     if (hse.dx == 0.0 && hse.dy == 0.0) {
1141       EXPECT_EQ(reinterpret_cast<Gesture*>(NULL), gs);
1142       continue;
1143     }
1144     ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
1145     EXPECT_EQ(kGestureTypeScroll, gs->type);
1146     EXPECT_FLOAT_EQ(hse.dx, gs->details.scroll.dx);
1147     EXPECT_FLOAT_EQ(hse.dy, gs->details.scroll.dy);
1148   }
1149 }
1150 
TEST(ImmediateInterpreterTest,RestingFingerTest)1151 TEST(ImmediateInterpreterTest, RestingFingerTest) {
1152   std::unique_ptr<ImmediateInterpreter> ii;
1153   HardwareProperties hwprops = {
1154     0,  // left edge
1155     0,  // top edge
1156     100,  // right edge
1157     100,  // bottom edge
1158     1,  // pixels/TP width
1159     1,  // pixels/TP height
1160     96,  // x screen DPI
1161     96,  // y screen DPI
1162     -1,  // orientation minimum
1163     2,   // orientation maximum
1164     2,  // max fingers
1165     5,  // max touch
1166     0,  // t5r2
1167     0,  // semi-mt
1168     1,  // is button pad
1169     0,  // has_wheel
1170     0,  // wheel_is_hi_res
1171     0,  // is haptic pad
1172   };
1173   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
1174 
1175   const float kX = 7;
1176   float dx = 7;
1177   const float kRestY = hwprops.bottom - 7;
1178   const float kMoveY = kRestY - 10;
1179 
1180   const float kTO = 1.0;  // time to wait for change timeout
1181 
1182   FingerState finger_states[] = {
1183     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1184 
1185     // Resting finger in lower left
1186     {0, 0, 0, 0, 50, 0, kX, kRestY, 1, 0},
1187     // Moving finger
1188     {0, 0, 0, 0, 50, 0, kX, kMoveY, 2, 0},
1189   };
1190 
1191   // Left to right movement, then right to left
1192   for (size_t direction = 0; direction < 2; direction++) {
1193     if (direction == 1)
1194       dx *= -1.0;
1195     ii.reset(new ImmediateInterpreter(NULL, NULL));
1196     wrapper.Reset(ii.get());
1197     for (size_t i = 0; i < 4; i++) {
1198       HardwareState hs = make_hwstate(kTO + 0.01 * i, 0, 2, 2, finger_states);
1199       if (i == 0) {
1200         hs.timestamp -= kTO;
1201         Gesture* gs = wrapper.SyncInterpret(&hs, NULL);
1202         EXPECT_EQ(static_cast<Gesture*>(NULL), gs);
1203         hs.timestamp += kTO;
1204         gs = wrapper.SyncInterpret(&hs, NULL);
1205         if (gs && gs->type == kGestureTypeMove) {
1206           EXPECT_FLOAT_EQ(0.0, gs->details.move.dx);
1207           EXPECT_FLOAT_EQ(0.0, gs->details.move.dy);
1208         }
1209       } else {
1210         Gesture* gs = wrapper.SyncInterpret(&hs, NULL);
1211         ASSERT_NE(static_cast<Gesture*>(NULL), gs);
1212         EXPECT_EQ(kGestureTypeMove, gs->type);
1213         EXPECT_FLOAT_EQ(dx, gs->details.move.dx);
1214         EXPECT_FLOAT_EQ(0.0, gs->details.move.dy);
1215       }
1216       finger_states[1].position_x += dx;
1217     }
1218   }
1219 }
1220 
TEST(ImmediateInterpreterTest,ThumbRetainTest)1221 TEST(ImmediateInterpreterTest, ThumbRetainTest) {
1222   ImmediateInterpreter ii(NULL, NULL);
1223   HardwareProperties hwprops = {
1224     0,  // left edge
1225     0,  // top edge
1226     100,  // right edge
1227     100,  // bottom edge
1228     1,  // pixels/TP width
1229     1,  // pixels/TP height
1230     1,  // x screen DPI
1231     1,  // y screen DPI
1232     -1,  // orientation minimum
1233     2,   // orientation maximum
1234     2,  // max fingers
1235     5,  // max touch
1236     0,  // tripletap
1237     0,  // semi-mt
1238     1,  // is button pad
1239     0,  // has_wheel
1240     0,  // wheel_is_hi_res
1241     0,  // is haptic pad
1242   };
1243 
1244   FingerState finger_states[] = {
1245     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1246     // id 1 = finger, 2 = thumb
1247     {0, 0, 0, 0, 24, 0, 30, 30, 1, 0},
1248     {0, 0, 0, 0, 58, 0, 30, 50, 2, 0},
1249 
1250     // thumb, post-move
1251     {0, 0, 0, 0, 58, 0, 50, 50, 2, 0},
1252   };
1253   HardwareState hardware_states[] = {
1254     // time, buttons, finger count, touch count, finger states pointer
1255     make_hwstate(0.000, 0, 2, 2, &finger_states[0]),
1256     make_hwstate(0.100, 0, 2, 2, &finger_states[0]),
1257     make_hwstate(0.110, 0, 1, 1, &finger_states[1]),  // finger goes away
1258     make_hwstate(0.210, 0, 1, 1, &finger_states[1]),
1259     make_hwstate(0.220, 0, 1, 1, &finger_states[2]),  // thumb moves
1260   };
1261 
1262   TestInterpreterWrapper wrapper(&ii, &hwprops);
1263   ii.tap_enable_.val_ = 0;
1264 
1265   for (size_t i = 0; i < arraysize(hardware_states); i++) {
1266     Gesture* gs = wrapper.SyncInterpret(&hardware_states[i], NULL);
1267     if (!gs)
1268       continue;
1269     EXPECT_EQ(kGestureTypeMove, gs->type) << "i=" << i;
1270     EXPECT_FLOAT_EQ(0.0, gs->details.move.dx) << "i=" << i;
1271     EXPECT_FLOAT_EQ(0.0, gs->details.move.dy) << "i=" << i;
1272   }
1273 }
1274 
TEST(ImmediateInterpreterTest,ThumbRetainReevaluateTest)1275 TEST(ImmediateInterpreterTest, ThumbRetainReevaluateTest) {
1276   ImmediateInterpreter ii(NULL, NULL);
1277   HardwareProperties hwprops = {
1278     0,  // left edge
1279     0,  // top edge
1280     100,  // right edge
1281     100,  // bottom edge
1282     1,  // pixels/TP width
1283     1,  // pixels/TP height
1284     1,  // x screen DPI
1285     1,  // y screen DPI
1286     -1,  // orientation minimum
1287     2,   // orientation maximum
1288     2,  // max fingers
1289     5,  // max touch
1290     0,  // tripletap
1291     0,  // semi-mt
1292     1,  // is button pad
1293     0,  // has_wheel
1294     0,  // wheel_is_hi_res
1295     0,  // is haptic pad
1296   };
1297 
1298   FingerState finger_states[] = {
1299     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1300     // one thumb, one finger (it seems)
1301     {0, 0, 0, 0, 24, 0, 3.0, 3, 3, 0},
1302     {0, 0, 0, 0, 58, 0, 13.5, 3, 4, 0},
1303     // two big fingers, it turns out!
1304     {0, 0, 0, 0, 27, 0, 3.0, 6, 3, 0},
1305     {0, 0, 0, 0, 58, 0, 13.5, 6, 4, 0},
1306     // they  move
1307     {0, 0, 0, 0, 27, 0, 3.0, 7, 3, 0},
1308     {0, 0, 0, 0, 58, 0, 13.5, 7, 4, 0},
1309   };
1310   HardwareState hardware_states[] = {
1311     // time, buttons, finger count, touch count, finger states pointer
1312     make_hwstate(1.000, 0, 2, 2, &finger_states[0]),  // 2 fingers arrive
1313     make_hwstate(1.010, 0, 2, 2, &finger_states[2]),  // pressures fix
1314     make_hwstate(1.100, 0, 2, 2, &finger_states[4]),  // they move
1315   };
1316 
1317   TestInterpreterWrapper wrapper(&ii, &hwprops);
1318   ii.tap_enable_.val_ = 0;
1319 
1320   for (size_t i = 0; i < arraysize(hardware_states); i++) {
1321     Gesture* gs = wrapper.SyncInterpret(&hardware_states[i], NULL);
1322     EXPECT_TRUE(!gs || gs->type == kGestureTypeScroll);
1323   }
1324 }
1325 
TEST(ImmediateInterpreterTest,SetHardwarePropertiesTwiceTest)1326 TEST(ImmediateInterpreterTest, SetHardwarePropertiesTwiceTest) {
1327   ImmediateInterpreter ii(NULL, NULL);
1328   HardwareProperties hwprops = {
1329     0,  // left edge
1330     0,  // top edge
1331     1000,  // right edge
1332     1000,  // bottom edge
1333     500,  // pixels/TP width
1334     500,  // pixels/TP height
1335     96,  // screen DPI x
1336     96,  // screen DPI y
1337     -1,  // orientation minimum
1338     2,   // orientation maximum
1339     2,  // max fingers
1340     5,  // max touch
1341     0,  // tripletap
1342     0,  // semi-mt
1343     1,  // is button pad
1344     0,  // has_wheel
1345     0,  // wheel_is_hi_res
1346     0,  // is haptic pad
1347   };
1348   hwprops.max_finger_cnt = 3;
1349   TestInterpreterWrapper wrapper(&ii, &hwprops);
1350 
1351   FingerState finger_states[] = {
1352     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1353     {0, 0, 0, 0, 1, 0, 0, 0, 1, 0},
1354     {0, 0, 0, 0, 1, 0, 0, 0, 2, 0},
1355     {0, 0, 0, 0, 1, 0, 0, 0, 3, 0},
1356     {0, 0, 0, 0, 0, 0, 0, 0, 4, 0},
1357     {0, 0, 0, 0, 0, 0, 0, 0, 5, 0}
1358   };
1359   HardwareState hardware_state = {
1360     // time, buttons, finger count, touch count, finger states pointer
1361     200000, 0, 5, 5, &finger_states[0], 0, 0, 0, 0, 0, 0.0
1362   };
1363   // This used to cause a crash:
1364   Gesture* gs = wrapper.SyncInterpret(&hardware_state, NULL);
1365   EXPECT_EQ(reinterpret_cast<Gesture*>(NULL), gs);
1366 }
1367 
TEST(ImmediateInterpreterTest,AmbiguousPalmCoScrollTest)1368 TEST(ImmediateInterpreterTest, AmbiguousPalmCoScrollTest) {
1369   ImmediateInterpreter ii(NULL, NULL);
1370   HardwareProperties hwprops = {
1371     0,  // left edge
1372     0,  // top edge
1373     100,  // right edge
1374     100,  // bottom edge
1375     1,  // x pixels/TP width
1376     1,  // y pixels/TP height
1377     1,  // x screen DPI
1378     1,  // y screen DPI
1379     -1,  // orientation minimum
1380     2,   // orientation maximum
1381     5,  // max fingers
1382     5,  // max touch
1383     0,  // t5r2
1384     0,  // semi-mt
1385     1,  // is button pad
1386     0,  // has_wheel
1387     0,  // wheel_is_hi_res
1388     0,  // is haptic pad
1389   };
1390   TestInterpreterWrapper wrapper(&ii, &hwprops);
1391 
1392   const int kPr = 20;
1393 
1394   const unsigned kPalmFlags = GESTURES_FINGER_POSSIBLE_PALM;
1395 
1396   FingerState finger_states[] = {
1397     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1398     // stationary palm - movement
1399     {0, 0, 0, 0, kPr, 0,  0, 40, 1, kPalmFlags},
1400     {0, 0, 0, 0, kPr, 0, 30, 35, 2, 0},
1401 
1402     {0, 0, 0, 0, kPr, 0,  0, 40, 1, kPalmFlags},
1403     {0, 0, 0, 0, kPr, 0, 30, 40, 2, 0},
1404 
1405     {0, 0, 0, 0, kPr, 0,  0, 40, 1, kPalmFlags},
1406     {0, 0, 0, 0, kPr, 0, 30, 45, 2, 0},
1407 
1408     // Same, but moving palm - scroll
1409     {0, 0, 0, 0, kPr, 0,  0, 35, 3, kPalmFlags},
1410     {0, 0, 0, 0, kPr, 0, 30, 35, 4, 0},
1411 
1412     {0, 0, 0, 0, kPr, 0,  0, 40, 3, kPalmFlags},
1413     {0, 0, 0, 0, kPr, 0, 30, 40, 4, 0},
1414 
1415     {0, 0, 0, 0, kPr, 0,  0, 45, 3, kPalmFlags},
1416     {0, 0, 0, 0, kPr, 0, 30, 45, 4, 0},
1417   };
1418   HardwareState hardware_state[] = {
1419     // time, buttons, finger count, touch count, finger states pointer
1420     make_hwstate(0.0, 0, 2, 2, &finger_states[0]),
1421     make_hwstate(0.1, 0, 2, 2, &finger_states[2]),
1422     make_hwstate(0.2, 0, 2, 2, &finger_states[4]),
1423     make_hwstate(3.0, 0, 2, 2, &finger_states[6]),
1424     make_hwstate(3.1, 0, 2, 2, &finger_states[8]),
1425     make_hwstate(3.2, 0, 2, 2, &finger_states[10]),
1426   };
1427   GestureType expected_gs[] = {
1428     kGestureTypeNull,
1429     kGestureTypeNull,
1430     kGestureTypeMove,
1431     kGestureTypeNull,
1432     kGestureTypeScroll,
1433     kGestureTypeScroll
1434   };
1435   if (ii.pinch_enable_.val_)
1436     // Movement delay is longer when pinch is enabled
1437     expected_gs[2] = kGestureTypeNull;
1438 
1439   ASSERT_EQ(arraysize(expected_gs), arraysize(hardware_state));
1440 
1441   for (size_t i = 0; i < arraysize(hardware_state); ++i) {
1442     Gesture* gs = wrapper.SyncInterpret(&hardware_state[i], NULL);
1443     if (expected_gs[i] == kGestureTypeNull) {
1444       EXPECT_EQ(static_cast<Gesture*>(NULL), gs) << "gs:" << gs->String();
1445     } else {
1446       ASSERT_NE(static_cast<Gesture*>(NULL), gs);
1447       EXPECT_EQ(expected_gs[i], gs->type) << "i=" << i
1448                                           << " gs: " << gs->String();
1449     }
1450   }
1451 }
1452 
TEST(ImmediateInterpreterTest,PressureChangeMoveTest)1453 TEST(ImmediateInterpreterTest, PressureChangeMoveTest) {
1454   ImmediateInterpreter ii(NULL, NULL);
1455   HardwareProperties hwprops = {
1456     0,  // left edge
1457     0,  // top edge
1458     1000,  // right edge
1459     1000,  // bottom edge
1460     500,  // x pixels/TP width
1461     500,  // y pixels/TP height
1462     96,  // x screen DPI
1463     96,  // y screen DPI
1464     -1,  // orientation minimum
1465     2,   // orientation maximum
1466     2,  // max fingers
1467     5,  // max touch
1468     0,  // t5r2
1469     0,  // semi-mt
1470     1,  // is button pad
1471     0,  // has_wheel
1472     0,  // wheel_is_hi_res
1473     0,  // is haptic pad
1474   };
1475   TestInterpreterWrapper wrapper(&ii, &hwprops);
1476 
1477   const int kBig = 81;  // large pressure
1478   const int kSml = 50;  // small pressure
1479 
1480   FingerState finger_states[] = {
1481     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1482     {0, 0, 0, 0, kSml, 0, 600, 300, 1, 0},
1483     {0, 0, 0, 0, kSml, 0, 600, 400, 1, 0},
1484     {0, 0, 0, 0, kBig, 0, 600, 500, 1, 0},
1485     {0, 0, 0, 0, kBig, 0, 600, 600, 1, 0},
1486   };
1487   HardwareState hardware_state[] = {
1488     // time, buttons, finger count, touch count, finger states pointer
1489     make_hwstate(2000.00, 0, 1, 1, &finger_states[0]),
1490     make_hwstate(2000.01, 0, 1, 1, &finger_states[1]),
1491     make_hwstate(2000.02, 0, 1, 1, &finger_states[2]),
1492     make_hwstate(2000.03, 0, 1, 1, &finger_states[3]),
1493   };
1494 
1495   for (size_t i = 0; i < arraysize(hardware_state); ++i) {
1496     Gesture* result = wrapper.SyncInterpret(&hardware_state[i], NULL);
1497     switch (i) {
1498       case 0:
1499         EXPECT_FALSE(result);
1500         break;
1501       case 2:
1502         ASSERT_TRUE(result);
1503         EXPECT_EQ(kGestureTypeMove, result->type);
1504         EXPECT_EQ(0.0, result->details.move.dy);
1505         break;
1506       case 1:  // fallthrough
1507       case 3:
1508         ASSERT_TRUE(result);
1509         EXPECT_EQ(kGestureTypeMove, result->type);
1510         EXPECT_NE(0.0, result->details.move.dy);
1511         break;
1512     }
1513   }
1514 }
1515 
TEST(ImmediateInterpreterTest,GetGesturingFingersTest)1516 TEST(ImmediateInterpreterTest, GetGesturingFingersTest) {
1517   ImmediateInterpreter ii(NULL, NULL);
1518   HardwareProperties hwprops = {
1519     0,  // left edge
1520     0,  // top edge
1521     1000,  // right edge
1522     1000,  // bottom edge
1523     500,  // pixels/TP width
1524     500,  // pixels/TP height
1525     96,  // screen DPI x
1526     96,  // screen DPI y
1527     -1,  // orientation minimum
1528     2,   // orientation maximum
1529     2,  // max fingers
1530     5,  // max touch
1531     0,  // t5r2
1532     0,  // semi-mt
1533     1,  // is button pad
1534     0,  // has_wheel
1535     0,  // wheel_is_hi_res
1536     0,  // is haptic pad
1537   };
1538   TestInterpreterWrapper wrapper(&ii, &hwprops);
1539 
1540   FingerState finger_states[] = {
1541     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1542     {0, 0, 0, 0, 1, 0, 61, 70, 91, 0},
1543     {0, 0, 0, 0, 1, 0, 62, 65, 92, 0},
1544     {0, 0, 0, 0, 1, 0, 62, 69, 93, 0},
1545     {0, 0, 0, 0, 1, 0, 62, 61, 94, 0}
1546   };
1547   HardwareState hardware_state[] = {
1548     // time, buttons, finger count, finger states pointer
1549     make_hwstate(200000, 0, 0, 0, NULL),
1550     make_hwstate(200001, 0, 1, 1, &finger_states[0]),
1551     make_hwstate(200002, 0, 2, 2, &finger_states[0]),
1552     make_hwstate(200002, 0, 3, 3, &finger_states[0]),
1553     make_hwstate(200002, 0, 4, 4, &finger_states[0]),
1554   };
1555   // few pointing fingers
1556   ii.ResetSameFingersState(hardware_state[0]);
1557   ii.UpdatePointingFingers(hardware_state[0]);
1558   EXPECT_TRUE(ii.GetGesturingFingers(hardware_state[0]).empty());
1559 
1560   ii.ResetSameFingersState(hardware_state[0]);
1561   ii.UpdatePointingFingers(hardware_state[1]);
1562   std::set<short> ids =
1563       ii.GetGesturingFingers(hardware_state[1]);
1564   EXPECT_EQ(1, ids.size());
1565   EXPECT_TRUE(ids.end() != ids.find(91));
1566 
1567   ii.ResetSameFingersState(hardware_state[0]);
1568   ii.UpdatePointingFingers(hardware_state[2]);
1569   ids = ii.GetGesturingFingers(hardware_state[2]);
1570   EXPECT_EQ(2, ids.size());
1571   EXPECT_TRUE(ids.end() != ids.find(91));
1572   EXPECT_TRUE(ids.end() != ids.find(92));
1573 
1574   ii.ResetSameFingersState(hardware_state[0]);
1575   ii.UpdatePointingFingers(hardware_state[3]);
1576   ids = ii.GetGesturingFingers(hardware_state[3]);
1577   EXPECT_EQ(3, ids.size());
1578   EXPECT_TRUE(ids.end() != ids.find(91));
1579   EXPECT_TRUE(ids.end() != ids.find(92));
1580   EXPECT_TRUE(ids.end() != ids.find(93));
1581 
1582   ii.ResetSameFingersState(hardware_state[0]);
1583   ii.UpdatePointingFingers(hardware_state[4]);
1584   ids = ii.GetGesturingFingers(hardware_state[4]);
1585   EXPECT_EQ(4, ids.size());
1586   EXPECT_TRUE(ids.end() != ids.find(91));
1587   EXPECT_TRUE(ids.end() != ids.find(92));
1588   EXPECT_TRUE(ids.end() != ids.find(93));
1589   EXPECT_TRUE(ids.end() != ids.find(94));
1590 
1591   // T5R2 test
1592   hwprops.supports_t5r2 = 1;
1593   wrapper.Reset(&ii, &hwprops);
1594   ii.ResetSameFingersState(hardware_state[0]);
1595   ii.UpdatePointingFingers(hardware_state[2]);
1596   ids = ii.GetGesturingFingers(hardware_state[2]);
1597   EXPECT_EQ(2, ids.size());
1598   EXPECT_TRUE(ids.end() != ids.find(91));
1599   EXPECT_TRUE(ids.end() != ids.find(92));
1600 }
1601 
1602 namespace {
MkSet()1603 std::set<short> MkSet() {
1604   return std::set<short>();
1605 }
MkSet(short the_id)1606 std::set<short> MkSet(short the_id) {
1607   std::set<short> ret;
1608   ret.insert(the_id);
1609   return ret;
1610 }
MkSet(short id1,short id2)1611 std::set<short> MkSet(short id1, short id2) {
1612   std::set<short> ret;
1613   ret.insert(id1);
1614   ret.insert(id2);
1615   return ret;
1616 }
MkSet(short id1,short id2,short id3)1617 std::set<short> MkSet(short id1, short id2, short id3) {
1618   std::set<short> ret;
1619   ret.insert(id1);
1620   ret.insert(id2);
1621   ret.insert(id3);
1622   return ret;
1623 }
1624 }  // namespace{}
1625 
TEST(ImmediateInterpreterTest,TapRecordTest)1626 TEST(ImmediateInterpreterTest, TapRecordTest) {
1627   ImmediateInterpreter ii(NULL, NULL);
1628   TapRecord tr(&ii);
1629   EXPECT_FALSE(tr.TapComplete());
1630   // two finger IDs:
1631   const short kF1 = 91;
1632   const short kF2 = 92;
1633   const float kTapMoveDist = 1.0;  // mm
1634   ii.tap_min_pressure_.val_ = 25;
1635 
1636   FingerState fs[] = {
1637     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1638     {0, 0, 0, 0, 50, 0, 4, 4, kF1, 0},
1639     {0, 0, 0, 0, 75, 0, 4, 9, kF2, 0},
1640     {0, 0, 0, 0, 50, 0, 7, 4, kF1, 0}
1641   };
1642   HardwareState nullstate = make_hwstate(0.0, 0, 0, 0, NULL);
1643   HardwareState hw[] = {
1644     // time, buttons, finger count, touch count, finger states pointer
1645     make_hwstate(0.0, 0, 1, 1, &fs[0]),
1646     make_hwstate(0.1, 0, 2, 2, &fs[0]),
1647     make_hwstate(0.2, 0, 1, 1, &fs[1]),
1648     make_hwstate(0.3, 0, 2, 2, &fs[0]),
1649     make_hwstate(0.4, 0, 1, 1, &fs[1]),
1650     make_hwstate(0.5, 0, 1, 1, &fs[2]),
1651   };
1652 
1653   /* Hack: Tap recorder points to immediate interpreter and assummes it contains
1654    * valid values, so we need to insert some origin timestamps */
1655   const_cast<ImmediateInterpreter*>(tr.immediate_interpreter_)->
1656                                                     origin_timestamps_[kF1] = 0;
1657   const_cast<ImmediateInterpreter*>(tr.immediate_interpreter_)->
1658                                                     origin_timestamps_[kF2] = 0;
1659   tr.Update(hw[0], nullstate, MkSet(kF1), MkSet(), MkSet());
1660   EXPECT_FALSE(tr.Moving(hw[0], kTapMoveDist));
1661   EXPECT_FALSE(tr.TapComplete());
1662   tr.Update(hw[1], hw[0], MkSet(), MkSet(), MkSet());
1663   EXPECT_FALSE(tr.Moving(hw[1], kTapMoveDist));
1664   EXPECT_FALSE(tr.TapComplete());
1665   tr.Update(hw[2], hw[1], MkSet(), MkSet(kF1), MkSet());
1666   EXPECT_FALSE(tr.Moving(hw[2], kTapMoveDist));
1667   EXPECT_TRUE(tr.TapComplete());
1668   EXPECT_EQ(GESTURES_BUTTON_LEFT, tr.TapType());
1669 
1670   tr.Clear();
1671   EXPECT_FALSE(tr.TapComplete());
1672   tr.Update(hw[2], hw[1], MkSet(kF2), MkSet(), MkSet());
1673   EXPECT_FALSE(tr.Moving(hw[2], kTapMoveDist));
1674   EXPECT_FALSE(tr.TapComplete());
1675   tr.Update(hw[3], hw[2], MkSet(kF1), MkSet(), MkSet(kF2));
1676   EXPECT_FALSE(tr.Moving(hw[3], kTapMoveDist));
1677   EXPECT_FALSE(tr.TapComplete());
1678   tr.Update(hw[4], hw[3], MkSet(), MkSet(kF1), MkSet());
1679   EXPECT_FALSE(tr.Moving(hw[4], kTapMoveDist));
1680   EXPECT_TRUE(tr.TapComplete());
1681 
1682   tr.Clear();
1683   EXPECT_FALSE(tr.TapComplete());
1684   tr.Update(hw[0], nullstate, MkSet(kF1), MkSet(), MkSet());
1685   tr.Update(hw[5], hw[4], MkSet(), MkSet(), MkSet());
1686   EXPECT_TRUE(tr.Moving(hw[5], kTapMoveDist));
1687   EXPECT_FALSE(tr.TapComplete());
1688 
1689   // This should log an error
1690   tr.Clear();
1691   tr.Update(hw[2], hw[1], MkSet(), MkSet(kF1), MkSet());
1692 }
1693 
1694 namespace {
1695 
1696 const long HWStateFlagStart          = 0x01000000;  // Start
1697 const long HWStateFlagContinue       = 0x02000000;  // Continue
1698 // Start; also start of slow double tap test:
1699 const long HWStateFlagStartDoubleTap = 0x04000000;
1700 // Start; also start of T5R2 tests:
1701 const long HWStateFlagStartT5R2      = 0x08000000;
1702 // Start; also tap dragging is disabled this time
1703 const long HWStateFlagStartNoDrag    = 0x10000000;
1704 const long HWStateFlagMask           = 0xff000000;
1705 
1706 #define S (__LINE__ + HWStateFlagStart)
1707 #define C (__LINE__ + HWStateFlagContinue)
1708 #define D (__LINE__ + HWStateFlagStartDoubleTap)
1709 #define T (__LINE__ + HWStateFlagStartT5R2)
1710 #define N (__LINE__ + HWStateFlagStartNoDrag)
1711 
1712 struct HWStateGs {
1713   long line_number_and_flags;
1714   HardwareState hws;
1715   stime_t callback_now;
1716   std::set<short> gs;
1717   unsigned expected_down;
1718   unsigned expected_up;
1719   ImmediateInterpreter::TapToClickState expected_state;
1720   bool timeout;
1721 
IsStartgestures::__anonb95748850311::HWStateGs1722   bool IsStart() {
1723     return line_number_and_flags & (HWStateFlagStart |
1724                                     HWStateFlagStartDoubleTap |
1725                                     HWStateFlagStartT5R2 |
1726                                     HWStateFlagStartNoDrag);
1727   }
LineNumbergestures::__anonb95748850311::HWStateGs1728   long LineNumber() {
1729     return line_number_and_flags & ~HWStateFlagMask;
1730   }
1731 };
1732 
NonT5R2States(const HWStateGs * states,size_t length)1733 size_t NonT5R2States(const HWStateGs* states, size_t length) {
1734   for (size_t i = 0; i < length; i++)
1735     if (states[i].line_number_and_flags & HWStateFlagStartT5R2)
1736       return i;
1737   return length;
1738 }
1739 
1740 }  // namespace {}
1741 
1742 // Shorter names so that HWStateGs defs take only 1 line each
1743 typedef ImmediateInterpreter::TapToClickState TapState;
1744 const TapState kIdl = ImmediateInterpreter::kTtcIdle;
1745 const TapState kFTB = ImmediateInterpreter::kTtcFirstTapBegan;
1746 const TapState kTpC = ImmediateInterpreter::kTtcTapComplete;
1747 const TapState kSTB = ImmediateInterpreter::kTtcSubsequentTapBegan;
1748 const TapState kDrg = ImmediateInterpreter::kTtcDrag;
1749 const TapState kDRl = ImmediateInterpreter::kTtcDragRelease;
1750 const TapState kDRt = ImmediateInterpreter::kTtcDragRetouch;
1751 const unsigned kBL = GESTURES_BUTTON_LEFT;
1752 const unsigned kBM = GESTURES_BUTTON_MIDDLE;
1753 const unsigned kBR = GESTURES_BUTTON_RIGHT;
1754 
TEST(ImmediateInterpreterTest,TapToClickStateMachineTest)1755 TEST(ImmediateInterpreterTest, TapToClickStateMachineTest) {
1756   std::unique_ptr<ImmediateInterpreter> ii;
1757 
1758   HardwareProperties hwprops = {
1759     0,  // left edge
1760     0,  // top edge
1761     200,  // right edge
1762     200,  // bottom edge
1763     1.0,  // pixels/TP width
1764     1.0,  // pixels/TP height
1765     1.0,  // screen DPI x
1766     1.0,  // screen DPI y
1767     -1,  // orientation minimum
1768     2,   // orientation maximum
1769     5,  // max fingers
1770     5,  // max touch
1771     0,  // t5r2
1772     0,  // semi-mt
1773     1,  // is button pad
1774     0,  // has_wheel
1775     0,  // wheel_is_hi_res
1776     0,  // is haptic pad
1777   };
1778   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
1779 
1780   FingerState fs[] = {
1781     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1782     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
1783     {0, 0, 0, 0, 75, 0, 4, 9, 92, 0},
1784     {0, 0, 0, 0, 50, 0, 4, 4, 93, 0},
1785     {0, 0, 0, 0, 50, 0, 4, 4, 94, 0},
1786     {0, 0, 0, 0, 50, 0, 4, 4, 95, 0},
1787     {0, 0, 0, 0, 50, 0, 6, 4, 95, 0},
1788     {0, 0, 0, 0, 50, 0, 8, 4, 95, 0},
1789     {0, 0, 0, 0, 50, 0, 4, 4, 96, 0},
1790     {0, 0, 0, 0, 50, 0, 6, 4, 96, 0},
1791     {0, 0, 0, 0, 50, 0, 8, 4, 96, 0},
1792 
1793     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},  // 10
1794     {0, 0, 0, 0, 50, 0, 9, 1, 98, 0},
1795     {0, 0, 0, 0, 50, 0, 4, 5, 97, 0},
1796     {0, 0, 0, 0, 50, 0, 9, 5, 98, 0},
1797     {0, 0, 0, 0, 50, 0, 4, 9, 97, 0},
1798     {0, 0, 0, 0, 50, 0, 9, 9, 98, 0},
1799 
1800     {0, 0, 0, 0, 80, 0, 5, 9, 70, 0},  // 16; thumb
1801     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
1802     {0, 0, 0, 0, 80, 0, 5, 9, 71, 0},  // thumb-new id
1803 
1804     {0, 0, 0, 0, 50, 0, 8.0, 4, 95, 0},  // 19; very close together fingers:
1805     {0, 0, 0, 0, 50, 0, 8.1, 4, 96, 0},
1806     {0, 0, 0, 0, 15, 0, 9.5, 4, 95, 0},  // very light pressure
1807     {0, 0, 0, 0, 15, 0, 11,  4, 96, 0},
1808 
1809     {0, 0, 0, 0, 50, 0, 20, 4, 95, 0},  // 23; Two fingers very far apart
1810     {0, 0, 0, 0, 50, 0, 90, 4, 96, 0},
1811 
1812     {0, 0, 0, 0, 50, 0, 50, 40, 95, 0},  // 25
1813     {0, 0, 0, 0, 15, 0, 70, 40, 96, 0},  // very light pressure
1814 
1815     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},  // 27
1816     {0, 0, 0, 0,  3, 0, 9, 1, 98, 0},
1817 
1818     {0, 0, 0, 0, 50, 0,  4, 1, 97, 0},  // 29
1819     {0, 0, 0, 0, 50, 0,  9, 1, 98, 0},
1820     {0, 0, 0, 0, 50, 0, 14, 1, 99, 0},
1821 
1822     {0, 0, 0, 0, 50, 0, 50, 40, 95, 0},  // 32
1823     {0, 0, 0, 0, 50, 0, 70, 40, 96, GESTURES_FINGER_NO_TAP},
1824 
1825     {0, 0, 0, 0, 50, 0, 4, 4, 91, GESTURES_FINGER_PALM},  // 34
1826   };
1827   HWStateGs hwsgs[] = {
1828     // Simple 1-finger tap
1829     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1830     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1831     {C,make_hwstate(0.07,0,0,0,NULL),.07,MkSet(),kBL,kBL,kIdl,false},
1832     // Simple 1-finger tap w/o dragging enabled
1833     {N,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1834     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),kBL,kBL,kIdl,false},
1835     // 1-finger tap with click
1836     {S,make_hwstate(0.00,kBL,1,1,&fs[0]),-1,MkSet(91),0,0,kIdl,false},
1837     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
1838     {C,make_hwstate(0.07,0,0,0,NULL),.07,MkSet(),0,0,kIdl,false},
1839     // 1-finger swipe
1840     {S,make_hwstate(0.00,0,1,1,&fs[4]),-1,MkSet(95),0,0,kFTB,false},
1841     {C,make_hwstate(0.01,0,1,1,&fs[5]),-1,MkSet(95),0,0,kIdl,false},
1842     {C,make_hwstate(0.02,0,1,1,&fs[6]),-1,MkSet(95),0,0,kIdl,false},
1843     {C,make_hwstate(0.03,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
1844     // Double 1-finger tap
1845     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1846     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1847     {C,make_hwstate(0.02,0,1,1,&fs[2]),-1,MkSet(93),0,0,kSTB,false},
1848     {C,make_hwstate(0.03,0,0,0,NULL),-1,MkSet(),kBL,kBL,kTpC,true},
1849     {C,make_hwstate(0.09,0,0,0,NULL),.09,MkSet(),kBL,kBL,kIdl,false},
1850     // Triple 1-finger tap
1851     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1852     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1853     {C,make_hwstate(0.02,0,1,1,&fs[2]),-1,MkSet(93),0,0,kSTB,false},
1854     {C,make_hwstate(0.03,0,0,0,NULL),-1,MkSet(),kBL,kBL,kTpC,true},
1855     {C,make_hwstate(0.04,0,1,1,&fs[3]),-1,MkSet(94),0,0,kSTB,false},
1856     {C,make_hwstate(0.05,0,0,0,NULL),-1,MkSet(),kBL,kBL,kTpC,true},
1857     {C,make_hwstate(0.11,0,0,0,NULL),.11,MkSet(),kBL,kBL,kIdl,false},
1858     // 1-finger tap + drag
1859     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1860     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1861     {C,make_hwstate(0.02,0,1,1,&fs[4]),-1,MkSet(95),0,0,kSTB,false},
1862     {C,make_hwstate(0.13,0,1,1,&fs[5]),-1,MkSet(95),kBL,0,kDrg,false},
1863     {C,make_hwstate(0.14,0,1,1,&fs[6]),-1,MkSet(95),0,0,kDrg,false},
1864     {C,make_hwstate(0.15,0,0,0,NULL),-1,MkSet(),0,0,kDRl,true},
1865     {C,make_hwstate(0.99,0,0,0,NULL),.99,MkSet(),0,kBL,kIdl,false},
1866     // 1-finger tap + move (drag expected)
1867     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1868     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1869     {C,make_hwstate(0.02,0,1,1,&fs[4]),-1,MkSet(95),0,0,kSTB,false},
1870     {C,make_hwstate(0.03,0,1,1,&fs[5]),-1,MkSet(95),kBL,0,kDrg,false},
1871     {C,make_hwstate(0.04,0,1,1,&fs[6]),-1,MkSet(95),0,0,kDrg,false},
1872     {C,make_hwstate(0.05,0,0,0,NULL),-1,MkSet(),0,0,kDRl,true},
1873     {C,make_hwstate(0.99,0,0,0,NULL),.99,MkSet(),0,kBL,kIdl,false},
1874     // 1-finger tap, move, release, move again (drag lock)
1875     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1876     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1877     {C,make_hwstate(0.02,0,1,1,&fs[4]),-1,MkSet(95),0,0,kSTB,false},
1878     {C,make_hwstate(0.08,0,1,1,&fs[5]),-1,MkSet(95),kBL,0,kDrg,false},
1879     {C,make_hwstate(0.09,0,1,1,&fs[6]),-1,MkSet(95),0,0,kDrg,false},
1880     {C,make_hwstate(0.10,0,0,0,NULL),-1,MkSet(),0,0,kDRl,true},
1881     {C,make_hwstate(0.11,0,1,1,&fs[7]),-1,MkSet(96),0,0,kDRt,false},
1882     {C,make_hwstate(0.12,0,1,1,&fs[8]),-1,MkSet(96),0,0,kDrg,false},
1883     {C,make_hwstate(0.13,0,1,1,&fs[9]),-1,MkSet(96),0,0,kDrg,false},
1884     {C,make_hwstate(0.14,0,0,0,NULL),-1,MkSet(),0,0,kDRl,true},
1885     {C,make_hwstate(0.99,0,0,0,NULL),.99,MkSet(),0,kBL,kIdl,false},
1886     // 1-finger long press
1887     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1888     {C,make_hwstate(0.02,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1889     {C,make_hwstate(0.04,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1890     {C,make_hwstate(0.06,0,1,1,&fs[0]),-1,MkSet(91),0,0,kIdl,false},
1891     {C,make_hwstate(0.07,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
1892     // 1-finger tap then long press
1893     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1894     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1895     {C,make_hwstate(0.02,0,1,1,&fs[4]),-1,MkSet(95),0,0,kSTB,false},
1896     {C,make_hwstate(0.14,0,1,1,&fs[4]),-1,MkSet(95),kBL,0,kDrg,false},
1897     {C,make_hwstate(0.16,0,1,1,&fs[4]),-1,MkSet(95),0,0,kDrg,false},
1898     {C,make_hwstate(0.18,0,1,1,&fs[4]),-1,MkSet(95),0,0,kDrg,false},
1899     {C,make_hwstate(0.19,0,0,0,NULL),-1,MkSet(),0,0,kDRl,true},
1900     {C,make_hwstate(0.99,0,0,0,NULL),.99,MkSet(),0,kBL,kIdl,false},
1901     // 2-finger tap (right click)
1902     {S,make_hwstate(0.00,0,2,2,&fs[10]),-1,MkSet(97,98),0,0,kFTB,false},
1903     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),kBR,kBR,kIdl,false},
1904     {C,make_hwstate(0.07,0,0,0,NULL),.07,MkSet(),0,0,kIdl,false},
1905     // 3-finger tap (middle click)
1906     {S,make_hwstate(0.00,0,3,3,&fs[29]),-1,MkSet(97,98,99),0,0,kFTB,false},
1907     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),kBM,kBM,kIdl,false},
1908     {C,make_hwstate(0.07,0,0,0,NULL),.07,MkSet(),0,0,kIdl,false},
1909     // 2-finger tap, but one finger is very very light, so left tap
1910     {S,make_hwstate(0.00,0,2,2,&fs[27]),-1,MkSet(97,98),0,0,kFTB,false},
1911     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1912     {C,make_hwstate(0.07,0,0,0,NULL),.07,MkSet(),kBL,kBL,kIdl,false},
1913     // 2-finger scroll
1914     {S,make_hwstate(0.00,0,2,2,&fs[10]),-1,MkSet(97,98),0,0,kFTB,false},
1915     {C,make_hwstate(0.01,0,2,2,&fs[12]),-1,MkSet(97,98),0,0,kIdl,false},
1916     {C,make_hwstate(0.02,0,2,2,&fs[14]),-1,MkSet(97,98),0,0,kIdl,false},
1917     {C,make_hwstate(0.03,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
1918     // left tap, right tap
1919     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1920     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1921     {C,make_hwstate(0.02,0,2,2,&fs[10]),-1,MkSet(97,98),kBL,kBL,kFTB,false},
1922     {C,make_hwstate(0.03,0,0,0,NULL),-1,MkSet(),kBR,kBR,kIdl,false},
1923     {C,make_hwstate(0.09,0,0,0,NULL),.09,MkSet(),0,0,kIdl,false},
1924     // left tap, multi-frame right tap
1925     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1926     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1927     {C,make_hwstate(0.02,0,1,1,&fs[10]),-1,MkSet(97),0,0,kSTB,false},
1928     {C,make_hwstate(0.03,0,1,1,&fs[11]),-1,MkSet(98),kBL,kBL,kFTB,false},
1929     {C,make_hwstate(0.04,0,0,0,NULL),-1,MkSet(),kBR,kBR,kIdl,false},
1930     // right tap, left tap
1931     {S,make_hwstate(0.00,0,2,2,&fs[10]),-1,MkSet(97,98),0,0,kFTB,false},
1932     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),kBR,kBR,kIdl,false},
1933     {C,make_hwstate(0.02,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1934     {C,make_hwstate(0.03,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1935     {C,make_hwstate(0.09,0,0,0,NULL),.09,MkSet(),kBL,kBL,kIdl,false},
1936     // middle tap, left tap
1937     {S,make_hwstate(0.00,0,3,3,&fs[29]),-1,MkSet(97,98,99),0,0,kFTB,false},
1938     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),kBM,kBM,kIdl,false},
1939     {C,make_hwstate(0.02,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1940     {C,make_hwstate(0.03,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1941     {C,make_hwstate(0.09,0,0,0,NULL),.09,MkSet(),kBL,kBL,kIdl,false},
1942     // right double-tap
1943     {S,make_hwstate(0.00,0,2,2,&fs[6]),-1,MkSet(95,96),0,0,kFTB,false},
1944     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),kBR,kBR,kIdl,false},
1945     {C,make_hwstate(0.02,0,2,2,&fs[10]),-1,MkSet(97,98),0,0,kFTB,false},
1946     {C,make_hwstate(0.03,0,0,0,NULL),-1,MkSet(),kBR,kBR,kIdl,false},
1947     {C,make_hwstate(0.09,0,0,0,NULL),.09,MkSet(),0,0,kIdl,false},
1948     // left drumroll separation on fast swipe
1949     {S,make_hwstate(0.00,0,1,1,&fs[32]),-1,MkSet(95),0,0,kFTB,false},
1950     {C,make_hwstate(0.01,0,1,1,&fs[33]),-1,MkSet(96),0,0,kIdl,false},
1951     {C,make_hwstate(0.02,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
1952     // left tap, right-drag
1953     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1954     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1955     {C,make_hwstate(0.02,0,2,2,&fs[10]),-1,MkSet(97,98),kBL,kBL,kFTB,false},
1956     {C,make_hwstate(0.03,0,2,2,&fs[12]),-1,MkSet(97,98),0,0,kIdl,false},
1957     {C,make_hwstate(0.04,0,2,2,&fs[14]),-1,MkSet(97,98),0,0,kIdl,false},
1958     {C,make_hwstate(0.05,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
1959     // left tap, right multi-frame drag
1960     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1961     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1962     {C,make_hwstate(0.02,0,1,1,&fs[10]),-1,MkSet(97),0,0,kSTB,false},
1963     {C,make_hwstate(0.03,0,2,2,&fs[12]),-1,MkSet(97,98),kBL,kBL,kIdl,false},
1964     {C,make_hwstate(0.04,0,2,2,&fs[14]),-1,MkSet(97,98),0,0,kIdl,false},
1965     {C,make_hwstate(0.05,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
1966     // left tap, drag + finger joined later
1967     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1968     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1969     {C,make_hwstate(0.02,0,1,1,&fs[10]),-1,MkSet(97),0,0,kSTB,false},
1970     {C,make_hwstate(0.13,0,1,1,&fs[10]),-1,MkSet(97),kBL,0,kDrg,false},
1971     {C,make_hwstate(0.14,0,2,2,&fs[12]),-1,MkSet(97,98),0,kBL,kIdl,false},
1972     {C,make_hwstate(0.15,0,2,2,&fs[14]),-1,MkSet(97,98),0,0,kIdl,false},
1973     {C,make_hwstate(0.16,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
1974     // right tap, left-drag
1975     {S,make_hwstate(0.00,0,2,2,&fs[14]),-1,MkSet(97,98),0,0,kFTB,false},
1976     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),kBR,kBR,kIdl,false},
1977     {C,make_hwstate(0.02,0,1,1,&fs[4]),-1,MkSet(95),0,0,kFTB,false},
1978     {C,make_hwstate(0.03,0,1,1,&fs[5]),-1,MkSet(95),0,0,kIdl,false},
1979     {C,make_hwstate(0.04,0,1,1,&fs[6]),-1,MkSet(95),0,0,kIdl,false},
1980     {C,make_hwstate(0.05,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
1981     // right tap, right-drag
1982     {S,make_hwstate(0.00,0,2,2,&fs[6]),-1,MkSet(95,96),0,0,kFTB,false},
1983     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),kBR,kBR,kIdl,false},
1984     {C,make_hwstate(0.02,0,2,2,&fs[10]),-1,MkSet(97,98),0,0,kFTB,false},
1985     {C,make_hwstate(0.03,0,2,2,&fs[12]),-1,MkSet(97,98),0,0,kIdl,false},
1986     {C,make_hwstate(0.04,0,2,2,&fs[14]),-1,MkSet(97,98),0,0,kIdl,false},
1987     {C,make_hwstate(0.05,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
1988     // drag then right-tap
1989     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
1990     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
1991     {C,make_hwstate(0.02,0,1,1,&fs[4]),-1,MkSet(95),0,0,kSTB,false},
1992     {C,make_hwstate(0.10,0,1,1,&fs[5]),-1,MkSet(95),kBL,0,kDrg,false},
1993     {C,make_hwstate(0.11,0,1,1,&fs[6]),-1,MkSet(95),0,0,kDrg,false},
1994     {C,make_hwstate(0.12,0,0,0,NULL),-1,MkSet(),0,0,kDRl,true},
1995     {C,make_hwstate(0.13,0,2,2,&fs[10]),-1,MkSet(97,98),0,0,kDRt,false},
1996     {C,make_hwstate(0.14,0,0,0,NULL),-1,MkSet(),0,kBL,kTpC,true},
1997     {C,make_hwstate(0.99,0,0,0,NULL),.99,MkSet(),kBR,kBR,kIdl,false},
1998     // slow double tap
1999     {D,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
2000     {C,make_hwstate(0.10,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
2001     {C,make_hwstate(0.12,0,1,1,&fs[2]),-1,MkSet(93),0,0,kSTB,false},
2002     {C,make_hwstate(0.22,0,0,0,NULL),-1,MkSet(),kBL,kBL,kTpC,true},
2003     {C,make_hwstate(0.90,0,0,0,NULL),.9,MkSet(),kBL,kBL,kIdl,false},
2004     // right tap, very close fingers - shouldn't tap
2005     {S,make_hwstate(0.00,0,2,2,&fs[19]),-1,MkSet(95,96),0,0,kIdl,false},
2006     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
2007     // very light left tap - shouldn't tap
2008     {S,make_hwstate(0.00,0,1,1,&fs[21]),-1,MkSet(95),0,0,kFTB,false},
2009     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
2010     // very light right tap - shouldn't tap
2011     {S,make_hwstate(0.00,0,2,2,&fs[21]),-1,MkSet(95,96),0,0,kFTB,false},
2012     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
2013     // half very light right tap - should tap
2014     {S,make_hwstate(0.00,0,2,2,&fs[20]),-1,MkSet(95,96),0,0,kFTB,false},
2015     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),kBR,kBR,kIdl,false},
2016     // Right tap, w/ fingers too far apart - shouldn't right tap
2017     {S,make_hwstate(0.00,0,2,2,&fs[23]),-1,MkSet(95,96),0,0,kFTB,false},
2018     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
2019     {C,make_hwstate(0.07,0,0,0,NULL),.07,MkSet(),kBL,kBL,kIdl,false},
2020     // Two fingers merge into one, then leave - shouldn't tap
2021     {S,make_hwstate(0.00,0,2,2,&fs[6]),-1,MkSet(95,96),0,0,kFTB,false},
2022     {C,make_hwstate(1.00,0,2,2,&fs[6]),-1,MkSet(95,96),0,0,kIdl,false},
2023     {C,make_hwstate(1.01,0,1,1,&fs[17]),-1,MkSet(91),0,0,kIdl,false},
2024     {C,make_hwstate(1.02,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
2025     // 1-finger marked as palm for a long time then unmarked - shouldn't tap
2026     {S,make_hwstate(0.00,0,1,1,&fs[34]),-1,MkSet(),0,0,kIdl,false},
2027     {C,make_hwstate(1.50,0,1,1,&fs[0]),-1,MkSet(91),0,0,kIdl,false},
2028     {C,make_hwstate(1.51,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
2029 
2030     //{C,make_hwstate(0.08,0,0,0,NULL),.07,MkSet(),0,0,kIdl,false},
2031     // Two fingers seem to tap, the bigger of which is the only one that
2032     // meets the minimum pressure threshold. Then that higher pressure finger
2033     // is no longer gesturing (e.g., it gets classified as a thumb).
2034     // There should be no tap b/c the one remaining finger didn't meet the
2035     // minimum pressure threshold.
2036     {S,make_hwstate(0.00,0,2,2,&fs[25]),-1,MkSet(95,96),0,0,kFTB,false},
2037     {C,make_hwstate(0.01,0,2,2,&fs[25]),-1,MkSet(96),0,0,kFTB,false},
2038     {C,make_hwstate(0.02,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
2039     // 2f click - shouldn't tap
2040     {S,make_hwstate(0.00,0,2,2,&fs[0]),-1,MkSet(91,92),0,0,kFTB,false},
2041     {C,make_hwstate(0.01,1,2,2,&fs[0]),-1,MkSet(91,92),0,0,kIdl,false},
2042     {C,make_hwstate(0.02,0,2,2,&fs[0]),-1,MkSet(91,92),0,0,kIdl,false},
2043     {C,make_hwstate(0.03,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
2044     // T5R2 tap tests:
2045     // (1f and 2f tap w/o resting thumb and 1f w/ resting thumb are the same as
2046     // above)
2047     // 2f tap w/ resting thumb
2048     {T,make_hwstate(0.00,0,1,1,&fs[16]),-1,MkSet(70),0,0,kFTB,false},
2049     {C,make_hwstate(1.00,0,1,1,&fs[16]),-1,MkSet(70),0,0,kIdl,false},
2050     {C,make_hwstate(1.01,0,1,3,&fs[16]),-1,MkSet(70),0,0,kFTB,false},
2051     {C,make_hwstate(1.02,0,2,3,&fs[16]),-1,MkSet(70,91),0,0,kFTB,false},
2052     {C,make_hwstate(1.03,0,0,2,NULL),-1,MkSet(),0,0,kFTB,false},
2053     {C,make_hwstate(1.04,0,1,1,&fs[18]),-1,MkSet(71),kBR,kBR,kIdl,false},
2054     // 3f tap w/o resting thumb
2055     {S,make_hwstate(0.00,0,2,3,&fs[0]),-1,MkSet(91,92),0,0,kFTB,false},
2056     {C,make_hwstate(0.01,0,0,1,NULL),-1,MkSet(),0,0,kFTB,false},
2057     {C,make_hwstate(0.02,0,0,0,NULL),-1,MkSet(),kBM,kBM,kIdl,false},
2058     // 3f tap w/o resting thumb (slightly different)
2059     {S,make_hwstate(0.00,0,2,3,&fs[0]),-1,MkSet(91,92),0,0,kFTB,false},
2060     {C,make_hwstate(0.01,0,2,3,&fs[0]),-1,MkSet(91,92),0,0,kFTB,false},
2061     {C,make_hwstate(0.02,0,0,0,NULL),-1,MkSet(),kBM,kBM,kIdl,false},
2062     // 3f tap w/ resting thumb
2063     {S,make_hwstate(0.00,0,1,1,&fs[16]),-1,MkSet(70),0,0,kFTB,false},
2064     {C,make_hwstate(1.00,0,1,1,&fs[16]),-1,MkSet(70),0,0,kIdl,false},
2065     {C,make_hwstate(1.01,0,1,4,&fs[16]),-1,MkSet(70),0,0,kFTB,false},
2066     {C,make_hwstate(1.02,0,2,4,&fs[16]),-1,MkSet(70,91),0,0,kFTB,false},
2067     {C,make_hwstate(1.03,0,1,1,&fs[16]),-1,MkSet(70),kBM,kBM,kIdl,false},
2068     // 4f tap w/o resting thumb
2069     {S,make_hwstate(0.00,0,2,3,&fs[0]),-1,MkSet(91,92),0,0,kFTB,false},
2070     {C,make_hwstate(0.01,0,1,4,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
2071     {C,make_hwstate(0.02,0,2,4,&fs[0]),-1,MkSet(91,92),0,0,kFTB,false},
2072     {C,make_hwstate(0.03,0,0,0,NULL),-1,MkSet(),kBR,kBR,kIdl,false},
2073     // 4f tap w/ resting thumb
2074     {S,make_hwstate(0.00,0,1,1,&fs[16]),-1,MkSet(70),0,0,kFTB,false},
2075     {C,make_hwstate(1.00,0,1,1,&fs[16]),-1,MkSet(70),0,0,kIdl,false},
2076     {C,make_hwstate(1.01,0,1,5,&fs[16]),-1,MkSet(70),0,0,kFTB,false},
2077     {C,make_hwstate(1.02,0,1,1,&fs[16]),-1,MkSet(70),kBR,kBR,kIdl,false},
2078     // 4f tap w/ resting thumb (slightly different)
2079     {S,make_hwstate(0.00,0,1,1,&fs[16]),-1,MkSet(70),0,0,kFTB,false},
2080     {C,make_hwstate(1.00,0,1,1,&fs[16]),-1,MkSet(70),0,0,kIdl,false},
2081     {C,make_hwstate(1.01,0,1,5,&fs[16]),-1,MkSet(70),0,0,kFTB,false},
2082     {C,make_hwstate(1.02,0,2,5,&fs[16]),-1,MkSet(70,91),0,0,kFTB,false},
2083     {C,make_hwstate(1.03,0,1,1,&fs[16]),-1,MkSet(70),kBR,kBR,kIdl,false},
2084     // 3f letting go, shouldn't tap at all
2085     {S,make_hwstate(0.00,0,2,3,&fs[0]),-1,MkSet(91,92),0,0,kFTB,false},
2086     {C,make_hwstate(1.01,0,2,3,&fs[0]),-1,MkSet(91,92),0,0,kIdl,false},
2087     {C,make_hwstate(1.02,0,0,2,NULL),-1,MkSet(),0,0,kIdl,false},
2088     {C,make_hwstate(1.03,0,2,2,&fs[10]),-1,MkSet(97,98),0,0,kIdl,false},
2089     {C,make_hwstate(1.04,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
2090     // tap then move with delay between touches. no drag expected
2091     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
2092     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
2093     {C,make_hwstate(0.22,0,1,1,&fs[4]),-1,MkSet(95),kBL,kBL,kIdl,false},
2094     {C,make_hwstate(0.23,0,1,1,&fs[5]),-1,MkSet(95),0,0,kIdl,false},
2095     {C,make_hwstate(0.25,0,1,1,&fs[6]),-1,MkSet(95),0,0,kIdl,false},
2096     {C,make_hwstate(0.26,0,0,0,NULL),-1,MkSet(),0,0,kIdl,false},
2097     {C,make_hwstate(0.99,0,0,0,NULL),.99,MkSet(),0,0,kIdl,false},
2098   };
2099   const size_t kT5R2TestFirstIndex = NonT5R2States(hwsgs, arraysize(hwsgs));
2100 
2101   // Algorithmically add a resting thumb to a copy of all above cases
2102   const size_t hwsgs_full_size = arraysize(hwsgs) + kT5R2TestFirstIndex;
2103   std::vector<HWStateGs> hwsgs_full;
2104   hwsgs_full.reserve(hwsgs_full_size);
2105   hwsgs_full.insert(hwsgs_full.end(), hwsgs, hwsgs + arraysize(hwsgs));
2106   hwsgs_full.insert(hwsgs_full.end(), hwsgs, hwsgs + kT5R2TestFirstIndex);
2107   std::vector<std::vector<FingerState> > thumb_fs(arraysize(hwsgs));
2108   const FingerState& fs_thumb = fs[18];
2109   bool thumb_gestures = true;
2110   for (size_t i = 0; i < kT5R2TestFirstIndex; ++i) {
2111     HardwareState* hs = &hwsgs_full[i + arraysize(hwsgs)].hws;
2112     if (hwsgs_full[i].IsStart())
2113       thumb_gestures = true;  // Start out w/ thumb being able to gesture
2114     if (hs->finger_cnt > 0)
2115       thumb_gestures = false;  // Once a finger is present, thumb can't gesture
2116     std::vector<FingerState>& newfs = thumb_fs[i];
2117     newfs.resize(hs->finger_cnt + 1);
2118     newfs[0] = fs_thumb;
2119     for (size_t j = 0; j < hs->finger_cnt; ++j)
2120       newfs[j + 1] = hs->fingers[j];
2121     std::set<short>& gs = hwsgs_full[i + arraysize(hwsgs)].gs;
2122     if (thumb_gestures)
2123       gs.insert(fs_thumb.tracking_id);
2124     hs->fingers = &thumb_fs[i][0];
2125     hs->finger_cnt++;
2126     hs->touch_cnt++;
2127   }
2128 
2129   for (size_t i = 0; i < hwsgs_full_size; ++i) {
2130     string desc;
2131     if (i < arraysize(hwsgs))
2132       desc = StringPrintf("State %zu, Line Number %ld", i,
2133                           hwsgs[i].LineNumber());
2134     else
2135       desc = StringPrintf("State %zu (resting thumb), Line Number %ld",
2136                           i - arraysize(hwsgs),
2137                           hwsgs[i - arraysize(hwsgs)].LineNumber());
2138 
2139     unsigned bdown = 0;
2140     unsigned bup = 0;
2141     stime_t tm = NO_DEADLINE;
2142     bool same_fingers = false;
2143     HardwareState* hwstate = &hwsgs_full[i].hws;
2144     stime_t now = hwsgs_full[i].callback_now;
2145     if (hwsgs_full[i].callback_now >= 0.0) {
2146       hwstate = NULL;
2147     } else {
2148       now = hwsgs_full[i].hws.timestamp;
2149     }
2150 
2151     if (hwstate && hwstate->timestamp == 0.0) {
2152       // Reset imm interpreter
2153       fprintf(stderr, "Resetting imm interpreter, i = %zd\n", i);
2154       ii.reset(new ImmediateInterpreter(NULL, NULL));
2155       wrapper.Reset(ii.get());
2156       ii->drag_lock_enable_.val_ = 1;
2157       ii->motion_tap_prevent_timeout_.val_ = 0;
2158       ii->tapping_finger_min_separation_.val_ = 1.0;
2159       ii->tap_drag_timeout_.val_ = 0.05;
2160       ii->tap_enable_.val_ = 1;
2161       ii->tap_drag_enable_.val_ =
2162           !(hwsgs_full[i].line_number_and_flags & HWStateFlagStartNoDrag);
2163       ii->tap_move_dist_.val_ = 1.0;
2164       ii->tap_timeout_.val_ = ii->inter_tap_timeout_.val_ = 0.05;
2165       ii->three_finger_click_enable_.val_ = 1;
2166       ii->t5r2_three_finger_click_enable_.val_ = 1;
2167       ii->zero_finger_click_enable_.val_ = 1;
2168       // For the slow tap case, we need to make tap_timeout_ bigger
2169       if (hwsgs_full[i].line_number_and_flags & HWStateFlagStartDoubleTap)
2170         ii->tap_timeout_.val_ = 0.11;
2171       EXPECT_EQ(kIdl, ii->tap_to_click_state_);
2172     } else {
2173       same_fingers = ii->state_buffer_.Get(1)->SameFingersAs(hwsgs_full[i].hws);
2174     }
2175 
2176     if (hwstate)
2177       ii->state_buffer_.PushState(*hwstate);
2178     for (auto finger: hwsgs_full[i].gs)
2179       ii->origin_timestamps_.emplace(finger, 0);
2180     ii->UpdateTapState(
2181         hwstate, hwsgs_full[i].gs, same_fingers, now, &bdown, &bup, &tm);
2182     ii->prev_gs_fingers_ = hwsgs_full[i].gs;
2183     EXPECT_EQ(hwsgs_full[i].expected_down, bdown) << desc;
2184     EXPECT_EQ(hwsgs_full[i].expected_up, bup) << desc;
2185     if (hwsgs_full[i].timeout)
2186       EXPECT_GT(tm, 0.0) << desc;
2187     else
2188       EXPECT_DOUBLE_EQ(NO_DEADLINE, tm) << desc;
2189     EXPECT_EQ(hwsgs_full[i].expected_state, ii->tap_to_click_state_)
2190         << desc;
2191   }
2192 }
2193 
2194 namespace {
2195 
2196 struct TapToClickLowPressureBeginOrEndInputs {
2197   stime_t now;
2198   float x0, y0, p0;  // (x, y), pressure
2199   short id0;  // tracking id
2200   float x1, y1, p1;  // (x, y), pressure
2201   short id1;  // tracking id
2202 };
2203 
2204 }  // namespace {}
2205 
2206 // Test that if a tap contact has some frames before and after that tap, with
2207 // a finger that's located far from the tap spot, but has low pressure at that
2208 // location, it's still a tap. We see this happen on some hardware particularly
2209 // for right clicks. This is based on two logs from Ken Moore.
TEST(ImmediateInterpreterTest,TapToClickLowPressureBeginOrEndTest)2210 TEST(ImmediateInterpreterTest, TapToClickLowPressureBeginOrEndTest) {
2211   std::unique_ptr<ImmediateInterpreter> ii;
2212   HardwareProperties hwprops = {
2213     0,  // left edge
2214     0,  // top edge
2215     106.666672,  // right edge
2216     68.000000,  // bottom edge
2217     1,  // pixels/TP width
2218     1,  // pixels/TP height
2219     25.4,  // screen DPI x
2220     25.4,  // screen DPI y
2221     -1,  // orientation minimum
2222     2,   // orientation maximum
2223     15,  // max fingers
2224     5,  // max touch
2225     0,  // t5r2
2226     0,  // semi-mt
2227     true,  // is button pad
2228     0,  // has_wheel
2229     0,  // wheel_is_hi_res
2230     false,  // is haptic pad
2231   };
2232   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
2233 
2234   TapToClickLowPressureBeginOrEndInputs inputs[] = {
2235     // Two runs
2236     { 32.4901, 55.5, 24.8,  7.0,  1,  0.0,  0.0,  0.0, -1 },
2237     { 32.5010, 57.7, 25.0, 43.0,  1, 42.0, 27.5, 36.0,  2 },
2238     { 32.5118, 58.0, 25.0, 44.0,  1, 42.0, 27.5, 43.0,  2 },
2239     { 32.5227, 58.0, 25.0, 44.0,  1, 42.0, 27.6, 44.0,  2 },
2240     { 32.5335, 58.0, 25.0, 45.0,  1, 42.0, 27.6, 45.0,  2 },
2241     { 32.5443, 58.0, 25.0, 44.0,  1, 42.0, 27.6, 45.0,  2 },
2242     { 32.5552, 58.0, 25.0, 44.0,  1, 42.0, 27.6, 44.0,  2 },
2243     { 32.5661, 58.0, 25.0, 42.0,  1, 42.0, 27.6, 42.0,  2 },
2244     { 32.5769, 58.0, 25.0, 35.0,  1, 42.0, 27.6, 35.0,  2 },
2245     { 32.5878, 58.0, 25.0, 15.0,  1, 41.9, 27.6, 18.0,  2 },
2246     { 32.5965, 45.9, 27.5,  7.0,  2,  0.0,  0.0,  0.0, -1 },
2247     { 32.6042,  0.0,  0.0,  0.0, -1,  0.0,  0.0,  0.0, -1 },
2248 
2249     { 90.6057, 64.0, 37.0, 18.0,  1,  0.0,  0.0,  0.0, -1 },
2250     { 90.6144, 63.6, 37.0, 43.0,  1,  0.0,  0.0,  0.0, -1 },
2251     { 90.6254, 63.6, 37.0, 43.0,  1, 46.5, 40.2, 47.0,  2 },
2252     { 90.6361, 63.6, 37.0, 44.0,  1, 46.5, 40.2, 44.0,  2 },
2253     { 90.6470, 63.6, 37.0, 45.0,  1, 46.5, 40.2, 46.0,  2 },
2254     { 90.6579, 63.6, 37.0, 45.0,  1, 46.5, 40.2, 46.0,  2 },
2255     { 90.6686, 63.6, 37.0, 45.0,  1, 46.5, 40.2, 47.0,  2 },
2256     { 90.6795, 63.6, 37.0, 46.0,  1, 46.5, 40.2, 47.0,  2 },
2257     { 90.6903, 63.6, 37.0, 45.0,  1, 46.5, 40.2, 46.0,  2 },
2258     { 90.7012, 63.6, 37.0, 44.0,  1, 46.3, 40.2, 44.0,  2 },
2259     { 90.7121, 63.6, 37.2, 38.0,  1, 46.4, 40.2, 31.0,  2 },
2260     { 90.7229, 63.6, 37.4, 22.0,  1, 46.4, 40.2, 12.0,  2 },
2261     { 90.7317, 61.1, 38.0,  8.0,  1,  0.0,  0.0,  0.0, -1 },
2262     { 90.7391,  0.0,  0.0,  0.0, -1,  0.0,  0.0,  0.0, -1 },
2263   };
2264 
2265   bool reset_next_time = true;
2266   for (size_t i = 0; i < arraysize(inputs); i++) {
2267     const TapToClickLowPressureBeginOrEndInputs& input = inputs[i];
2268     if (reset_next_time) {
2269       ii.reset(new ImmediateInterpreter(NULL, NULL));
2270       wrapper.Reset(ii.get());
2271       ii->tap_enable_.val_ = 1;
2272       reset_next_time = false;
2273     }
2274     // Prep inputs
2275     FingerState fs[] = {
2276       { 0, 0, 0, 0, input.p0, 0, input.x0, input.y0, input.id0, 0 },
2277       { 0, 0, 0, 0, input.p1, 0, input.x1, input.y1, input.id1, 0 },
2278     };
2279     unsigned short finger_cnt = fs[0].tracking_id == -1 ? 0 :
2280         (fs[1].tracking_id == -1 ? 1 : 2);
2281     HardwareState hs = make_hwstate(input.now, 0, finger_cnt, finger_cnt, fs);
2282     stime_t timeout = NO_DEADLINE;
2283     Gesture* gs = wrapper.SyncInterpret(&hs, &timeout);
2284     if (finger_cnt > 0) {
2285       // Expect no timeout
2286       EXPECT_LT(timeout, 0);
2287     } else {
2288       // No timeout b/c it's right click. Expect the right click gesture
2289       ASSERT_NE(static_cast<Gesture*>(NULL), gs) << "timeout:" << timeout;
2290       EXPECT_EQ(kGestureTypeButtonsChange, gs->type);
2291       EXPECT_EQ(GESTURES_BUTTON_RIGHT, gs->details.buttons.down);
2292       EXPECT_EQ(GESTURES_BUTTON_RIGHT, gs->details.buttons.up);
2293       reset_next_time = true;  // All done w/ this run.
2294     }
2295   }
2296 }
2297 
2298 // Does two tap gestures, one with keyboard interference.
TEST(ImmediateInterpreterTest,TapToClickKeyboardTest)2299 TEST(ImmediateInterpreterTest, TapToClickKeyboardTest) {
2300   std::unique_ptr<ImmediateInterpreter> ii;
2301 
2302   HardwareProperties hwprops = {
2303     0,  // left edge
2304     0,  // top edge
2305     200,  // right edge
2306     200,  // bottom edge
2307     1.0,  // pixels/TP width
2308     1.0,  // pixels/TP height
2309     1.0,  // screen DPI x
2310     1.0,  // screen DPI y
2311     -1,  // orientation minimum
2312     2,   // orientation maximum
2313     5,  // max fingers
2314     5,  // max touch
2315     0,  // t5r2
2316     0,  // semi-mt
2317     1,  // is button pad
2318     0,  // has_wheel
2319     0,  // wheel_is_hi_res
2320     0,  // is haptic pad
2321   };
2322   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
2323 
2324   FingerState fs = {
2325     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
2326     0, 0, 0, 0, 50, 0, 4, 4, 91, 0
2327   };
2328   HardwareState hwstates[] = {
2329     // Simple 1-finger tap
2330     make_hwstate(0.01, 0, 1, 1, &fs),
2331     make_hwstate(0.02, 0, 0, 0, NULL),
2332     make_hwstate(0.30, 0, 0, 0, NULL),
2333   };
2334 
2335   enum {
2336     kWithoutKeyboard = 0,
2337     kWithKeyboard,
2338     kMaxTests
2339   };
2340   for (size_t test = 0; test != kMaxTests; test++) {
2341     ii.reset(new ImmediateInterpreter(NULL, NULL));
2342     wrapper.Reset(ii.get());
2343     ii->motion_tap_prevent_timeout_.val_ = 0;
2344     ii->tap_enable_.val_ = 1;
2345     ii->tap_drag_enable_.val_ = 1;
2346 
2347     if (test == kWithKeyboard)
2348       ii->keyboard_touched_ = 0.001;
2349 
2350     unsigned down = 0;
2351     unsigned up = 0;
2352     for (size_t i = 0; i < arraysize(hwstates); i++) {
2353       down = 0;
2354       up = 0;
2355       stime_t timeout = NO_DEADLINE;
2356       std::set<short> gs =
2357           hwstates[i].finger_cnt == 1 ? MkSet(91) : MkSet();
2358       for (auto finger: gs)
2359         ii->origin_timestamps_.emplace(finger, 0);
2360       ii->UpdateTapState(
2361           &hwstates[i],
2362           gs,
2363           false,  // same fingers
2364           hwstates[i].timestamp,
2365           &down,
2366           &up,
2367           &timeout);
2368     }
2369     EXPECT_EQ(down, up);
2370     if (test == kWithoutKeyboard)
2371       EXPECT_EQ(GESTURES_BUTTON_LEFT, down);
2372     else
2373       EXPECT_EQ(0, down);
2374   }
2375 }
2376 
TEST(ImmediateInterpreterTest,TapToClickEnableTest)2377 TEST(ImmediateInterpreterTest, TapToClickEnableTest) {
2378   std::unique_ptr<ImmediateInterpreter> ii;
2379 
2380   HardwareProperties hwprops = {
2381     0,  // left edge
2382     0,  // top edge
2383     200,  // right edge
2384     200,  // bottom edge
2385     1.0,  // pixels/TP width
2386     1.0,  // pixels/TP height
2387     1.0,  // screen DPI x
2388     1.0,  // screen DPI y
2389     -1,  // orientation minimum
2390     2,   // orientation maximum
2391     5,  // max fingers
2392     5,  // max touch
2393     0,  // t5r2
2394     0,  // semi-mt
2395     1,  // is button pad
2396     0,  // has_wheel
2397     0,  // wheel_is_hi_res
2398     0,  // is haptic pad
2399   };
2400   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
2401 
2402   FingerState fs[] = {
2403     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
2404     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2405     {0, 0, 0, 0, 50, 0, 4, 4, 92, 0},
2406     {0, 0, 0, 0, 50, 0, 6, 4, 92, 0},
2407     {0, 0, 0, 0, 50, 0, 8, 4, 92, 0},
2408     {0, 0, 0, 0, 50, 0, 4, 4, 93, 0},
2409     {0, 0, 0, 0, 50, 0, 6, 4, 93, 0},
2410     {0, 0, 0, 0, 50, 0, 8, 4, 93, 0},
2411   };
2412 
2413   HWStateGs hwsgs_list[] = {
2414     // 1-finger tap, move, release, move again (drag lock)
2415     {S,make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
2416     {C,make_hwstate(0.01,0,0,0,NULL),-1,MkSet(),0,0,kTpC,true},
2417     {C,make_hwstate(0.02,0,1,1,&fs[1]),-1,MkSet(92),0,0,kSTB,false},
2418     {C,make_hwstate(0.08,0,1,1,&fs[2]),-1,MkSet(92),kBL,0,kDrg,false},
2419     {C,make_hwstate(0.09,0,1,1,&fs[3]),-1,MkSet(92),0,0,kDrg,false},
2420     {C,make_hwstate(0.10,0,0,0,NULL),-1,MkSet(),0,0,kDRl,true},
2421     {C,make_hwstate(0.11,0,1,1,&fs[4]),-1,MkSet(93),0,0,kDRt,false},
2422     {C,make_hwstate(0.12,0,1,1,&fs[5]),-1,MkSet(93),0,0,kDrg,false},
2423     {C,make_hwstate(0.13,0,1,1,&fs[6]),-1,MkSet(93),0,0,kDrg,false},
2424     {C,make_hwstate(0.14,0,0,0,NULL),-1,MkSet(),0,0,kDRl,true},
2425     {C,make_hwstate(0.99,0,0,0,NULL),.99,MkSet(),0,kBL,kIdl,false}
2426   };
2427 
2428   for (int iter = 0; iter < 5; ++iter) {
2429     for (size_t i = 0; i < arraysize(hwsgs_list); ++i) {
2430       string desc;
2431       stime_t disable_time = 0.0;
2432       stime_t pause_time = 0.0;
2433       switch (iter) {
2434         case 0:  // test with tap enabled
2435           desc = StringPrintf("State %zu (tap enabled)", i);
2436           disable_time = -1;  // unreachable time
2437           pause_time = -1;
2438           break;
2439         case 1:  // test with tap disabled during gesture
2440           desc = StringPrintf("State %zu (tap disabled during gesture)", i);
2441           disable_time = 0.02;
2442           pause_time = -1;
2443           break;
2444         case 2:  // test with tap disabled before gesture (while Idle)
2445           desc = StringPrintf("State %zu (tap disabled while Idle)", i);
2446           disable_time = 0.00;
2447           pause_time = -1;
2448           break;
2449         case 3:  // test with tap paused during gesture
2450           desc = StringPrintf("State %zu (tap paused during gesture)", i);
2451           disable_time = -1;
2452           pause_time = 0.02;
2453           break;
2454         case 4:  // test with tap paused before gesture (while Idle)
2455           desc = StringPrintf("State %zu (tap paused while Idle)", i);
2456           disable_time = 0.00;
2457           pause_time = -1;
2458           break;
2459       }
2460 
2461       HWStateGs &hwsgs = hwsgs_list[i];
2462       HardwareState* hwstate = &hwsgs.hws;
2463       stime_t now = hwsgs.callback_now;
2464       if (hwsgs.callback_now >= 0.0)
2465         hwstate = NULL;
2466       else
2467         now = hwsgs.hws.timestamp;
2468 
2469       bool same_fingers = false;
2470       if (hwstate && hwstate->timestamp == 0.0) {
2471         // Reset imm interpreter
2472         fprintf(stderr, "Resetting imm interpreter, i = %zd\n", i);
2473         ii.reset(new ImmediateInterpreter(NULL, NULL));
2474         wrapper.Reset(ii.get());
2475         ii->drag_lock_enable_.val_ = 1;
2476         ii->motion_tap_prevent_timeout_.val_ = 0;
2477         ii->tap_drag_timeout_.val_ = 0.05;
2478         ii->tap_enable_.val_ = 1;
2479         ii->tap_drag_enable_.val_ = 1;
2480         ii->tap_paused_.val_ = 0;
2481         ii->tap_move_dist_.val_ = 1.0;
2482         ii->tap_timeout_.val_ = 0.05;
2483         EXPECT_EQ(kIdl, ii->tap_to_click_state_);
2484         EXPECT_TRUE(ii->tap_enable_.val_);
2485       } else {
2486         same_fingers = ii->state_buffer_.Get(1)->SameFingersAs(hwsgs.hws);
2487       }
2488 
2489       // Disable tap in the middle of the gesture
2490       if (hwstate && hwstate->timestamp == disable_time)
2491         ii->tap_enable_.val_ = 0;
2492 
2493       if (hwstate && hwstate->timestamp == pause_time)
2494         ii->tap_paused_.val_ = true;
2495 
2496       if (hwstate)
2497         ii->state_buffer_.PushState(*hwstate);
2498       unsigned bdown = 0;
2499       unsigned bup = 0;
2500       stime_t tm = NO_DEADLINE;
2501       for (auto finger: hwsgs.gs)
2502         ii->origin_timestamps_.emplace(finger, 0);
2503       ii->UpdateTapState(
2504           hwstate, hwsgs.gs, same_fingers, now, &bdown, &bup, &tm);
2505       ii->prev_gs_fingers_ = hwsgs.gs;
2506 
2507       switch (iter) {
2508         case 0:  // tap should be enabled
2509         case 1:
2510         case 3:
2511           EXPECT_EQ(hwsgs.expected_down, bdown) << desc;
2512           EXPECT_EQ(hwsgs.expected_up, bup) << desc;
2513           if (hwsgs.timeout)
2514             EXPECT_GT(tm, 0.0) << desc;
2515           else
2516             EXPECT_DOUBLE_EQ(NO_DEADLINE, tm) << desc;
2517           EXPECT_EQ(hwsgs.expected_state, ii->tap_to_click_state_) << desc;
2518           break;
2519         case 2:  // tap should be disabled
2520         case 4:
2521           EXPECT_EQ(0, bdown) << desc;
2522           EXPECT_EQ(0, bup) << desc;
2523           EXPECT_DOUBLE_EQ(NO_DEADLINE, tm) << desc;
2524           EXPECT_EQ(kIdl, ii->tap_to_click_state_) << desc;
2525           break;
2526       }
2527     }
2528   }
2529 }
2530 
2531 struct ClickTestHardwareStateAndExpectations {
2532   HardwareState hs;
2533   stime_t timeout;
2534   unsigned expected_down;
2535   unsigned expected_up;
2536 };
2537 
TEST(ImmediateInterpreterTest,ClickTest)2538 TEST(ImmediateInterpreterTest, ClickTest) {
2539   ImmediateInterpreter ii(NULL, NULL);
2540   HardwareProperties hwprops = {
2541     0,  // left edge
2542     0,  // top edge
2543     100,  // right edge
2544     100,  // bottom edge
2545     1,  // x pixels/mm
2546     1,  // y pixels/mm
2547     96,  // x screen DPI
2548     96,  // y screen DPI
2549     -1,  // orientation minimum
2550     2,   // orientation maximum
2551     2,  // max fingers
2552     5,  // max touch
2553     0,  // t5r2
2554     0,  // semi-mt
2555     1,  // is button pad
2556     0,  // has_wheel
2557     0,  // wheel_is_hi_res
2558     0,  // is haptic pad
2559   };
2560   TestInterpreterWrapper wrapper(&ii, &hwprops);
2561   EXPECT_FLOAT_EQ(10.0, ii.tapping_finger_min_separation_.val_);
2562 
2563   FingerState finger_states[] = {
2564     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
2565     {0, 0, 0, 0, 10, 0, 50, 50, 1, 0},
2566     {0, 0, 0, 0, 10, 0, 70, 50, 2, 0},
2567     // Fingers very close together - shouldn't right click
2568     {0, 0, 0, 0, 10, 0, 50, 50, 1, 0},
2569     {0, 0, 0, 0, 10, 0, 55, 50, 2, 0},
2570     // Large vertical dist - shouldn right click when timing is good.
2571     {0, 0, 0, 0, 10, 0,  8.4, 94, 1, 0},
2572     {0, 0, 0, 0, 10, 0, 51.2, 70, 2, 0},
2573   };
2574   ClickTestHardwareStateAndExpectations records[] = {
2575     // reset
2576     {make_hwstate(0,0,0,0,NULL),NO_DEADLINE,0,0},
2577 
2578     // button down, 2 fingers touch, button up, 2 fingers lift
2579     {make_hwstate(1,1,0,0,NULL),NO_DEADLINE,0,0},
2580     {make_hwstate(1.01,1,2,2,&finger_states[0]), NO_DEADLINE, 0, 0},
2581     {make_hwstate(2,0,2,2,&finger_states[0]),
2582      NO_DEADLINE, GESTURES_BUTTON_RIGHT, GESTURES_BUTTON_RIGHT},
2583     {make_hwstate(3,0,0,0,NULL), NO_DEADLINE, 0, 0},
2584 
2585     // button down, 2 close fingers touch, fingers lift
2586     {make_hwstate(7,1,0,0,NULL), NO_DEADLINE, 0, 0},
2587     {make_hwstate(7.01,1,2,2,&finger_states[2]), NO_DEADLINE, 0, 0},
2588     {make_hwstate(7.02,0,2,2,&finger_states[2]),
2589      NO_DEADLINE, GESTURES_BUTTON_LEFT,GESTURES_BUTTON_LEFT},
2590     {make_hwstate(8,0,0,0,NULL), NO_DEADLINE, 0, 0},
2591 
2592     // button down with 2 fingers, button up, fingers lift
2593     {make_hwstate(9.01,1,2,2,&finger_states[4]),NO_DEADLINE,0,0},
2594     {make_hwstate(9.02,1,2,2,&finger_states[4]),NO_DEADLINE,0,0},
2595     {make_hwstate(9.5,0,2,2,&finger_states[4]),
2596      NO_DEADLINE, GESTURES_BUTTON_RIGHT,GESTURES_BUTTON_RIGHT},
2597     {make_hwstate(10,0,0,0,NULL), NO_DEADLINE, 0, 0},
2598 
2599     // button down with 2 fingers, timeout, button up, fingers lift
2600     {make_hwstate(11,1,2,2,&finger_states[4]), NO_DEADLINE, 0, 0},
2601     {make_hwstate(0,0,0,0,NULL),11.5,GESTURES_BUTTON_RIGHT,0},
2602     {make_hwstate(12,0,2,2,&finger_states[4]), NO_DEADLINE, 0,
2603      GESTURES_BUTTON_RIGHT},
2604     {make_hwstate(10,0,0,0,NULL), NO_DEADLINE, 0, 0}
2605   };
2606 
2607   for (size_t i = 0; i < arraysize(records); ++i) {
2608     Gesture* result = NULL;
2609     if (records[i].timeout < 0.0)
2610       result = wrapper.SyncInterpret(&records[i].hs, NULL);
2611     else
2612       result = wrapper.HandleTimer(records[i].timeout, NULL);
2613     if (records[i].expected_down == 0 && records[i].expected_up == 0) {
2614       EXPECT_EQ(static_cast<Gesture*>(NULL), result) << "i=" << i;
2615     } else {
2616       ASSERT_NE(static_cast<Gesture*>(NULL), result) << "i=" << i;
2617       EXPECT_EQ(records[i].expected_down, result->details.buttons.down);
2618       EXPECT_EQ(records[i].expected_up, result->details.buttons.up);
2619     }
2620   }
2621 }
2622 
2623 struct BigHandsRightClickInputAndExpectations {
2624   HardwareState hs;
2625   unsigned out_buttons_down;
2626   unsigned out_buttons_up;
2627   FingerState fs[2];
2628 };
2629 
2630 // This was recorded from Ian Fette, who had trouble right-clicking.
2631 // This test plays back part of his log to ensure that it generates a
2632 // right click.
TEST(ImmediateInterpreterTest,BigHandsRightClickTest)2633 TEST(ImmediateInterpreterTest, BigHandsRightClickTest) {
2634   HardwareProperties hwprops = {
2635     0,  // left edge
2636     0,  // top edge
2637     106.666672,  // right edge
2638     68.000000,  // bottom edge
2639     1,  // pixels/TP width
2640     1,  // pixels/TP height
2641     25.4,  // screen DPI x
2642     25.4,  // screen DPI y
2643     -1,  // orientation minimum
2644     2,   // orientation maximum
2645     15,  // max fingers
2646     5,  // max touch
2647     0,  // t5r2
2648     0,  // semi-mt
2649     true,  // is button pad
2650     0,  // has_wheel
2651     0,  // wheel_is_hi_res
2652     false,  // is haptic pad
2653   };
2654   BigHandsRightClickInputAndExpectations records[] = {
2655     { make_hwstate(1329527921.327647, 0, 2, 2, NULL), 0, 0,
2656       { { 0, 0, 0, 0, 50.013428, 0, 20.250002, 59.400002, 130, 0 },
2657         { 0, 0, 0, 0, 41.862095, 0, 57.458694, 43.700001, 131, 0 } } },
2658     { make_hwstate(1329527921.344421, 0, 2, 2, NULL), 0, 0,
2659       { { 0, 0, 0, 0, 50.301102, 0, 20.250002, 59.400002, 130, 0 },
2660         { 0, 0, 0, 0, 42.007469, 0, 57.479977, 43.700001, 131, 0 } } },
2661     { make_hwstate(1329527921.361196, 1, 2, 2, NULL), 0, 0,
2662       { { 0, 0, 0, 0, 50.608433, 0, 20.250002, 59.400002, 130, 0 },
2663         { 0, 0, 0, 0, 42.065464, 0, 57.494164, 43.700001, 131, 0 } } },
2664     { make_hwstate(1329527921.372364, 1, 2, 2, NULL), 0, 0,
2665       { { 0, 0, 0, 0, 50.840954, 0, 20.250002, 59.400002, 130, 0 },
2666         { 0, 0, 0, 0, 42.071739, 0, 57.507217, 43.700001, 131, 0 } } },
2667     { make_hwstate(1329527921.383517, 1, 2, 2, NULL), 0, 0,
2668       { { 0, 0, 0, 0, 51.047310, 0, 20.250002, 59.400002, 130, 0 },
2669         { 0, 0, 0, 0, 42.054974, 0, 57.527523, 43.700001, 131, 0 } } },
2670     { make_hwstate(1329527921.394680, 1, 2, 2, NULL), 0, 0,
2671       { { 0, 0, 0, 0, 51.355824, 0, 20.250002, 59.400002, 130, 0 },
2672         { 0, 0, 0, 0, 42.066948, 0, 57.550964, 43.700001, 131, 0 } } },
2673     { make_hwstate(1329527921.405842, 1, 2, 2, NULL), 0, 0,
2674       { { 0, 0, 0, 0, 51.791901, 0, 20.250002, 59.400002, 130, 0 },
2675         { 0, 0, 0, 0, 42.188736, 0, 57.569374, 43.700001, 131, 0 } } },
2676     { make_hwstate(1329527921.416791, 1, 2, 2, NULL), GESTURES_BUTTON_RIGHT, 0,
2677       { { 0, 0, 0, 0, 52.264156, 0, 20.250002, 59.400002, 130, 0 },
2678         { 0, 0, 0, 0, 42.424179, 0, 57.586361, 43.700001, 131, 0 } } },
2679     { make_hwstate(1329527921.427937, 1, 2, 2, NULL), 0, 0,
2680       { { 0, 0, 0, 0, 52.725105, 0, 20.250002, 59.400002, 130, 0 },
2681         { 0, 0, 0, 0, 42.676739, 0, 57.609421, 43.700001, 131, 0 } } },
2682     { make_hwstate(1329527921.439094, 1, 2, 2, NULL), 0, 0,
2683       { { 0, 0, 0, 0, 53.191925, 0, 20.250002, 59.400002, 130, 0 },
2684         { 0, 0, 0, 0, 42.868217, 0, 57.640007, 43.700001, 131, 0 } } },
2685     { make_hwstate(1329527921.461392, 1, 2, 2, NULL), 0, 0,
2686       { { 0, 0, 0, 0, 53.602665, 0, 20.250002, 59.400002, 130, 0 },
2687         { 0, 0, 0, 0, 43.016544, 0, 57.676689, 43.700001, 131, 0 } } },
2688     { make_hwstate(1329527921.483690, 1, 2, 2, NULL), 0, 0,
2689       { { 0, 0, 0, 0, 53.879429, 0, 20.250002, 59.400002, 130, 0 },
2690         { 0, 0, 0, 0, 43.208221, 0, 57.711613, 43.700001, 131, 0 } } },
2691     { make_hwstate(1329527921.511815, 1, 2, 2, NULL), 0, 0,
2692       { { 0, 0, 0, 0, 54.059937, 0, 20.250002, 59.400002, 130, 0 },
2693         { 0, 0, 0, 0, 43.467258, 0, 57.736385, 43.700001, 131, 0 } } },
2694     { make_hwstate(1329527921.539940, 1, 2, 2, NULL), 0, 0,
2695       { { 0, 0, 0, 0, 54.253189, 0, 20.250002, 59.400002, 130, 0 },
2696         { 0, 0, 0, 0, 43.717934, 0, 57.750286, 43.700001, 131, 0 } } },
2697     { make_hwstate(1329527921.556732, 1, 2, 2, NULL), 0, 0,
2698       { { 0, 0, 0, 0, 54.500740, 0, 20.250002, 59.400002, 130, 0 },
2699         { 0, 0, 0, 0, 43.863792, 0, 57.758759, 43.700001, 131, 0 } } },
2700     { make_hwstate(1329527921.573523, 1, 2, 2, NULL), 0, 0,
2701       { { 0, 0, 0, 0, 54.737640, 0, 20.250002, 59.400002, 130, 0 },
2702         { 0, 0, 0, 0, 43.825844, 0, 57.771137, 43.700001, 131, 0 } } },
2703     { make_hwstate(1329527921.584697, 1, 2, 2, NULL), 0, 0,
2704       { { 0, 0, 0, 0, 54.906223, 0, 20.250002, 59.400002, 130, 0 },
2705         { 0, 0, 0, 0, 43.654804, 0, 57.790218, 43.700001, 131, 0 } } },
2706     { make_hwstate(1329527921.595872, 1, 2, 2, NULL), 0, 0,
2707       { { 0, 0, 0, 0, 55.001118, 0, 20.250002, 59.400002, 130, 0 },
2708         { 0, 0, 0, 0, 43.542431, 0, 57.809731, 43.700001, 131, 0 } } },
2709     { make_hwstate(1329527921.618320, 1, 2, 2, NULL), 0, 0,
2710       { { 0, 0, 0, 0, 55.039989, 0, 20.252811, 59.400002, 130, 0 },
2711         { 0, 0, 0, 0, 43.585777, 0, 57.824154, 43.700001, 131, 0 } } },
2712     { make_hwstate(1329527921.640768, 1, 2, 2, NULL), 0, 0,
2713       { { 0, 0, 0, 0, 55.045246, 0, 20.264456, 59.400002, 130, 0 },
2714         { 0, 0, 0, 0, 43.715435, 0, 57.832584, 43.700001, 131, 0 } } },
2715     { make_hwstate(1329527921.691161, 1, 2, 2, NULL), 0, 0,
2716       { { 0, 0, 0, 0, 55.068935, 0, 20.285036, 59.400002, 130, 0 },
2717         { 0, 0, 0, 0, 43.845741, 0, 57.836266, 43.700001, 131, 0 } } },
2718     { make_hwstate(1329527921.741554, 1, 2, 2, NULL), 0, 0,
2719       { { 0, 0, 0, 0, 55.195026, 0, 20.306564, 59.400002, 130, 0 },
2720         { 0, 0, 0, 0, 43.941154, 0, 57.836994, 43.700001, 131, 0 } } },
2721     { make_hwstate(1329527921.758389, 1, 2, 2, NULL), 0, 0,
2722       { { 0, 0, 0, 0, 55.430550, 0, 20.322674, 59.400002, 130, 0 },
2723         { 0, 0, 0, 0, 43.962692, 0, 57.836308, 43.700001, 131, 0 } } },
2724     { make_hwstate(1329527921.775225, 1, 2, 2, NULL), 0, 0,
2725       { { 0, 0, 0, 0, 55.681423, 0, 20.332201, 59.400002, 130, 0 },
2726         { 0, 0, 0, 0, 43.846741, 0, 57.835224, 43.700001, 131, 0 } } },
2727     { make_hwstate(1329527921.786418, 1, 2, 2, NULL), 0, 0,
2728       { { 0, 0, 0, 0, 55.803486, 0, 20.336439, 59.400002, 130, 0 },
2729         { 0, 0, 0, 0, 43.604134, 0, 57.834267, 43.700001, 131, 0 } } },
2730     { make_hwstate(1329527921.803205, 1, 2, 2, NULL), 0, 0,
2731       { { 0, 0, 0, 0, 55.738258, 0, 20.337351, 59.396629, 130, 0 },
2732         { 0, 0, 0, 0, 43.340977, 0, 57.833622, 43.700001, 131, 0 } } },
2733     { make_hwstate(1329527921.819993, 1, 2, 2, NULL), 0, 0,
2734       { { 0, 0, 0, 0, 55.647045, 0, 20.336643, 59.382656, 130, 0 },
2735         { 0, 0, 0, 0, 43.140343, 0, 57.833279, 43.700001, 131, 0 } } },
2736     { make_hwstate(1329527921.831121, 1, 2, 2, NULL), 0, 0,
2737       { { 0, 0, 0, 0, 55.670898, 0, 20.335459, 59.357960, 130, 0 },
2738         { 0, 0, 0, 0, 43.019653, 0, 57.827530, 43.700001, 131, 0 } } },
2739     { make_hwstate(1329527921.842232, 1, 2, 2, NULL), 0, 0,
2740       { { 0, 0, 0, 0, 55.769543, 0, 20.334396, 59.332127, 130, 0 },
2741         { 0, 0, 0, 0, 42.964531, 0, 57.807049, 43.700001, 131, 0 } } },
2742     { make_hwstate(1329527921.853342, 1, 2, 2, NULL), 0, 0,
2743       { { 0, 0, 0, 0, 55.872444, 0, 20.333672, 59.312794, 130, 0 },
2744         { 0, 0, 0, 0, 42.951347, 0, 57.771957, 43.700001, 131, 0 } } },
2745     { make_hwstate(1329527921.864522, 1, 2, 2, NULL), 0, 0,
2746       { { 0, 0, 0, 0, 55.949341, 0, 20.333281, 59.301361, 130, 0 },
2747         { 0, 0, 0, 0, 42.959034, 0, 57.729061, 43.700001, 131, 0 } } },
2748     { make_hwstate(1329527921.875702, 1, 2, 2, NULL), 0, 0,
2749       { { 0, 0, 0, 0, 55.994751, 0, 20.333134, 59.296276, 130, 0 },
2750         { 0, 0, 0, 0, 42.973259, 0, 57.683277, 43.700001, 131, 0 } } },
2751     { make_hwstate(1329527921.886840, 1, 2, 2, NULL), 0, 0,
2752       { { 0, 0, 0, 0, 56.014912, 0, 20.333128, 59.295181, 130, 0 },
2753         { 0, 0, 0, 0, 42.918892, 0, 57.640221, 43.700001, 131, 0 } } },
2754     { make_hwstate(1329527921.898031, 1, 2, 2, NULL), 0, 0,
2755       { { 0, 0, 0, 0, 55.951756, 0, 20.333181, 59.296028, 130, 0 },
2756         { 0, 0, 0, 0, 42.715969, 0, 57.601479, 43.700001, 131, 0 } } },
2757     { make_hwstate(1329527921.909149, 1, 2, 2, NULL), 0, 0,
2758       { { 0, 0, 0, 0, 55.736336, 0, 20.333244, 59.297451, 130, 0 },
2759         { 0, 0, 0, 0, 42.304108, 0, 57.563725, 43.700001, 131, 0 } } },
2760     { make_hwstate(1329527921.920301, 0, 2, 2, NULL), 0, GESTURES_BUTTON_RIGHT,
2761       { { 0, 0, 0, 0, 55.448730, 0, 20.333294, 59.298725, 130, 0 },
2762         { 0, 0, 0, 0, 41.444939, 0, 57.525326, 43.700001, 131, 0 } } }
2763   };
2764   ImmediateInterpreter ii(NULL, NULL);
2765   TestInterpreterWrapper wrapper(&ii, &hwprops);
2766   for (size_t i = 0; i < arraysize(records); i++) {
2767     // Make the hwstate point to the fingers
2768     HardwareState* hs = &records[i].hs;
2769     hs->fingers = records[i].fs;
2770     Gesture* gs_out = wrapper.SyncInterpret(hs, NULL);
2771     if (!gs_out || gs_out->type != kGestureTypeButtonsChange) {
2772       // We got no output buttons gesture. Make sure we expected that
2773       EXPECT_EQ(0, records[i].out_buttons_down);
2774       EXPECT_EQ(0, records[i].out_buttons_up);
2775     } else if (gs_out) {
2776       // We got a buttons gesture
2777       EXPECT_EQ(gs_out->details.buttons.down, records[i].out_buttons_down);
2778       EXPECT_EQ(gs_out->details.buttons.up, records[i].out_buttons_up);
2779     } else {
2780       ADD_FAILURE();  // This should be unreachable
2781     }
2782   }
2783 }
2784 
TEST(ImmediateInterpreterTest,ChangeTimeoutTest)2785 TEST(ImmediateInterpreterTest, ChangeTimeoutTest) {
2786   ImmediateInterpreter ii(NULL, NULL);
2787   HardwareProperties hwprops = {
2788     0,  // left edge
2789     0,  // top edge
2790     1000,  // right edge
2791     1000,  // bottom edge
2792     500,  // pixels/TP width
2793     500,  // pixels/TP height
2794     96,  // screen DPI x
2795     96,  // screen DPI y
2796     -1,  // orientation minimum
2797     2,   // orientation maximum
2798     2,  // max fingers
2799     5,  // max touch
2800     0,  // tripletap
2801     0,  // semi-mt
2802     1,  // is button pad
2803     0,  // has_wheel
2804     0,  // wheel_is_hi_res
2805     0,  // is haptic pad
2806   };
2807 
2808   FingerState finger_states[] = {
2809     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
2810     {0, 0, 0, 0, 21, 0, 30, 30, 2, 0},
2811     {0, 0, 0, 0, 21, 0, 10, 10, 1, 0},
2812     {0, 0, 0, 0, 21, 0, 10, 20, 1, 0},
2813     {0, 0, 0, 0, 21, 0, 20, 20, 1, 0}
2814   };
2815   HardwareState hardware_states[] = {
2816     // time, buttons down, finger count, finger states pointer
2817     // One finger moves
2818     make_hwstate(0.10, 0, 1, 1, &finger_states[1]),
2819     make_hwstate(0.12, 0, 1, 1, &finger_states[2]),
2820     make_hwstate(0.16, 0, 1, 1, &finger_states[3]),
2821     make_hwstate(0.5, 0, 0, 0, NULL),
2822     // One finger moves after another finger leaves
2823     make_hwstate(1.09, 0, 2, 2, &finger_states[0]),
2824     make_hwstate(1.10, 0, 1, 1, &finger_states[1]),
2825     make_hwstate(1.12, 0, 1, 1, &finger_states[2]),
2826     make_hwstate(1.36, 0, 1, 1, &finger_states[3]),
2827     make_hwstate(1.5, 0, 0, 0, NULL),
2828   };
2829 
2830   TestInterpreterWrapper wrapper(&ii, &hwprops);
2831 
2832   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[0], NULL));
2833 
2834   // One finger moves, change_timeout_ is not applied.
2835   Gesture* gs = wrapper.SyncInterpret(&hardware_states[1], NULL);
2836   ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
2837   EXPECT_EQ(kGestureTypeMove, gs->type);
2838   EXPECT_EQ(0, gs->details.move.dx);
2839   EXPECT_EQ(10, gs->details.move.dy);
2840   EXPECT_EQ(0.10, gs->start_time);
2841   EXPECT_EQ(0.12, gs->end_time);
2842 
2843   // One finger moves, change_timeout_ does not block the gesture.
2844   gs = wrapper.SyncInterpret(&hardware_states[2], NULL);
2845   EXPECT_NE(reinterpret_cast<Gesture*>(NULL), gs);
2846   EXPECT_EQ(kGestureTypeMove, gs->type);
2847   EXPECT_EQ(10, gs->details.move.dx);
2848   EXPECT_EQ(0, gs->details.move.dy);
2849   EXPECT_EQ(0.12, gs->start_time);
2850   EXPECT_EQ(0.16, gs->end_time);
2851 
2852   // No finger.
2853   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[3], NULL));
2854 
2855   // Start with 2 fingers.
2856   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[4], NULL));
2857   // One finger leaves, finger_leave_time_ recorded.
2858   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[5], NULL));
2859   EXPECT_EQ(ii.finger_leave_time_, 1.10);
2860   // One finger moves, change_timeout_ blocks the gesture.
2861   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[6], NULL));
2862 
2863   // One finger moves, finger_leave_time_ + change_timeout_
2864   // has been passed.
2865   gs = wrapper.SyncInterpret(&hardware_states[7], NULL);
2866   EXPECT_NE(reinterpret_cast<Gesture*>(NULL), gs);
2867   EXPECT_EQ(kGestureTypeMove, gs->type);
2868   EXPECT_EQ(10, gs->details.move.dx);
2869   EXPECT_EQ(0, gs->details.move.dy);
2870   EXPECT_EQ(1.12, gs->start_time);
2871   EXPECT_EQ(1.36, gs->end_time);
2872 
2873   EXPECT_EQ(NULL, wrapper.SyncInterpret(&hardware_states[8], NULL));
2874 }
2875 
2876 // Tests that fingers that have been present a while, but are stationary,
2877 // can be evaluated multiple times when they start moving.
2878 
2879 enum PinchTestExpectedResult {
2880   kPinch,
2881   kNoPinch,
2882   kAny,
2883   kNull
2884 };
2885 
2886 struct PinchTestInput {
2887   HardwareState hs;
2888   PinchTestExpectedResult expected_result;
2889 };
2890 
TEST(ImmediateInterpreterTest,PinchTests)2891 TEST(ImmediateInterpreterTest, PinchTests) {
2892   ImmediateInterpreter ii(NULL, NULL);
2893   ii.pinch_enable_.val_ = 1;
2894   HardwareProperties hwprops = {
2895     0,  // left edge
2896     0,  // top edge
2897     100,  // right edge
2898     100,  // bottom edge
2899     1,  // pixels/TP width
2900     1,  // pixels/TP height
2901     96,  // x screen DPI
2902     96,  // y screen DPI
2903     -1,  // orientation minimum
2904     2,   // orientation maximum
2905     2,  // max fingers
2906     5,  // max touch
2907     0,  // tripletap
2908     0,  // semi-mt
2909     1,  // is button pad
2910     0,  // has_wheel
2911     0,  // wheel_is_hi_res
2912     0,  // is haptic pad
2913   };
2914 
2915   FingerState finger_states[] = {
2916     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
2917     // 0: start position
2918     {0, 0, 0, 0, 20, 0, 40, 40, 1, 0},
2919     {0, 0, 0, 0, 20, 0, 90, 90, 2, 0},
2920 
2921     // 2: pinch inwards
2922     {0, 0, 0, 0, 20, 0, 41, 41, 1, 0},
2923     {0, 0, 0, 0, 20, 0, 89, 89, 2, 0},
2924     {0, 0, 0, 0, 20, 0, 42, 42, 1, 0},
2925     {0, 0, 0, 0, 20, 0, 88, 88, 2, 0},
2926     {0, 0, 0, 0, 20, 0, 43, 43, 1, 0},
2927     {0, 0, 0, 0, 20, 0, 87, 87, 2, 0},
2928     {0, 0, 0, 0, 20, 0, 44, 44, 1, 0},
2929     {0, 0, 0, 0, 20, 0, 86, 86, 2, 0},
2930     {0, 0, 0, 0, 20, 0, 45, 45, 1, 0},
2931     {0, 0, 0, 0, 20, 0, 85, 85, 2, 0},
2932 
2933     // 12: pinch outwards
2934     {0, 0, 0, 0, 20, 0, 39, 39, 1, 0},
2935     {0, 0, 0, 0, 20, 0, 91, 91, 2, 0},
2936     {0, 0, 0, 0, 20, 0, 38, 38, 1, 0},
2937     {0, 0, 0, 0, 20, 0, 92, 92, 2, 0},
2938     {0, 0, 0, 0, 20, 0, 37, 37, 1, 0},
2939     {0, 0, 0, 0, 20, 0, 93, 93, 2, 0},
2940     {0, 0, 0, 0, 20, 0, 36, 36, 1, 0},
2941     {0, 0, 0, 0, 20, 0, 94, 94, 2, 0},
2942     {0, 0, 0, 0, 20, 0, 35, 35, 1, 0},
2943     {0, 0, 0, 0, 20, 0, 95, 95, 2, 0},
2944 
2945     // 22: single finger pinch
2946     {0, 0, 0, 0, 20, 0, 39, 39, 1, 0},
2947     {0, 0, 0, 0, 20, 0, 90, 90, 2, 0},
2948     {0, 0, 0, 0, 20, 0, 38, 38, 1, 0},
2949     {0, 0, 0, 0, 20, 0, 90, 90, 2, 0},
2950     {0, 0, 0, 0, 20, 0, 37, 37, 1, 0},
2951     {0, 0, 0, 0, 20, 0, 90, 90, 2, 0},
2952     {0, 0, 0, 0, 20, 0, 36, 36, 1, 0},
2953     {0, 0, 0, 0, 20, 0, 90, 90, 2, 0},
2954     {0, 0, 0, 0, 20, 0, 35, 35, 1, 0},
2955     {0, 0, 0, 0, 20, 0, 90, 90, 2, 0},
2956   };
2957 
2958   PinchTestInput input_states[] = {
2959     // time, buttons, finger count, touch count, finger states pointer
2960     {make_hwstate(0.00, 0, 0, 0, NULL), kAny},
2961 
2962     // fast pinch outwards
2963     {make_hwstate(0.11, 0, 2, 2, &finger_states[0]), kAny},
2964     {make_hwstate(0.12, 0, 2, 2, &finger_states[4]), kAny},
2965     {make_hwstate(0.13, 0, 2, 2, &finger_states[8]), kAny},
2966     {make_hwstate(0.14, 0, 2, 2, &finger_states[10]), kPinch},
2967     {make_hwstate(0.15, 0, 0, 0, NULL), kAny},
2968 
2969     // slow pinch
2970     {make_hwstate(1.01, 0, 2, 2, &finger_states[0]), kAny},
2971     {make_hwstate(1.02, 0, 2, 2, &finger_states[0]), kAny},
2972     {make_hwstate(1.03, 0, 2, 2, &finger_states[2]), kAny},
2973     {make_hwstate(1.04, 0, 2, 2, &finger_states[2]), kAny},
2974     {make_hwstate(1.05, 0, 2, 2, &finger_states[4]), kAny},
2975     {make_hwstate(1.06, 0, 2, 2, &finger_states[4]), kAny},
2976     {make_hwstate(1.07, 0, 2, 2, &finger_states[6]), kAny},
2977     {make_hwstate(1.08, 0, 2, 2, &finger_states[6]), kAny},
2978     {make_hwstate(1.09, 0, 2, 2, &finger_states[8]), kAny},
2979     {make_hwstate(1.10, 0, 2, 2, &finger_states[8]), kAny},
2980     {make_hwstate(1.11, 0, 2, 2, &finger_states[10]), kPinch},
2981     {make_hwstate(1.12, 0, 2, 2, &finger_states[10]), kNull},
2982     {make_hwstate(1.13, 0, 0, 0, NULL), kAny},
2983 
2984     // single finger pinch
2985     {make_hwstate(2.01, 0, 2, 2, &finger_states[22]), kAny},
2986     {make_hwstate(2.02, 0, 2, 2, &finger_states[26]), kAny},
2987     {make_hwstate(2.03, 0, 2, 2, &finger_states[30]), kAny},
2988     {make_hwstate(2.04, 0, 2, 2, &finger_states[30]), kNoPinch},
2989     {make_hwstate(2.05, 0, 0, 0, NULL), kAny},
2990 
2991 
2992     // first single finger pinch, then second moves too.
2993     {make_hwstate(3.01, 0, 2, 2, &finger_states[22]), kAny},
2994     {make_hwstate(3.02, 0, 2, 2, &finger_states[24]), kAny},
2995     {make_hwstate(3.03, 0, 2, 2, &finger_states[6]), kAny},
2996     {make_hwstate(3.04, 0, 2, 2, &finger_states[8]), kAny},
2997     {make_hwstate(3.05, 0, 2, 2, &finger_states[10]), kPinch},
2998     {make_hwstate(3.06, 0, 0, 0, NULL), kAny},
2999 
3000     // fast pinch inwards
3001     {make_hwstate(4.01, 0, 2, 2, &finger_states[10]), kAny},
3002     {make_hwstate(4.02, 0, 2, 2, &finger_states[8]), kAny},
3003     {make_hwstate(4.03, 0, 2, 2, &finger_states[4]), kAny},
3004     {make_hwstate(4.04, 0, 2, 2, &finger_states[0]), kPinch},
3005     {make_hwstate(4.05, 0, 0, 0, NULL), kAny},
3006   };
3007 
3008   TestInterpreterWrapper wrapper(&ii, &hwprops);
3009 
3010   for (size_t idx = 0; idx < arraysize(input_states); ++idx) {
3011     Gesture* gs = wrapper.SyncInterpret(&input_states[idx].hs, NULL);
3012     // assert pinch detected
3013     if (input_states[idx].expected_result == kPinch) {
3014       ASSERT_NE(reinterpret_cast<Gesture*>(NULL), gs);
3015       EXPECT_EQ(kGestureTypePinch, gs->type) << "idx=" << idx;
3016     }
3017     // assert pinch not detected
3018     if (input_states[idx].expected_result == kNoPinch) {
3019       if (gs != NULL) {
3020         EXPECT_NE(kGestureTypePinch, gs->type);
3021       }
3022     }
3023     // assert if NULL is not given back
3024     if (input_states[idx].expected_result == kNull) {
3025       ASSERT_EQ(reinterpret_cast<Gesture*>(NULL), gs);
3026     }
3027   }
3028 }
3029 
3030 struct AvoidAccidentalPinchTestInput {
3031   TestCaseStartOrContinueFlag flag;
3032   stime_t now;
3033   float x0, y0, p0, x1, y1, p1;  // (x, y) coordinate + pressure per finger
3034   GestureType expected_gesture;
3035 };
3036 
3037 // These data are from real logs where a move with resting thumb was appempted,
3038 // but pinch code prevented it.
TEST(ImmediateInterpreterTest,AvoidAccidentalPinchTest)3039 TEST(ImmediateInterpreterTest, AvoidAccidentalPinchTest) {
3040   std::unique_ptr<ImmediateInterpreter> ii;
3041   HardwareProperties hwprops = {
3042     0,  // left edge
3043     0,  // top edge
3044     106.666672,  // right edge
3045     68.000000,  // bottom edge
3046     1,  // pixels/TP width
3047     1,  // pixels/TP height
3048     25.4,  // screen DPI x
3049     25.4,  // screen DPI y
3050     -1,  // orientation minimum
3051     2,   // orientation maximum
3052     15,  // max fingers
3053     5,  // max touch
3054     0,  // t5r2
3055     0,  // semi-mt
3056     true,  // is button pad
3057     0,  // has_wheel
3058     0,  // wheel_is_hi_res
3059     false,  // is haptic pad
3060   };
3061   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
3062 
3063   const GestureType kMov = kGestureTypeMove;
3064   const GestureType kAny = kGestureTypeNull;
3065 
3066   AvoidAccidentalPinchTestInput inputs[] = {
3067     { kS, 0.97697, 44.08, 64.30, 118.20, 35.91, 27.70, 44.46, kAny },
3068     { kC, 0.98755, 44.08, 64.30, 118.20, 35.91, 27.70, 50.28, kAny },
3069     { kC, 0.99816, 44.08, 64.30, 118.20, 35.91, 27.70, 54.16, kAny },
3070     { kC, 1.00876, 45.33, 65.50,  98.79, 35.91, 27.60, 56.10, kAny },
3071     { kC, 1.01936, 45.33, 65.50,  98.79, 35.91, 27.60, 58.04, kAny },
3072     { kC, 1.03026, 45.33, 65.50, 100.73, 34.50, 26.70, 63.87, kAny },
3073     { kC, 1.04124, 45.33, 65.50, 102.67, 33.00, 26.10, 65.81, kMov },
3074     { kC, 1.05198, 45.33, 65.50, 102.67, 31.25, 25.60, 71.63, kMov },
3075     { kC, 1.06279, 45.33, 65.50, 104.61, 28.75, 25.10, 73.57, kMov },
3076     { kC, 1.07364, 45.33, 65.50, 104.61, 27.00, 24.60, 71.63, kMov },
3077     { kC, 1.08451, 45.33, 65.50, 104.61, 25.41, 24.10, 71.63, kMov },
3078     { kC, 1.09512, 45.33, 65.50, 102.67, 23.58, 23.50, 75.51, kMov },
3079     { kC, 1.10573, 45.33, 65.50, 104.61, 22.25, 23.30, 73.57, kMov },
3080     { kC, 1.11671, 45.33, 65.50, 104.61, 21.16, 23.20, 75.51, kMov },
3081     { kC, 1.12744, 45.33, 65.50, 104.61, 20.25, 23.20, 81.33, kMov },
3082     { kC, 1.13833, 45.33, 65.50, 104.61, 19.41, 23.20, 79.39, kMov },
3083     { kC, 1.14913, 45.33, 65.50, 104.61, 18.33, 23.20, 81.33, kMov },
3084     { kC, 1.15985, 45.41, 65.50, 104.61, 17.50, 23.40, 79.39, kMov },
3085     { kC, 1.17044, 45.58, 65.50, 106.55, 16.75, 23.80, 81.33, kMov },
3086     { kC, 1.18117, 45.58, 65.50, 106.55, 16.33, 24.20, 77.45, kMov },
3087     { kC, 1.19188, 45.58, 65.50, 106.55, 16.00, 24.30, 71.63, kMov },
3088     { kC, 1.20260, 45.58, 65.50, 106.55, 16.00, 24.50, 48.34, kAny },
3089     { kC, 1.21331, 45.58, 65.50, 106.55, 15.91, 24.80,  9.54, kAny },
3090 
3091     { kS, 3.92951, 58.50, 58.40, 118.20, 38.25, 14.40,  3.71, kAny },
3092     { kC, 3.94014, 58.33, 58.40, 118.20, 38.25, 14.40, 38.64, kAny },
3093     { kC, 3.95082, 58.25, 58.40, 118.20, 38.33, 14.40, 50.28, kAny },
3094     { kC, 3.96148, 58.08, 58.40, 118.20, 38.41, 14.40, 52.22, kAny },
3095     { kC, 3.97222, 57.91, 58.40, 118.20, 38.41, 14.50, 56.10, kAny },
3096     { kC, 3.98303, 57.83, 58.40, 118.20, 38.58, 14.60, 59.99, kAny },
3097     { kC, 3.99376, 57.66, 58.40, 118.20, 38.75, 14.80, 63.87, kAny },
3098     { kC, 4.00452, 57.58, 58.40, 118.20, 38.91, 15.00, 65.81, kAny },
3099     { kC, 4.01528, 57.50, 58.40, 118.20, 39.33, 15.30, 67.75, kAny },
3100     { kC, 4.02621, 57.41, 58.40, 118.20, 39.50, 15.70, 69.69, kAny },
3101     { kC, 4.03697, 57.41, 58.40, 118.20, 39.75, 16.10, 73.57, kMov },
3102     { kC, 4.04781, 57.25, 58.40, 118.20, 40.00, 16.60, 71.63, kMov },
3103     { kC, 4.05869, 57.25, 58.40, 118.20, 40.25, 17.00, 71.63, kMov },
3104     { kC, 4.06966, 57.25, 58.40, 118.20, 40.50, 17.30, 69.69, kMov },
3105     { kC, 4.08034, 57.16, 58.40, 118.20, 40.75, 17.70, 71.63, kMov },
3106     { kC, 4.09120, 57.08, 58.40, 118.20, 41.16, 17.90, 73.57, kMov },
3107     { kC, 4.10214, 57.00, 58.40, 118.20, 41.50, 18.30, 73.57, kMov },
3108     { kC, 4.11304, 56.83, 58.29, 118.20, 42.00, 18.60, 71.63, kMov },
3109     { kC, 4.12390, 56.83, 58.29, 118.20, 42.58, 19.00, 71.63, kMov },
3110     { kC, 4.13447, 56.66, 58.29, 118.20, 43.16, 19.60, 67.75, kMov },
3111     { kC, 4.14521, 56.66, 58.29, 118.20, 43.75, 20.20, 67.75, kMov },
3112     { kC, 4.15606, 56.50, 58.20, 118.20, 44.41, 21.10, 69.69, kMov },
3113     { kC, 4.16692, 56.50, 58.20, 118.20, 44.91, 22.10, 67.75, kMov },
3114     { kC, 4.17778, 56.41, 58.20, 118.20, 45.58, 23.00, 65.81, kMov },
3115     { kC, 4.18894, 56.33, 58.10, 118.20, 46.08, 23.60, 65.81, kMov },
3116     { kC, 4.20017, 56.33, 58.10, 118.20, 46.50, 24.10, 65.81, kMov },
3117     { kC, 4.21111, 56.33, 58.10, 118.20, 46.83, 24.50, 63.87, kMov },
3118     { kC, 4.22204, 56.33, 58.10, 118.20, 47.08, 24.80, 61.93, kMov },
3119     { kC, 4.23308, 56.25, 58.10, 118.20, 47.50, 25.20, 59.99, kMov },
3120     { kC, 4.24371, 56.25, 58.10, 118.20, 48.00, 25.80, 58.04, kMov },
3121     { kC, 4.25438, 56.25, 58.10, 118.20, 48.66, 26.50, 58.04, kMov },
3122     { kC, 4.26508, 56.08, 58.00, 118.20, 49.50, 27.50, 54.16, kMov },
3123     { kC, 4.27572, 56.00, 58.00, 118.20, 50.33, 28.60, 56.10, kMov },
3124     { kC, 4.28662, 56.00, 58.00, 118.20, 51.33, 29.50, 58.04, kMov },
3125     { kC, 4.29757, 55.91, 58.00, 118.20, 51.58, 31.90, 56.10, kMov },
3126     { kC, 4.30850, 55.91, 58.00, 118.20, 52.08, 32.00, 54.16, kMov },
3127     { kC, 4.31943, 55.91, 58.00, 118.20, 52.58, 32.40, 54.16, kMov },
3128     { kC, 4.33022, 55.83, 57.90, 118.20, 52.75, 33.10, 52.22, kMov },
3129     { kC, 4.34104, 55.83, 57.90, 118.20, 53.16, 33.60, 52.22, kMov },
3130     { kC, 4.35167, 55.83, 57.90, 118.20, 53.58, 34.20, 50.28, kMov },
3131     { kC, 4.36225, 55.83, 57.90, 118.20, 53.91, 35.00, 48.34, kMov },
3132     { kC, 4.37290, 55.75, 57.90, 118.20, 54.58, 35.50, 50.28, kMov },
3133     { kC, 4.38368, 55.66, 57.90, 118.20, 55.33, 36.10, 48.34, kMov },
3134     { kC, 4.39441, 55.66, 57.90, 118.20, 55.91, 36.70, 48.34, kMov },
3135     { kC, 4.40613, 56.16, 57.90, 118.20, 57.00, 37.20, 50.28, kMov },
3136     { kC, 4.41787, 56.16, 57.90, 118.20, 57.33, 37.70, 50.28, kMov },
3137     { kC, 4.42925, 56.16, 57.90, 118.20, 57.58, 37.90, 48.34, kMov },
3138     { kC, 4.44080, 56.16, 57.90, 118.20, 57.66, 38.00, 50.28, kMov },
3139     { kC, 4.45249, 56.16, 57.90, 118.20, 57.75, 38.10, 50.28, kMov },
3140     { kC, 4.46393, 56.16, 57.90, 118.20, 57.75, 38.10, 50.28, kAny },
3141     { kC, 4.47542, 56.16, 57.90, 118.20, 57.75, 38.15, 50.28, kMov },
3142     { kC, 4.48691, 56.16, 57.90, 118.20, 57.75, 38.20, 50.28, kMov },
3143     { kC, 4.49843, 56.16, 57.90, 118.20, 57.75, 38.20, 50.28, kAny },
3144     { kC, 4.51581, 56.16, 57.90, 118.20, 57.75, 38.25, 51.25, kMov },
3145     { kC, 4.53319, 56.16, 57.90, 118.20, 57.75, 38.29, 52.22, kMov },
3146     { kC, 4.54472, 56.16, 57.90, 118.20, 57.75, 38.70, 50.28, kMov },
3147     { kC, 4.55630, 56.16, 57.90, 118.20, 57.75, 38.70, 50.28, kAny },
3148     { kC, 4.56787, 56.16, 57.90, 118.20, 57.75, 38.70, 52.22, kAny },
3149     { kC, 4.57928, 56.16, 57.90, 118.20, 58.33, 38.50, 50.28, kMov },
3150     { kC, 4.59082, 56.16, 57.90, 118.20, 58.25, 38.60, 50.28, kMov },
3151     { kC, 4.60234, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kMov },
3152     { kC, 4.61389, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3153     { kC, 4.62545, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3154     { kC, 4.64281, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3155     { kC, 4.66018, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3156     { kC, 4.67747, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3157     { kC, 4.69476, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3158     { kC, 4.70628, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3159     { kC, 4.71781, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3160     { kC, 4.72934, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3161     { kC, 4.74087, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3162     { kC, 4.75240, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3163     { kC, 4.76418, 56.16, 57.90, 118.20, 58.33, 38.60, 50.28, kAny },
3164     { kC, 4.77545, 56.08, 57.90, 118.20, 58.33, 38.60, 50.28, kAny },
3165     { kC, 4.78690, 56.08, 57.90, 118.20, 58.33, 38.60, 48.34, kAny },
3166     { kC, 4.79818, 56.08, 57.90, 118.20, 58.33, 38.60, 27.00, kAny },
3167     { kC, 4.80970, 56.08, 57.90, 118.20, 58.33, 38.60,  9.54, kAny },
3168   };
3169 
3170   for (size_t i = 0; i < arraysize(inputs); i++) {
3171     const AvoidAccidentalPinchTestInput& input = inputs[i];
3172     if (input.flag == kS) {
3173       ii.reset(new ImmediateInterpreter(NULL, NULL));
3174       ii->pinch_enable_.val_ = true;
3175       MetricsProperties* mprops = new MetricsProperties(NULL);
3176       mprops->two_finger_close_vertical_distance_thresh.val_ = 35.0;
3177       wrapper.Reset(ii.get(), mprops);
3178       EXPECT_EQ(ImmediateInterpreter::TapToClickState::kTtcIdle,
3179                 ii->tap_to_click_state());
3180     }
3181     // Prep inputs
3182     FingerState fs[] = {
3183       { 0, 0, 0, 0, input.p0, 0, input.x0, input.y0, 1, 0 },
3184       { 0, 0, 0, 0, input.p1, 0, input.x1, input.y1, 2, 0 },
3185     };
3186     HardwareState hs = make_hwstate(input.now, 0, 2, 2, fs);
3187     stime_t timeout = NO_DEADLINE;
3188     Gesture* gs = wrapper.SyncInterpret(&hs, &timeout);
3189     if (input.expected_gesture != kAny) {
3190       if (gs)
3191         EXPECT_EQ(input.expected_gesture, gs->type);
3192     }
3193   }
3194 }
3195 
TEST(ImmediateInterpreterTest,SemiMtActiveAreaTest)3196 TEST(ImmediateInterpreterTest, SemiMtActiveAreaTest) {
3197   ImmediateInterpreter ii(NULL, NULL);
3198 
3199   HardwareProperties old_hwprops = {
3200     0,  // left edge
3201     0,  // top edge
3202     90.404251,  // right edge
3203     48.953846,  // bottom edge
3204     1,  // pixels/TP width
3205     1,  // pixels/TP height
3206     133,  // screen DPI x
3207     133,  // screen DPI y
3208     -1,  // orientation minimum
3209     2,   // orientation maximum
3210     2,  // max fingers
3211     3,  // max touch
3212     0,  // t5r2
3213     1,  // semi-mt
3214     true,  // is button pad
3215     0,  // has_wheel
3216     0,  // wheel_is_hi_res
3217     false,  // is haptic pad
3218   };
3219 
3220   const unsigned kNonPalmFlags = GESTURES_FINGER_WARP_X |
3221       GESTURES_FINGER_WARP_Y;
3222   const unsigned kPalmFlags = kNonPalmFlags | GESTURES_FINGER_PALM;
3223 
3224   FingerState old_finger_states[] = {
3225     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID, flags
3226     { 0, 0, 0, 0, 14, 0, 50, 8, 11, kPalmFlags },
3227     { 0, 0, 0, 0, 33, 0, 50, 8, 11, kPalmFlags },
3228     { 0, 0, 0, 0, 37, 0, 50, 8, 11, kPalmFlags },
3229     { 0, 0, 0, 0, 39, 0, 50, 8, 11, kPalmFlags },
3230   };
3231 
3232   HardwareState old_hardware_states[] = {
3233     // time, buttons down, finger count, touch count, finger states pointer
3234     make_hwstate(0.05, 0, 1, 1, &old_finger_states[0]),
3235     make_hwstate(0.10, 0, 1, 1, &old_finger_states[1]),
3236     make_hwstate(0.15, 0, 1, 1, &old_finger_states[2]),
3237     make_hwstate(0.20, 0, 1, 1, &old_finger_states[3]),
3238   };
3239 
3240   TestInterpreterWrapper wrapper(&ii, &old_hwprops);
3241   ii.tap_enable_.val_ = 1;
3242 
3243   // The finger will not change the tap_to_click_state_ at all.
3244   for (size_t idx = 0; idx < arraysize(old_hardware_states); ++idx) {
3245     wrapper.SyncInterpret(&old_hardware_states[idx], NULL);
3246     EXPECT_EQ(kIdl, ii.tap_to_click_state_);
3247   }
3248 
3249   HardwareProperties new_hwprops = {
3250     0,  // left edge
3251     0,  // top edge
3252     96.085106,  // right edge
3253     57.492310,  // bottom edge
3254     1,  // pixels/TP width
3255     1,  // pixels/TP height
3256     133,  // screen DPI x
3257     133,  // screen DPI y
3258     -1,  // orientation minimum
3259     2,   // orientation maximum
3260     2,  // max fingers
3261     3,  // max touch
3262     0,  // t5r2
3263     1,  // semi-mt
3264     true,  // is button pad
3265     0,  // has_wheel
3266     0,  // wheel_is_hi_res
3267     false,  // is haptic pad
3268   };
3269 
3270   FingerState new_finger_states[] = {
3271     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID, flags
3272     { 0, 0, 0, 0, 14, 0, 55, 12, 7, kNonPalmFlags },
3273     { 0, 0, 0, 0, 33, 0, 55, 12, 7, kNonPalmFlags },
3274     { 0, 0, 0, 0, 37, 0, 55, 12, 7, kNonPalmFlags },
3275     { 0, 0, 0, 0, 39, 0, 55, 12, 7, kNonPalmFlags },
3276   };
3277 
3278   HardwareState new_hardware_states[] = {
3279     // time, buttons down, finger count, touch count, finger states pointer
3280     make_hwstate(0.05, 0, 1, 1, &new_finger_states[0]),
3281     make_hwstate(0.10, 0, 1, 1, &new_finger_states[1]),
3282     make_hwstate(0.15, 0, 1, 1, &new_finger_states[2]),
3283     make_hwstate(0.20, 0, 1, 1, &new_finger_states[3]),
3284   };
3285 
3286   wrapper.Reset(&ii, &new_hwprops);
3287   ii.tap_enable_.val_ = true;
3288 
3289   // With new active area, the finger changes the tap_to_click_state_ to
3290   // FirstTapBegan.
3291   for (size_t idx = 0; idx < arraysize(new_hardware_states); ++idx) {
3292     wrapper.SyncInterpret(&new_hardware_states[idx], NULL);
3293     EXPECT_EQ(ii.kTtcFirstTapBegan, ii.tap_to_click_state_);
3294   }
3295 }
3296 
TEST(ImmediateInterpreterTest,SemiMtNoPinchTest)3297 TEST(ImmediateInterpreterTest, SemiMtNoPinchTest) {
3298   ImmediateInterpreter ii(NULL, NULL);
3299   ii.pinch_enable_.val_ = 1;
3300 
3301   HardwareProperties hwprops = {
3302     0,  // left edge
3303     0,  // top edge
3304     90.404251,  // right edge
3305     48.953846,  // bottom edge
3306     1,  // pixels/TP width
3307     1,  // pixels/TP height
3308     133,  // screen DPI x
3309     133,  // screen DPI y
3310     -1,  // orientation minimum
3311     2,   // orientation maximum
3312     2,  // max fingers
3313     3,  // max touch
3314     0,  // t5r2
3315     0,  // semi-mt
3316     true,  // is button pad
3317     0,  // has_wheel
3318     0,  // wheel_is_hi_res
3319     false,  // is haptic pad
3320   };
3321 
3322   FingerState finger_state[] = {
3323     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID, flags
3324     {0, 0, 0, 0, 25, 0, 30, 53, 1, 0},  // index 0
3325     {0, 0, 0, 0, 46, 0, 30, 53, 1, 0},  // index 1
3326     {0, 0, 0, 0, 69, 0, 30, 53, 1, 0},  // index 2
3327 
3328     {0, 0, 0, 0, 67, 0, 30, 53, 1, 0},  // index 3
3329     {0, 0, 0, 0, 67, 0, 68, 27, 2, 0},
3330 
3331     {0, 0, 0, 0, 91, 0, 43, 52, 1, 0},  // index 5
3332     {0, 0, 0, 0, 91, 0, 44, 23, 2, 0},
3333 
3334     {0, 0, 0, 0, 91, 0, 43, 52, 1, 0},  // index 7
3335     {0, 0, 0, 0, 91, 0, 43, 23, 2, 0},
3336   };
3337 
3338 
3339   HardwareState hardware_states[] = {
3340     // time, buttons down, finger count, touch count, finger states pointer
3341     make_hwstate(2106.273252, 0, 1, 1, &finger_state[0]),
3342     make_hwstate(2106.285466, 0, 1, 1, &finger_state[1]),
3343     make_hwstate(2106.298021, 0, 1, 1, &finger_state[2]),
3344     make_hwstate(2106.325599, 0, 2, 2, &finger_state[3]),
3345     make_hwstate(2106.648152, 0, 2, 2, &finger_state[5]),
3346     make_hwstate(2106.660447, 0, 2, 2, &finger_state[7]),
3347     // pinch if not semi_mt device
3348   };
3349 
3350   TestInterpreterWrapper wrapper(&ii, &hwprops);
3351 
3352   Gesture *gesture;
3353   for (size_t idx = 0; idx < arraysize(hardware_states); ++idx) {
3354     gesture = wrapper.SyncInterpret(&hardware_states[idx], NULL);
3355     // reset finger flags
3356     for (size_t fidx = 0; fidx < hardware_states[idx].finger_cnt; ++fidx)
3357       hardware_states[idx].fingers[fidx].flags = 0;
3358   }
3359   if (gesture)
3360     EXPECT_EQ(gesture->type, kGestureTypePinch);
3361 
3362   // For a semi_mt device, replay the same inputs should not generate
3363   // a pinch gesture.
3364   hwprops.support_semi_mt = 1;
3365   wrapper.Reset(&ii, &hwprops);
3366   for (size_t idx = 0; idx < arraysize(hardware_states); ++idx) {
3367     gesture = wrapper.SyncInterpret(&hardware_states[idx], NULL);
3368     // reset finger flags
3369     for (size_t fidx = 0; fidx < hardware_states[idx].finger_cnt; ++fidx)
3370       hardware_states[idx].fingers[fidx].flags = 0;
3371   }
3372   if (gesture)
3373     EXPECT_NE(gesture->type, kGestureTypePinch);
3374 }
3375 
TEST(ImmediateInterpreterTest,WarpedFingersTappingTest)3376 TEST(ImmediateInterpreterTest, WarpedFingersTappingTest) {
3377   ImmediateInterpreter ii(NULL, NULL);
3378 
3379   HardwareProperties hwprops = {
3380     0,  // left edge
3381     0,  // top edge
3382     90.404251,  // right edge
3383     48.953846,  // bottom edge
3384     1,  // pixels/TP width
3385     1,  // pixels/TP height
3386     133,  // screen DPI x
3387     133,  // screen DPI y
3388     -1,  // orientation minimum
3389     2,   // orientation maximum
3390     2,  // max fingers
3391     3,  // max touch
3392     0,  // t5r2
3393     1,  // semi-mt
3394     true,  // is button pad
3395     0,  // has_wheel
3396     0,  // wheel_is_hi_res
3397     false,  // is haptic pad
3398   };
3399 
3400   unsigned flags = GESTURES_FINGER_WARP_X_NON_MOVE |
3401       GESTURES_FINGER_WARP_Y_NON_MOVE |
3402       GESTURES_FINGER_WARP_X_TAP_MOVE |
3403       GESTURES_FINGER_WARP_Y_TAP_MOVE;
3404 
3405   FingerState finger_state[] = {
3406     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID, flags
3407     { 0, 0, 0, 0, 42.139996, 0, 46.106384, 39.800003, 0, flags },  // index 0
3408     { 0, 0, 0, 0, 42.139996, 0, 69.106384, 28.461538, 1, flags },
3409 
3410     // The finger 0 moves more than default threshold 2.0 in Y, but it should
3411     // still generate final right-click gesture as the WARP flag is set.
3412     { 0, 0, 0, 0, 43.350002, 0, 45.425529, 36.353844, 0, flags },  // index 2
3413     { 0, 0, 0, 0, 43.350002, 0, 69.063828, 28.507692, 1, flags },
3414 
3415     { 0, 0, 0, 0, 43.350002, 0, 69.085106, 28.307692, 1, flags },  // index 4
3416   };
3417 
3418   HardwareState hardware_states[] = {
3419     // time, buttons down, finger count, touch count, finger states pointer
3420     make_hwstate(3897.124791, 0, 2, 2, &finger_state[0]),
3421     make_hwstate(3897.136733, 0, 2, 2, &finger_state[2]),
3422     make_hwstate(3897.148675, 0, 1, 1, &finger_state[4]),
3423     make_hwstate(3897.160675, 0, 0, 0, NULL),
3424   };
3425 
3426   ii.tap_enable_.val_ = 1;
3427   TestInterpreterWrapper wrapper(&ii, &hwprops);
3428 
3429   Gesture *gesture;
3430   for (size_t idx = 0; idx < arraysize(hardware_states); ++idx)
3431     gesture = wrapper.SyncInterpret(&hardware_states[idx], NULL);
3432 
3433   ASSERT_NE(gesture, static_cast<Gesture*>(NULL));
3434   EXPECT_EQ(gesture->type, kGestureTypeButtonsChange);
3435 }
3436 
3437 // Test that fling_buffer_depth controls the number of scroll samples to use
3438 // to compute fling.
TEST(ImmediateInterpreterTest,FlingDepthTest)3439 TEST(ImmediateInterpreterTest, FlingDepthTest) {
3440   ImmediateInterpreter ii(NULL, NULL);
3441   HardwareProperties hwprops = {
3442     0,  // left edge
3443     0,  // top edge
3444     100,  // right edge
3445     100,  // bottom edge
3446     1,  // pixels/TP width
3447     1,  // pixels/TP height
3448     96,  // x screen DPI
3449     96,  // y screen DPI
3450     -1,  // orientation minimum
3451     2,   // orientation maximum
3452     2,  // max fingers
3453     5,  // max touch
3454     0,  // tripletap
3455     1,  // semi-mt
3456     1,  // is button pad
3457     0,  // has_wheel
3458     0,  // wheel_is_hi_res
3459     0,  // is haptic pad
3460   };
3461 
3462   FingerState finger_states[] = {
3463     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
3464     // Consistent movement for 6 frames
3465     {0, 0, 0, 0, 20, 0, 40, 20, 1, 0}, // 0
3466     {0, 0, 0, 0, 20, 0, 60, 20, 2, 0},
3467 
3468     {0, 0, 0, 0, 20, 0, 40, 25, 1, 0}, // 2
3469     {0, 0, 0, 0, 20, 0, 60, 25, 2, 0},
3470 
3471     {0, 0, 0, 0, 20, 0, 40, 30, 1, 0}, // 4
3472     {0, 0, 0, 0, 20, 0, 60, 30, 2, 0},
3473 
3474     {0, 0, 0, 0, 20, 0, 40, 35, 1, 0}, // 6
3475     {0, 0, 0, 0, 20, 0, 60, 35, 2, 0},
3476 
3477     {0, 0, 0, 0, 20, 0, 40, 40, 1, 0}, // 8
3478     {0, 0, 0, 0, 20, 0, 60, 40, 2, 0},
3479 
3480     {0, 0, 0, 0, 20, 0, 40, 45, 1, 0}, // 10
3481     {0, 0, 0, 0, 20, 0, 60, 45, 2, 0},
3482 
3483     {0, 0, 0, 0, 20, 0, 40, 50, 1, 0}, // 12
3484     {0, 0, 0, 0, 20, 0, 60, 50, 2, 0},
3485 
3486     {0, 0, 0, 0, 20, 0, 40, 55, 1, 0}, // 14
3487     {0, 0, 0, 0, 20, 0, 60, 55, 2, 0},
3488   };
3489   HardwareState hardware_states[] = {
3490     // time, buttons, finger count, touch count, finger states pointer
3491     make_hwstate(1.00, 0, 2, 2, &finger_states[0]),
3492     make_hwstate(1.01, 0, 2, 2, &finger_states[2]),
3493     make_hwstate(1.02, 0, 2, 2, &finger_states[4]),
3494     make_hwstate(1.03, 0, 2, 2, &finger_states[6]),
3495     make_hwstate(1.04, 0, 2, 2, &finger_states[8]),
3496     make_hwstate(1.05, 0, 2, 2, &finger_states[10]),
3497     make_hwstate(1.06, 0, 2, 2, &finger_states[12]),
3498     make_hwstate(1.07, 0, 2, 2, &finger_states[14]),
3499   };
3500 
3501   TestInterpreterWrapper wrapper(&ii, &hwprops);
3502 
3503   ii.scroll_manager_.fling_buffer_depth_.val_ = 6;
3504   size_t fling_buffer_depth =
3505     (size_t)ii.scroll_manager_.fling_buffer_depth_.val_;
3506 
3507   // The unittest is only meaningful if there are enough hwstates
3508   ASSERT_GT(arraysize(hardware_states) - 1, fling_buffer_depth)
3509       << "Hardware state list must be > fling buffer depth + 1";
3510 
3511   // Fill scroll buffer with a set of scrolls
3512   ii.scroll_buffer_.Clear();
3513   const HardwareState* prev_hs = NULL;
3514   for (size_t idx = 0; idx < arraysize(hardware_states); ++idx) {
3515     const HardwareState* hs = &hardware_states[idx];
3516     if (prev_hs != NULL) {
3517       // Cheating here, only using first finger to compute scroll
3518       const FingerState* fs = &hs->fingers[0];
3519       const FingerState* prev_fs = prev_hs->GetFingerState(fs->tracking_id);
3520       EXPECT_NE(reinterpret_cast<const FingerState*>(NULL), prev_fs);
3521       float dx = fs->position_x - prev_fs->position_x;
3522       float dy = fs->position_y - prev_fs->position_y;
3523       float dt = hs->timestamp - prev_hs->timestamp;
3524       ii.scroll_buffer_.Insert(dx, dy, dt);
3525       // Enforce assumption that all scrolls are positive in Y only
3526       EXPECT_DOUBLE_EQ(dx, 0);
3527       EXPECT_GT(dy, 0);
3528       EXPECT_GT(dt, 0);
3529       size_t expected_fling_events = std::min(idx, fling_buffer_depth);
3530       EXPECT_EQ(ii.scroll_manager_.ScrollEventsForFlingCount(ii.scroll_buffer_),
3531                 expected_fling_events);
3532     }
3533     prev_hs = hs;
3534   }
3535 }
3536 
TEST(ImmediateInterpreterTest,ScrollResetTapTest)3537 TEST(ImmediateInterpreterTest, ScrollResetTapTest) {
3538   ImmediateInterpreter ii(NULL, NULL);
3539 
3540   HardwareProperties hwprops = {
3541     0,  // left edge
3542     0,  // top edge
3543     96.085106,  // right edge
3544     57.492310,  // bottom edge
3545     1,  // pixels/TP width
3546     1,  // pixels/TP height
3547     25.4,  // screen DPI x
3548     25.4,  // screen DPI y
3549     -1,  // orientation minimum
3550     2,   // orientation maximum
3551     2,  // max fingers
3552     3,  // max touch
3553     0,  // t5r2
3554     1,  // semi-mt
3555     1,  // is button pad
3556     0,  // has_wheel
3557     0,  // wheel_is_hi_res
3558     0,  // is haptic pad
3559   };
3560 
3561   FingerState finger_state[] = {
3562     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID, flags
3563     { 0, 0, 0, 0, 71.180000, 0, 58.446808, 24.000002, 0, 3 },  // index 0
3564     { 0, 0, 0, 0, 71.180000, 0, 75.042549, 23.676924, 1, 3 },
3565 
3566     { 0, 0, 0, 0, 82.070000, 0, 55.276596, 23.492308, 0, 3 },  // index 2
3567     { 0, 0, 0, 0, 82.070000, 0, 70.361702, 23.015387, 1, 3 },
3568 
3569     { 0, 0, 0, 0, 76.625000, 0, 58.542553, 23.030769, 0, 3 },  // index 4
3570     { 0, 0, 0, 0, 76.625000, 0, 59.127659, 22.500002, 1, 1 },
3571 
3572     // prev_result will be scroll, we expect the tap state will be idle
3573     // after the sample is processed.
3574     { 0, 0, 0, 0, 71.180000, 0, 61.808510, 22.569231, 0, 3 },  // index 6
3575     { 0, 0, 0, 0, 71.180000, 0, 47.893616, 21.984617, 1, 1 },
3576 
3577     { 0, 0, 0, 0, 16.730000, 0, 57.617020, 20.830770, 0, 3 },  // index 8
3578   };
3579 
3580   HardwareState hardware_states[] = {
3581     // time, buttons down, finger count, touch count, finger states pointer
3582     make_hwstate(1296.498245, 0, 2, 2, &finger_state[0]),
3583     make_hwstate(1296.510735, 0, 2, 2, &finger_state[2]),
3584     make_hwstate(1296.523224, 0, 2, 2, &finger_state[4]),
3585     make_hwstate(1296.535753, 0, 2, 2, &finger_state[6]),
3586     make_hwstate(1296.548282, 0, 1, 1, &finger_state[8]),
3587   };
3588 
3589   // SemiMt-specific properties
3590   ii.tapping_finger_min_separation_.val_ = 0.0;
3591 
3592   ii.tap_enable_.val_ = 1;
3593   TestInterpreterWrapper wrapper(&ii, &hwprops);
3594 
3595   for (size_t idx = 0; idx < arraysize(hardware_states); ++idx) {
3596     Gesture* gs = wrapper.SyncInterpret(&hardware_states[idx], NULL);
3597     if (gs != NULL) {
3598       if (idx == 2)
3599         EXPECT_EQ(kGestureTypeScroll, gs->type);
3600       else
3601         EXPECT_NE(kGestureTypeButtonsChange, gs->type);
3602     }
3603     if (idx >= 3)
3604       EXPECT_EQ(kIdl, ii.tap_to_click_state_);
3605   }
3606 }
3607 
TEST(ImmediateInterpreterTest,ZeroClickInitializationTest)3608 TEST(ImmediateInterpreterTest, ZeroClickInitializationTest) {
3609   ImmediateInterpreter ii(NULL, NULL);
3610 
3611   HardwareProperties hwprops = {
3612     0,  // left edge
3613     0,  // top edge
3614     1000,  // right edge
3615     1000,  // bottom edge
3616     500,  // pixels/TP width
3617     500,  // pixels/TP height
3618     96,  // screen DPI x
3619     96,  // screen DPI y
3620     -1,  // orientation minimum
3621     2,   // orientation maximum
3622     2,  // max fingers
3623     5,  // max touch
3624     0,  // tripletap
3625     0,  // semi-mt
3626     1,  // is button pad
3627     0,  // has_wheel
3628     0,  // wheel_is_hi_res
3629     0,  // is haptic pad
3630   };
3631   TestInterpreterWrapper wrapper(&ii, &hwprops);
3632 
3633   // Test touchpad with intergrated button switch.
3634   EXPECT_EQ(0, ii.zero_finger_click_enable_.val_);
3635   // Test touchpad with separate buttons.
3636   hwprops.is_button_pad = 0;
3637   wrapper.Reset(&ii, &hwprops);
3638   EXPECT_EQ(1, ii.zero_finger_click_enable_.val_);
3639 }
3640 
TEST(ImmediateInterpreterTest,PointTest)3641 TEST(ImmediateInterpreterTest, PointTest) {
3642   Point point;
3643   Point point_eq;
3644   Point point_ne0(42.0, 0.0);
3645   Point point_ne1(0.0, 42.0);
3646   EXPECT_TRUE(point == point_eq);
3647   EXPECT_FALSE(point == point_ne0);
3648   EXPECT_FALSE(point == point_ne1);
3649   EXPECT_FALSE(point != point_eq);
3650   EXPECT_TRUE(point != point_ne0);
3651   EXPECT_TRUE(point != point_ne1);
3652 }
3653 
3654 }  // namespace gestures
3655