[RFC libinput] Add an API for touchpad gesture events

Peter Hutterer peter.hutterer at who-t.net
Thu Jan 22 20:21:10 PST 2015


CC-ing Carlos too, I'd like to get his input here.

On Thu, Jan 22, 2015 at 04:52:50PM +0100, Hans de Goede wrote:
> For touchscreens we always send raw touch events to the compositor, and the
> compositor or application toolkits do gesture recognition. This makes sense
> because on a touchscreen which window / widget the touches are over is
> important context to know to interpret gestures.
> 
> On touchpads however we never send raw events since a touchpad is an absolute
> device which primary function is to send pointer motion delta-s, so we always
> need to do processing (and a lot of it) on the raw events.
> 
> Moreover there is nothing underneath the finger which influences how to
> interpret gestures, and there is a lot of touchpad and libinput configuration
> specific context necessary for gesture recognition. E.g. is this a clickpad,
> and if so are softbuttons or clickfinger used? What is the size of the
> softbuttons? Is this a true multi-touch touchpad or a semi multi-touch touchpad
> which only gives us a bounding box enclosing the fingers? Etc.
> 
> So for touchpads it is better to do gesture processing in libinput, this commit
> adds an initial implementation of a Gesture event API which only supports swipe
> gestures, other gestures will be added later following the same model wrt,
> having clear start and stop events and the number of fingers involved being
> fixed once a gesture sequence starts.
> 
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> ---
>  src/libinput.h | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 154 insertions(+), 1 deletion(-)
> 
> diff --git a/src/libinput.h b/src/libinput.h
> index 7b7a2db..1507772 100644
> --- a/src/libinput.h
> +++ b/src/libinput.h
> @@ -173,7 +173,11 @@ enum libinput_event_type {
>  	 * Signals the end of a set of touchpoints at one device sample
>  	 * time. This event has no coordinate information attached.
>  	 */
> -	LIBINPUT_EVENT_TOUCH_FRAME
> +	LIBINPUT_EVENT_TOUCH_FRAME,
> +
> +	LIBINPUT_EVENT_GESTURE_SWIPE_START = 600,
> +	LIBINPUT_EVENT_GESTURE_SWIPE,

To avoid accidental ambiguity, I'd use ...SWIPE_UPDATE here.

> +	LIBINPUT_EVENT_GESTURE_SWIPE_END,
>  };
>  
>  /**
> @@ -350,6 +354,19 @@ libinput_event_get_touch_event(struct libinput_event *event);
>  /**
>   * @ingroup event
>   *
> + * Return the gesture event that is this input event. If the event type does
> + * not match the gesture event types, this function returns NULL.
> + *
> + * The inverse of this function is libinput_event_gesture_get_base_event().
> + *
> + * @return A gesture event, or NULL for other events
> + */
> +struct libinput_event_gesture *
> +libinput_event_get_gesture_event(struct libinput_event *event);
> +
> +/**
> + * @ingroup event
> + *
>   * Return the device event that is this input event. If the event type does
>   * not match the device event types, this function returns NULL.
>   *
> @@ -884,6 +901,142 @@ struct libinput_event *
>  libinput_event_touch_get_base_event(struct libinput_event_touch *event);
>  
>  /**
> + * @defgroup event_gesture Gesture events
> + *
> + * Gesture events are generated when a gesture is recognized on a touchpad.
> + *
> + * Gesture sequences always start with a LIBINPUT_EVENT_GESTURE_FOO_START
> + * event. All following gesture events will be of the
> + * LIBINPUT_EVENT_GESTURE_FOO type until a LIBINPUT_EVENT_GESTURE_FOO_STOP is
> + * generated which signals the end of the gesture.
> + */

btw, we should add a @page for gestures at a later point but until we have
the implementation we can skip it.

> +
> +/**
> + * @ingroup event_gesture
> + *
> + * @return The event time for this event
> + */
> +uint32_t
> +libinput_event_gesture_get_time(struct libinput_event_gesture *event);
> +
> +/**
> + * @ingroup event_gesture
> + *
> + * @return The generic libinput_event of this event
> + */
> +struct libinput_event *
> +libinput_event_gesture_get_base_event(struct libinput_event_gesture *event);
> +
> +/**
> + * @ingroup event_gesture
> + *
> + * Return the number of fingers used for a gesture. This can be used e.g.
> + * to differentiate between 3 or 4 finger swipes.
> + *
> + * This function can be called on all gesture events including
> + * LIBINPUT_EVENT_GESTURE_FOO_START and the returned finger count value will
> + * not change during a sequence. IOW libinput_event_gesture_get_finger_count
> + * will only return a different value then a previous call after a
> + * LIBINPUT_EVENT_GESTURE_FOO_STOP has been received.

hehe. tbh, the IOW... sentence made it more confusing, I think you can skip
it.

> + *
> + * @return the number of fingers used for a gesture
> + */
> +enum libinput_key_state
> +libinput_event_gesture_get_finger_count(struct libinput_event_gesture *event);
> +
> +/**
> + * @ingroup event_gesture
> + *
> + * Return the delta between the last event and the current event. For gesture
> + * events that are not of type @ref LIBINPUT_EVENT_GESTURE_SWIPE, this
> + * function returns 0.
> + *
> + * If a device employs pointer acceleration, the delta returned by this
> + * function is the accelerated delta.

should we provide the unaccelerated data here as well? we do for pointer
events.

> + *
> + * Relative motion deltas are normalized to represent those of a device with
> + * 1000dpi resolution. See @ref motion_normalization for more details.
> + *
> + * @note It is an application bug to call this function for events other than
> + * @ref LIBINPUT_EVENT_GESTURE_SWIPE.
> + *
> + * @return the relative x movement since the last event
> + */
> +double
> +libinput_event_gesture_get_dx(struct libinput_event_gesture *event);
> +
> +/**
> + * @ingroup event_gesture
> + *
> + * Return the delta between the last event and the current event. For gesture
> + * events that are not of type @ref LIBINPUT_EVENT_GESTURE_SWIPE, this
> + * function returns 0.
> + *
> + * If a device employs pointer acceleration, the delta returned by this
> + * function is the accelerated delta.
> + *
> + * Relative motion deltas are normalized to represent those of a device with
> + * 1000dpi resolution. See @ref motion_normalization for more details.
> + *
> + * @note It is an application bug to call this function for events other than
> + * @ref LIBINPUT_EVENT_GESTURE_SWIPE.
> + *
> + * @return the relative y movement since the last event
> + */
> +double
> +libinput_event_gesture_get_dy(struct libinput_event_gesture *event);
> +
> +/**
> + * @ingroup event_gesture
> + *
> + * Return the absolute x coordinate of the current center position of a
> + * swipe gesture. This can be used e.g. to determine if a swipe is starting
> + * close to a touchpad edge, or to synchronize an animation with how much

s/much/many/ (I think)

> + * percent of the width of a touchpad a swipe gesture has travelled.
> + *
> + * The returned value is in the range of 0.0 to 1.0 with 0.0 indicating that
> + * the center is on the right edge of the touchpad, and 1.0 indicating that it
> + * is on the left edge.
> + *
> + * For gesture events that are not of type
> + * @ref LIBINPUT_EVENT_GESTURE_SWIPE_START, @ref LIBINPUT_EVENT_GESTURE_SWIPE
> + * or @ref LIBINPUT_EVENT_GESTURE_SWIPE_STOP this function returns 0.
> + *
> + * @note It is an application bug to call this function for events other than
> + * @ref LIBINPUT_EVENT_GESTURE_SWIPE_START, @ref LIBINPUT_EVENT_GESTURE_SWIPE
> + * or @ref LIBINPUT_EVENT_GESTURE_SWIPE_STOP.
> + *
> + * @return the current absolute x coordinate
> + */
> +double
> +libinput_event_gesture_get_absolute_x(struct libinput_event_gesture *event);

this is a bit inconsistent with the other API where absolute_x returns a
value in mm. I think we should do that here as well and provide 
get_absolute_x_transformed - callers that need it in relation to the
touchpad size can just provide 1.0 as width/height.

> +
> +/**
> + * @ingroup event_gesture
> + *
> + * Return the absolute y coordinate of the current center position of a
> + * swipe gesture. This can be used e.g. to determine if a swipe is starting
> + * close to a touchpad edge, or to synchronize an animation with how much

s/much/many/

> + * percent of the height of a touchpad a swipe gesture has travelled.
> + *
> + * The returned value is in the range of 0.0 to 1.0 with 0.0 indicating that
> + * the center is on the top edge of the touchpad, and 1.0 indicating that it
> + * is on the bottom edge.
> + *
> + * For gesture events that are not of type
> + * @ref LIBINPUT_EVENT_GESTURE_SWIPE_START, @ref LIBINPUT_EVENT_GESTURE_SWIPE
> + * or @ref LIBINPUT_EVENT_GESTURE_SWIPE_STOP this function returns 0.
> + *
> + * @note It is an application bug to call this function for events other than
> + * @ref LIBINPUT_EVENT_GESTURE_SWIPE_START, @ref LIBINPUT_EVENT_GESTURE_SWIPE
> + * or @ref LIBINPUT_EVENT_GESTURE_SWIPE_STOP.
> + *
> + * @return the current absolute y coordinate
> + */
> +double
> +libinput_event_gesture_get_absolute_y(struct libinput_event_gesture *event);
> +
> +/**
>   * @defgroup base Initialization and manipulation of libinput contexts
>   */

Just a comment, I think this should be good for other gestures as well. If
we look at pinch/rotate to have a vector length and a center of gravity,
then the dx/dy can represent the vector.
so minus the nitpicks above this looks good.

Cheers,
   Peter


More information about the wayland-devel mailing list