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