summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--driver/multitouch.c8
-rw-r--r--include/gestures.h4
-rw-r--r--include/memory.h13
-rw-r--r--include/mtdev-iobuf.h1
-rw-r--r--include/mtouch.h2
-rw-r--r--mtdev/iobuf.c9
-rw-r--r--src/gestures.c43
-rw-r--r--src/memory.c84
-rw-r--r--src/mtouch.c8
-rw-r--r--src/test.c4
10 files changed, 176 insertions, 0 deletions
diff --git a/driver/multitouch.c b/driver/multitouch.c
index 888c4c4..73a025d 100644
--- a/driver/multitouch.c
+++ b/driver/multitouch.c
@@ -245,6 +245,10 @@ static void handle_gestures(LocalDevicePtr local,
245 int step = 1 + rot_fraction * get_cap_xsize(caps); 245 int step = 1 + rot_fraction * get_cap_xsize(caps);
246 button_scroll(local, 14, 15, &rot, step, gs->rot); 246 button_scroll(local, 14, 15, &rot, step, gs->rot);
247 } 247 }
248 if (GETBIT(gs->type, GS_TAP) && gs->ntap == 1) {
249 foreach_bit(i, gs->tapmask)
250 tickle_button(local, i + 1);
251 }
248} 252}
249 253
250/* called for each full received packet from the touchpad */ 254/* called for each full received packet from the touchpad */
@@ -258,6 +262,10 @@ static void read_input(LocalDevicePtr local)
258 extract_gestures(&gs, mt); 262 extract_gestures(&gs, mt);
259 handle_gestures(local, &gs, &mt->caps); 263 handle_gestures(local, &gs, &mt->caps);
260 } 264 }
265 if (mt_is_idle(mt, local->fd)) {
266 extract_delayed_gestures(&gs, mt);
267 handle_gestures(local, &gs, &mt->caps);
268 }
261 } 269 }
262} 270}
263 271
diff --git a/include/gestures.h b/include/gestures.h
index 1d70a25..6bc92cd 100644
--- a/include/gestures.h
+++ b/include/gestures.h
@@ -32,13 +32,17 @@
32#define GS_HSWIPE 5 32#define GS_HSWIPE 5
33#define GS_SCALE 6 33#define GS_SCALE 6
34#define GS_ROTATE 7 34#define GS_ROTATE 7
35#define GS_TAP 8
35 36
36struct Gestures { 37struct Gestures {
37 bitmask_t type, btmask, btdata; 38 bitmask_t type, btmask, btdata;
38 int same_fingers, dx, dy, scale, rot; 39 int same_fingers, dx, dy, scale, rot;
40 bitmask_t tapmask;
41 int ntap;
39}; 42};
40 43
41void extract_gestures(struct Gestures *gs, struct MTouch* mt); 44void extract_gestures(struct Gestures *gs, struct MTouch* mt);
45void extract_delayed_gestures(struct Gestures *gs, struct MTouch* mt);
42void output_gesture(const struct Gestures *gs); 46void output_gesture(const struct Gestures *gs);
43 47
44#endif 48#endif
diff --git a/include/memory.h b/include/memory.h
index 1a1b688..3054828 100644
--- a/include/memory.h
+++ b/include/memory.h
@@ -40,6 +40,16 @@
40 * @mvforget: movement before this point in time is discarded 40 * @mvforget: movement before this point in time is discarded
41 * @dx: array of accumulated horiontal movement per finger 41 * @dx: array of accumulated horiontal movement per finger
42 * @dy: array of accumulated vertical movement per finger 42 * @dy: array of accumulated vertical movement per finger
43 * @tpdown: time of first touch
44 * @tpup: time of last release
45 * @tprelax: time of next possible touch
46 * @xdown: x position of first touch
47 * @ydown: y position of first touch
48 * @xup: x position of last release
49 * @yup: y position of last release
50 * @wait: time to wait for a second tap
51 * @maxtap: max number of pointing fingers during touch
52 * @ntap: number of taps in sequence
43 * 53 *
44 */ 54 */
45struct Memory { 55struct Memory {
@@ -49,6 +59,9 @@ struct Memory {
49 int ybar; 59 int ybar;
50 mstime_t mvhold, mvforget; 60 mstime_t mvhold, mvforget;
51 int dx[DIM_FINGER], dy[DIM_FINGER]; 61 int dx[DIM_FINGER], dy[DIM_FINGER];
62 mstime_t tpdown, tpup, tprelax;
63 int xdown, ydown, xup, yup;
64 int wait, maxtap, ntap;
52}; 65};
53 66
54void init_memory(struct Memory *mem); 67void init_memory(struct Memory *mem);
diff --git a/include/mtdev-iobuf.h b/include/mtdev-iobuf.h
index 976b85b..7d4265c 100644
--- a/include/mtdev-iobuf.h
+++ b/include/mtdev-iobuf.h
@@ -33,5 +33,6 @@ struct IOBuffer {
33 33
34void init_iobuf(struct IOBuffer *buf); 34void init_iobuf(struct IOBuffer *buf);
35const struct input_event *get_iobuf_event(struct IOBuffer *buf, int fd); 35const struct input_event *get_iobuf_event(struct IOBuffer *buf, int fd);
36int poll_iobuf(struct IOBuffer *buf, int fd, int ms);
36 37
37#endif 38#endif
diff --git a/include/mtouch.h b/include/mtouch.h
index 2b76652..c73eb29 100644
--- a/include/mtouch.h
+++ b/include/mtouch.h
@@ -40,6 +40,8 @@ int close_mtouch(struct MTouch *mt, int fd);
40 40
41int parse_event(struct MTouch *mt, const struct input_event *ev); 41int parse_event(struct MTouch *mt, const struct input_event *ev);
42 42
43int mt_is_idle(struct MTouch *mt, int fd);
44
43static inline void mt_delay_movement(struct MTouch *mt, int t) 45static inline void mt_delay_movement(struct MTouch *mt, int t)
44{ 46{
45 mem_hold_movement(&mt->mem, mt->state.evtime + t); 47 mem_hold_movement(&mt->mem, mt->state.evtime + t);
diff --git a/mtdev/iobuf.c b/mtdev/iobuf.c
index 8e367b8..65c33f6 100644
--- a/mtdev/iobuf.c
+++ b/mtdev/iobuf.c
@@ -20,6 +20,7 @@
20 **************************************************************************/ 20 **************************************************************************/
21 21
22#include <mtdev-iobuf.h> 22#include <mtdev-iobuf.h>
23#include <sys/poll.h>
23 24
24void init_iobuf(struct IOBuffer *buf) 25void init_iobuf(struct IOBuffer *buf)
25{ 26{
@@ -52,3 +53,11 @@ const struct input_event *get_iobuf_event(struct IOBuffer *buf, int fd)
52 buf->at += EVENT_SIZE; 53 buf->at += EVENT_SIZE;
53 return ev; 54 return ev;
54} 55}
56
57int poll_iobuf(struct IOBuffer *buf, int fd, int ms)
58{
59 struct pollfd fds = { fd, POLLIN, 0 };
60 if (buf->top != buf->at)
61 return 1;
62 return poll(&fds, 1, ms);
63}
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}