[PATCH libinput 01/10] Replace pointer acceleration with a much simpler linear one

Peter Hutterer peter.hutterer at who-t.net
Thu Sep 18 22:44:26 PDT 2014


We ran a userstudy, evaluating three different accel methods. Detailed results are
available at:
http://www.who-t.net/publications/hutterer2014_libinput_ptraccel_study.pdf

We found that there was little difference between the method we had in
libinput 0.6 and this three-line function. Users didn't really notice a
difference, but measured data suggests that it has slight advantages in some
use-cases.

The method proposed here is the one labeled "linear" in the paper, its profile
looks roughly like this:

        _____________
       /
  ____/
 /
/

where the x axis is the speed, y is the acceleration factor.
The first plateau is at the acceleration factor 1 (i.e. unaccelerated
movement), the second plateau is at the max acceleration factor. The threshold
in the code defines where and how long the plateau is.

Differences to the previous accel function:
- both inclines are linear rather than curved
- the second incline is less steep than the current method

>From a maintainer's point-of-view, this function is significantly easier to
understand and manipulate than the previous one.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev-mt-touchpad.c |  2 +-
 src/evdev.c             |  2 +-
 src/filter.c            | 43 +++++++++----------------------------------
 src/filter.h            | 13 ++++---------
 4 files changed, 15 insertions(+), 45 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 70a4e40..0b51809 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -841,7 +841,7 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
 	}
 
 	accel = create_pointer_accelator_filter(
-			pointer_accel_profile_smooth_simple);
+			pointer_accel_profile_linear);
 	if (accel == NULL)
 		return -1;
 
diff --git a/src/evdev.c b/src/evdev.c
index 4e9db2f..de7ee16 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -865,7 +865,7 @@ configure_pointer_acceleration(struct evdev_device *device)
 {
 	device->pointer.filter =
 		create_pointer_accelator_filter(
-			pointer_accel_profile_smooth_simple);
+			pointer_accel_profile_linear);
 	if (!device->pointer.filter)
 		return -1;
 
diff --git a/src/filter.c b/src/filter.c
index d65adfb..804058a 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -270,41 +270,16 @@ calc_penumbral_gradient(double x)
 }
 
 double
-pointer_accel_profile_smooth_simple(struct motion_filter *filter,
-				    void *data,
-				    double velocity, /* units/ms */
-				    uint64_t time)
+pointer_accel_profile_linear(struct motion_filter *filter,
+			     void *data,
+			     double speed_in,
+			     uint64_t time)
 {
-	double threshold = DEFAULT_THRESHOLD; /* units/ms */
-	double accel = DEFAULT_ACCELERATION; /* unitless factor */
-	double smooth_accel_coefficient; /* unitless factor */
-	double factor; /* unitless factor */
+	double s1, s2;
+	const int max_accel = DEFAULT_ACCELERATION;
 
-	if (threshold < 0.1)
-		threshold = 0.1;
-	if (accel < 1.0)
-		accel = 1.0;
+	s1 = min(1, speed_in * 5);
+	s2 = 1 + (speed_in - DEFAULT_THRESHOLD) * 1.1;
 
-	/* We use units/ms as velocity but it has no real meaning unless all
-	   devices have the same resolution. For touchpads, we normalize to
-	   400dpi (15.75 units/mm), but the resolution on USB mice is all
-	   over the place. Though most mice these days have either 400
-	   dpi (15.75 units/mm), 800 dpi or 1000dpi, excluding gaming mice
-	   that can usually adjust it on the fly anyway and currently go up
-	   to 8200dpi.
-	  */
-	if (velocity < (threshold / 2.0))
-		return calc_penumbral_gradient(0.5 + velocity / threshold) * 2.0 - 1.0;
-
-	if (velocity <= threshold)
-		return 1.0;
-
-	factor = velocity/threshold;
-	if (factor >= accel)
-		return accel;
-
-	/* factor is between 1.0 and accel, scale this to 0.0 - 1.0 */
-	factor = (factor - 1.0) / (accel - 1.0);
-	smooth_accel_coefficient = calc_penumbral_gradient(factor);
-	return 1.0 + (smooth_accel_coefficient * (accel - 1.0));
+	return min(max_accel, s2 > 1 ? s2 : s1);
 }
diff --git a/src/filter.h b/src/filter.h
index 8553495..be48838 100644
--- a/src/filter.h
+++ b/src/filter.h
@@ -65,14 +65,9 @@ create_pointer_accelator_filter(accel_profile_func_t filter);
  * Pointer acceleration profiles.
  */
 
-/*
- * Profile similar which is similar to nonaccelerated but with a smooth
- * transition between accelerated and non-accelerated.
- */
 double
-pointer_accel_profile_smooth_simple(struct motion_filter *filter,
-				    void *data,
-				    double velocity,
-				    uint64_t time);
-
+pointer_accel_profile_linear(struct motion_filter *filter,
+			     void *data,
+			     double speed_in,
+			     uint64_t time);
 #endif /* FILTER_H */
-- 
1.9.3



More information about the wayland-devel mailing list