[PATCH libinput 15/19] touchpad: add fake-touch support for BTN_TOOL_DOUBLETAP and friends
Peter Hutterer
peter.hutterer at who-t.net
Sun Feb 16 22:48:34 PST 2014
This enables two-finger scrolling and two- and three-finger tapping on a
single-touch touchpad if BTN_TOOL_DOUBLETAP and BTN_TOOL_TRIPLETAP is set.
These require a bit of special processing:
BTN_TOUCH is set with the first finger down, but somewhat randomly unset and
re-set when switching between the various BTN_TOOL_*TAP values.
BTN_TOOL_<N>TAP is only set for N fingers down, thus a double->triple move
will see a release for DOUBLETAP and a press for TRIPLETAP. This may happen in
the same event, or across two consecutive events.
This patch adds a fake_touches mask to the touchpad struct. The mask is set
for each matching BTN_* event and used to count the number of expected
fake touchpoints. From that we begin/end the number of actual touchpoints
required. Fake touchpoints take their x/y coordinates from the first
touchpoint, which reads ABS_X/ABS_Y.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
src/evdev-mt-touchpad.c | 78 ++++++++++++++++++++++++++++++++++++++++++-------
src/evdev-mt-touchpad.h | 1 +
2 files changed, 68 insertions(+), 11 deletions(-)
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index f8edb8c..d0864fe 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -142,6 +142,13 @@ tp_current_touch(struct tp_dispatch *tp)
return &tp->touches[min(tp->slot, tp->ntouches)];
}
+static inline struct tp_touch *
+tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
+{
+ assert(slot < tp->ntouches);
+ return &tp->touches[slot];
+}
+
static inline void
tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t)
{
@@ -248,6 +255,54 @@ tp_process_absolute_st(struct tp_dispatch *tp,
}
static void
+tp_process_fake_touch(struct tp_dispatch *tp,
+ const struct input_event *e,
+ uint32_t time)
+{
+ struct tp_touch *t;
+ unsigned int fake_touches;
+ unsigned int nfake_touches;
+ unsigned int i;
+ unsigned int shift;
+
+ if (e->code != BTN_TOUCH &&
+ (e->code < BTN_TOOL_DOUBLETAP || e->code > BTN_TOOL_QUADTAP))
+ return;
+
+ shift = e->code == BTN_TOUCH ? 0 : (e->code - BTN_TOOL_DOUBLETAP + 1);
+
+ if (e->value)
+ tp->fake_touches |= 1 << shift;
+ else
+ tp->fake_touches &= ~(0x1 << shift);
+
+ fake_touches = tp->fake_touches;
+ nfake_touches = 0;
+ while (fake_touches) {
+ nfake_touches++;
+ fake_touches >>= 1;
+ }
+
+ for (i = 0; i < tp->ntouches; i++) {
+ t = tp_get_touch(tp, i);
+ if (i >= nfake_touches) {
+ if (t->state != TOUCH_NONE) {
+ tp_end_touch(tp, t);
+ t->millis = time;
+ }
+ } else if (t->state != TOUCH_UPDATE &&
+ t->state != TOUCH_BEGIN) {
+ t->state = TOUCH_NONE;
+ tp_begin_touch(tp, t);
+ t->millis = time;
+ t->fake =true;
+ }
+ }
+
+ assert(tp->nfingers_down == nfake_touches);
+}
+
+static void
tp_process_key(struct tp_dispatch *tp,
const struct input_event *e,
uint32_t time)
@@ -268,16 +323,11 @@ tp_process_key(struct tp_dispatch *tp,
}
break;
case BTN_TOUCH:
- if (!tp->has_mt) {
- struct tp_touch *t = tp_current_touch(tp);
- if (e->value) {
- tp_begin_touch(tp, t);
- t->fake = true;
- } else {
- tp_end_touch(tp, t);
- }
- t->millis = time;
- }
+ case BTN_TOOL_DOUBLETAP:
+ case BTN_TOOL_TRIPLETAP:
+ case BTN_TOOL_QUADTAP:
+ if (!tp->has_mt)
+ tp_process_fake_touch(tp, e, time);
break;
}
}
@@ -286,9 +336,15 @@ static void
tp_process_state(struct tp_dispatch *tp, uint32_t time)
{
struct tp_touch *t;
+ struct tp_touch *first = tp_get_touch(tp, 0);
tp_for_each_touch(tp, t) {
- if (!t->dirty)
+ if (!tp->has_mt && t != first && first->fake) {
+ t->x = first->x;
+ t->y = first->y;
+ if (!t->dirty)
+ t->dirty = first->dirty;
+ } else if (!t->dirty)
continue;
tp_motion_hysteresis(tp, t);
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 1e09497..84d8cec 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -101,6 +101,7 @@ struct tp_dispatch {
unsigned int ntouches; /* number of slots */
struct tp_touch *touches; /* len == ntouches */
+ unsigned int fake_touches; /* fake touch mask */
struct {
int32_t margin_x;
--
1.8.4.2
More information about the wayland-devel
mailing list