diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2015-08-27 13:13:47 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2015-09-11 00:54:01 +1000 |
commit | 8d9e7a1bcf8eac3a344d8c1135b2b546c37e8b04 (patch) | |
tree | 72229c2a0e52505bfc90f8f3ea2063ead02fd3a4 /src/filter.c | |
parent | 0c7ef582ebeceb567b2972de2163e9156c7b6283 (diff) |
Add an API to change pointer acceleration profiles
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@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'src/filter.c')
-rw-r--r-- | src/filter.c | 99 |
1 files changed, 97 insertions, 2 deletions
diff --git a/src/filter.c b/src/filter.c index a6468579..0d0b95d4 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; +} |