summarylogtreecommitdiffstats
path: root/0003-TFD-add-debounce-state-for-touch-count-decrease.patch
blob: 98b8d2b292015f1ae26295d02e88913ee42179a2 (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
From ae9d1112b78ebc2a6c57212fa289d3161c6dd735 Mon Sep 17 00:00:00 2001
From: abc def <24701-abcdef@users.noreply.gitlab.freedesktop.org>
Date: Thu, 6 Jan 2022 13:22:42 +0100
Subject: [PATCH 3/3] TFD: add debounce state for touch count decrease

Don't allow motion events within a certain interval from a touch count decrease (to 1 finger) to finish the drag. This should make even very quick drags remain in drag-lock instead of being unintentionally finished by the last finger.

Signed-off-by: Temp Name <test@example.com>
---
 src/evdev-mt-touchpad-tfd.c | 93 ++++++++++++++++++++++++++++++++++---
 src/evdev-mt-touchpad.h     | 13 ++++--
 2 files changed, 96 insertions(+), 10 deletions(-)

diff --git a/src/evdev-mt-touchpad-tfd.c b/src/evdev-mt-touchpad-tfd.c
index c12bc27b..49c576bd 100644
--- a/src/evdev-mt-touchpad-tfd.c
+++ b/src/evdev-mt-touchpad-tfd.c
@@ -44,6 +44,7 @@ tfd_state_to_str(enum tp_tfd_state state)
 	CASE_RETURN_STRING(TFD_STATE_IDLE);
 	CASE_RETURN_STRING(TFD_STATE_POSSIBLE_DRAG);
 	CASE_RETURN_STRING(TFD_STATE_DRAG);
+	CASE_RETURN_STRING(TFD_STATE_POSSIBLE_ZERO_FINGERS);
 	CASE_RETURN_STRING(TFD_STATE_AWAIT_RESUME);
 	CASE_RETURN_STRING(TFD_STATE_POSSIBLE_RESUME);
 	}
@@ -275,6 +276,8 @@ tp_tfd_possible_drag_handle_event(struct tp_dispatch *tp,
 		}
 		break;
 	case TFD_EVENT_MOTION:
+	/* this event must ensure it fires upon cursor movement -- alternatively, if
+	impossible, TODO: cursor should be pinned in this state to ensure this */
 		switch (nfingers_down) {
 		default: 
 			log_tfd_bug(tp, event, nfingers_down);
@@ -303,6 +306,12 @@ tp_tfd_possible_drag_handle_event(struct tp_dispatch *tp,
 	}
 }
 
+
+		/* TODO: Future improvement: When one finger moves considerably 
+		faster than the others, don't average their deltas for cursor 
+		position updates -- use the fastest finger only */
+
+
 static void
 tp_tfd_drag_handle_event(struct tp_dispatch *tp,
 			      struct tp_touch *t,
@@ -315,10 +324,7 @@ tp_tfd_drag_handle_event(struct tp_dispatch *tp,
 	case TFD_EVENT_TOUCH_COUNT_DECREASE:
 		switch (nfingers_down) {
 		case 0: 
-		case 1:
 			tp_tfd_pin_fingers(tp);
-			/* removing all, or all but one, fingers gives you ~0.7 seconds to 
-			place three fingers back on the touchpad before the drag ends */
 			tp_tfd_set_await_resume_timer(tp, time);
 			tp->tfd.state = TFD_STATE_AWAIT_RESUME;
 
@@ -327,15 +333,18 @@ tp_tfd_drag_handle_event(struct tp_dispatch *tp,
 			// 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;
 		default: 
 			break;
 		}
 		break;
 	case TFD_EVENT_MOTION:
-		/* TODO: Future improvement: When one finger moves considerably 
-		faster than the others, don't average their deltas for cursor 
-		position updates -- use the fastest finger only */
 		break;
 	case TFD_EVENT_RESUME_TIMEOUT:
 	case TFD_EVENT_TIMEOUT:
@@ -352,6 +361,73 @@ tp_tfd_drag_handle_event(struct tp_dispatch *tp,
 	}
 }
 
+
+/* Waiting for zero fingers. Drag has decreased to 1 finger, but it might be 
+a transitory phase towards 0 fingers. Allow a small amount of time for that
+before allowing one finger to break out of the drag in the AWAIT state. Makes it
+harder to end very fast, brief drags. */
+static void
+tp_tfd_possible_zero_fingers_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_DECREASE:
+		switch (nfingers_down) {
+		case 0: 
+			tp_tfd_clear_timer(tp);
+			tp->tfd.state = TFD_STATE_AWAIT_RESUME;
+			break;
+		default:
+			log_tfd_bug(tp, event, nfingers_down);
+			break;
+		}
+		break;
+	case TFD_EVENT_MOTION:
+		break;
+	case TFD_EVENT_RESUME_TIMEOUT: 
+		/* this shouldn't have time to happen */
+		log_tfd_bug(tp, event, nfingers_down);
+		tp->tfd.state = TFD_STATE_IDLE;
+		tp_tfd_clear_timer(tp);
+		tp_tfd_unpin_fingers(tp);
+		break;
+	case TFD_EVENT_TOUCH_COUNT_INCREASE:
+		/* an increase forces immediate evaluation as if the timer had fired */
+		tp_tfd_clear_timer(tp);
+		/* fallthrough */
+	case TFD_EVENT_TIMEOUT:
+		/* time to (most probably) transition to the AWAIT state with 0 or 1 fingers */
+		switch (nfingers_down) {
+		case 0:
+		case 1:
+		case 2:
+			tp->tfd.state = TFD_STATE_AWAIT_RESUME;
+			break;
+		case 3:
+			tp_tfd_set_await_more_fingers_timer(tp, time);
+			tp->tfd.state = TFD_STATE_POSSIBLE_RESUME;
+			break;
+		default:
+			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;
+		}
+		break;
+	case TFD_EVENT_TAP:
+	case TFD_EVENT_BUTTON:
+		tp_tfd_unpin_fingers(tp);
+		tp->tfd.state = TFD_STATE_IDLE;
+		tp_tfd_clear_resume_timer(tp);
+		tp_tfd_clear_timer(tp);
+		tp_tfd_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
+		break;
+	}
+}
+
 /* Drag-lock; After leaving 3 finger dragging there's a small time window where you can 
 resume the drag with 3 fingers. */
 static void
@@ -621,6 +697,10 @@ tp_tfd_handle_event(struct tp_dispatch *tp,
 		tp_tfd_drag_handle_event(tp, t, event, time, nfingers_down);
 		break;
 
+	case TFD_STATE_POSSIBLE_ZERO_FINGERS:
+		tp_tfd_possible_zero_fingers_handle_event(tp, t, event, time, nfingers_down);
+		break;
+
 	case TFD_STATE_AWAIT_RESUME:
 		tp_tfd_await_resume_handle_event(tp, t, event, time, nfingers_down);
 		break;
@@ -816,6 +896,7 @@ void
 tp_tfd_handle_tap(struct tp_dispatch *tp, uint64_t time)
 {
 	switch (tp->tfd.state) {
+		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);
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 12403ca3..ccd38bc4 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -136,15 +136,20 @@ enum tp_tap_state {
 
 
 enum tp_tfd_state {
+	/* [debounce] = brief states anticipating a further increase/decrease in finger
+	count, preventing unintended drops on account of motion events */
+
 	/* waiting for 3 fingers */
 	TFD_STATE_IDLE,
-	/* 3 fingers down, possible 4+ f gesture */
+	/* 3 fingers touching, possible 4+ f gesture */
 	TFD_STATE_POSSIBLE_DRAG,
-	/* 3 fingers down and button press has been output */
+	/* 3 fingers touching and button press has been output */
 	TFD_STATE_DRAG,
-	/* drag-lock; waiting for drag continuation */
+	/* [debounce] drag-lock; 1 finger touching, possibly going to 0 fingers */
+	TFD_STATE_POSSIBLE_ZERO_FINGERS,
+	/* drag-lock; waiting for 3 finger drag continuation */
 	TFD_STATE_AWAIT_RESUME,
-	/* disambiguate between drag continuation and a possible 4+ gesture */
+	/* [debounce] disambiguate between drag continuation and a possible 4+ gesture */
 	TFD_STATE_POSSIBLE_RESUME,
 };
 
-- 
2.41.0