[PATCH libinput 18/23] filter: split the mouse acceleration out into a separate file

Peter Hutterer peter.hutterer at who-t.net
Thu Apr 12 06:34:44 UTC 2018


Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 meson.build        |   1 +
 src/filter-mouse.c | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/filter.c       | 297 +-----------------------------------------------
 3 files changed, 329 insertions(+), 295 deletions(-)
 create mode 100644 src/filter-mouse.c

diff --git a/meson.build b/meson.build
index 9473dc12..25bccee0 100644
--- a/meson.build
+++ b/meson.build
@@ -153,6 +153,7 @@ src_libfilter = [
 		'src/filter.c',
 		'src/filter-flat.c',
 		'src/filter-low-dpi.c',
+		'src/filter-mouse.c',
 		'src/filter-touchpad.c',
 		'src/filter-touchpad-x230.c',
 		'src/filter-tablet.c',
diff --git a/src/filter-mouse.c b/src/filter-mouse.c
new file mode 100644
index 00000000..94794c17
--- /dev/null
+++ b/src/filter-mouse.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright © 2006-2009 Simon Thum
+ * Copyright © 2012 Jonas Ådahl
+ * Copyright © 2014-2015 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include <math.h>
+
+#include "filter.h"
+#include "libinput-util.h"
+#include "filter-private.h"
+
+/*
+ * Default parameters for pointer acceleration profiles.
+ */
+
+#define DEFAULT_THRESHOLD v_ms2us(0.4)		/* in units/us */
+#define MINIMUM_THRESHOLD v_ms2us(0.2)		/* in units/us */
+#define DEFAULT_ACCELERATION 2.0		/* unitless factor */
+#define DEFAULT_INCLINE 1.1			/* unitless factor */
+
+/**
+ * Calculate the acceleration factor for the given delta with the timestamp.
+ *
+ * @param accel The acceleration filter
+ * @param unaccelerated The raw delta in the device's dpi
+ * @param data Caller-specific data
+ * @param time Current time in µs
+ *
+ * @return A unitless acceleration factor, to be applied to the delta
+ */
+static inline double
+calculate_acceleration_factor(struct pointer_accelerator *accel,
+			      const struct device_float_coords *unaccelerated,
+			      void *data,
+			      uint64_t time)
+{
+	double velocity; /* units/us in device-native dpi*/
+	double accel_factor;
+
+	feed_trackers(&accel->trackers, unaccelerated, time);
+	velocity = calculate_velocity(&accel->trackers, time);
+	accel_factor = calculate_acceleration_simpsons(&accel->base,
+						       accel->profile,
+						       data,
+						       velocity,
+						       accel->last_velocity,
+						       time);
+	accel->last_velocity = velocity;
+
+	return accel_factor;
+}
+
+/**
+ * Generic filter that calculates the acceleration factor and applies it to
+ * the coordinates.
+ *
+ * @param filter The acceleration filter
+ * @param unaccelerated The raw delta in the device's dpi
+ * @param data Caller-specific data
+ * @param time Current time in µs
+ *
+ * @return An accelerated tuple of coordinates representing accelerated
+ * motion, still in device units.
+ */
+static struct device_float_coords
+accelerator_filter_generic(struct motion_filter *filter,
+			   const struct device_float_coords *unaccelerated,
+			   void *data, uint64_t time)
+{
+	struct pointer_accelerator *accel =
+		(struct pointer_accelerator *) filter;
+	double accel_value; /* unitless factor */
+	struct device_float_coords accelerated;
+
+	accel_value = calculate_acceleration_factor(accel,
+						    unaccelerated,
+						    data,
+						    time);
+
+	accelerated.x = accel_value * unaccelerated->x;
+	accelerated.y = accel_value * unaccelerated->y;
+
+	return accelerated;
+}
+
+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;
+}
+
+/**
+ * Generic filter that does nothing beyond converting from the device's
+ * native dpi into normalized coordinates.
+ *
+ * @param filter The acceleration filter
+ * @param unaccelerated The raw delta in the device's dpi
+ * @param data Caller-specific data
+ * @param time Current time in µs
+ *
+ * @return An accelerated tuple of coordinates representing normalized
+ * motion
+ */
+static struct normalized_coords
+accelerator_filter_noop(struct motion_filter *filter,
+			const struct device_float_coords *unaccelerated,
+			void *data, uint64_t time)
+{
+	struct pointer_accelerator *accel =
+		(struct pointer_accelerator *) filter;
+
+	return normalize_for_dpi(unaccelerated, accel->dpi);
+}
+
+static void
+accelerator_restart(struct motion_filter *filter,
+		    void *data,
+		    uint64_t time)
+{
+	struct pointer_accelerator *accel =
+		(struct pointer_accelerator *) filter;
+
+	reset_trackers(&accel->trackers, time);
+}
+
+static void
+accelerator_destroy(struct motion_filter *filter)
+{
+	struct pointer_accelerator *accel =
+		(struct pointer_accelerator *) filter;
+
+	free_trackers(&accel->trackers);
+	free(accel);
+}
+
+static bool
+accelerator_set_speed(struct motion_filter *filter,
+		      double speed_adjustment)
+{
+	struct pointer_accelerator *accel_filter =
+		(struct pointer_accelerator *)filter;
+
+	assert(speed_adjustment >= -1.0 && speed_adjustment <= 1.0);
+
+	/* Note: the numbers below are nothing but trial-and-error magic,
+	   don't read more into them other than "they mostly worked ok" */
+
+	/* delay when accel kicks in */
+	accel_filter->threshold = DEFAULT_THRESHOLD -
+					v_ms2us(0.25) * speed_adjustment;
+	if (accel_filter->threshold < MINIMUM_THRESHOLD)
+		accel_filter->threshold = MINIMUM_THRESHOLD;
+
+	/* adjust max accel factor */
+	accel_filter->accel = DEFAULT_ACCELERATION + speed_adjustment * 1.5;
+
+	/* higher speed -> faster to reach max */
+	accel_filter->incline = DEFAULT_INCLINE + speed_adjustment * 0.75;
+
+	filter->speed_adjustment = speed_adjustment;
+	return true;
+}
+
+double
+pointer_accel_profile_linear(struct motion_filter *filter,
+			     void *data,
+			     double speed_in, /* in device units (units/µs) */
+			     uint64_t time)
+{
+	struct pointer_accelerator *accel_filter =
+		(struct pointer_accelerator *)filter;
+	const double max_accel = accel_filter->accel; /* unitless factor */
+	const double threshold = accel_filter->threshold; /* units/us */
+	const double incline = accel_filter->incline;
+	double factor; /* unitless */
+
+	/* Normalize to 1000dpi, because the rest below relies on that */
+	speed_in = speed_in * DEFAULT_MOUSE_DPI/accel_filter->dpi;
+
+	/*
+	   Our acceleration function calculates a factor to accelerate input
+	   deltas with. The function is a double incline with a plateau,
+	   with a rough shape like this:
+
+	  accel
+	 factor
+	   ^
+	   |        /
+	   |  _____/
+	   | /
+	   |/
+	   +-------------> speed in
+
+	   The two inclines are linear functions in the form
+		   y = ax + b
+		   where y is speed_out
+		         x is speed_in
+			 a is the incline of acceleration
+			 b is minimum acceleration factor
+
+	   for speeds up to 0.07 u/ms, we decelerate, down to 30% of input
+	   speed.
+		   hence 1 = a * 0.07 + 0.3
+		       0.7 = a * 0.07 => a := 10
+		   deceleration function is thus:
+			y = 10x + 0.3
+
+	  Note:
+	  * 0.07u/ms as threshold is a result of trial-and-error and
+	    has no other intrinsic meaning.
+	  * 0.3 is chosen simply because it is above the Nyquist frequency
+	    for subpixel motion within a pixel.
+	*/
+	if (v_us2ms(speed_in) < 0.07) {
+		factor = 10 * v_us2ms(speed_in) + 0.3;
+	/* up to the threshold, we keep factor 1, i.e. 1:1 movement */
+	} else if (speed_in < threshold) {
+		factor = 1;
+
+	} else {
+	/* Acceleration function above the threshold:
+		y = ax' + b
+		where T is threshold
+		      x is speed_in
+		      x' is speed
+	        and
+			y(T) == 1
+		hence 1 = ax' + 1
+			=> x' := (x - T)
+	 */
+		factor = incline * v_us2ms(speed_in - threshold) + 1;
+	}
+
+	/* Cap at the maximum acceleration factor */
+	factor = min(max_accel, factor);
+
+	return factor;
+}
+
+struct motion_filter_interface accelerator_interface = {
+	.type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
+	.filter = accelerator_filter_pre_normalized,
+	.filter_constant = accelerator_filter_noop,
+	.restart = accelerator_restart,
+	.destroy = accelerator_destroy,
+	.set_speed = accelerator_set_speed,
+};
+
+static struct pointer_accelerator *
+create_default_filter(int dpi)
+{
+	struct pointer_accelerator *filter;
+
+	filter = zalloc(sizeof *filter);
+	filter->last_velocity = 0.0;
+
+	init_trackers(&filter->trackers);
+
+	filter->threshold = DEFAULT_THRESHOLD;
+	filter->accel = DEFAULT_ACCELERATION;
+	filter->incline = DEFAULT_INCLINE;
+	filter->dpi = dpi;
+
+	return filter;
+}
+
+struct motion_filter *
+create_pointer_accelerator_filter_linear(int dpi)
+{
+	struct pointer_accelerator *filter;
+
+	filter = create_default_filter(dpi);
+	if (!filter)
+		return NULL;
+
+	filter->base.interface = &accelerator_interface;
+	filter->profile = pointer_accel_profile_linear;
+
+	return &filter->base;
+}
diff --git a/src/filter.c b/src/filter.c
index d7709838..48a9e8cc 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -36,6 +36,8 @@
 #include "libinput-util.h"
 #include "filter-private.h"
 
+#define MOTION_TIMEOUT		ms2us(1000)
+
 struct normalized_coords
 filter_dispatch(struct motion_filter *filter,
 		const struct device_float_coords *unaccelerated,
@@ -88,21 +90,6 @@ filter_get_type(struct motion_filter *filter)
 	return filter->interface->type;
 }
 
-/*
- * Default parameters for pointer acceleration profiles.
- */
-
-#define DEFAULT_THRESHOLD v_ms2us(0.4)		/* in units/us */
-#define MINIMUM_THRESHOLD v_ms2us(0.2)		/* in units/us */
-#define DEFAULT_ACCELERATION 2.0		/* unitless factor */
-#define DEFAULT_INCLINE 1.1			/* unitless factor */
-
-/*
- * Pointer acceleration filter constants
- */
-
-#define MOTION_TIMEOUT		ms2us(1000)
-
 void
 init_trackers(struct pointer_trackers *trackers)
 {
@@ -310,283 +297,3 @@ calculate_acceleration_simpsons(struct motion_filter *filter,
 
 	return factor; /* unitless factor */
 }
-
-/**
- * Calculate the acceleration factor for the given delta with the timestamp.
- *
- * @param accel The acceleration filter
- * @param unaccelerated The raw delta in the device's dpi
- * @param data Caller-specific data
- * @param time Current time in µs
- *
- * @return A unitless acceleration factor, to be applied to the delta
- */
-static inline double
-calculate_acceleration_factor(struct pointer_accelerator *accel,
-			      const struct device_float_coords *unaccelerated,
-			      void *data,
-			      uint64_t time)
-{
-	double velocity; /* units/us in device-native dpi*/
-	double accel_factor;
-
-	feed_trackers(&accel->trackers, unaccelerated, time);
-	velocity = calculate_velocity(&accel->trackers, time);
-	accel_factor = calculate_acceleration_simpsons(&accel->base,
-						       accel->profile,
-						       data,
-						       velocity,
-						       accel->last_velocity,
-						       time);
-	accel->last_velocity = velocity;
-
-	return accel_factor;
-}
-
-/**
- * Generic filter that calculates the acceleration factor and applies it to
- * the coordinates.
- *
- * @param filter The acceleration filter
- * @param unaccelerated The raw delta in the device's dpi
- * @param data Caller-specific data
- * @param time Current time in µs
- *
- * @return An accelerated tuple of coordinates representing accelerated
- * motion, still in device units.
- */
-static struct device_float_coords
-accelerator_filter_generic(struct motion_filter *filter,
-			   const struct device_float_coords *unaccelerated,
-			   void *data, uint64_t time)
-{
-	struct pointer_accelerator *accel =
-		(struct pointer_accelerator *) filter;
-	double accel_value; /* unitless factor */
-	struct device_float_coords accelerated;
-
-	accel_value = calculate_acceleration_factor(accel,
-						    unaccelerated,
-						    data,
-						    time);
-
-	accelerated.x = accel_value * unaccelerated->x;
-	accelerated.y = accel_value * unaccelerated->y;
-
-	return accelerated;
-}
-
-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;
-}
-
-/**
- * Generic filter that does nothing beyond converting from the device's
- * native dpi into normalized coordinates.
- *
- * @param filter The acceleration filter
- * @param unaccelerated The raw delta in the device's dpi
- * @param data Caller-specific data
- * @param time Current time in µs
- *
- * @return An accelerated tuple of coordinates representing normalized
- * motion
- */
-static struct normalized_coords
-accelerator_filter_noop(struct motion_filter *filter,
-			const struct device_float_coords *unaccelerated,
-			void *data, uint64_t time)
-{
-	struct pointer_accelerator *accel =
-		(struct pointer_accelerator *) filter;
-
-	return normalize_for_dpi(unaccelerated, accel->dpi);
-}
-
-static void
-accelerator_restart(struct motion_filter *filter,
-		    void *data,
-		    uint64_t time)
-{
-	struct pointer_accelerator *accel =
-		(struct pointer_accelerator *) filter;
-
-	reset_trackers(&accel->trackers, time);
-}
-
-static void
-accelerator_destroy(struct motion_filter *filter)
-{
-	struct pointer_accelerator *accel =
-		(struct pointer_accelerator *) filter;
-
-	free_trackers(&accel->trackers);
-	free(accel);
-}
-
-static bool
-accelerator_set_speed(struct motion_filter *filter,
-		      double speed_adjustment)
-{
-	struct pointer_accelerator *accel_filter =
-		(struct pointer_accelerator *)filter;
-
-	assert(speed_adjustment >= -1.0 && speed_adjustment <= 1.0);
-
-	/* Note: the numbers below are nothing but trial-and-error magic,
-	   don't read more into them other than "they mostly worked ok" */
-
-	/* delay when accel kicks in */
-	accel_filter->threshold = DEFAULT_THRESHOLD -
-					v_ms2us(0.25) * speed_adjustment;
-	if (accel_filter->threshold < MINIMUM_THRESHOLD)
-		accel_filter->threshold = MINIMUM_THRESHOLD;
-
-	/* adjust max accel factor */
-	accel_filter->accel = DEFAULT_ACCELERATION + speed_adjustment * 1.5;
-
-	/* higher speed -> faster to reach max */
-	accel_filter->incline = DEFAULT_INCLINE + speed_adjustment * 0.75;
-
-	filter->speed_adjustment = speed_adjustment;
-	return true;
-}
-
-double
-pointer_accel_profile_linear(struct motion_filter *filter,
-			     void *data,
-			     double speed_in, /* in device units (units/µs) */
-			     uint64_t time)
-{
-	struct pointer_accelerator *accel_filter =
-		(struct pointer_accelerator *)filter;
-	const double max_accel = accel_filter->accel; /* unitless factor */
-	const double threshold = accel_filter->threshold; /* units/us */
-	const double incline = accel_filter->incline;
-	double factor; /* unitless */
-
-	/* Normalize to 1000dpi, because the rest below relies on that */
-	speed_in = speed_in * DEFAULT_MOUSE_DPI/accel_filter->dpi;
-
-	/*
-	   Our acceleration function calculates a factor to accelerate input
-	   deltas with. The function is a double incline with a plateau,
-	   with a rough shape like this:
-
-	  accel
-	 factor
-	   ^
-	   |        /
-	   |  _____/
-	   | /
-	   |/
-	   +-------------> speed in
-
-	   The two inclines are linear functions in the form
-		   y = ax + b
-		   where y is speed_out
-		         x is speed_in
-			 a is the incline of acceleration
-			 b is minimum acceleration factor
-
-	   for speeds up to 0.07 u/ms, we decelerate, down to 30% of input
-	   speed.
-		   hence 1 = a * 0.07 + 0.3
-		       0.7 = a * 0.07 => a := 10
-		   deceleration function is thus:
-			y = 10x + 0.3
-
-	  Note:
-	  * 0.07u/ms as threshold is a result of trial-and-error and
-	    has no other intrinsic meaning.
-	  * 0.3 is chosen simply because it is above the Nyquist frequency
-	    for subpixel motion within a pixel.
-	*/
-	if (v_us2ms(speed_in) < 0.07) {
-		factor = 10 * v_us2ms(speed_in) + 0.3;
-	/* up to the threshold, we keep factor 1, i.e. 1:1 movement */
-	} else if (speed_in < threshold) {
-		factor = 1;
-
-	} else {
-	/* Acceleration function above the threshold:
-		y = ax' + b
-		where T is threshold
-		      x is speed_in
-		      x' is speed
-	        and
-			y(T) == 1
-		hence 1 = ax' + 1
-			=> x' := (x - T)
-	 */
-		factor = incline * v_us2ms(speed_in - threshold) + 1;
-	}
-
-	/* Cap at the maximum acceleration factor */
-	factor = min(max_accel, factor);
-
-	return factor;
-}
-
-struct motion_filter_interface accelerator_interface = {
-	.type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
-	.filter = accelerator_filter_pre_normalized,
-	.filter_constant = accelerator_filter_noop,
-	.restart = accelerator_restart,
-	.destroy = accelerator_destroy,
-	.set_speed = accelerator_set_speed,
-};
-
-static struct pointer_accelerator *
-create_default_filter(int dpi)
-{
-	struct pointer_accelerator *filter;
-
-	filter = zalloc(sizeof *filter);
-	filter->last_velocity = 0.0;
-
-	init_trackers(&filter->trackers);
-
-	filter->threshold = DEFAULT_THRESHOLD;
-	filter->accel = DEFAULT_ACCELERATION;
-	filter->incline = DEFAULT_INCLINE;
-	filter->dpi = dpi;
-
-	return filter;
-}
-
-struct motion_filter *
-create_pointer_accelerator_filter_linear(int dpi)
-{
-	struct pointer_accelerator *filter;
-
-	filter = create_default_filter(dpi);
-	if (!filter)
-		return NULL;
-
-	filter->base.interface = &accelerator_interface;
-	filter->profile = pointer_accel_profile_linear;
-
-	return &filter->base;
-}
-- 
2.14.3



More information about the wayland-devel mailing list