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

Reply via email to