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