[PATCH libinput] Add pointer axis sources to the API
Hans de Goede
hdegoede at redhat.com
Mon Nov 10 00:52:50 PST 2014
Hi,
On 11/06/2014 06:02 AM, Peter Hutterer wrote:
> For a caller to implement/provide kinetic scrolling (intertial scrolling,
> fling scrolling), it needs to know how the scrolling motion was implemented,
> and what to expect in the future. Add this information to the pointer axis
> event.
>
> The three scroll sources we have are:
> * wheels: scrolling is in discreet steps, you don't know when it ends, the
> wheel will just stop sending events
> * fingers: scrolling is continuous coordinate space, we know when it stops and
> we can tell the caller
> * continuous: scrolling is in continuous coordinate space but we may or may not
> know when it stops. if scroll lock is used, the device may never technically
> get out of scroll mode even if it doesn't send events at any given moment
> Use case: trackpoint/trackball scroll emulation on button press
>
> The stop event is now codified in the API documentation, so callers can use
> that for kinetic scrolling. libinput does not implement kinetic scrolling
> itself.
>
> Not covered by this patch:
> * The wheel event is currently defined as "typical mouse wheel step", this is
> different to Qt where the step value is 1/8 of a degree. Some better
> definition here may help.
> * It is unclear how an absolute device would map into relative motion if the
> device itself is not controlling absolute motion.
> * For diagonal scrolling, the vertical/horizontal terminator events would come
> in separately. The caller would have to deal with that somehow.
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
Looks good:
Reviewed-by: Hans de Goede <hdegoede at redhat.com>
Regards,
Hans
> ---
> src/evdev-mt-touchpad.c | 16 +++++++++---
> src/evdev.c | 15 ++++++++++--
> src/evdev.h | 5 +++-
> src/libinput-private.h | 1 +
> src/libinput.c | 9 +++++++
> src/libinput.h | 65 ++++++++++++++++++++++++++++++++++++++++++++++---
> test/pointer.c | 2 ++
> test/touchpad.c | 23 +++++++++++++++++
> test/trackpoint.c | 23 +++++++++++++++++
> 9 files changed, 149 insertions(+), 10 deletions(-)
>
> diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
> index b7a559f..1b1ff84 100644
> --- a/src/evdev-mt-touchpad.c
> +++ b/src/evdev-mt-touchpad.c
> @@ -499,7 +499,9 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
> dy = -dy;
> }
>
> - evdev_post_scroll(tp->device, time, dx, dy);
> + evdev_post_scroll(tp->device, time,
> + LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
> + dx, dy);
> }
>
> static int
> @@ -515,7 +517,9 @@ tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time)
> }
>
> if (nfingers_down != 2) {
> - evdev_stop_scroll(tp->device, time);
> + evdev_stop_scroll(tp->device,
> + time,
> + LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
> return 0;
> }
>
> @@ -540,7 +544,9 @@ tp_post_events(struct tp_dispatch *tp, uint64_t time)
> filter_motion |= tp_post_button_events(tp, time);
>
> if (filter_motion || tp->sendevents.trackpoint_active) {
> - evdev_stop_scroll(tp->device, time);
> + evdev_stop_scroll(tp->device,
> + time,
> + LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
> return;
> }
>
> @@ -703,7 +709,9 @@ tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data)
> return;
>
> if (!tp->sendevents.trackpoint_active) {
> - evdev_stop_scroll(tp->device, time);
> + evdev_stop_scroll(tp->device,
> + time,
> + LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
> tp_tap_suspend(tp, time);
> tp->sendevents.trackpoint_active = true;
> }
> diff --git a/src/evdev.c b/src/evdev.c
> index 3aa87a7..d04da88 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -217,6 +217,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
> hw_is_key_down(device, BTN_MIDDLE)) {
> if (device->scroll.middle_button_scroll_active)
> evdev_post_scroll(device, time,
> + LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS,
> motion.dx, motion.dy);
> break;
> }
> @@ -381,7 +382,8 @@ evdev_middle_button_scroll_button(struct evdev_device *device,
> } else {
> libinput_timer_cancel(&device->scroll.timer);
> if (device->scroll.middle_button_scroll_active) {
> - evdev_stop_scroll(device, time);
> + evdev_stop_scroll(device, time,
> + LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS);
> device->scroll.middle_button_scroll_active = false;
> } else {
> /* If the button is released quickly enough emit the
> @@ -545,6 +547,7 @@ evdev_process_relative(struct evdev_device *device,
> base,
> time,
> LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
> + LIBINPUT_POINTER_AXIS_SOURCE_WHEEL,
> -1 * e->value * DEFAULT_AXIS_STEP_DISTANCE);
> break;
> case REL_HWHEEL:
> @@ -558,6 +561,7 @@ evdev_process_relative(struct evdev_device *device,
> base,
> time,
> LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
> + LIBINPUT_POINTER_AXIS_SOURCE_WHEEL,
> e->value * DEFAULT_AXIS_STEP_DISTANCE);
> break;
> default:
> @@ -1483,6 +1487,7 @@ evdev_device_get_size(struct evdev_device *device,
> void
> evdev_post_scroll(struct evdev_device *device,
> uint64_t time,
> + enum libinput_pointer_axis_source source,
> double dx,
> double dy)
> {
> @@ -1497,6 +1502,7 @@ evdev_post_scroll(struct evdev_device *device,
> pointer_notify_axis(&device->base,
> time,
> LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
> + source,
> dy);
> }
>
> @@ -1505,23 +1511,28 @@ evdev_post_scroll(struct evdev_device *device,
> pointer_notify_axis(&device->base,
> time,
> LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
> + source,
> dx);
> }
> }
>
> void
> -evdev_stop_scroll(struct evdev_device *device, uint64_t time)
> +evdev_stop_scroll(struct evdev_device *device,
> + uint64_t time,
> + enum libinput_pointer_axis_source source)
> {
> /* terminate scrolling with a zero scroll event */
> if (device->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
> pointer_notify_axis(&device->base,
> time,
> LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
> + source,
> 0);
> if (device->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
> pointer_notify_axis(&device->base,
> time,
> LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
> + source,
> 0);
>
> device->scroll.direction = 0;
> diff --git a/src/evdev.h b/src/evdev.h
> index 666c8dc..19f6137 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -275,12 +275,15 @@ evdev_pointer_notify_button(struct evdev_device *device,
> void
> evdev_post_scroll(struct evdev_device *device,
> uint64_t time,
> + enum libinput_pointer_axis_source source,
> double dx,
> double dy);
>
>
> void
> -evdev_stop_scroll(struct evdev_device *device, uint64_t time);
> +evdev_stop_scroll(struct evdev_device *device,
> + uint64_t time,
> + enum libinput_pointer_axis_source source);
>
> void
> evdev_device_remove(struct evdev_device *device);
> diff --git a/src/libinput-private.h b/src/libinput-private.h
> index 92bd96b..7b71da2 100644
> --- a/src/libinput-private.h
> +++ b/src/libinput-private.h
> @@ -263,6 +263,7 @@ void
> pointer_notify_axis(struct libinput_device *device,
> uint64_t time,
> enum libinput_pointer_axis axis,
> + enum libinput_pointer_axis_source source,
> double value);
>
> void
> diff --git a/src/libinput.c b/src/libinput.c
> index 35262dd..b97117b 100644
> --- a/src/libinput.c
> +++ b/src/libinput.c
> @@ -63,6 +63,7 @@ struct libinput_event_pointer {
> uint32_t seat_button_count;
> enum libinput_button_state state;
> enum libinput_pointer_axis axis;
> + enum libinput_pointer_axis_source source;
> double value;
> };
>
> @@ -374,6 +375,12 @@ libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event)
> return event->value;
> }
>
> +LIBINPUT_EXPORT enum libinput_pointer_axis_source
> +libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event)
> +{
> + return event->source;
> +}
> +
> LIBINPUT_EXPORT uint32_t
> libinput_event_touch_get_time(struct libinput_event_touch *event)
> {
> @@ -960,6 +967,7 @@ void
> pointer_notify_axis(struct libinput_device *device,
> uint64_t time,
> enum libinput_pointer_axis axis,
> + enum libinput_pointer_axis_source source,
> double value)
> {
> struct libinput_event_pointer *axis_event;
> @@ -972,6 +980,7 @@ pointer_notify_axis(struct libinput_device *device,
> .time = time,
> .axis = axis,
> .value = value,
> + .source = source,
> };
>
> post_device_event(device, time,
> diff --git a/src/libinput.h b/src/libinput.h
> index 5623bff..932e65d 100644
> --- a/src/libinput.h
> +++ b/src/libinput.h
> @@ -202,6 +202,28 @@ enum libinput_pointer_axis {
> };
>
> /**
> + * @ingroup device
> + *
> + * The source for a libinput_pointer_axis event. See
> + * libinput_event_pointer_get_axis_source() for details.
> + */
> +enum libinput_pointer_axis_source {
> + /**
> + * The event is caused by the rotation of a wheel.
> + */
> + LIBINPUT_POINTER_AXIS_SOURCE_WHEEL = 1,
> + /**
> + * The event is caused by the movement of one or more fingers on a
> + * device.
> + */
> + LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
> + /**
> + * The event is caused by the motion of some device.
> + */
> + LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS,
> +};
> +
> +/**
> * @ingroup base
> *
> * Event type for events returned by libinput_get_event().
> @@ -637,9 +659,8 @@ libinput_event_pointer_get_axis(struct libinput_event_pointer *event);
> * LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL and
> * LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, the value of the event is in
> * relative scroll units, with the positive direction being down or right,
> - * respectively. The dimension of a scroll unit is equal to one unit of
> - * motion in the respective axis, where applicable (e.g. touchpad two-finger
> - * scrolling).
> + * respectively. For the interpretation of the value, see
> + * libinput_event_pointer_get_axis_source().
> *
> * For pointer events that are not of type LIBINPUT_EVENT_POINTER_AXIS,
> * this function returns 0.
> @@ -655,6 +676,44 @@ libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event);
> /**
> * @ingroup event_pointer
> *
> + * Return the source for a given axis event. Axis events (scroll events) can
> + * be caused by a hardware item such as a scroll wheel or emulated from
> + * other input sources, such as two-finger or edge scrolling on a
> + * touchpad.
> + *
> + * If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_FINGER, libinput
> + * guarantees that a scroll sequence is terminated with a scroll value of 0.
> + * A caller may use this information to decide on whether kinetic scrolling
> + * should be triggered on this scroll sequence.
> + * The coordinate system is identical to the cursor movement, i.e. a
> + * scroll value of 1 represents the equivalent relative motion of 1.
> + *
> + * If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, no terminating
> + * event is guaranteed (though it may happen).
> + * Scrolling is in discreet steps, a value of 10 representing one click
> + * of a typical mouse wheel. Some mice may have differently grained wheels,
> + * libinput will adjust the value accordingly. It is up to the caller how to
> + * interpret such different step sizes.
> + *
> + * If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS, no
> + * terminating event is guaranteed (though it may happen).
> + * The coordinate system is identical to the cursor movement, i.e. a
> + * scroll value of 1 represents the equivalent relative motion of 1.
> + *
> + * For pointer events that are not of type LIBINPUT_EVENT_POINTER_AXIS,
> + * this function returns 0.
> + *
> + * @note It is an application bug to call this function for events other than
> + * LIBINPUT_EVENT_POINTER_AXIS.
> + *
> + * @return the source for this axis event
> + */
> +enum libinput_pointer_axis_source
> +libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event);
> +
> +/**
> + * @ingroup event_pointer
> + *
> * @return The generic libinput_event of this event
> */
> struct libinput_event *
> diff --git a/test/pointer.c b/test/pointer.c
> index 56b6709..b82f2b8 100644
> --- a/test/pointer.c
> +++ b/test/pointer.c
> @@ -262,6 +262,8 @@ test_wheel_event(struct litest_device *dev, int which, int amount)
> LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL :
> LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
> ck_assert_int_eq(libinput_event_pointer_get_axis_value(ptrev), expected);
> + ck_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev),
> + LIBINPUT_POINTER_AXIS_SOURCE_WHEEL);
> libinput_event_destroy(event);
> }
>
> diff --git a/test/touchpad.c b/test/touchpad.c
> index 8cd838e..70de791 100644
> --- a/test/touchpad.c
> +++ b/test/touchpad.c
> @@ -1368,6 +1368,28 @@ START_TEST(touchpad_2fg_scroll)
> }
> END_TEST
>
> +START_TEST(touchpad_2fg_scroll_source)
> +{
> + struct litest_device *dev = litest_current_device();
> + struct libinput *li = dev->libinput;
> + struct libinput_event *event;
> + struct libinput_event_pointer *ptrev;
> +
> + litest_drain_events(li);
> +
> + test_2fg_scroll(dev, 0.1, 40, 0);
> + litest_wait_for_event_of_type(li, LIBINPUT_EVENT_POINTER_AXIS, -1);
> +
> + event = libinput_get_event(li);
> + ptrev = libinput_event_get_pointer_event(event);
> +
> + ck_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev),
> + LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
> +
> + libinput_event_destroy(event);
> +}
> +END_TEST
> +
> START_TEST(touchpad_scroll_natural_defaults)
> {
> struct litest_device *dev = litest_current_device();
> @@ -1984,6 +2006,7 @@ int main(int argc, char **argv) {
> litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_move_out_ignore, LITEST_TOPBUTTONPAD, LITEST_ANY);
>
> litest_add("touchpad:scroll", touchpad_2fg_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
> + litest_add("touchpad:scroll", touchpad_2fg_scroll_source, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
> litest_add("touchpad:scroll", touchpad_scroll_natural_defaults, LITEST_TOUCHPAD, LITEST_ANY);
> litest_add("touchpad:scroll", touchpad_scroll_natural_enable_config, LITEST_TOUCHPAD, LITEST_ANY);
> litest_add("touchpad:scroll", touchpad_scroll_natural, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
> diff --git a/test/trackpoint.c b/test/trackpoint.c
> index d4dfe41..729062a 100644
> --- a/test/trackpoint.c
> +++ b/test/trackpoint.c
> @@ -94,10 +94,33 @@ START_TEST(trackpoint_scroll)
> }
> END_TEST
>
> +START_TEST(trackpoint_scroll_source)
> +{
> + struct litest_device *dev = litest_current_device();
> + struct libinput *li = dev->libinput;
> + struct libinput_event *event;
> + struct libinput_event_pointer *ptrev;
> +
> + litest_drain_events(li);
> +
> + test_2fg_scroll(dev, 1, 6);
> + litest_wait_for_event_of_type(li, LIBINPUT_EVENT_POINTER_AXIS, -1);
> +
> + event = libinput_get_event(li);
> + ptrev = libinput_event_get_pointer_event(event);
> +
> + ck_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev),
> + LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS);
> +
> + litest_assert_empty_queue(li);
> +}
> +END_TEST
> +
> int main(int argc, char **argv) {
>
> litest_add("trackpoint:middlebutton", trackpoint_middlebutton, LITEST_POINTINGSTICK, LITEST_ANY);
> litest_add("trackpoint:scroll", trackpoint_scroll, LITEST_POINTINGSTICK, LITEST_ANY);
> + litest_add("trackpoint:scroll", trackpoint_scroll_source, LITEST_POINTINGSTICK, LITEST_ANY);
>
> return litest_run(argc, argv);
> }
>
More information about the wayland-devel
mailing list