[PATCH libinput 07/11] touchpad: Gesture support preparation

Peter Hutterer peter.hutterer at who-t.net
Sun Feb 22 18:56:56 PST 2015


On Wed, Feb 18, 2015 at 01:26:50PM +0100, Hans de Goede wrote:
> Handle everything which is not handeld by the tap, (soft)button or edge-scroll

typo: handled

> code/statemachines in a unified way. Everything is treated as a X-finger
> gesture now, and the action to take on finger movement is decided by
> the gesture.finger_mode setting. Pointer control now simply is seen as a
> 1 finger gesture, and 2fg scrolling as a 2fg gesture.
> 
> This removed the need for special casing things like switching back to

special-casing, I think (i.e. with a -)

> pointer mode when lifting a finger in 2fg scrolling mode, and also lays the
> groundwork for adding 3+ fg gesture support.
> 
> Note that 1 test-case needs to be updated to wait for the finger mode
> switching when switching mode while a gesture has already been started.
> This is actually an improvement as this stops sending spurious pointer
> motion events at the end of 2fg scrolling when not lifting both fingers at
> exactly the same time.
> 
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>

only comment I have here: can we rename finger_mode to finger_count? it's
less ambiguous.

Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
for the series up to here.

Cheers,
   Peter

> ---
>  src/Makefile.am                     |   1 +
>  src/evdev-mt-touchpad-buttons.c     |   1 -
>  src/evdev-mt-touchpad-edge-scroll.c |   1 -
>  src/evdev-mt-touchpad-gestures.c    | 146 ++++++++++++++++++++++++++++++++++++
>  src/evdev-mt-touchpad.c             | 129 ++++++-------------------------
>  src/evdev-mt-touchpad.h             |  47 +++++++++---
>  test/litest.c                       |   6 ++
>  test/litest.h                       |   1 +
>  test/touchpad.c                     |  12 +++
>  9 files changed, 225 insertions(+), 119 deletions(-)
>  create mode 100644 src/evdev-mt-touchpad-gestures.c
> 
> diff --git a/src/Makefile.am b/src/Makefile.am
> index b5eba73..ff65ff7 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -15,6 +15,7 @@ libinput_la_SOURCES =			\
>  	evdev-mt-touchpad-tap.c		\
>  	evdev-mt-touchpad-buttons.c	\
>  	evdev-mt-touchpad-edge-scroll.c	\
> +	evdev-mt-touchpad-gestures.c	\
>  	filter.c			\
>  	filter.h			\
>  	filter-private.h		\
> diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c
> index 9dbb513..12f8023 100644
> --- a/src/evdev-mt-touchpad-buttons.c
> +++ b/src/evdev-mt-touchpad-buttons.c
> @@ -156,7 +156,6 @@ tp_button_set_state(struct tp_dispatch *tp, struct tp_touch *t,
>  		break;
>  	case BUTTON_STATE_AREA:
>  		t->button.curr = BUTTON_EVENT_IN_AREA;
> -		tp_set_pointer(tp, t);
>  		break;
>  	case BUTTON_STATE_BOTTOM:
>  		t->button.curr = event;
> diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c
> index df181d5..28f29c2 100644
> --- a/src/evdev-mt-touchpad-edge-scroll.c
> +++ b/src/evdev-mt-touchpad-edge-scroll.c
> @@ -86,7 +86,6 @@ tp_edge_scroll_set_state(struct tp_dispatch *tp,
>  		break;
>  	case EDGE_SCROLL_TOUCH_STATE_AREA:
>  		t->scroll.edge = EDGE_NONE;
> -		tp_set_pointer(tp, t);
>  		break;
>  	}
>  }
> diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c
> new file mode 100644
> index 0000000..28ac74b
> --- /dev/null
> +++ b/src/evdev-mt-touchpad-gestures.c
> @@ -0,0 +1,146 @@
> +/*
> + * Copyright © 2015 Red Hat, Inc.
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and
> + * its documentation for any purpose is hereby granted without fee, provided
> + * that the above copyright notice appear in all copies and that both that
> + * copyright notice and this permission notice appear in supporting
> + * documentation, and that the name of the copyright holders not be used in
> + * advertising or publicity pertaining to distribution of the software
> + * without specific, written prior permission.  The copyright holders make
> + * no representations about the suitability of this software for any
> + * purpose.  It is provided "as is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
> + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
> + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
> + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
> + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
> + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
> + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include "config.h"
> +
> +#include <assert.h>
> +#include <math.h>
> +#include <stdbool.h>
> +#include <limits.h>
> +
> +#include "evdev-mt-touchpad.h"
> +
> +#define DEFAULT_GESTURE_SWITCH_TIMEOUT 100 /* ms */
> +
> +void
> +tp_gesture_start(struct tp_dispatch *tp, uint64_t time)
> +{
> +	if (tp->gesture.started)
> +		return;
> +
> +	switch (tp->gesture.finger_mode) {
> +	case 2:
> +		/* NOP */
> +		break;
> +	}
> +	tp->gesture.started = true;
> +}
> +
> +void
> +tp_gesture_post_events(struct tp_dispatch *tp, uint64_t time)
> +{
> +	if (tp->gesture.finger_mode == 0)
> +		return;
> +
> +	/* When tap-and-dragging, or a clickpad is clicked force 1fg mode */
> +	if (tp_tap_dragging(tp) || (tp->buttons.is_clickpad && tp->buttons.state)) {
> +		tp_gesture_stop(tp, time);
> +		tp->gesture.finger_mode = 1;
> +		tp->gesture.finger_mode_pending = 0;
> +	}
> +
> +	/* Don't send events when we're unsure in which mode we are */
> +	if (tp->gesture.finger_mode_pending)
> +		return;
> +
> +	switch (tp->gesture.finger_mode) {
> +	case 1:
> +		tp_gesture_post_pointer_motion(tp, time);
> +		break;
> +	case 2:
> +		tp_gesture_post_twofinger_scroll(tp, time);
> +		break;
> +	}
> +}
> +
> +void
> +tp_gesture_stop(struct tp_dispatch *tp, uint64_t time)
> +{
> +	if (!tp->gesture.started)
> +		return;
> +
> +	switch (tp->gesture.finger_mode) {
> +	case 2:
> +		tp_gesture_stop_twofinger_scroll(tp, time);
> +		break;
> +	}
> +	tp->gesture.started = false;
> +}
> +
> +static void
> +tp_gesture_finger_mode_switch_timeout(uint64_t now, void *data)
> +{
> +	struct tp_dispatch *tp = data;
> +
> +	if (!tp->gesture.finger_mode_pending)
> +		return;
> +
> +	tp_gesture_stop(tp, now); /* End current gesture */
> +	tp->gesture.finger_mode = tp->gesture.finger_mode_pending;
> +	tp->gesture.finger_mode_pending = 0;
> +}
> +
> +void
> +tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time)
> +{
> +	unsigned int active_touches = 0;
> +	struct tp_touch *t;
> +
> +	tp_for_each_touch(tp, t)
> +		if (tp_touch_active(tp, t))
> +			active_touches++;
> +
> +	if (active_touches != tp->gesture.finger_mode) {
> +		/* If all fingers are lifted immediately end the gesture */
> +		if (active_touches == 0) {
> +			tp_gesture_stop(tp, time);
> +			tp->gesture.finger_mode = 0;
> +			tp->gesture.finger_mode_pending = 0;
> +		/* Immediately switch to new mode to avoid initial latency */
> +		} else if (!tp->gesture.started) {
> +			tp->gesture.finger_mode = active_touches;
> +			tp->gesture.finger_mode_pending = 0;
> +		/* Else debounce finger changes */
> +		} else if (active_touches != tp->gesture.finger_mode_pending) {
> +			tp->gesture.finger_mode_pending = active_touches;
> +			libinput_timer_set(&tp->gesture.finger_mode_switch_timer,
> +				time + DEFAULT_GESTURE_SWITCH_TIMEOUT);
> +		}
> +	} else {
> +		 tp->gesture.finger_mode_pending = 0;
> +	}
> +}
> +
> +int
> +tp_init_gesture(struct tp_dispatch *tp)
> +{
> +	libinput_timer_init(&tp->gesture.finger_mode_switch_timer,
> +			    tp->device->base.seat->libinput,
> +			    tp_gesture_finger_mode_switch_timeout, tp);
> +	return 0;
> +}
> +
> +void
> +tp_remove_gesture(struct tp_dispatch *tp)
> +{
> +	libinput_timer_cancel(&tp->gesture.finger_mode_switch_timer);
> +}
> diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
> index c6c48d3..947678a 100644
> --- a/src/evdev-mt-touchpad.c
> +++ b/src/evdev-mt-touchpad.c
> @@ -227,7 +227,6 @@ tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
>  	}
>  
>  	t->dirty = true;
> -	t->is_pointer = false;
>  	t->palm.is_palm = false;
>  	t->state = TOUCH_END;
>  	t->pinned.is_pinned = false;
> @@ -424,7 +423,6 @@ tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
>  	if (xdist * xdist + ydist * ydist >=
>  			tp->buttons.motion_dist * tp->buttons.motion_dist) {
>  		t->pinned.is_pinned = false;
> -		tp_set_pointer(tp, t);
>  		return;
>  	}
>  
> @@ -439,14 +437,13 @@ tp_pin_fingers(struct tp_dispatch *tp)
>  	struct tp_touch *t;
>  
>  	tp_for_each_touch(tp, t) {
> -		t->is_pointer = false;
>  		t->pinned.is_pinned = true;
>  		t->pinned.center_x = t->x;
>  		t->pinned.center_y = t->y;
>  	}
>  }
>  
> -static int
> +int
>  tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
>  {
>  	return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
> @@ -456,21 +453,6 @@ tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
>  		tp_edge_scroll_touch_active(tp, t);
>  }
>  
> -void
> -tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t)
> -{
> -	struct tp_touch *tmp = NULL;
> -
> -	/* Only set the touch as pointer if we don't have one yet */
> -	tp_for_each_touch(tp, tmp) {
> -		if (tmp->is_pointer)
> -			return;
> -	}
> -
> -	if (tp_touch_active(tp, t))
> -		t->is_pointer = true;
> -}
> -
>  static void
>  tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
>  {
> @@ -487,7 +469,6 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
>  			int dirs = vector_get_direction(t->x - t->palm.x, t->y - t->palm.y);
>  			if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) {
>  				t->palm.is_palm = false;
> -				tp_set_pointer(tp, t);
>  			}
>  		}
>  		return;
> @@ -530,8 +511,6 @@ tp_get_average_touches_delta(struct tp_dispatch *tp, double *dx, double *dy)
>  			*dx += tmpx;
>  			*dy += tmpy;
>  		}
> -		/* Stop spurious MOTION events at the end of scrolling */
> -		t->is_pointer = false;
>  	}
>  
>  	if (nchanged == 0)
> @@ -541,80 +520,30 @@ tp_get_average_touches_delta(struct tp_dispatch *tp, double *dx, double *dy)
>  	*dy /= nchanged;
>  }
>  
> -static void
> -tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
> +void
> +tp_gesture_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
>  {
>  	double dx = 0, dy =0;
>  
>  	tp_get_average_touches_delta(tp, &dx, &dy);
>  	tp_filter_motion(tp, &dx, &dy, NULL, NULL, time);
>  
> +	if (dx == 0.0 && dy == 0.0)
> +		return;	
> +
> +	tp_gesture_start(tp, time);
>  	evdev_post_scroll(tp->device,
>  			  time,
>  			  LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
>  			  dx, dy);
> -	tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_ACTIVE;
>  }
>  
> -static void
> -tp_twofinger_stop_scroll(struct tp_dispatch *tp, uint64_t time)
> +void
> +tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
>  {
> -	struct tp_touch *t, *ptr = NULL;
> -	int nfingers_down = 0;
> -
>  	evdev_stop_scroll(tp->device,
>  			  time,
>  			  LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
> -
> -	/* If we were scrolling and now there's exactly 1 active finger,
> -	   switch back to pointer movement */
> -	if (tp->scroll.twofinger_state == TWOFINGER_SCROLL_STATE_ACTIVE) {
> -		tp_for_each_touch(tp, t) {
> -			if (tp_touch_active(tp, t)) {
> -				nfingers_down++;
> -				if (ptr == NULL)
> -					ptr = t;
> -			}
> -		}
> -
> -		if (nfingers_down == 1)
> -			tp_set_pointer(tp, ptr);
> -	}
> -
> -	tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_NONE;
> -}
> -
> -static int
> -tp_twofinger_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
> -{
> -	struct tp_touch *t;
> -	int nfingers_down = 0;
> -
> -	if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG)
> -		return 0;
> -
> -	/* No 2fg scrolling during tap-n-drag */
> -	if (tp_tap_dragging(tp))
> -		return 0;
> -
> -	/* No 2fg scrolling while a clickpad is clicked */
> -	if (tp->buttons.is_clickpad && tp->buttons.state)
> -		return 0;
> -
> -	/* Only count active touches for 2 finger scrolling */
> -	tp_for_each_touch(tp, t) {
> -		if (tp_touch_active(tp, t))
> -			nfingers_down++;
> -	}
> -
> -	if (nfingers_down == 2) {
> -		tp_post_twofinger_scroll(tp, time);
> -		return 1;
> -	}
> -
> -	tp_twofinger_stop_scroll(tp, time);
> -
> -	return 0;
>  }
>  
>  static void
> @@ -718,6 +647,8 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
>  	if ((tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) &&
>  	    tp->buttons.is_clickpad)
>  		tp_pin_fingers(tp);
> +
> +	tp_gesture_handle_state(tp, time);
>  }
>  
>  static void
> @@ -749,24 +680,6 @@ tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
>  }
>  
>  static void
> -tp_get_pointer_delta(struct tp_dispatch *tp, double *dx, double *dy)
> -{
> -	struct tp_touch *t = tp_current_touch(tp);
> -
> -	if (!t->is_pointer) {
> -		tp_for_each_touch(tp, t) {
> -			if (t->is_pointer)
> -				break;
> -		}
> -	}
> -
> -	if (!t->is_pointer || !t->dirty)
> -		return;
> -
> -	tp_get_delta(t, dx, dy);
> -}
> -
> -static void
>  tp_get_combined_touches_delta(struct tp_dispatch *tp, double *dx, double *dy)
>  {
>  	struct tp_touch *t;
> @@ -785,8 +698,8 @@ tp_get_combined_touches_delta(struct tp_dispatch *tp, double *dx, double *dy)
>  	}
>  }
>  
> -static void
> -tp_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
> +void
> +tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
>  {
>  	double dx = 0.0, dy = 0.0;
>  	double dx_unaccel, dy_unaccel;
> @@ -795,7 +708,7 @@ tp_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
>  	if (tp->buttons.is_clickpad && tp->buttons.state)
>  		tp_get_combined_touches_delta(tp, &dx, &dy);
>  	else
> -		tp_get_pointer_delta(tp, &dx, &dy);
> +		tp_get_average_touches_delta(tp, &dx, &dy);
>  
>  	tp_filter_motion(tp, &dx, &dy, &dx_unaccel, &dy_unaccel, time);
>  
> @@ -821,16 +734,14 @@ tp_post_events(struct tp_dispatch *tp, uint64_t time)
>  
>  	if (filter_motion || tp->sendevents.trackpoint_active) {
>  		tp_edge_scroll_stop_events(tp, time);
> -		tp_twofinger_stop_scroll(tp, time);
> +		tp_gesture_stop(tp, time);
>  		return;
>  	}
>  
>  	if (tp_edge_scroll_post_events(tp, time) != 0)
>  		return;
> -	if (tp_twofinger_scroll_post_events(tp, time) != 0)
> -		return;
>  
> -	tp_post_pointer_motion(tp, time);
> +	tp_gesture_post_events(tp, time);
>  }
>  
>  static void
> @@ -887,6 +798,7 @@ tp_remove(struct evdev_dispatch *dispatch)
>  	tp_remove_buttons(tp);
>  	tp_remove_sendevents(tp);
>  	tp_remove_edge_scroll(tp);
> +	tp_remove_gesture(tp);
>  }
>  
>  static void
> @@ -980,7 +892,7 @@ tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data)
>  
>  	if (!tp->sendevents.trackpoint_active) {
>  		tp_edge_scroll_stop_events(tp, time);
> -		tp_twofinger_stop_scroll(tp, time);
> +		tp_gesture_stop(tp, time);
>  		tp_tap_suspend(tp, time);
>  		tp->sendevents.trackpoint_active = true;
>  	}
> @@ -1221,7 +1133,7 @@ tp_scroll_config_scroll_method_set_method(struct libinput_device *device,
>  		return LIBINPUT_CONFIG_STATUS_SUCCESS;
>  
>  	tp_edge_scroll_stop_events(tp, time);
> -	tp_twofinger_stop_scroll(tp, time);
> +	tp_gesture_stop_twofinger_scroll(tp, time);
>  
>  	tp->scroll.method = method;
>  
> @@ -1359,6 +1271,9 @@ tp_init(struct tp_dispatch *tp,
>  	if (tp_init_scroll(tp, device) != 0)
>  		return -1;
>  
> +	if (tp_init_gesture(tp) != 0)
> +		return -1;
> +
>  	device->seat_caps |= EVDEV_DEVICE_POINTER;
>  
>  	return 0;
> diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
> index 3479e5e..4d8e875 100644
> --- a/src/evdev-mt-touchpad.h
> +++ b/src/evdev-mt-touchpad.h
> @@ -118,11 +118,6 @@ enum tp_edge_scroll_touch_state {
>  	EDGE_SCROLL_TOUCH_STATE_AREA,
>  };
>  
> -enum tp_twofinger_scroll_state {
> -	TWOFINGER_SCROLL_STATE_NONE,
> -	TWOFINGER_SCROLL_STATE_ACTIVE,
> -};
> -
>  struct tp_motion {
>  	int32_t x;
>  	int32_t y;
> @@ -133,7 +128,6 @@ struct tp_touch {
>  	enum touch_state state;
>  	bool has_ended;				/* TRACKING_ID == -1 */
>  	bool dirty;
> -	bool is_pointer;			/* the pointer-controlling touch */
>  	int32_t x;
>  	int32_t y;
>  	uint64_t millis;
> @@ -217,6 +211,13 @@ struct tp_dispatch {
>  	} accel;
>  
>  	struct {
> +		bool started;
> +		unsigned int finger_mode;
> +		unsigned int finger_mode_pending;
> +		struct libinput_timer finger_mode_switch_timer;
> +	} gesture;
> +
> +	struct {
>  		bool is_clickpad;		/* true for clickpads */
>  		bool has_topbuttons;
>  		bool use_clickfinger;		/* number of fingers decides button number */
> @@ -253,7 +254,6 @@ struct tp_dispatch {
>  		enum libinput_config_scroll_method method;
>  		int32_t right_edge;
>  		int32_t bottom_edge;
> -		enum tp_twofinger_scroll_state twofinger_state;
>  	} scroll;
>  
>  	enum touchpad_event queued;
> @@ -288,15 +288,15 @@ void
>  tp_get_delta(struct tp_touch *t, double *dx, double *dy);
>  
>  void
> -tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t);
> -
> -void
>  tp_filter_motion(struct tp_dispatch *tp,
>  	         double *dx, double *dy,
>  	         double *dx_unaccel, double *dy_unaccel,
>  		 uint64_t time);
>  
>  int
> +tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t);
> +
> +int
>  tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time);
>  
>  int
> @@ -368,4 +368,31 @@ tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time);
>  int
>  tp_edge_scroll_touch_active(struct tp_dispatch *tp, struct tp_touch *t);
>  
> +int
> +tp_init_gesture(struct tp_dispatch *tp);
> +
> +void
> +tp_remove_gesture(struct tp_dispatch *tp);
> +
> +void
> +tp_gesture_start(struct tp_dispatch *tp, uint64_t time);
> +
> +void
> +tp_gesture_stop(struct tp_dispatch *tp, uint64_t time);
> +
> +void
> +tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time);
> +
> +void
> +tp_gesture_post_events(struct tp_dispatch *tp, uint64_t time);
> +
> +void
> +tp_gesture_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time);
> +
> +void
> +tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time);
> +
> +void
> +tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time);
> +
>  #endif
> diff --git a/test/litest.c b/test/litest.c
> index b938cce..cf12424 100644
> --- a/test/litest.c
> +++ b/test/litest.c
> @@ -1385,6 +1385,12 @@ litest_timeout_buttonscroll(void)
>  }
>  
>  void
> +litest_timeout_finger_switch(void)
> +{
> +	msleep(120);
> +}
> +
> +void
>  litest_push_event_frame(struct litest_device *dev)
>  {
>  	assert(!dev->skip_ev_syn);
> diff --git a/test/litest.h b/test/litest.h
> index 60ec458..d78bf0e 100644
> --- a/test/litest.h
> +++ b/test/litest.h
> @@ -180,6 +180,7 @@ struct libevdev_uinput * litest_create_uinput_abs_device(const char *name,
>  void litest_timeout_tap(void);
>  void litest_timeout_softbuttons(void);
>  void litest_timeout_buttonscroll(void);
> +void litest_timeout_finger_switch(void);
>  
>  void litest_push_event_frame(struct litest_device *dev);
>  void litest_pop_event_frame(struct litest_device *dev);
> diff --git a/test/touchpad.c b/test/touchpad.c
> index 9c34b50..3627352 100644
> --- a/test/touchpad.c
> +++ b/test/touchpad.c
> @@ -1871,9 +1871,15 @@ START_TEST(touchpad_2fg_scroll_return_to_motion)
>  
>  	/* 2fg scroll */
>  	litest_touch_down(dev, 1, 53, 50);
> +	libinput_dispatch(li);
> +	litest_timeout_finger_switch();
> +	libinput_dispatch(li);
>  	litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0);
>  	litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0);
>  	litest_touch_up(dev, 1);
> +	libinput_dispatch(li);
> +	litest_timeout_finger_switch();
> +	libinput_dispatch(li);
>  	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
>  
>  	litest_touch_move_to(dev, 0, 47, 70, 47, 50, 10, 0);
> @@ -1881,9 +1887,15 @@ START_TEST(touchpad_2fg_scroll_return_to_motion)
>  
>  	/* back to 2fg scroll, lifting the other finger */
>  	litest_touch_down(dev, 1, 50, 50);
> +	libinput_dispatch(li);
> +	litest_timeout_finger_switch();
> +	libinput_dispatch(li);
>  	litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0);
>  	litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0);
>  	litest_touch_up(dev, 0);
> +	libinput_dispatch(li);
> +	litest_timeout_finger_switch();
> +	libinput_dispatch(li);
>  	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
>  
>  	/* move with second finger */
> -- 
> 2.1.0
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
> 


More information about the wayland-devel mailing list