aboutsummaryrefslogtreecommitdiffstats
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
parent523d193b089111849873d9de0ec1bf29f4176fbc (diff)
downloadxorg-input-kobomultitouch-21a363a2486a713434e890fc1f6b86a180755230.tar.gz
xorg-input-kobomultitouch-21a363a2486a713434e890fc1f6b86a180755230.tar.bz2
xorg-input-kobomultitouch-21a363a2486a713434e890fc1f6b86a180755230.zip
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>
-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,
int step = 1 + rot_fraction * get_cap_xsize(caps);
button_scroll(local, 14, 15, &rot, step, gs->rot);
}
+ if (GETBIT(gs->type, GS_TAP) && gs->ntap == 1) {
+ foreach_bit(i, gs->tapmask)
+ tickle_button(local, i + 1);
+ }
}
/* called for each full received packet from the touchpad */
@@ -258,6 +262,10 @@ static void read_input(LocalDevicePtr local)
extract_gestures(&gs, mt);
handle_gestures(local, &gs, &mt->caps);
}
+ if (mt_is_idle(mt, local->fd)) {
+ extract_delayed_gestures(&gs, mt);
+ handle_gestures(local, &gs, &mt->caps);
+ }
}
}
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 @@
#define GS_HSWIPE 5
#define GS_SCALE 6
#define GS_ROTATE 7
+#define GS_TAP 8
struct Gestures {
bitmask_t type, btmask, btdata;
int same_fingers, dx, dy, scale, rot;
+ bitmask_t tapmask;
+ int ntap;
};
void extract_gestures(struct Gestures *gs, struct MTouch* mt);
+void extract_delayed_gestures(struct Gestures *gs, struct MTouch* mt);
void output_gesture(const struct Gestures *gs);
#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 @@
* @mvforget: movement before this point in time is discarded
* @dx: array of accumulated horiontal movement per finger
* @dy: array of accumulated vertical movement per finger
+ * @tpdown: time of first touch
+ * @tpup: time of last release
+ * @tprelax: time of next possible touch
+ * @xdown: x position of first touch
+ * @ydown: y position of first touch
+ * @xup: x position of last release
+ * @yup: y position of last release
+ * @wait: time to wait for a second tap
+ * @maxtap: max number of pointing fingers during touch
+ * @ntap: number of taps in sequence
*
*/
struct Memory {
@@ -49,6 +59,9 @@ struct Memory {
int ybar;
mstime_t mvhold, mvforget;
int dx[DIM_FINGER], dy[DIM_FINGER];
+ mstime_t tpdown, tpup, tprelax;
+ int xdown, ydown, xup, yup;
+ int wait, maxtap, ntap;
};
void 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 {
void init_iobuf(struct IOBuffer *buf);
const struct input_event *get_iobuf_event(struct IOBuffer *buf, int fd);
+int poll_iobuf(struct IOBuffer *buf, int fd, int ms);
#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);
int parse_event(struct MTouch *mt, const struct input_event *ev);
+int mt_is_idle(struct MTouch *mt, int fd);
+
static inline void mt_delay_movement(struct MTouch *mt, int t)
{
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 @@
**************************************************************************/
#include <mtdev-iobuf.h>
+#include <sys/poll.h>
void init_iobuf(struct IOBuffer *buf)
{
@@ -52,3 +53,11 @@ const struct input_event *get_iobuf_event(struct IOBuffer *buf, int fd)
buf->at += EVENT_SIZE;
return ev;
}
+
+int poll_iobuf(struct IOBuffer *buf, int fd, int ms)
+{
+ struct pollfd fds = { fd, POLLIN, 0 };
+ if (buf->top != buf->at)
+ return 1;
+ return poll(&fds, 1, ms);
+}
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 @@
static const int FINGER_THUMB_MS = 600;
static const int BUTTON_HOLD_MS = 200;
+#define use_tapping 0
/**
* extract_buttons
@@ -50,6 +51,12 @@ static void extract_buttons(struct Gestures *gs, struct MTouch* mt)
gs->btmask = (btdata ^ mt->mem.btdata) & BITONES(DIM_BUTTON);
gs->btdata = btdata;
mt->mem.btdata = btdata;
+ } else if (btdata == 0 && mt->mem.ntap) {
+ if (npoint == 1 && mt->mem.maxtap == 1)
+ btdata = BITMASK(MT_BUTTON_LEFT);
+ gs->btmask = (btdata ^ mt->mem.btdata) & BITONES(DIM_BUTTON);
+ gs->btdata = btdata;
+ mt->mem.btdata = btdata;
}
if (gs->btmask) {
mt_delay_movement(mt, BUTTON_HOLD_MS);
@@ -178,6 +185,40 @@ void extract_gestures(struct Gestures *gs, struct MTouch* mt)
mt->prev_state = mt->state;
}
+/**
+ * extract_delayed_gestures
+ *
+ * Extract delayed gestures, such as tapping
+ *
+ * Reset memory after use.
+ *
+ */
+void extract_delayed_gestures(struct Gestures *gs, struct MTouch* mt)
+{
+ mt->mem.wait = 0;
+
+ if (!use_tapping && mt->caps.has_left)
+ return;
+
+ if (mt->mem.tpdown < mt->mem.tpup) {
+ switch (mt->mem.maxtap) {
+ case 1:
+ gs->tapmask = BITMASK(MT_BUTTON_LEFT);
+ break;
+ case 2:
+ gs->tapmask = BITMASK(MT_BUTTON_RIGHT);
+ break;
+ case 3:
+ gs->tapmask = BITMASK(MT_BUTTON_MIDDLE);
+ break;
+ }
+ }
+
+ if (gs->tapmask)
+ SETBIT(gs->type, GS_TAP);
+
+ gs->ntap = mt->mem.ntap;
+}
void output_gesture(const struct Gestures *gs)
{
@@ -199,4 +240,6 @@ void output_gesture(const struct Gestures *gs)
xf86Msg(X_INFO, "scale: %d\n", gs->scale);
if (GETBIT(gs->type, GS_ROTATE))
xf86Msg(X_INFO, "rotate: %d\n", gs->rot);
+ foreach_bit(i, gs->tapmask)
+ xf86Msg(X_INFO, "tap: %d %d\n", i, gs->ntap);
}
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 @@
/* fraction of max movement threshold */
#define DELTA_CUT(x) (0.5 * (x))
+/* fraction of tap movement threshold */
+#define TAP_XMOVE(c) (0.05 * get_cap_xsize(c))
+#define TAP_YMOVE(c) (0.05 * get_cap_ysize(c))
+
/* timer for cursor stability on finger touch/release */
static const int FINGER_ATTACK_MS = 40;
static const int FINGER_DECAY_MS = 120;
static const int FINGER_CORNER_MS = 300;
+/* tapping timings */
+static const int TAP_SETTLE_MS = 400;
+static const int TAP_TOUCH_MS = 120;
+static const int TAP_GAP_MS = 200;
+
static inline int dxval(const struct FingerState *a,
const struct FingerState *b)
{
@@ -43,6 +52,23 @@ static inline int dyval(const struct FingerState *a,
return a->position_y - b->position_y;
}
+static inline void relax_tapping(struct Memory *m, const struct MTState *state)
+{
+ m->tprelax = state->evtime + TAP_SETTLE_MS;
+ m->wait = 0;
+ m->ntap = 0;
+}
+
+static inline int unrelated_taps(const struct Memory *m,
+ const struct Capabilities *caps)
+{
+ return abs(m->xdown - m->xup) > TAP_XMOVE(caps) ||
+ abs(m->ydown - m->yup) > TAP_YMOVE(caps);
+}
+
+/**
+ * init_memory
+ */
void init_memory(struct Memory *mem)
{
memset(mem, 0, sizeof(struct Memory));
@@ -188,6 +214,63 @@ static void update_movement(struct Memory *m,
m->moving = m->pending;
}
+/**
+ * update_tapping
+ *
+ * Update tpdown, tpup, tprelax, wait, maxtap, ntap.
+ *
+ * Precondition: pointing and thumb are set
+ *
+ * Postcondition: tpdown, tpup, tprelax, wait, maxtap, ntap set
+ *
+ */
+static void update_tapping(struct Memory *m,
+ const struct MTState *prev_state,
+ const struct MTState *state,
+ const struct Capabilities *caps)
+{
+ int x, y, i, npoint = bitcount(m->pointing);
+
+ /* use a position independent on the number of fingers */
+ if (state->nfinger) {
+ x = state->finger[0].position_x;
+ y = state->finger[0].position_y;
+ for (i = 1; i < state->nfinger; i++) {
+ x = minval(x, state->finger[i].position_x);
+ y = minval(y, state->finger[i].position_y);
+ }
+ }
+
+ if (m->thumb || state->evtime < m->mvforget) {
+ relax_tapping(m, state);
+ } else if (state->nfinger && !prev_state->nfinger) {
+ m->tpdown = state->evtime;
+ m->xdown = x;
+ m->ydown = y;
+ m->wait = 0;
+ m->maxtap = npoint;
+ if (m->tpdown > m->tpup + TAP_GAP_MS)
+ m->ntap = 0;
+ else if (unrelated_taps(m, caps))
+ relax_tapping(m, state);
+ m->xup = x;
+ m->yup = y;
+ } else if (!state->nfinger && prev_state->nfinger) {
+ m->tpup = state->evtime;
+ if (m->tpup > m->tprelax &&
+ m->tpup <= m->tpdown + TAP_TOUCH_MS) {
+ m->wait = TAP_GAP_MS;
+ m->ntap++;
+ if (unrelated_taps(m, caps))
+ relax_tapping(m, state);
+ }
+ } else if (state->nfinger) {
+ m->xup = minval(m->xup, x);
+ m->yup = minval(m->yup, y);
+ m->maxtap = maxval(m->maxtap, npoint);
+ }
+}
+
void refresh_memory(struct Memory *m,
const struct MTState *prev_state,
const struct MTState *state,
@@ -196,6 +279,7 @@ void refresh_memory(struct Memory *m,
update_configuration(m, prev_state, state);
update_pointers(m, state, caps);
update_movement(m, prev_state, state, caps);
+ update_tapping(m, prev_state, state, caps);
}
void 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)
#endif
return 1;
}
+
+int mt_is_idle(struct MTouch *mt, int fd)
+{
+ return mt->mem.wait &&
+ evbuf_empty(&mt->dev.outbuf) &&
+ evbuf_empty(&mt->dev.inbuf) &&
+ poll_iobuf(&mt->buf, fd, mt->mem.wait) == 0;
+}
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)
extract_gestures(&gs, &mt);
output_gesture(&gs);
}
+ if (mt_is_idle(&mt, fd)) {
+ extract_delayed_gestures(&gs, &mt);
+ output_gesture(&gs);
+ }
}
close_mtouch(&mt, fd);
}