diff options
author | Hans de Goede <hdegoede@redhat.com> | 2014-07-18 11:06:38 +0200 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2014-07-21 20:20:49 +1000 |
commit | 64f431c303fab787eaf8a7cb14752d908b3da8b2 (patch) | |
tree | 0b48c8fc27078018e9fe9897226afcfe3db4aefe | |
parent | 9720c16eccec922630cde4ebf20490a688b33f35 (diff) |
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>
-rw-r--r-- | src/evdev-mt-touchpad.c | 74 | ||||
-rw-r--r-- | src/evdev-mt-touchpad.h | 4 |
2 files changed, 40 insertions, 38 deletions
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index efe24d1c..4d4856f6 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -247,7 +247,7 @@ tp_process_fake_touch(struct tp_dispatch *tp, struct tp_touch *t; unsigned int fake_touches; unsigned int nfake_touches; - unsigned int i; + unsigned int i, start; unsigned int shift; if (e->code != BTN_TOUCH && @@ -268,16 +268,18 @@ tp_process_fake_touch(struct tp_dispatch *tp, 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); - if (i < nfake_touches) { + if (i < nfake_touches) tp_begin_touch(tp, t, time); - t->fake =true; - } else + else 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 @@ -295,8 +297,7 @@ tp_process_key(struct tp_dispatch *tp, case BTN_TOOL_DOUBLETAP: case BTN_TOOL_TRIPLETAP: case BTN_TOOL_QUADTAP: - if (!tp->has_mt) - tp_process_fake_touch(tp, e, time); + tp_process_fake_touch(tp, e, time); break; } } @@ -401,9 +402,11 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time) { struct tp_touch *t; struct tp_touch *first = tp_get_touch(tp, 0); + unsigned int i; - tp_for_each_touch(tp, t) { - if (!tp->has_mt && t != first && first->fake) { + for (i = 0; i < tp->ntouches; i++) { + t = tp_get_touch(tp, i); + if (i >= tp->real_touches && t->state != TOUCH_NONE) { t->x = first->x; t->y = first->y; if (!t->dirty) @@ -443,10 +446,9 @@ tp_post_process_state(struct tp_dispatch *tp, uint64_t time) if (!t->dirty) continue; - if (t->state == TOUCH_END) { + if (t->state == TOUCH_END) t->state = TOUCH_NONE; - t->fake = false; - } else if (t->state == TOUCH_BEGIN) + else if (t->state == TOUCH_BEGIN) t->state = TOUCH_UPDATE; t->dirty = false; @@ -642,41 +644,41 @@ static int tp_init_slots(struct tp_dispatch *tp, struct evdev_device *device) { - size_t i; 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); if (absinfo) { - tp->ntouches = absinfo->maximum + 1; + tp->real_touches = absinfo->maximum + 1; tp->slot = absinfo->value; tp->has_mt = true; } else { - 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; - + tp->real_touches = 1; tp->slot = 0; tp->has_mt = false; - tp->ntouches = 1; + } - ARRAY_FOR_EACH(max_touches, m) { - if (libevdev_has_event_code(device->evdev, - EV_KEY, - m->code)) { - tp->ntouches = m->ntouches; - break; - } + ARRAY_FOR_EACH(max_touches, m) { + if (libevdev_has_event_code(device->evdev, + EV_KEY, + m->code)) { + n_btn_tool_touches = m->ntouches; + 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) return -1; diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 192c401a..af6a3a38 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -103,7 +103,6 @@ struct tp_touch { struct tp_dispatch *tp; enum touch_state state; bool dirty; - bool fake; /* a fake touch */ bool is_pointer; /* the pointer-controlling touch */ int32_t x; int32_t y; @@ -156,7 +155,8 @@ struct tp_dispatch { unsigned int slot; /* current slot */ 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 */ unsigned int fake_touches; /* fake touch mask */ |