diff options
-rw-r--r-- | doc/pointer-acceleration.dox | 17 | ||||
-rw-r--r-- | src/evdev-mt-touchpad.c | 40 | ||||
-rw-r--r-- | src/evdev.c | 118 | ||||
-rw-r--r-- | src/filter-private.h | 1 | ||||
-rw-r--r-- | src/filter.c | 99 | ||||
-rw-r--r-- | src/filter.h | 5 | ||||
-rw-r--r-- | src/libinput-private.h | 6 | ||||
-rw-r--r-- | src/libinput.c | 47 | ||||
-rw-r--r-- | src/libinput.h | 74 | ||||
-rw-r--r-- | src/libinput.sym | 7 | ||||
-rw-r--r-- | test/pointer.c | 114 | ||||
-rw-r--r-- | tools/libinput-list-devices.c | 33 | ||||
-rw-r--r-- | tools/shared.c | 24 | ||||
-rw-r--r-- | 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. +@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. +@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 080e0a1..aef0456 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 be99af5..e146c26 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -150,6 +150,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 b88bab1..f5c75b0 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -2245,7 +2245,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) { @@ -2264,6 +2263,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 { |