summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-06-16 18:48:53 +0200
committerHenrik Rydberg <rydberg@euromail.se>2010-06-16 18:54:52 +0200
commit21a363a2486a713434e890fc1f6b86a180755230 (patch)
treeca788ccf7c8269c5cbd41350463fa478aa499903 /src
parent523d193b089111849873d9de0ec1bf29f4176fbc (diff)
Add tapping logic
This patch adds tap-to-click, tap-and-hold for dragging, two-finger and three-finger taps. Turned on by default for touch screens only; switch on in gestures.c. Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'src')
-rw-r--r--src/gestures.c43
-rw-r--r--src/memory.c84
-rw-r--r--src/mtouch.c8
-rw-r--r--src/test.c4
4 files changed, 139 insertions, 0 deletions
diff --git a/src/gestures.c b/src/gestures.c
index a5a17ca..3f59a1e 100644
--- a/src/gestures.c
+++ b/src/gestures.c
@@ -27,6 +27,7 @@
27 27
28static const int FINGER_THUMB_MS = 600; 28static const int FINGER_THUMB_MS = 600;
29static const int BUTTON_HOLD_MS = 200; 29static const int BUTTON_HOLD_MS = 200;
30#define use_tapping 0
30 31
31/** 32/**
32 * extract_buttons 33 * extract_buttons
@@ -50,6 +51,12 @@ static void extract_buttons(struct Gestures *gs, struct MTouch* mt)
50 gs->btmask = (btdata ^ mt->mem.btdata) & BITONES(DIM_BUTTON); 51 gs->btmask = (btdata ^ mt->mem.btdata) & BITONES(DIM_BUTTON);
51 gs->btdata = btdata; 52 gs->btdata = btdata;
52 mt->mem.btdata = btdata; 53 mt->mem.btdata = btdata;
54 } else if (btdata == 0 && mt->mem.ntap) {
55 if (npoint == 1 && mt->mem.maxtap == 1)
56 btdata = BITMASK(MT_BUTTON_LEFT);
57 gs->btmask = (btdata ^ mt->mem.btdata) & BITONES(DIM_BUTTON);
58 gs->btdata = btdata;
59 mt->mem.btdata = btdata;
53 } 60 }
54 if (gs->btmask) { 61 if (gs->btmask) {
55 mt_delay_movement(mt, BUTTON_HOLD_MS); 62 mt_delay_movement(mt, BUTTON_HOLD_MS);
@@ -178,6 +185,40 @@ void extract_gestures(struct Gestures *gs, struct MTouch* mt)
178 mt->prev_state = mt->state; 185 mt->prev_state = mt->state;
179} 186}
180 187
188/**
189 * extract_delayed_gestures
190 *
191 * Extract delayed gestures, such as tapping
192 *
193 * Reset memory after use.
194 *
195 */
196void extract_delayed_gestures(struct Gestures *gs, struct MTouch* mt)
197{
198 mt->mem.wait = 0;
199
200 if (!use_tapping && mt->caps.has_left)
201 return;
202
203 if (mt->mem.tpdown < mt->mem.tpup) {
204 switch (mt->mem.maxtap) {
205 case 1:
206 gs->tapmask = BITMASK(MT_BUTTON_LEFT);
207 break;
208 case 2:
209 gs->tapmask = BITMASK(MT_BUTTON_RIGHT);
210 break;
211 case 3:
212 gs->tapmask = BITMASK(MT_BUTTON_MIDDLE);
213 break;
214 }
215 }
216
217 if (gs->tapmask)
218 SETBIT(gs->type, GS_TAP);
219
220 gs->ntap = mt->mem.ntap;
221}
181 222
182void output_gesture(const struct Gestures *gs) 223void output_gesture(const struct Gestures *gs)
183{ 224{
@@ -199,4 +240,6 @@ void output_gesture(const struct Gestures *gs)
199 xf86Msg(X_INFO, "scale: %d\n", gs->scale); 240 xf86Msg(X_INFO, "scale: %d\n", gs->scale);
200 if (GETBIT(gs->type, GS_ROTATE)) 241 if (GETBIT(gs->type, GS_ROTATE))
201 xf86Msg(X_INFO, "rotate: %d\n", gs->rot); 242 xf86Msg(X_INFO, "rotate: %d\n", gs->rot);
243 foreach_bit(i, gs->tapmask)
244 xf86Msg(X_INFO, "tap: %d %d\n", i, gs->ntap);
202} 245}
diff --git a/src/memory.c b/src/memory.c
index cd88d7a..2bb4d95 100644
--- a/src/memory.c
+++ b/src/memory.c
@@ -27,11 +27,20 @@
27/* fraction of max movement threshold */ 27/* fraction of max movement threshold */
28#define DELTA_CUT(x) (0.5 * (x)) 28#define DELTA_CUT(x) (0.5 * (x))
29 29
30/* fraction of tap movement threshold */
31#define TAP_XMOVE(c) (0.05 * get_cap_xsize(c))
32#define TAP_YMOVE(c) (0.05 * get_cap_ysize(c))
33
30/* timer for cursor stability on finger touch/release */ 34/* timer for cursor stability on finger touch/release */
31static const int FINGER_ATTACK_MS = 40; 35static const int FINGER_ATTACK_MS = 40;
32static const int FINGER_DECAY_MS = 120; 36static const int FINGER_DECAY_MS = 120;
33static const int FINGER_CORNER_MS = 300; 37static const int FINGER_CORNER_MS = 300;
34 38
39/* tapping timings */
40static const int TAP_SETTLE_MS = 400;
41static const int TAP_TOUCH_MS = 120;
42static const int TAP_GAP_MS = 200;
43
35static inline int dxval(const struct FingerState *a, 44static inline int dxval(const struct FingerState *a,
36 const struct FingerState *b) 45 const struct FingerState *b)
37{ 46{
@@ -43,6 +52,23 @@ static inline int dyval(const struct FingerState *a,
43 return a->position_y - b->position_y; 52 return a->position_y - b->position_y;
44} 53}
45 54
55static inline void relax_tapping(struct Memory *m, const struct MTState *state)
56{
57 m->tprelax = state->evtime + TAP_SETTLE_MS;
58 m->wait = 0;
59 m->ntap = 0;
60}
61
62static inline int unrelated_taps(const struct Memory *m,
63 const struct Capabilities *caps)
64{
65 return abs(m->xdown - m->xup) > TAP_XMOVE(caps) ||
66 abs(m->ydown - m->yup) > TAP_YMOVE(caps);
67}
68
69/**
70 * init_memory
71 */
46void init_memory(struct Memory *mem) 72void init_memory(struct Memory *mem)
47{ 73{
48 memset(mem, 0, sizeof(struct Memory)); 74 memset(mem, 0, sizeof(struct Memory));
@@ -188,6 +214,63 @@ static void update_movement(struct Memory *m,
188 m->moving = m->pending; 214 m->moving = m->pending;
189} 215}
190 216
217/**
218 * update_tapping
219 *
220 * Update tpdown, tpup, tprelax, wait, maxtap, ntap.
221 *
222 * Precondition: pointing and thumb are set
223 *
224 * Postcondition: tpdown, tpup, tprelax, wait, maxtap, ntap set
225 *
226 */
227static void update_tapping(struct Memory *m,
228 const struct MTState *prev_state,
229 const struct MTState *state,
230 const struct Capabilities *caps)
231{
232 int x, y, i, npoint = bitcount(m->pointing);
233
234 /* use a position independent on the number of fingers */
235 if (state->nfinger) {
236 x = state->finger[0].position_x;
237 y = state->finger[0].position_y;
238 for (i = 1; i < state->nfinger; i++) {
239 x = minval(x, state->finger[i].position_x);
240 y = minval(y, state->finger[i].position_y);
241 }
242 }
243
244 if (m->thumb || state->evtime < m->mvforget) {
245 relax_tapping(m, state);
246 } else if (state->nfinger && !prev_state->nfinger) {
247 m->tpdown = state->evtime;
248 m->xdown = x;
249 m->ydown = y;
250 m->wait = 0;
251 m->maxtap = npoint;
252 if (m->tpdown > m->tpup + TAP_GAP_MS)
253 m->ntap = 0;
254 else if (unrelated_taps(m, caps))
255 relax_tapping(m, state);
256 m->xup = x;
257 m->yup = y;
258 } else if (!state->nfinger && prev_state->nfinger) {
259 m->tpup = state->evtime;
260 if (m->tpup > m->tprelax &&
261 m->tpup <= m->tpdown + TAP_TOUCH_MS) {
262 m->wait = TAP_GAP_MS;
263 m->ntap++;
264 if (unrelated_taps(m, caps))
265 relax_tapping(m, state);
266 }
267 } else if (state->nfinger) {
268 m->xup = minval(m->xup, x);
269 m->yup = minval(m->yup, y);
270 m->maxtap = maxval(m->maxtap, npoint);
271 }
272}
273
191void refresh_memory(struct Memory *m, 274void refresh_memory(struct Memory *m,
192 const struct MTState *prev_state, 275 const struct MTState *prev_state,
193 const struct MTState *state, 276 const struct MTState *state,
@@ -196,6 +279,7 @@ void refresh_memory(struct Memory *m,
196 update_configuration(m, prev_state, state); 279 update_configuration(m, prev_state, state);
197 update_pointers(m, state, caps); 280 update_pointers(m, state, caps);
198 update_movement(m, prev_state, state, caps); 281 update_movement(m, prev_state, state, caps);
282 update_tapping(m, prev_state, state, caps);
199} 283}
200 284
201void output_memory(const struct Memory *m) 285void output_memory(const struct Memory *m)
diff --git a/src/mtouch.c b/src/mtouch.c
index 7272edf..14c0fd9 100644
--- a/src/mtouch.c
+++ b/src/mtouch.c
@@ -73,3 +73,11 @@ int parse_event(struct MTouch *mt, const struct input_event *ev)
73#endif 73#endif
74 return 1; 74 return 1;
75} 75}
76
77int mt_is_idle(struct MTouch *mt, int fd)
78{
79 return mt->mem.wait &&
80 evbuf_empty(&mt->dev.outbuf) &&
81 evbuf_empty(&mt->dev.inbuf) &&
82 poll_iobuf(&mt->buf, fd, mt->mem.wait) == 0;
83}
diff --git a/src/test.c b/src/test.c
index 0088cdd..ce2fdf5 100644
--- a/src/test.c
+++ b/src/test.c
@@ -42,6 +42,10 @@ static void loop_device(int fd)
42 extract_gestures(&gs, &mt); 42 extract_gestures(&gs, &mt);
43 output_gesture(&gs); 43 output_gesture(&gs);
44 } 44 }
45 if (mt_is_idle(&mt, fd)) {
46 extract_delayed_gestures(&gs, &mt);
47 output_gesture(&gs);
48 }
45 } 49 }
46 close_mtouch(&mt, fd); 50 close_mtouch(&mt, fd);
47} 51}