[PATCH libinput 2/2] filter: normalize deltas before processing or returning them

Peter Hutterer peter.hutterer at who-t.net
Thu Jan 19 02:34:45 UTC 2017


When the filter code switched to raw device coordinates (bdd4264d) the input
data remained in device coordinates. Since the factor for touchpads was still
based on the physical velocity (and thus all touchpads get the same
acceleration factor for identical moves), the actual delta was dependent on
the resolution. e.g.

touchpad with 40u/mm: delta of 2/2 * accel factor 2 -> accel delta of 4/4
touchpad with 20u/mm: delta of 1/1 * accel factor 2 -> accel delta of 2/2

The normalized coordinates should be independent of the touchpad's resolution
though.

Affected by this was the standard mouse accel code and the touchpad accel
code, other filters always returned unnormalized coordinates (separate bug,
not addressed here).

This patch restores the correct behaviour for mice and touchpads
while leaving the special filters untouched. For comparision:
* 1000+dpi mice: accelerate normalized, return normalized
* touchpads: accelerate unnormalized, return normalized
* low-dpi mice: accelerate unnormalized, return unnormalized
* trackpoints: accelerate unnormalized, return unnormalized
* x230: don't touch, already does the right thing

https://bugs.freedesktop.org/show_bug.cgi?id=99383

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
Obviously there's a bit more cleanup needed, but I'll leave that for
after 1.6

 src/filter.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 68 insertions(+), 8 deletions(-)

diff --git a/src/filter.c b/src/filter.c
index 3035234..7c500f8 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -405,10 +405,10 @@ calculate_acceleration_factor(struct pointer_accelerator *accel,
  * @param data Caller-specific data
  * @param time Current time in ┬Ás
  *
- * @return An accelerated tuple of coordinates representing normalized
- * motion
+ * @return An accelerated tuple of coordinates representing accelerated
+ * motion, still in device units.
  */
-static struct normalized_coords
+static struct device_float_coords
 accelerator_filter_generic(struct motion_filter *filter,
 			   const struct device_float_coords *unaccelerated,
 			   void *data, uint64_t time)
@@ -416,7 +416,7 @@ accelerator_filter_generic(struct motion_filter *filter,
 	struct pointer_accelerator *accel =
 		(struct pointer_accelerator *) filter;
 	double accel_value; /* unitless factor */
-	struct normalized_coords accelerated;
+	struct device_float_coords accelerated;
 
 	accel_value = calculate_acceleration_factor(accel,
 						    unaccelerated,
@@ -429,6 +429,66 @@ accelerator_filter_generic(struct motion_filter *filter,
 	return accelerated;
 }
 
+static struct normalized_coords
+accelerator_filter_post_normalized(struct motion_filter *filter,
+				   const struct device_float_coords *unaccelerated,
+				   void *data, uint64_t time)
+{
+	struct pointer_accelerator *accel =
+		(struct pointer_accelerator *) filter;
+	struct device_float_coords accelerated;
+
+	/* Accelerate for device units, normalize afterwards */
+	accelerated = accelerator_filter_generic(filter,
+						 unaccelerated,
+						 data,
+						 time);
+	return normalize_for_dpi(&accelerated, accel->dpi);
+}
+
+static struct normalized_coords
+accelerator_filter_pre_normalized(struct motion_filter *filter,
+				  const struct device_float_coords *unaccelerated,
+				  void *data, uint64_t time)
+{
+	struct pointer_accelerator *accel =
+		(struct pointer_accelerator *) filter;
+	struct normalized_coords normalized;
+	struct device_float_coords converted, accelerated;
+
+	/* Accelerate for normalized units and return normalized units.
+	   API requires device_floats, so we just copy the bits around */
+	normalized = normalize_for_dpi(unaccelerated, accel->dpi);
+	converted.x = normalized.x;
+	converted.y = normalized.y;
+
+	accelerated = accelerator_filter_generic(filter,
+						 &converted,
+						 data,
+						 time);
+	normalized.x = accelerated.x;
+	normalized.y = accelerated.y;
+	return normalized;
+}
+
+static struct normalized_coords
+accelerator_filter_unnormalized(struct motion_filter *filter,
+				const struct device_float_coords *unaccelerated,
+				void *data, uint64_t time)
+{
+	struct device_float_coords accelerated;
+	struct normalized_coords normalized;
+
+	/* Accelerate for device units and return device units */
+	accelerated = accelerator_filter_generic(filter,
+						 unaccelerated,
+						 data,
+						 time);
+	normalized.x = accelerated.x;
+	normalized.y = accelerated.y;
+	return normalized;
+}
+
 /**
  * Generic filter that does nothing beyond converting from the device's
  * native dpi into normalized coordinates.
@@ -878,7 +938,7 @@ trackpoint_accel_profile(struct motion_filter *filter,
 
 struct motion_filter_interface accelerator_interface = {
 	.type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
-	.filter = accelerator_filter_generic,
+	.filter = accelerator_filter_pre_normalized,
 	.filter_constant = accelerator_filter_noop,
 	.restart = accelerator_restart,
 	.destroy = accelerator_destroy,
@@ -925,7 +985,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_generic,
+	.filter = accelerator_filter_unnormalized,
 	.filter_constant = accelerator_filter_noop,
 	.restart = accelerator_restart,
 	.destroy = accelerator_destroy,
@@ -949,7 +1009,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_generic,
+	.filter = accelerator_filter_post_normalized,
 	.filter_constant = touchpad_constant_filter,
 	.restart = accelerator_restart,
 	.destroy = accelerator_destroy,
@@ -1011,7 +1071,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_generic,
+	.filter = accelerator_filter_unnormalized,
 	.filter_constant = accelerator_filter_noop,
 	.restart = accelerator_restart,
 	.destroy = accelerator_destroy,
-- 
2.9.3



More information about the wayland-devel mailing list