summaryrefslogtreecommitdiff
path: root/src/filter.c
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2015-08-27 13:13:47 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2015-09-11 00:54:01 +1000
commit8d9e7a1bcf8eac3a344d8c1135b2b546c37e8b04 (patch)
tree72229c2a0e52505bfc90f8f3ea2063ead02fd3a4 /src/filter.c
parent0c7ef582ebeceb567b2972de2163e9156c7b6283 (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.c99
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;
+}