mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-10 22:10:15 +01:00
touchpad: use the top-most touch for fake finger positions
The average human hand has four fingers but only one thumb, i.e. the chance of a fake finger being close to the top-most touch is higher than to whatever the first touch was (which may be a thumb at the bottom of the touchpad). So search for the top-most real touch and copy its position into the fake touches. This also fixes another bug with the previous code - the first slot may not be active but we still used its position for the fake touches. Whether that was really triggerable is questionable though. The test is only run for the T440 touchpad - we know it's big enough to enable thumb detection and that way we don't have to double-check in the how big the touchpad is, etc. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
f6bef12bfa
commit
7a6026104b
2 changed files with 107 additions and 7 deletions
|
|
@ -722,16 +722,58 @@ tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
|
|||
|
||||
}
|
||||
|
||||
static inline void
|
||||
tp_position_fake_touches(struct tp_dispatch *tp)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
struct tp_touch *topmost = NULL;
|
||||
unsigned int start, i;
|
||||
|
||||
if (tp_fake_finger_count(tp) <= tp->num_slots)
|
||||
return;
|
||||
|
||||
/* We have at least one fake touch down. Find the top-most real
|
||||
* touch and copy its coordinates over to to all fake touches.
|
||||
* This is more reliable than just taking the first touch.
|
||||
*/
|
||||
for (i = 0; i < tp->num_slots; i++) {
|
||||
t = tp_get_touch(tp, i);
|
||||
if (t->state == TOUCH_END ||
|
||||
t->state == TOUCH_NONE)
|
||||
continue;
|
||||
|
||||
if (topmost == NULL || t->point.y < topmost->point.y)
|
||||
topmost = t;
|
||||
}
|
||||
|
||||
if (!topmost) {
|
||||
log_bug_libinput(tp_libinput_context(tp),
|
||||
"Unable to find topmost touch\n");
|
||||
return;
|
||||
}
|
||||
|
||||
start = tp->has_mt ? tp->num_slots : 1;
|
||||
for (i = start; i < tp->ntouches; i++) {
|
||||
t = tp_get_touch(tp, i);
|
||||
if (t->state == TOUCH_NONE)
|
||||
continue;
|
||||
|
||||
t->point = topmost->point;
|
||||
if (!t->dirty)
|
||||
t->dirty = topmost->dirty;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
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;
|
||||
bool restart_filter = false;
|
||||
|
||||
tp_process_fake_touches(tp, time);
|
||||
tp_unhover_touches(tp, time);
|
||||
tp_position_fake_touches(tp);
|
||||
|
||||
for (i = 0; i < tp->ntouches; i++) {
|
||||
t = tp_get_touch(tp, i);
|
||||
|
|
@ -740,12 +782,6 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
|
|||
if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down)
|
||||
tp_motion_history_reset(t);
|
||||
|
||||
if (i >= tp->num_slots && t->state != TOUCH_NONE) {
|
||||
t->point = first->point;
|
||||
if (!t->dirty)
|
||||
t->dirty = first->dirty;
|
||||
}
|
||||
|
||||
if (!t->dirty)
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -795,6 +795,66 @@ START_TEST(touchpad_area_to_clickfinger_method_while_down)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_clickfinger_3fg_tool_position)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
enable_clickfinger(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* one in thumb area, one in normal area. spread is wide so the two
|
||||
* real fingers don't count together. we expect a 2-finger click */
|
||||
litest_touch_down(dev, 0, 5, 99);
|
||||
litest_touch_down(dev, 1, 90, 15);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_clickfinger_4fg_tool_position)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
enable_clickfinger(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 5, 99);
|
||||
litest_touch_down(dev, 1, 90, 15);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_QUADTAP, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_btn_left)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -4348,6 +4408,10 @@ litest_setup_tests(void)
|
|||
litest_add("touchpad:clickfinger", touchpad_area_to_clickfinger_method, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:clickfinger",
|
||||
touchpad_area_to_clickfinger_method_while_down, LITEST_CLICKPAD, LITEST_ANY);
|
||||
/* run those two for the T440 one only so we don't have to worry
|
||||
* about small touchpads messing with thumb detection expectations */
|
||||
litest_add_for_device("touchpad:clickfinger", touchpad_clickfinger_3fg_tool_position, LITEST_SYNAPTICS_TOPBUTTONPAD);
|
||||
litest_add_for_device("touchpad:clickfinger", touchpad_clickfinger_4fg_tool_position, LITEST_SYNAPTICS_TOPBUTTONPAD);
|
||||
|
||||
litest_add("touchpad:click", touchpad_click_defaults_clickfinger, LITEST_APPLE_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:click", touchpad_click_defaults_btnarea, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue