[PATCH v2 libinput] Add an API to change pointer acceleration profiles
Hans de Goede
hdegoede at redhat.com
Mon Sep 7 04:16:41 PDT 2015
Hi,
On 07-09-15 07:47, Peter Hutterer wrote:
>
> The quartett of new config functions is:
> libinput_device_config_accel_get_profiles
> libinput_device_config_accel_get_profile
> libinput_device_config_accel_set_profile
> libinput_device_config_accel_get_default_profile
>
> The profile defines how the pointer acceleration works, from a very high-level
> perspective. Two profiles are on offer, "adaptive", the standard one we have
> used so far and "flat" which is a simple multiplier of input deltas and
> provides 1:1 mapping of device movement vs pointer movement.
>
> The speed setting is on top of the profile, a speed of 0 (default) is the
> equivalent to "no pointer acceleration". This is popular among gamers and
> users of switchable-dpi mice.
>
> The flat profile unnormalizes the deltas, i.e. you get what the device does
> and any device below 800dpi will feel excruciatingly slow. The speed range
> [-1, 1] maps into 0-200% of the speed. At 200%, a delta of 1 is translated
> into a 2 pixel movement, anything higher makes it rather pointless.
>
> The flat profile is currently available for all pointer devices but touchpads.
>
> https://bugs.freedesktop.org/show_bug.cgi?id=89485
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
Bit of a big patch, but I guess there is no easy way to split this up.
Otherwise looks good to me:
Reviewed-by: Hans de Goede <hdegoede at redhat.com>
Regards,
Hans
> ---
> Sorry, left a memleak in the first patch.
>
> Changes to v1:
> - the flat filter now has a destroy() hook
>
> doc/pointer-acceleration.dox | 17 ++++++
> src/evdev-mt-touchpad.c | 40 +++++++++++++-
> src/evdev.c | 118 ++++++++++++++++++++++++++++++++----------
> src/filter-private.h | 1 +
> src/filter.c | 99 ++++++++++++++++++++++++++++++++++-
> src/filter.h | 5 ++
> src/libinput-private.h | 6 +++
> src/libinput.c | 47 ++++++++++++++++-
> src/libinput.h | 74 ++++++++++++++++++++++++++
> src/libinput.sym | 7 +++
> test/pointer.c | 114 ++++++++++++++++++++++++++++++++++++++++
> tools/libinput-list-devices.c | 33 ++++++++++++
> tools/shared.c | 24 ++++++++-
> tools/shared.h | 1 +
> 14 files changed, 555 insertions(+), 31 deletions(-)
>
> diff --git a/doc/pointer-acceleration.dox b/doc/pointer-acceleration.dox
> index a372e15..7ec5e74 100644
> --- a/doc/pointer-acceleration.dox
> +++ b/doc/pointer-acceleration.dox
> @@ -9,6 +9,16 @@ This page explains the high-level concepts used in the code. It aims to
> provide an overview for developers and is not necessarily useful for
> users.
>
> + at section ptraccel-profiles Pointer acceleration profiles
> +
> +The profile decides the general method of pointer acceleration.
> +libinput currently supports two profiles: "adaptive" and "flat". The aptive
> +profile is the default profile for all devices and takes the current speed
> +of the device into account when deciding on acceleration. The flat profile
> +is simply a constant factor applied to all device deltas, regardless of the
> +speed of motion (see @ref ptraccel-profile-flat). Most of this document
> +describes the adaptive pointer acceleration.
> +
> @section ptraccel-velocity Velocity calculation
>
> The device's speed of movement is measured across multiple input events
> @@ -107,4 +117,11 @@ The image above shows the trackpoint acceleration profile in comparison to the
> @ref ptraccel-linear. The constant acceleration factor, usually applied by
> udev, shapes the acceleration profile.
>
> + at section ptraccel-profile-flat The flat pointer acceleration profile
> +
> +In a flat profile, the acceleration factor is constant regardless of the
> +velocity of the pointer and each delta (dx, dy) results in an accelerated delta
> +(dx * factor, dy * factor). This provides 1:1 movement between the device
> +and the pointer on-screen.
> +
> */
> diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
> index aeb6c31..8804658 100644
> --- a/src/evdev-mt-touchpad.c
> +++ b/src/evdev-mt-touchpad.c
> @@ -1518,11 +1518,38 @@ tp_init_slots(struct tp_dispatch *tp,
> return 0;
> }
>
> +static uint32_t
> +tp_accel_config_get_profiles(struct libinput_device *libinput_device)
> +{
> + return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
> +}
> +
> +static enum libinput_config_status
> +tp_accel_config_set_profile(struct libinput_device *libinput_device,
> + enum libinput_config_accel_profile profile)
> +{
> + return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
> +}
> +
> +static enum libinput_config_accel_profile
> +tp_accel_config_get_profile(struct libinput_device *libinput_device)
> +{
> + return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
> +}
> +
> +static enum libinput_config_accel_profile
> +tp_accel_config_get_default_profile(struct libinput_device *libinput_device)
> +{
> + return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
> +}
> +
> static int
> tp_init_accel(struct tp_dispatch *tp, double diagonal)
> {
> + struct evdev_device *device = tp->device;
> int res_x, res_y;
> struct motion_filter *filter;
> + int rc;
>
> res_x = tp->device->abs.absinfo_x->resolution;
> res_y = tp->device->abs.absinfo_y->resolution;
> @@ -1545,7 +1572,18 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
> if (!filter)
> return -1;
>
> - return evdev_device_init_pointer_acceleration(tp->device, filter);
> + rc = evdev_device_init_pointer_acceleration(tp->device, filter);
> + if (rc != 0)
> + return rc;
> +
> + /* we override the profile hooks for accel configuration with hooks
> + * that don't allow selection of profiles */
> + device->pointer.config.get_profiles = tp_accel_config_get_profiles;
> + device->pointer.config.set_profile = tp_accel_config_set_profile;
> + device->pointer.config.get_profile = tp_accel_config_get_profile;
> + device->pointer.config.get_default_profile = tp_accel_config_get_default_profile;
> +
> + return 0;
> }
>
> static uint32_t
> diff --git a/src/evdev.c b/src/evdev.c
> index 094320e..a846f86 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -1385,6 +1385,27 @@ evdev_device_dispatch(void *data)
> }
> }
>
> +static inline int
> +evdev_init_accel(struct evdev_device *device,
> + enum libinput_config_accel_profile which)
> +{
> + struct motion_filter *filter;
> +
> + if (which == LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT)
> + filter = create_pointer_accelerator_filter_flat(device->dpi);
> + else if (device->tags & EVDEV_TAG_TRACKPOINT)
> + filter = create_pointer_accelerator_filter_trackpoint(device->dpi);
> + else if (device->dpi < DEFAULT_MOUSE_DPI)
> + filter = create_pointer_accelerator_filter_linear_low_dpi(device->dpi);
> + else
> + filter = create_pointer_accelerator_filter_linear(device->dpi);
> +
> + if (!filter)
> + return -1;
> +
> + return evdev_device_init_pointer_acceleration(device, filter);
> +}
> +
> static int
> evdev_accel_config_available(struct libinput_device *device)
> {
> @@ -1418,20 +1439,83 @@ evdev_accel_config_get_default_speed(struct libinput_device *device)
> return 0.0;
> }
>
> +static uint32_t
> +evdev_accel_config_get_profiles(struct libinput_device *libinput_device)
> +{
> + struct evdev_device *device = (struct evdev_device*)libinput_device;
> +
> + if (!device->pointer.filter)
> + return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
> +
> + return LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE |
> + LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT;
> +}
> +
> +static enum libinput_config_status
> +evdev_accel_config_set_profile(struct libinput_device *libinput_device,
> + enum libinput_config_accel_profile profile)
> +{
> + struct evdev_device *device = (struct evdev_device*)libinput_device;
> + struct motion_filter *filter;
> + double speed;
> +
> + filter = device->pointer.filter;
> + if (filter_get_type(filter) == profile)
> + return LIBINPUT_CONFIG_STATUS_SUCCESS;
> +
> + speed = filter_get_speed(filter);
> + device->pointer.filter = NULL;
> +
> + if (evdev_init_accel(device, profile) == 0) {
> + evdev_accel_config_set_speed(libinput_device, speed);
> + filter_destroy(filter);
> + } else {
> + device->pointer.filter = filter;
> + }
> +
> + return LIBINPUT_CONFIG_STATUS_SUCCESS;
> +}
> +
> +static enum libinput_config_accel_profile
> +evdev_accel_config_get_profile(struct libinput_device *libinput_device)
> +{
> + struct evdev_device *device = (struct evdev_device*)libinput_device;
> +
> + return filter_get_type(device->pointer.filter);
> +}
> +
> +static enum libinput_config_accel_profile
> +evdev_accel_config_get_default_profile(struct libinput_device *libinput_device)
> +{
> + struct evdev_device *device = (struct evdev_device*)libinput_device;
> +
> + if (!device->pointer.filter)
> + return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
> +
> + /* No device has a flat profile as default */
> + return LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
> +}
> +
> int
> evdev_device_init_pointer_acceleration(struct evdev_device *device,
> struct motion_filter *filter)
> {
> device->pointer.filter = filter;
>
> - device->pointer.config.available = evdev_accel_config_available;
> - device->pointer.config.set_speed = evdev_accel_config_set_speed;
> - device->pointer.config.get_speed = evdev_accel_config_get_speed;
> - device->pointer.config.get_default_speed = evdev_accel_config_get_default_speed;
> - device->base.config.accel = &device->pointer.config;
> + if (device->base.config.accel == NULL) {
> + device->pointer.config.available = evdev_accel_config_available;
> + device->pointer.config.set_speed = evdev_accel_config_set_speed;
> + device->pointer.config.get_speed = evdev_accel_config_get_speed;
> + device->pointer.config.get_default_speed = evdev_accel_config_get_default_speed;
> + device->pointer.config.get_profiles = evdev_accel_config_get_profiles;
> + device->pointer.config.set_profile = evdev_accel_config_set_profile;
> + device->pointer.config.get_profile = evdev_accel_config_get_profile;
> + device->pointer.config.get_default_profile = evdev_accel_config_get_default_profile;
> + device->base.config.accel = &device->pointer.config;
>
> - evdev_accel_config_set_speed(&device->base,
> - evdev_accel_config_get_default_speed(&device->base));
> + evdev_accel_config_set_speed(&device->base,
> + evdev_accel_config_get_default_speed(&device->base));
> + }
>
> return 0;
> }
> @@ -1868,24 +1952,6 @@ evdev_configure_mt_device(struct evdev_device *device)
> return 0;
> }
>
> -static inline int
> -evdev_init_accel(struct evdev_device *device)
> -{
> - struct motion_filter *filter;
> -
> - if (device->tags & EVDEV_TAG_TRACKPOINT)
> - filter = create_pointer_accelerator_filter_trackpoint(device->dpi);
> - else if (device->dpi < DEFAULT_MOUSE_DPI)
> - filter = create_pointer_accelerator_filter_linear_low_dpi(device->dpi);
> - else
> - filter = create_pointer_accelerator_filter_linear(device->dpi);
> -
> - if (!filter)
> - return -1;
> -
> - return evdev_device_init_pointer_acceleration(device, filter);
> -}
> -
> static int
> evdev_configure_device(struct evdev_device *device)
> {
> @@ -1988,7 +2054,7 @@ evdev_configure_device(struct evdev_device *device)
>
> if (libevdev_has_event_code(evdev, EV_REL, REL_X) &&
> libevdev_has_event_code(evdev, EV_REL, REL_Y) &&
> - evdev_init_accel(device) == -1)
> + evdev_init_accel(device, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE) == -1)
> return -1;
>
> device->seat_caps |= EVDEV_DEVICE_POINTER;
> diff --git a/src/filter-private.h b/src/filter-private.h
> index eaf84ed..637125a 100644
> --- a/src/filter-private.h
> +++ b/src/filter-private.h
> @@ -29,6 +29,7 @@
> #include "filter.h"
>
> struct motion_filter_interface {
> + enum libinput_config_accel_profile type;
> struct normalized_coords (*filter)(
> struct motion_filter *filter,
> const struct normalized_coords *unaccelerated,
> diff --git a/src/filter.c b/src/filter.c
> index a646857..0d0b95d 100644
> --- a/src/filter.c
> +++ b/src/filter.c
> @@ -76,13 +76,14 @@ void
> filter_restart(struct motion_filter *filter,
> void *data, uint64_t time)
> {
> - filter->interface->restart(filter, data, time);
> + if (filter->interface->restart)
> + filter->interface->restart(filter, data, time);
> }
>
> void
> filter_destroy(struct motion_filter *filter)
> {
> - if (!filter)
> + if (!filter || !filter->interface->destroy)
> return;
>
> filter->interface->destroy(filter);
> @@ -101,6 +102,12 @@ filter_get_speed(struct motion_filter *filter)
> return filter->speed_adjustment;
> }
>
> +enum libinput_config_accel_profile
> +filter_get_type(struct motion_filter *filter)
> +{
> + return filter->interface->type;
> +}
> +
> /*
> * Default parameters for pointer acceleration profiles.
> */
> @@ -149,6 +156,13 @@ struct pointer_accelerator {
> double dpi_factor;
> };
>
> +struct pointer_accelerator_flat {
> + struct motion_filter base;
> +
> + double factor;
> + double dpi_factor;
> +};
> +
> static void
> feed_trackers(struct pointer_accelerator *accel,
> const struct normalized_coords *delta,
> @@ -714,6 +728,7 @@ trackpoint_accel_profile(struct motion_filter *filter,
> }
>
> struct motion_filter_interface accelerator_interface = {
> + .type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
> .filter = accelerator_filter,
> .filter_constant = accelerator_filter_noop,
> .restart = accelerator_restart,
> @@ -761,6 +776,7 @@ create_pointer_accelerator_filter_linear(int dpi)
> }
>
> struct motion_filter_interface accelerator_interface_low_dpi = {
> + .type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
> .filter = accelerator_filter_low_dpi,
> .filter_constant = accelerator_filter_noop,
> .restart = accelerator_restart,
> @@ -784,6 +800,7 @@ create_pointer_accelerator_filter_linear_low_dpi(int dpi)
> }
>
> struct motion_filter_interface accelerator_interface_touchpad = {
> + .type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
> .filter = accelerator_filter,
> .filter_constant = touchpad_constant_filter,
> .restart = accelerator_restart,
> @@ -807,6 +824,7 @@ create_pointer_accelerator_filter_touchpad(int dpi)
> }
>
> struct motion_filter_interface accelerator_interface_x230 = {
> + .type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
> .filter = accelerator_filter_x230,
> .filter_constant = accelerator_filter_constant_x230,
> .restart = accelerator_restart,
> @@ -845,6 +863,7 @@ create_pointer_accelerator_filter_lenovo_x230(int dpi)
> }
>
> struct motion_filter_interface accelerator_interface_trackpoint = {
> + .type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
> .filter = accelerator_filter_trackpoint,
> .filter_constant = accelerator_filter_noop,
> .restart = accelerator_restart,
> @@ -869,3 +888,79 @@ create_pointer_accelerator_filter_trackpoint(int dpi)
>
> return &filter->base;
> }
> +
> +static struct normalized_coords
> +accelerator_filter_flat(struct motion_filter *filter,
> + const struct normalized_coords *unaccelerated,
> + void *data, uint64_t time)
> +{
> + struct pointer_accelerator_flat *accel_filter =
> + (struct pointer_accelerator_flat *)filter;
> + double factor; /* unitless factor */
> + struct normalized_coords accelerated;
> + struct normalized_coords unnormalized;
> +
> + /* You want flat acceleration, you get flat acceleration for the
> + * device */
> + unnormalized.x = unaccelerated->x * accel_filter->dpi_factor;
> + unnormalized.y = unaccelerated->y * accel_filter->dpi_factor;
> + factor = accel_filter->factor;
> +
> + accelerated.x = factor * unnormalized.x;
> + accelerated.y = factor * unnormalized.y;
> +
> + return accelerated;
> +}
> +
> +static bool
> +accelerator_set_speed_flat(struct motion_filter *filter,
> + double speed_adjustment)
> +{
> + struct pointer_accelerator_flat *accel_filter =
> + (struct pointer_accelerator_flat *)filter;
> +
> + assert(speed_adjustment >= -1.0 && speed_adjustment <= 1.0);
> +
> + /* Speed rage is 0-200% of the nominal speed, with 0 mapping to the
> + * nominal speed. Anything above 200 is pointless, we're already
> + * skipping over ever second pixel at 200% speed.
> + */
> +
> + accel_filter->factor = 1 + speed_adjustment;
> + filter->speed_adjustment = speed_adjustment;
> +
> + return true;
> +}
> +
> +static void
> +accelerator_destroy_flat(struct motion_filter *filter)
> +{
> + struct pointer_accelerator_flat *accel =
> + (struct pointer_accelerator_flat *) filter;
> +
> + free(accel);
> +}
> +
> +struct motion_filter_interface accelerator_interface_flat = {
> + .type = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT,
> + .filter = accelerator_filter_flat,
> + .filter_constant = accelerator_filter_noop,
> + .restart = NULL,
> + .destroy = accelerator_destroy_flat,
> + .set_speed = accelerator_set_speed_flat,
> +};
> +
> +struct motion_filter *
> +create_pointer_accelerator_filter_flat(int dpi)
> +{
> + struct pointer_accelerator_flat *filter;
> +
> + filter = zalloc(sizeof *filter);
> + if (filter == NULL)
> + return NULL;
> +
> + filter->base.interface = &accelerator_interface_flat;
> + filter->dpi_factor = dpi/(double)DEFAULT_MOUSE_DPI;
> +
> + return &filter->base;
> +}
> diff --git a/src/filter.h b/src/filter.h
> index c8ade07..e156642 100644
> --- a/src/filter.h
> +++ b/src/filter.h
> @@ -74,12 +74,17 @@ filter_set_speed(struct motion_filter *filter,
> double
> filter_get_speed(struct motion_filter *filter);
>
> +enum libinput_config_accel_profile
> +filter_get_type(struct motion_filter *filter);
> +
> typedef double (*accel_profile_func_t)(struct motion_filter *filter,
> void *data,
> double velocity,
> uint64_t time);
>
> /* Pointer acceleration types */
> +struct motion_filter *
> +create_pointer_accelerator_filter_flat(int dpi);
>
> struct motion_filter *
> create_pointer_accelerator_filter_linear(int dpi);
> diff --git a/src/libinput-private.h b/src/libinput-private.h
> index 8b161cc..b5245e0 100644
> --- a/src/libinput-private.h
> +++ b/src/libinput-private.h
> @@ -148,6 +148,12 @@ struct libinput_device_config_accel {
> double speed);
> double (*get_speed)(struct libinput_device *device);
> double (*get_default_speed)(struct libinput_device *device);
> +
> + uint32_t (*get_profiles)(struct libinput_device *device);
> + enum libinput_config_status (*set_profile)(struct libinput_device *device,
> + enum libinput_config_accel_profile);
> + enum libinput_config_accel_profile (*get_profile)(struct libinput_device *device);
> + enum libinput_config_accel_profile (*get_default_profile)(struct libinput_device *device);
> };
>
> struct libinput_device_config_natural_scroll {
> diff --git a/src/libinput.c b/src/libinput.c
> index e564571..87b2c4c 100644
> --- a/src/libinput.c
> +++ b/src/libinput.c
> @@ -2212,7 +2212,6 @@ libinput_device_config_accel_set_speed(struct libinput_device *device,
>
> return device->config.accel->set_speed(device, speed);
> }
> -
> LIBINPUT_EXPORT double
> libinput_device_config_accel_get_speed(struct libinput_device *device)
> {
> @@ -2231,6 +2230,52 @@ libinput_device_config_accel_get_default_speed(struct libinput_device *device)
> return device->config.accel->get_default_speed(device);
> }
>
> +LIBINPUT_EXPORT uint32_t
> +libinput_device_config_accel_get_profiles(struct libinput_device *device)
> +{
> + if (!libinput_device_config_accel_is_available(device))
> + return 0;
> +
> + return device->config.accel->get_profiles(device);
> +}
> +
> +LIBINPUT_EXPORT enum libinput_config_accel_profile
> +libinput_device_config_accel_get_profile(struct libinput_device *device)
> +{
> + if (!libinput_device_config_accel_is_available(device))
> + return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
> +
> + return device->config.accel->get_profile(device);
> +}
> +
> +LIBINPUT_EXPORT enum libinput_config_accel_profile
> +libinput_device_config_accel_get_default_profile(struct libinput_device *device)
> +{
> + if (!libinput_device_config_accel_is_available(device))
> + return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
> +
> + return device->config.accel->get_profile(device);
> +}
> +
> +LIBINPUT_EXPORT enum libinput_config_status
> +libinput_device_config_accel_set_profile(struct libinput_device *device,
> + enum libinput_config_accel_profile profile)
> +{
> + switch (profile) {
> + case LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT:
> + case LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE:
> + break;
> + default:
> + return LIBINPUT_CONFIG_STATUS_INVALID;
> + }
> +
> + if (!libinput_device_config_accel_is_available(device) ||
> + (libinput_device_config_accel_get_profiles(device) & profile) == 0)
> + return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
> +
> + return device->config.accel->set_profile(device, profile);
> +}
> +
> LIBINPUT_EXPORT int
> libinput_device_config_scroll_has_natural_scroll(struct libinput_device *device)
> {
> diff --git a/src/libinput.h b/src/libinput.h
> index 898d26e..9057446 100644
> --- a/src/libinput.h
> +++ b/src/libinput.h
> @@ -2549,6 +2549,80 @@ libinput_device_config_accel_get_speed(struct libinput_device *device);
> double
> libinput_device_config_accel_get_default_speed(struct libinput_device *device);
>
> +enum libinput_config_accel_profile {
> + /**
> + * Placeholder for devices that don't have a configurable pointer
> + * acceleration profile.
> + */
> + LIBINPUT_CONFIG_ACCEL_PROFILE_NONE = 0,
> + /**
> + * A flat acceleration profile. Pointer motion is accelerated by a
> + * constant (device-specific) factor, depending on the current
> + * speed.
> + *
> + * @see libinput_device_config_accel_set_speed
> + */
> + LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT = (1 << 0),
> +
> + /**
> + * An adaptive acceleration profile. Pointer acceleration depends
> + * on the input speed. This is the default profile for most devices.
> + */
> + LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE = (1 << 1),
> +};
> +
> +/**
> + * @ingroup config
> + *
> + * Returns a bitmask of the configurable acceleration modes available on
> + * this device.
> + *
> + * @param device The device to configure
> + *
> + * @return A bitmask of all configurable modes availble on this device.
> + */
> +uint32_t
> +libinput_device_config_accel_get_profiles(struct libinput_device *device);
> +
> +/**
> + * @ingroup config
> + *
> + * Set the pointer acceleration profile of this pointer device to the given
> + * mode.
> + *
> + * @param device The device to configure
> + * @param mode The mode to set the device to.
> + *
> + * @return A config status code
> + */
> +enum libinput_config_status
> +libinput_device_config_accel_set_profile(struct libinput_device *device,
> + enum libinput_config_accel_profile mode);
> +
> +/**
> + * @ingroup config
> + *
> + * Get the current pointer acceleration profile for this pointer device.
> + *
> + * @param device The device to configure
> + *
> + * @return The currently configured pointer acceleration profile.
> + */
> +enum libinput_config_accel_profile
> +libinput_device_config_accel_get_profile(struct libinput_device *device);
> +
> +/**
> + * @ingroup config
> + *
> + * Return the default pointer acceleration profile for this pointer device.
> + *
> + * @param device The device to configure
> + *
> + * @return The default acceleration profile for this device.
> + */
> +enum libinput_config_accel_profile
> +libinput_device_config_accel_get_default_profile(struct libinput_device *device);
> +
> /**
> * @ingroup config
> *
> diff --git a/src/libinput.sym b/src/libinput.sym
> index 7e0ef1c..15203c8 100644
> --- a/src/libinput.sym
> +++ b/src/libinput.sym
> @@ -172,3 +172,10 @@ LIBINPUT_0.21.0 {
> libinput_event_pointer_get_time_usec;
> libinput_event_touch_get_time_usec;
> } LIBINPUT_0.20.0;
> +
> +LIBINPUT_1.1 {
> + libinput_device_config_accel_get_profile;
> + libinput_device_config_accel_get_profiles;
> + libinput_device_config_accel_get_default_profile;
> + libinput_device_config_accel_set_profile;
> +} LIBINPUT_0.21.0;
> diff --git a/test/pointer.c b/test/pointer.c
> index f711d38..e12034a 100644
> --- a/test/pointer.c
> +++ b/test/pointer.c
> @@ -1029,6 +1029,116 @@ START_TEST(pointer_accel_direction_change)
> }
> END_TEST
>
> +START_TEST(pointer_accel_profile_defaults)
> +{
> + struct litest_device *dev = litest_current_device();
> + struct libinput_device *device = dev->libinput_device;
> + enum libinput_config_status status;
> + enum libinput_config_accel_profile profile;
> + uint32_t profiles;
> +
> + ck_assert(libinput_device_config_accel_is_available(device));
> +
> + profile = libinput_device_config_accel_get_default_profile(device);
> + ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
> +
> + profile = libinput_device_config_accel_get_profile(device);
> + ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
> +
> + profiles = libinput_device_config_accel_get_profiles(device);
> + ck_assert(profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
> + ck_assert(profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
> +
> + status = libinput_device_config_accel_set_profile(device,
> + LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
> + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
> + profile = libinput_device_config_accel_get_profile(device);
> + ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
> +
> + status = libinput_device_config_accel_set_profile(device,
> + LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
> + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
> + profile = libinput_device_config_accel_get_profile(device);
> + ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
> +}
> +END_TEST
> +
> +START_TEST(pointer_accel_profile_defaults_noprofile)
> +{
> + struct litest_device *dev = litest_current_device();
> + struct libinput_device *device = dev->libinput_device;
> + enum libinput_config_status status;
> + enum libinput_config_accel_profile profile;
> + uint32_t profiles;
> +
> + ck_assert(libinput_device_config_accel_is_available(device));
> +
> + profile = libinput_device_config_accel_get_default_profile(device);
> + ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
> +
> + profile = libinput_device_config_accel_get_profile(device);
> + ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
> +
> + profiles = libinput_device_config_accel_get_profiles(device);
> + ck_assert_int_eq(profiles, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
> +
> + status = libinput_device_config_accel_set_profile(device,
> + LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
> + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
> + profile = libinput_device_config_accel_get_profile(device);
> + ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
> +
> + status = libinput_device_config_accel_set_profile(device,
> + LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
> + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
> + profile = libinput_device_config_accel_get_profile(device);
> + ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
> +}
> +END_TEST
> +
> +START_TEST(pointer_accel_profile_invalid)
> +{
> + struct litest_device *dev = litest_current_device();
> + struct libinput_device *device = dev->libinput_device;
> + enum libinput_config_status status;
> +
> + ck_assert(libinput_device_config_accel_is_available(device));
> +
> + status = libinput_device_config_accel_set_profile(device,
> + LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
> + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
> +
> + status = libinput_device_config_accel_set_profile(device,
> + LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE + 1);
> + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
> +
> + status = libinput_device_config_accel_set_profile(device,
> + LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE |LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
> + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
> +}
> +END_TEST
> +
> +START_TEST(pointer_accel_profile_flat_motion_relative)
> +{
> + struct litest_device *dev = litest_current_device();
> + struct libinput_device *device = dev->libinput_device;
> +
> + libinput_device_config_accel_set_profile(device,
> + LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
> + litest_drain_events(dev->libinput);
> +
> + test_relative_event(dev, 1, 0);
> + test_relative_event(dev, 1, 1);
> + test_relative_event(dev, 1, -1);
> + test_relative_event(dev, 0, 1);
> +
> + test_relative_event(dev, -1, 0);
> + test_relative_event(dev, -1, 1);
> + test_relative_event(dev, -1, -1);
> + test_relative_event(dev, 0, -1);
> +}
> +END_TEST
> +
> START_TEST(middlebutton)
> {
> struct litest_device *device = litest_current_device();
> @@ -1479,6 +1589,10 @@ litest_setup_tests(void)
> litest_add("pointer:accel", pointer_accel_defaults_absolute, LITEST_ABSOLUTE, LITEST_RELATIVE);
> litest_add("pointer:accel", pointer_accel_defaults_absolute_relative, LITEST_ABSOLUTE|LITEST_RELATIVE, LITEST_ANY);
> litest_add("pointer:accel", pointer_accel_direction_change, LITEST_RELATIVE, LITEST_ANY);
> + litest_add("pointer:accel", pointer_accel_profile_defaults, LITEST_RELATIVE, LITEST_TOUCHPAD);
> + litest_add("pointer:accel", pointer_accel_profile_defaults_noprofile, LITEST_TOUCHPAD, LITEST_ANY);
> + litest_add("pointer:accel", pointer_accel_profile_invalid, LITEST_RELATIVE, LITEST_ANY);
> + litest_add("pointer:accel", pointer_accel_profile_flat_motion_relative, LITEST_RELATIVE, LITEST_TOUCHPAD);
>
> litest_add("pointer:middlebutton", middlebutton, LITEST_BUTTON, LITEST_ANY);
> litest_add("pointer:middlebutton", middlebutton_timeout, LITEST_BUTTON, LITEST_ANY);
> diff --git a/tools/libinput-list-devices.c b/tools/libinput-list-devices.c
> index c156bf0..21685d9 100644
> --- a/tools/libinput-list-devices.c
> +++ b/tools/libinput-list-devices.c
> @@ -172,6 +172,35 @@ click_defaults(struct libinput_device *device)
> return str;
> }
>
> +static char*
> +accel_profiles(struct libinput_device *device)
> +{
> + uint32_t profiles;
> + char *str;
> + enum libinput_config_accel_profile profile;
> +
> + if (!libinput_device_config_accel_is_available(device)) {
> + xasprintf(&str, "n/a");
> + return str;
> + }
> +
> + profiles = libinput_device_config_accel_get_profiles(device);
> + if (profiles == LIBINPUT_CONFIG_ACCEL_PROFILE_NONE) {
> + xasprintf(&str, "none");
> + return str;
> + }
> +
> + profile = libinput_device_config_accel_get_default_profile(device);
> + xasprintf(&str,
> + "%s%s%s%s",
> + (profile == LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT) ? "*" : "",
> + (profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT) ? "flat" : "",
> + (profile == LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE) ? "*" : "",
> + (profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE) ? "adaptive" : "");
> +
> + return str;
> +}
> +
> static const char *
> dwt_default(struct libinput_device *device)
> {
> @@ -249,6 +278,10 @@ print_device_notify(struct libinput_event *ev)
>
> printf("Disable-w-typing: %s\n", dwt_default(dev));
>
> + str = accel_profiles(dev);
> + printf("Accel profiles: %s\n", str);
> + free(str);
> +
> printf("\n");
> }
>
> diff --git a/tools/shared.c b/tools/shared.c
> index 9dba955..5fe5862 100644
> --- a/tools/shared.c
> +++ b/tools/shared.c
> @@ -59,6 +59,7 @@ enum options {
> OPT_SCROLL_METHOD,
> OPT_SCROLL_BUTTON,
> OPT_SPEED,
> + OPT_PROFILE,
> };
>
> static void
> @@ -94,6 +95,7 @@ tools_usage()
> "--set-click-method=[none|clickfinger|buttonareas] .... set the desired click method\n"
> "--set-scroll-method=[none|twofinger|edge|button] ... set the desired scroll method\n"
> "--set-scroll-button=BTN_MIDDLE ... set the button to the given button code\n"
> + "--set-profile=[adaptive|flat].... set pointer acceleration profile\n"
> "--set-speed=<value>.... set pointer acceleration speed\n"
> "\n"
> "These options apply to all applicable devices, if a feature\n"
> @@ -126,6 +128,7 @@ tools_init_context(struct tools_context *context)
> options->backend = BACKEND_UDEV;
> options->seat = "seat0";
> options->speed = 0.0;
> + options->profile = LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
> }
>
> int
> @@ -157,6 +160,7 @@ tools_parse_args(int argc, char **argv, struct tools_context *context)
> { "set-click-method", 1, 0, OPT_CLICK_METHOD },
> { "set-scroll-method", 1, 0, OPT_SCROLL_METHOD },
> { "set-scroll-button", 1, 0, OPT_SCROLL_BUTTON },
> + { "set-profile", 1, 0, OPT_PROFILE },
> { "speed", 1, 0, OPT_SPEED },
> { 0, 0, 0, 0}
> };
> @@ -288,6 +292,20 @@ tools_parse_args(int argc, char **argv, struct tools_context *context)
> }
> options->speed = atof(optarg);
> break;
> + case OPT_PROFILE:
> + if (!optarg) {
> + tools_usage();
> + return 1;
> + }
> + if (streq(optarg, "adaptive")) {
> + options->profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
> + } else if (streq(optarg, "flat")) {
> + options->profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT;
> + } else {
> + tools_usage();
> + return 1;
> + }
> + break;
> default:
> tools_usage();
> return 1;
> @@ -445,7 +463,11 @@ tools_device_apply_config(struct libinput_device *device,
> libinput_device_config_scroll_set_button(device,
> options->scroll_button);
>
> - if (libinput_device_config_accel_is_available(device))
> + if (libinput_device_config_accel_is_available(device)) {
> libinput_device_config_accel_set_speed(device,
> options->speed);
> + if (options->profile != LIBINPUT_CONFIG_ACCEL_PROFILE_NONE)
> + libinput_device_config_accel_set_profile(device,
> + options->profile);
> + }
> }
> diff --git a/tools/shared.h b/tools/shared.h
> index a9cf6d9..0065fcc 100644
> --- a/tools/shared.h
> +++ b/tools/shared.h
> @@ -48,6 +48,7 @@ struct tools_options {
> int scroll_button;
> double speed;
> int dwt;
> + enum libinput_config_accel_profile profile;
> };
>
> struct tools_context {
>
More information about the wayland-devel
mailing list