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