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 @@
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);
}