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 <[email protected]>
Looks good: Reviewed-by: Hans de Goede <[email protected]> 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); > } > _______________________________________________ wayland-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
