[PATCH libinput 05/11] touchpad: use the top-most touch for fake finger positions

Hans de Goede hdegoede at redhat.com
Wed Jul 22 06:48:13 PDT 2015


Hi,

On 22-07-15 07:09, Peter Hutterer wrote:
> 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 at who-t.net>

Patches 1 - 5 look good to me:

Reviewed-by: Hans de Goede <hdegoede at redhat.com>

Regards,

Hans



> ---
>   src/evdev-mt-touchpad.c | 50 ++++++++++++++++++++++++++++++++------
>   test/touchpad.c         | 64 +++++++++++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 107 insertions(+), 7 deletions(-)
>
> diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
> index 8629e40..b4399d2 100644
> --- a/src/evdev-mt-touchpad.c
> +++ b/src/evdev-mt-touchpad.c
> @@ -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;
>
> diff --git a/test/touchpad.c b/test/touchpad.c
> index 40d9c33..7b8324c 100644
> --- a/test/touchpad.c
> +++ b/test/touchpad.c
> @@ -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);
>


More information about the wayland-devel mailing list