[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