summarylogtreecommitdiffstats
path: root/0007-Abort-TFD-within-50-ms-on-detection-of-4-fingers.patch
blob: f1e9eef7c613928a037d9ed85325923a8c795fcc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
From c703c263a9aae5df6419abf2ba20e23a061da821 Mon Sep 17 00:00:00 2001
From: abc def <24701-abcdef@users.noreply.gitlab.freedesktop.org>
Date: Mon, 14 Feb 2022 13:59:11 +0100
Subject: [PATCH 7/7] Abort TFD within 50 ms on detection of 4+ fingers

Improved method of disambiguating between three finger drags and four finger gestures.
---
 src/evdev-mt-touchpad-tfd.c | 239 ++++++++++++++++++++++++------------
 src/evdev-mt-touchpad.h     |  12 +-
 2 files changed, 169 insertions(+), 82 deletions(-)

diff --git a/src/evdev-mt-touchpad-tfd.c b/src/evdev-mt-touchpad-tfd.c
index 33fb4a06..681beedf 100644
--- a/src/evdev-mt-touchpad-tfd.c
+++ b/src/evdev-mt-touchpad-tfd.c
@@ -7,7 +7,7 @@
 #include "evdev-mt-touchpad.h"
 
 /* when three fingers are detected, this is how long we wait to see if the user
-actually intends a 3 finger gesture, or is transitioning to e.g. 4 fingers */
+actually intends a 3 finger gesture or is transitioning to e.g. 4 fingers */
 #define DEFAULT_DRAG3_WAIT_FOR_FINGERS_DURATION ms2us(50)
 /* The interval between three fingers touching and a button press being 
 performed, if the fingers remain stationary */
@@ -42,8 +42,9 @@ tfd_state_to_str(enum tp_tfd_state state)
 {
 	switch(state) {
 	CASE_RETURN_STRING(TFD_STATE_IDLE);
-	CASE_RETURN_STRING(TFD_STATE_POSSIBLE_BEGIN);
+	// CASE_RETURN_STRING(TFD_STATE_POSSIBLE_BEGIN);
 	CASE_RETURN_STRING(TFD_STATE_AWAIT_DRAG);
+	CASE_RETURN_STRING(TFD_STATE_DRAG_AND_DEBOUNCE);
 	CASE_RETURN_STRING(TFD_STATE_DRAG);
 	CASE_RETURN_STRING(TFD_STATE_POSSIBLE_ZERO_FINGERS);
 	CASE_RETURN_STRING(TFD_STATE_AWAIT_RESUME);
@@ -237,12 +238,15 @@ tp_tfd_idle_handle_event(struct tp_dispatch *tp,
 			 enum tfd_event event, uint64_t time, int nfingers_down)
 {
 	switch (event) {
-	case TFD_EVENT_TOUCH_COUNT_INCREASE:
 	case TFD_EVENT_TOUCH_COUNT_DECREASE:
+		/* turns out it's distracting to accidentally initiate dragging while 
+		removing fingers after a 4+ swipe gesture. */
+		break;
+	case TFD_EVENT_TOUCH_COUNT_INCREASE:
 		if (nfingers_down == 3) {
-			tp->tfd.state = TFD_STATE_POSSIBLE_BEGIN;
-			// tp_tfd_set_button_press_delay_timer(tp, time);
-			tp_tfd_set_await_more_fingers_timer(tp, time);
+			tp->tfd.state = TFD_STATE_AWAIT_DRAG;
+			tp_tfd_set_button_press_delay_timer(tp, time);
+			// tp_tfd_set_await_more_fingers_timer(tp, time);
 		}
 		break;
 	case TFD_EVENT_MOTION:
@@ -260,70 +264,70 @@ tp_tfd_idle_handle_event(struct tp_dispatch *tp,
 
 
 
-
+// unused -- TODO: remove if drag_and_debounce is successful
 /* Waiting for more fingers. Three fingers have been detected, but it might be 
 a transitory phase towards 4 or more fingers, which should not begin the
 drag. */
-static void
-tp_tfd_possible_begin_handle_event(struct tp_dispatch *tp,
-				  struct tp_touch *t,
-				  enum tfd_event event, uint64_t time,
-				   int nfingers_down)
-{
-	switch (event) {
-	case TFD_EVENT_TOUCH_COUNT_INCREASE:
-		switch (nfingers_down) {
-		case 0: 
-		case 1:
-		case 2:
-		case 3:
-			break; // bug?
-		default:
-			tp_tfd_unpin_fingers(tp);
-			tp->tfd.state = TFD_STATE_IDLE;
-			tp_tfd_clear_timer(tp);
-			break;
-		}
-		break;
-	case TFD_EVENT_MOTION:
-		break;
-	case TFD_EVENT_RESUME_TIMEOUT: 
-		break; // bug
-	case TFD_EVENT_TOUCH_COUNT_DECREASE:
-		/* a decrease forces immediate evaluation as if the timer had fired */
-		tp_tfd_clear_timer(tp);
-		/* fallthrough */
-	case TFD_EVENT_TIMEOUT:
-		/* time to check whether we have 3 fingers touching */
-		switch (nfingers_down) {
-		case 0:
-		case 1:
-		case 2:
-		default:
-			tp_tfd_unpin_fingers(tp);
-			tp->tfd.state = TFD_STATE_IDLE;
-			break;
-		case 3:
-			tp_tfd_unpin_fingers(tp);
-			// TODO: compensate for the duration of this state 
-			tp_tfd_set_button_press_delay_timer(tp, time);
-			tp->tfd.state = TFD_STATE_AWAIT_DRAG;
-			break;
-		}
-		break;
-	case TFD_EVENT_TAP:
-	case TFD_EVENT_BUTTON:
-		tp_tfd_unpin_fingers(tp);
-		tp->tfd.state = TFD_STATE_IDLE;
-		tp_tfd_clear_timer(tp);
-		break;
-	}
-}
+// static void
+// tp_tfd_possible_begin_handle_event(struct tp_dispatch *tp,
+// 				  struct tp_touch *t,
+// 				  enum tfd_event event, uint64_t time,
+// 				   int nfingers_down)
+// {
+// 	switch (event) {
+// 	case TFD_EVENT_TOUCH_COUNT_INCREASE:
+// 		switch (nfingers_down) {
+// 		case 0: 
+// 		case 1:
+// 		case 2:
+// 		case 3:
+// 			break; // bug?
+// 		default:
+// 			tp_tfd_unpin_fingers(tp);
+// 			tp->tfd.state = TFD_STATE_IDLE;
+// 			tp_tfd_clear_timer(tp);
+// 			break;
+// 		}
+// 		break;
+// 	case TFD_EVENT_MOTION:
+// 		break;
+// 	case TFD_EVENT_RESUME_TIMEOUT: 
+// 		break; // bug
+// 	case TFD_EVENT_TOUCH_COUNT_DECREASE:
+// 		/* a decrease forces immediate evaluation as if the timer had fired */
+// 		tp_tfd_clear_timer(tp);
+// 		/* fallthrough */
+// 	case TFD_EVENT_TIMEOUT:
+// 		/* time to check whether we have 3 fingers touching */
+// 		switch (nfingers_down) {
+// 		case 0:
+// 		case 1:
+// 		case 2:
+// 		default:
+// 			tp_tfd_unpin_fingers(tp);
+// 			tp->tfd.state = TFD_STATE_IDLE;
+// 			break;
+// 		case 3:
+// 			tp_tfd_unpin_fingers(tp);
+// 			// TODO: compensate for the duration of this state 
+// 			tp_tfd_set_button_press_delay_timer(tp, time);
+// 			tp->tfd.state = TFD_STATE_AWAIT_DRAG;
+// 			break;
+// 		}
+// 		break;
+// 	case TFD_EVENT_TAP:
+// 	case TFD_EVENT_BUTTON:
+// 		tp_tfd_unpin_fingers(tp);
+// 		tp->tfd.state = TFD_STATE_IDLE;
+// 		tp_tfd_clear_timer(tp);
+// 		break;
+// 	}
+// }
 
 
 
 
-/* finishes hold gestures and cancels other gestures */
+/* takes appropriate action to cancel or finish a gesture in progress */
 static void
 tp_tfd_interrupt_gestures(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
 {
@@ -387,9 +391,10 @@ tp_tfd_await_drag_handle_event(struct tp_dispatch *tp,
 			/* show special consideration for overlapping hold gestures */
 			tp_tfd_interrupt_gestures(tp, t, time);
 
-			tp->tfd.state = TFD_STATE_DRAG;
+			// tp_tfd_clear_timer(tp);
+			tp_tfd_set_await_more_fingers_timer(tp, time);
+			tp->tfd.state = TFD_STATE_DRAG_AND_DEBOUNCE;
 			tp_tfd_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
-			tp_tfd_clear_timer(tp);
 		}
 		break;
 	case TFD_EVENT_RESUME_TIMEOUT:
@@ -401,14 +406,18 @@ tp_tfd_await_drag_handle_event(struct tp_dispatch *tp,
 		/* show special consideration for overlapping hold gestures */
 		tp_tfd_interrupt_gestures(tp, t, time);
 
-		tp->tfd.state = TFD_STATE_DRAG;
+		tp_tfd_set_await_more_fingers_timer(tp, time);
+		tp->tfd.state = TFD_STATE_DRAG_AND_DEBOUNCE;
 		tp_tfd_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
 		break;
 	case TFD_EVENT_TAP:
 	case TFD_EVENT_BUTTON:
 		// TODO: undecided
 		//tp->tfd.state = TFD_STATE_IDLE;
-		//tp_tfd_clear_timer(tp);
+		/* if a button is pressed while waiting for timeout, cancel the timeout
+		since it will most likely just result in a somewhat unanticipated second 
+		button press */
+		tp_tfd_clear_timer(tp);
 		break;
 	}
 }
@@ -419,6 +428,71 @@ tp_tfd_await_drag_handle_event(struct tp_dispatch *tp,
 		position updates -- use the fastest finger only */
 
 
+/* Brief cancellable drag state to disambiguate between drag and a 4+ finger swipe.
+Otherwise same as the drag state. Replaces POSSIBLE_BEGIN state. */
+static void
+tp_tfd_drag_and_debounce_handle_event(struct tp_dispatch *tp,
+			      struct tp_touch *t,
+			      enum tfd_event event, uint64_t time,
+				   int nfingers_down)
+{	
+	switch (event) {
+	// case TFD_EVENT_TOUCH_COUNT:
+	case TFD_EVENT_TOUCH_COUNT_INCREASE:
+	case TFD_EVENT_TOUCH_COUNT_DECREASE:
+		switch (nfingers_down) {
+		case 0: 
+			tp_tfd_pin_fingers(tp);
+			tp_tfd_set_await_resume_timer(tp, time);
+			tp->tfd.state = TFD_STATE_AWAIT_RESUME;
+
+			// tp_tfd_pin_fingers(tp);
+			// tp_tfd_set_await_resume_timer(tp, time);
+			// tp_tfd_set_await_more_fingers_timer(tp, time);
+			// tp->tfd.state = TFD_STATE_POSSIBLE_RESUME;
+
+			break;
+		case 1:
+			tp_tfd_pin_fingers(tp);
+			tp_tfd_set_await_resume_timer(tp, time);
+			tp_tfd_set_await_more_fingers_timer(tp, time);
+			tp->tfd.state = TFD_STATE_POSSIBLE_ZERO_FINGERS;
+			break;
+		case 2: 
+			/* Seems far-fetched to interpret 0 -> 3 -> 2 fingers as an intent
+			to scroll. Fallthrough. */
+		case 3:
+			break;
+		default: 
+			/* 4+ fingers; the drag should abort to give way to 4+ finger 
+			gestures */
+			// tp_tfd_unpin_fingers(tp);
+			tp->tfd.state = TFD_STATE_IDLE;
+			tp_tfd_clear_timer(tp);
+			tp_tfd_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
+			break;
+		}
+		break;
+	case TFD_EVENT_MOTION:
+		break;
+	case TFD_EVENT_RESUME_TIMEOUT:
+		log_tfd_bug(tp, event, nfingers_down);
+		break; // bug
+	case TFD_EVENT_TIMEOUT:
+		// 4+ finger gesture didn't happen -- time to exit the debounce state
+		tp->tfd.state = TFD_STATE_DRAG;
+		break;
+	case TFD_EVENT_TAP:
+		break;
+	case TFD_EVENT_BUTTON:
+		// tp_tfd_unpin_fingers(tp);
+		tp->tfd.state = TFD_STATE_IDLE;
+		tp_tfd_clear_timer(tp);
+		tp_tfd_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
+		break;
+	}
+}
+
 static void
 tp_tfd_drag_handle_event(struct tp_dispatch *tp,
 			      struct tp_touch *t,
@@ -462,7 +536,6 @@ tp_tfd_drag_handle_event(struct tp_dispatch *tp,
 	case TFD_EVENT_BUTTON:
 		tp_tfd_unpin_fingers(tp);
 		tp->tfd.state = TFD_STATE_IDLE;
-		tp_tfd_clear_resume_timer(tp);
 		tp_tfd_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
 		break;
 	}
@@ -797,7 +870,6 @@ tp_tfd_handle_event(struct tp_dispatch *tp,
 	previous_state = tp->tfd.state;
 
 	assert(nfingers_down >= 0);
-	// assert(nfingers_down < 6); // TODO: temp, remove
 
 	switch (event) {
 		case TFD_EVENT_MOTION:
@@ -822,14 +894,18 @@ tp_tfd_handle_event(struct tp_dispatch *tp,
 		tp_tfd_idle_handle_event(tp, t, event, time, nfingers_down);
 		break;
 		
-	case TFD_STATE_POSSIBLE_BEGIN:
-		tp_tfd_possible_begin_handle_event(tp, t, event, time, nfingers_down);
-		break;
+	// case TFD_STATE_POSSIBLE_BEGIN:
+	// 	tp_tfd_possible_begin_handle_event(tp, t, event, time, nfingers_down);
+	// 	break;
 
 	case TFD_STATE_AWAIT_DRAG:
 		tp_tfd_await_drag_handle_event(tp, t, event, time, nfingers_down);
 		break;
 
+	case TFD_STATE_DRAG_AND_DEBOUNCE:
+		tp_tfd_drag_and_debounce_handle_event(tp, t, event, time, nfingers_down);
+		break;
+
 	case TFD_STATE_DRAG:
 		tp_tfd_drag_handle_event(tp, t, event, time, nfingers_down);
 		break;
@@ -1033,16 +1109,17 @@ void
 tp_tfd_handle_tap(struct tp_dispatch *tp, uint64_t time)
 {
 	switch (tp->tfd.state) {
+		case TFD_STATE_IDLE:
+		// case TFD_STATE_POSSIBLE_BEGIN:
+		case TFD_STATE_AWAIT_DRAG:
+		case TFD_STATE_DRAG_AND_DEBOUNCE:
+		case TFD_STATE_DRAG:
+			break;
 		case TFD_STATE_POSSIBLE_ZERO_FINGERS:
 		case TFD_STATE_AWAIT_RESUME:
 		case TFD_STATE_POSSIBLE_RESUME:
 			tp_tfd_handle_event(tp, NULL, TFD_EVENT_TAP, time, tp->tfd.finger_count);
 			break;
-		case TFD_STATE_IDLE:
-		case TFD_STATE_POSSIBLE_BEGIN:
-		case TFD_STATE_AWAIT_DRAG:
-		case TFD_STATE_DRAG:
-			break;
 	}
 }
 
@@ -1101,12 +1178,16 @@ bool
 tp_tfd_dragging(const struct tp_dispatch *tp)
 {
 	switch (tp->tfd.state) {
+		case TFD_STATE_IDLE:
+		case TFD_STATE_AWAIT_DRAG:
+			return false;
+		case TFD_STATE_DRAG_AND_DEBOUNCE:
 		case TFD_STATE_DRAG:
+		case TFD_STATE_POSSIBLE_ZERO_FINGERS:
 		case TFD_STATE_AWAIT_RESUME:
 		case TFD_STATE_POSSIBLE_RESUME:
 			return true;
-		default:
-			return false;
 	}
+	return false;
 }
 
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index ec64b747..5553726d 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -141,16 +141,22 @@ enum tp_tfd_state {
 
 	/* waiting for 3 fingers */
 	TFD_STATE_IDLE,
-	/* [debounce] disambiguate between starting a drag and a possible 4+ gesture */
-	TFD_STATE_POSSIBLE_BEGIN,
+	// not used -- TODO: remove after testing drag_and_debounce
+	// /* [debounce] disambiguate between starting a drag and a possible 4+ gesture */
+	// TFD_STATE_POSSIBLE_BEGIN,
 	/* 3 fingers touching, waiting for motion or timeout */
 	TFD_STATE_AWAIT_DRAG,
+	/* [debounce] same as drag state, but cancellable in case of possible 4+ 
+	gesture. Replacement state for POSSIBLE_BEGIN */
+	TFD_STATE_DRAG_AND_DEBOUNCE,
 	/* 3 fingers touching and button press has been output */
 	TFD_STATE_DRAG,
-	/* [debounce] drag-lock; 1 finger touching, possibly going to 0 fingers */
+	/* [debounce] drag-lock; 1 finger touching, possibly going to 0 fingers.
+	Prevents premature cancellation of AWAIT_RESUME by 1 finger motion events. */
 	TFD_STATE_POSSIBLE_ZERO_FINGERS,
 	/* drag-lock; waiting for 3 finger drag continuation */
 	TFD_STATE_AWAIT_RESUME,
+	/* TODO: possible to replace this state with DRAG_AND_DEBOUNCE as well? */
 	/* [debounce] disambiguate between drag continuation and a possible 4+ gesture */
 	TFD_STATE_POSSIBLE_RESUME,
 };
-- 
2.47.1