touchpad: if two fingers are within the lower thumb area, they're not thumbs

The shape of the average hand implies that two fingers down within the lower
thumb area (the bottom few mm of the touchpad) cannot be thumbs without
significant contortion. So let's not mark them as thumb.

Fixes #126

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2018-10-03 14:19:11 +10:00
parent 9847329d2c
commit 655f565fba
4 changed files with 103 additions and 0 deletions

View file

@ -1143,6 +1143,28 @@ tp_thumb_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
}
}
/* If the finger is below the upper thumb line and we have another
* finger in the same area, neither finger is a thumb (unless we've
* already labeled it as such).
*/
if (t->point.y > tp->thumb.upper_thumb_line &&
tp->nfingers_down > 1) {
struct tp_touch *other;
tp_for_each_touch(tp, other) {
if (other->state != TOUCH_BEGIN &&
other->state != TOUCH_UPDATE)
continue;
if (other->point.y > tp->thumb.upper_thumb_line) {
t->thumb.state = THUMB_STATE_NO;
if (other->thumb.state == THUMB_STATE_MAYBE)
other->thumb.state = THUMB_STATE_NO;
break;
}
}
}
/* Note: a thumb at the edge of the touchpad won't trigger the
* threshold, the surface area is usually too small. So we have a
* two-stage detection: pressure and time within the area.

View file

@ -3570,6 +3570,12 @@ litest_timeout_hysteresis(void)
msleep(90);
}
void
litest_timeout_thumb(void)
{
msleep(320);
}
void
litest_push_event_frame(struct litest_device *dev)
{

View file

@ -819,6 +819,9 @@ litest_timeout_touch_arbitration(void);
void
litest_timeout_hysteresis(void);
void
litest_timeout_thumb(void);
void
litest_push_event_frame(struct litest_device *dev);

View file

@ -5199,6 +5199,76 @@ START_TEST(touchpad_thumb_move_and_tap)
}
END_TEST
START_TEST(touchpad_thumb_no_doublethumb)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
litest_disable_tap(dev->libinput_device);
litest_enable_clickfinger(dev);
if (!has_thumb_detect(dev))
return;
litest_drain_events(li);
litest_touch_down(dev, 0, 50, 99);
litest_touch_down(dev, 1, 70, 99);
/* move touch to trigger the thumb detection */
litest_touch_move(dev, 0, 50, 99.2);
libinput_dispatch(li);
litest_timeout_thumb();
libinput_dispatch(li);
/* move touch to trigger the thumb detection */
litest_touch_move(dev, 1, 70, 99.2);
libinput_dispatch(li);
litest_touch_move_two_touches(dev, 50, 99, 70, 99, 0, -20, 10);
litest_touch_up(dev, 0);
litest_touch_up(dev, 1);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
}
END_TEST
START_TEST(touchpad_thumb_no_doublethumb_with_timeout)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
litest_disable_tap(dev->libinput_device);
litest_enable_clickfinger(dev);
if (!has_thumb_detect(dev))
return;
litest_drain_events(li);
litest_touch_down(dev, 0, 50, 99.9);
libinput_dispatch(li);
litest_timeout_thumb();
libinput_dispatch(li);
/* Thumbs don't have a timeout handler, so we have to move the thumb
* a bit to trigger. */
litest_touch_move(dev, 0, 50, 99.8);
/* first touch should now be a thumb */
litest_touch_down(dev, 1, 70, 99.9);
libinput_dispatch(li);
litest_timeout_thumb();
libinput_dispatch(li);
litest_touch_move(dev, 1, 70, 99.8);
litest_touch_move_two_touches(dev, 50, 99, 70, 99, 0, -20, 10);
litest_touch_up(dev, 0);
litest_touch_up(dev, 1);
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
}
END_TEST
START_TEST(touchpad_tool_tripletap_touch_count)
{
struct litest_device *dev = litest_current_device();
@ -6783,6 +6853,8 @@ TEST_COLLECTION(touchpad)
litest_add("touchpad:thumb", touchpad_thumb_tap_hold_2ndfg, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH);
litest_add("touchpad:thumb", touchpad_thumb_tap_hold_2ndfg_tap, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH);
litest_add("touchpad:thumb", touchpad_thumb_move_and_tap, LITEST_CLICKPAD, LITEST_ANY);
litest_add("touchpad:thumb", touchpad_thumb_no_doublethumb, LITEST_CLICKPAD, LITEST_ANY);
litest_add("touchpad:thumb", touchpad_thumb_no_doublethumb_with_timeout, LITEST_CLICKPAD, LITEST_ANY);
litest_add_for_device("touchpad:bugs", touchpad_tool_tripletap_touch_count, LITEST_SYNAPTICS_TOPBUTTONPAD);
litest_add_for_device("touchpad:bugs", touchpad_tool_tripletap_touch_count_late, LITEST_SYNAPTICS_TOPBUTTONPAD);