mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-19 20:20:31 +01:00
touchpad: stop palm detection when a second finger is detected
This avoids accidental palm detection during two-finger scrolling if one finger is inside the edge exclusion zone. Palm detection is designed to avoid accidental touches while typing. If a non-palm finger is on the touchpad already the user is unlikely to be typing. So stop palm detection in this case and process the fingers as normal. This implementation has a minor bug: if both palm touches start within the palm exclusion zone within the same frame, neither will be labelled as palm due to how we check the other touches. Since this is an extremeley niche case we can live with that. https://bugs.freedesktop.org/show_bug.cgi?id=95417 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
4bb0adfc1c
commit
7860a9ed77
2 changed files with 99 additions and 5 deletions
|
|
@ -652,6 +652,35 @@ tp_palm_detect_move_out_of_edge(struct tp_dispatch *tp,
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
tp_palm_detect_multifinger(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
||||
{
|
||||
struct tp_touch *other;
|
||||
|
||||
if (tp->nfingers_down < 2)
|
||||
return false;
|
||||
|
||||
/* If we have at least one other active non-palm touch make this
|
||||
* touch non-palm too. This avoids palm detection during two-finger
|
||||
* scrolling.
|
||||
*
|
||||
* Note: if both touches start in the palm zone within the same
|
||||
* frame the second touch will still be PALM_NONE and thus detected
|
||||
* here as non-palm touch. This is too niche to worry about for now.
|
||||
*/
|
||||
tp_for_each_touch(tp, other) {
|
||||
if (other == t)
|
||||
continue;
|
||||
|
||||
if (tp_touch_active(tp, other) &&
|
||||
other->palm.state == PALM_NONE) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
||||
{
|
||||
|
|
@ -662,17 +691,24 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
if (tp_palm_detect_trackpoint(tp, t, time))
|
||||
goto out;
|
||||
|
||||
/* If labelled a touch as palm, we unlabel as palm when
|
||||
we move out of the palm edge zone within the timeout, provided
|
||||
the direction is within 45 degrees of the horizontal.
|
||||
*/
|
||||
if (t->palm.state == PALM_EDGE) {
|
||||
if (tp_palm_detect_move_out_of_edge(tp, t, time)) {
|
||||
if (tp_palm_detect_multifinger(tp, t, time)) {
|
||||
t->palm.state = PALM_NONE;
|
||||
log_debug(tp_libinput_context(tp),
|
||||
"palm: touch released, multiple fingers\n");
|
||||
|
||||
/* If labelled a touch as palm, we unlabel as palm when
|
||||
we move out of the palm edge zone within the timeout, provided
|
||||
the direction is within 45 degrees of the horizontal.
|
||||
*/
|
||||
} else if (tp_palm_detect_move_out_of_edge(tp, t, time)) {
|
||||
t->palm.state = PALM_NONE;
|
||||
log_debug(tp_libinput_context(tp),
|
||||
"palm: touch released, out of edge zone\n");
|
||||
}
|
||||
return;
|
||||
} else if (tp_palm_detect_multifinger(tp, t, time)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* palm must start in exclusion zone, it's ok to move into
|
||||
|
|
|
|||
|
|
@ -1135,6 +1135,62 @@ START_TEST(touchpad_palm_detect_tap_clickfinger)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_no_palm_detect_2fg_scroll)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
if (!touchpad_has_palm_detect_size(dev) ||
|
||||
!litest_has_2fg_scroll(dev))
|
||||
return;
|
||||
|
||||
litest_enable_2fg_scroll(dev);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* first finger is palm, second finger isn't so we trigger 2fg
|
||||
* scrolling */
|
||||
litest_touch_down(dev, 0, 99, 50);
|
||||
litest_touch_move_to(dev, 0, 99, 50, 99, 40, 10, 0);
|
||||
litest_touch_move_to(dev, 0, 99, 40, 99, 50, 10, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
litest_touch_down(dev, 1, 50, 50);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_touch_move_two_touches(dev, 99, 50, 50, 50, 0, -20, 10, 0);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_palm_detect_both_edges)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
if (!touchpad_has_palm_detect_size(dev) ||
|
||||
!litest_has_2fg_scroll(dev))
|
||||
return;
|
||||
|
||||
litest_enable_2fg_scroll(dev);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* two fingers moving up/down in the left/right palm zone must not
|
||||
* generate events */
|
||||
litest_touch_down(dev, 0, 99, 50);
|
||||
litest_touch_move_to(dev, 0, 99, 50, 99, 40, 10, 0);
|
||||
litest_touch_move_to(dev, 0, 99, 40, 99, 50, 10, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
litest_touch_down(dev, 1, 1, 50);
|
||||
litest_touch_move_to(dev, 1, 1, 50, 1, 40, 10, 0);
|
||||
litest_touch_move_to(dev, 1, 1, 40, 1, 50, 10, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_touch_move_two_touches(dev, 99, 50, 1, 50, 0, -20, 10, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_left_handed)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -4102,6 +4158,8 @@ litest_setup_tests(void)
|
|||
litest_add("touchpad:palm", touchpad_palm_detect_tap_softbuttons, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:palm", touchpad_palm_detect_tap_clickfinger, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:palm", touchpad_no_palm_detect_at_edge_for_edge_scrolling, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:palm", touchpad_no_palm_detect_2fg_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:palm", touchpad_palm_detect_both_edges, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
|
||||
litest_add("touchpad:left-handed", touchpad_left_handed, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:left-handed", touchpad_left_handed_clickpad, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue