mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-08 12:28:10 +02:00
touchpad: Create fake touches for BTN_TOOL_FOO on multi-touch pads too
Multi-touch pads may track less touches then they can report fingers being present through BTN_TOOL_FOO. So create fake touches for fingers reported by BTN_TOOL_FOO on multi-touch pads too (when necessary). This fixes e.g. 3 finger tap not working on the T440s. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
9720c16ecc
commit
64f431c303
2 changed files with 40 additions and 38 deletions
|
|
@ -247,7 +247,7 @@ tp_process_fake_touch(struct tp_dispatch *tp,
|
||||||
struct tp_touch *t;
|
struct tp_touch *t;
|
||||||
unsigned int fake_touches;
|
unsigned int fake_touches;
|
||||||
unsigned int nfake_touches;
|
unsigned int nfake_touches;
|
||||||
unsigned int i;
|
unsigned int i, start;
|
||||||
unsigned int shift;
|
unsigned int shift;
|
||||||
|
|
||||||
if (e->code != BTN_TOUCH &&
|
if (e->code != BTN_TOUCH &&
|
||||||
|
|
@ -268,16 +268,18 @@ tp_process_fake_touch(struct tp_dispatch *tp,
|
||||||
fake_touches >>= 1;
|
fake_touches >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < tp->ntouches; i++) {
|
/* For single touch tps we use BTN_TOUCH for begin / end of touch 0 */
|
||||||
|
start = tp->has_mt ? tp->real_touches : 0;
|
||||||
|
for (i = start; i < tp->ntouches; i++) {
|
||||||
t = tp_get_touch(tp, i);
|
t = tp_get_touch(tp, i);
|
||||||
if (i < nfake_touches) {
|
if (i < nfake_touches)
|
||||||
tp_begin_touch(tp, t, time);
|
tp_begin_touch(tp, t, time);
|
||||||
t->fake =true;
|
else
|
||||||
} else
|
|
||||||
tp_end_touch(tp, t, time);
|
tp_end_touch(tp, t, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(tp->nfingers_down == nfake_touches);
|
/* On mt the actual touch info may arrive after BTN_TOOL_FOO */
|
||||||
|
assert(tp->has_mt || tp->nfingers_down == nfake_touches);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -295,8 +297,7 @@ tp_process_key(struct tp_dispatch *tp,
|
||||||
case BTN_TOOL_DOUBLETAP:
|
case BTN_TOOL_DOUBLETAP:
|
||||||
case BTN_TOOL_TRIPLETAP:
|
case BTN_TOOL_TRIPLETAP:
|
||||||
case BTN_TOOL_QUADTAP:
|
case BTN_TOOL_QUADTAP:
|
||||||
if (!tp->has_mt)
|
tp_process_fake_touch(tp, e, time);
|
||||||
tp_process_fake_touch(tp, e, time);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -401,9 +402,11 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
|
||||||
{
|
{
|
||||||
struct tp_touch *t;
|
struct tp_touch *t;
|
||||||
struct tp_touch *first = tp_get_touch(tp, 0);
|
struct tp_touch *first = tp_get_touch(tp, 0);
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
tp_for_each_touch(tp, t) {
|
for (i = 0; i < tp->ntouches; i++) {
|
||||||
if (!tp->has_mt && t != first && first->fake) {
|
t = tp_get_touch(tp, i);
|
||||||
|
if (i >= tp->real_touches && t->state != TOUCH_NONE) {
|
||||||
t->x = first->x;
|
t->x = first->x;
|
||||||
t->y = first->y;
|
t->y = first->y;
|
||||||
if (!t->dirty)
|
if (!t->dirty)
|
||||||
|
|
@ -443,10 +446,9 @@ tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
|
||||||
if (!t->dirty)
|
if (!t->dirty)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (t->state == TOUCH_END) {
|
if (t->state == TOUCH_END)
|
||||||
t->state = TOUCH_NONE;
|
t->state = TOUCH_NONE;
|
||||||
t->fake = false;
|
else if (t->state == TOUCH_BEGIN)
|
||||||
} else if (t->state == TOUCH_BEGIN)
|
|
||||||
t->state = TOUCH_UPDATE;
|
t->state = TOUCH_UPDATE;
|
||||||
|
|
||||||
t->dirty = false;
|
t->dirty = false;
|
||||||
|
|
@ -642,41 +644,41 @@ static int
|
||||||
tp_init_slots(struct tp_dispatch *tp,
|
tp_init_slots(struct tp_dispatch *tp,
|
||||||
struct evdev_device *device)
|
struct evdev_device *device)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
const struct input_absinfo *absinfo;
|
const struct input_absinfo *absinfo;
|
||||||
|
struct map {
|
||||||
|
unsigned int code;
|
||||||
|
int ntouches;
|
||||||
|
} max_touches[] = {
|
||||||
|
{ BTN_TOOL_QUINTTAP, 5 },
|
||||||
|
{ BTN_TOOL_QUADTAP, 4 },
|
||||||
|
{ BTN_TOOL_TRIPLETAP, 3 },
|
||||||
|
{ BTN_TOOL_DOUBLETAP, 2 },
|
||||||
|
};
|
||||||
|
struct map *m;
|
||||||
|
unsigned int i, n_btn_tool_touches = 1;
|
||||||
|
|
||||||
absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_SLOT);
|
absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_SLOT);
|
||||||
if (absinfo) {
|
if (absinfo) {
|
||||||
tp->ntouches = absinfo->maximum + 1;
|
tp->real_touches = absinfo->maximum + 1;
|
||||||
tp->slot = absinfo->value;
|
tp->slot = absinfo->value;
|
||||||
tp->has_mt = true;
|
tp->has_mt = true;
|
||||||
} else {
|
} else {
|
||||||
struct map {
|
tp->real_touches = 1;
|
||||||
unsigned int code;
|
|
||||||
int ntouches;
|
|
||||||
} max_touches[] = {
|
|
||||||
{ BTN_TOOL_QUINTTAP, 5 },
|
|
||||||
{ BTN_TOOL_QUADTAP, 4 },
|
|
||||||
{ BTN_TOOL_TRIPLETAP, 3 },
|
|
||||||
{ BTN_TOOL_DOUBLETAP, 2 },
|
|
||||||
};
|
|
||||||
struct map *m;
|
|
||||||
|
|
||||||
tp->slot = 0;
|
tp->slot = 0;
|
||||||
tp->has_mt = false;
|
tp->has_mt = false;
|
||||||
tp->ntouches = 1;
|
}
|
||||||
|
|
||||||
ARRAY_FOR_EACH(max_touches, m) {
|
ARRAY_FOR_EACH(max_touches, m) {
|
||||||
if (libevdev_has_event_code(device->evdev,
|
if (libevdev_has_event_code(device->evdev,
|
||||||
EV_KEY,
|
EV_KEY,
|
||||||
m->code)) {
|
m->code)) {
|
||||||
tp->ntouches = m->ntouches;
|
n_btn_tool_touches = m->ntouches;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tp->touches = calloc(tp->ntouches,
|
|
||||||
sizeof(struct tp_touch));
|
tp->ntouches = max(tp->real_touches, n_btn_tool_touches);
|
||||||
|
tp->touches = calloc(tp->ntouches, sizeof(struct tp_touch));
|
||||||
if (!tp->touches)
|
if (!tp->touches)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,6 @@ struct tp_touch {
|
||||||
struct tp_dispatch *tp;
|
struct tp_dispatch *tp;
|
||||||
enum touch_state state;
|
enum touch_state state;
|
||||||
bool dirty;
|
bool dirty;
|
||||||
bool fake; /* a fake touch */
|
|
||||||
bool is_pointer; /* the pointer-controlling touch */
|
bool is_pointer; /* the pointer-controlling touch */
|
||||||
int32_t x;
|
int32_t x;
|
||||||
int32_t y;
|
int32_t y;
|
||||||
|
|
@ -156,7 +155,8 @@ struct tp_dispatch {
|
||||||
unsigned int slot; /* current slot */
|
unsigned int slot; /* current slot */
|
||||||
bool has_mt;
|
bool has_mt;
|
||||||
|
|
||||||
unsigned int ntouches; /* number of slots */
|
unsigned int real_touches; /* number of slots */
|
||||||
|
unsigned int ntouches; /* no slots inc. fakes */
|
||||||
struct tp_touch *touches; /* len == ntouches */
|
struct tp_touch *touches; /* len == ntouches */
|
||||||
unsigned int fake_touches; /* fake touch mask */
|
unsigned int fake_touches; /* fake touch mask */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue