mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-04 19:50:25 +01:00
touchpad: add fake-touch support for BTN_TOOL_DOUBLETAP and friends
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@who-t.net>
This commit is contained in:
parent
efc8d95171
commit
4e8f1259cc
2 changed files with 68 additions and 11 deletions
|
|
@ -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)
|
||||
{
|
||||
|
|
@ -247,6 +254,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,
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue