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.hutte...@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 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel