Signed-off-by: Peter Hutterer <[email protected]>
---
 meson.build           |   1 +
 src/filter-touchpad.c | 332 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/filter.c          | 177 ---------------------------
 3 files changed, 333 insertions(+), 177 deletions(-)
 create mode 100644 src/filter-touchpad.c

diff --git a/meson.build b/meson.build
index ecc92fd5..e9b165ec 100644
--- a/meson.build
+++ b/meson.build
@@ -151,6 +151,7 @@ dep_libinput_util = declare_dependency(link_with : 
libinput_util)
 ############ libfilter.a ############
 src_libfilter = [
                'src/filter.c',
+               'src/filter-touchpad.c',
                'src/filter-touchpad-x230.c',
                'src/filter-tablet.c',
                'src/filter-trackpoint.c',
diff --git a/src/filter-touchpad.c b/src/filter-touchpad.c
new file mode 100644
index 00000000..717b6803
--- /dev/null
+++ b/src/filter-touchpad.c
@@ -0,0 +1,332 @@
+/*
+ * 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"
+
+/* Once normalized, touchpads see the same acceleration as mice. that is
+ * technically correct but subjectively wrong, we expect a touchpad to be a
+ * lot slower than a mouse. Apply a magic factor to slow down all movements
+ */
+#define TP_MAGIC_SLOWDOWN 0.37 /* unitless factor */
+
+/*
+ * 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 */
+
+/* Touchpad acceleration */
+#define TOUCHPAD_DEFAULT_THRESHOLD 254         /* mm/s */
+#define TOUCHPAD_THRESHOLD_RANGE 184           /* mm/s */
+#define TOUCHPAD_ACCELERATION 9.0              /* unitless factor */
+#define TOUCHPAD_INCLINE 0.011                 /* unitless factor */
+
+/*
+ * Pointer acceleration filter constants
+ */
+#define NUM_POINTER_TRACKERS   16
+
+/**
+ * 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_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 bool
+touchpad_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" */
+
+       /* adjust when accel kicks in */
+       accel_filter->threshold = TOUCHPAD_DEFAULT_THRESHOLD -
+               TOUCHPAD_THRESHOLD_RANGE * speed_adjustment;
+       accel_filter->accel = TOUCHPAD_ACCELERATION;
+       accel_filter->incline = TOUCHPAD_INCLINE;
+       filter->speed_adjustment = speed_adjustment;
+
+       return true;
+}
+
+static struct normalized_coords
+touchpad_constant_filter(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;
+
+       normalized = normalize_for_dpi(unaccelerated, accel->dpi);
+       normalized.x = TP_MAGIC_SLOWDOWN * normalized.x;
+       normalized.y = TP_MAGIC_SLOWDOWN * normalized.y;
+
+       return normalized;
+}
+
+static void
+touchpad_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
+touchpad_accelerator_destroy(struct motion_filter *filter)
+{
+       struct pointer_accelerator *accel =
+               (struct pointer_accelerator *) filter;
+
+       free_trackers(&accel->trackers);
+       free(accel);
+}
+
+double
+touchpad_accel_profile_linear(struct motion_filter *filter,
+                             void *data,
+                             double speed_in, /* in device 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 */
+
+       /* Convert to mm/s because that's something one can understand */
+       speed_in = v_us2s(speed_in) * 25.4/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 the lower threshold, we decelerate, down to 30%
+          of input speed.
+                  hence 1 = a * 7 + 0.3
+                      0.7 = a * 7  => a := 0.1
+                  deceleration function is thus:
+                       y = 0.1x + 0.3
+
+         Note:
+         * The minimum 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 (speed_in < 7.0) {
+               factor = 0.1 * 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 * (speed_in - threshold) + 1;
+       }
+
+       /* Cap at the maximum acceleration factor */
+       factor = min(max_accel, factor);
+
+       /* Scale everything depending on the acceleration set */
+       factor *= 1 + 0.5 * filter->speed_adjustment;
+
+       return factor * TP_MAGIC_SLOWDOWN;
+}
+
+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, NUM_POINTER_TRACKERS);
+
+       filter->threshold = DEFAULT_THRESHOLD;
+       filter->accel = DEFAULT_ACCELERATION;
+       filter->incline = DEFAULT_INCLINE;
+       filter->dpi = dpi;
+
+       return filter;
+}
+
+struct motion_filter_interface accelerator_interface_touchpad = {
+       .type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
+       .filter = accelerator_filter_post_normalized,
+       .filter_constant = touchpad_constant_filter,
+       .restart = touchpad_accelerator_restart,
+       .destroy = touchpad_accelerator_destroy,
+       .set_speed = touchpad_accelerator_set_speed,
+};
+
+struct motion_filter *
+create_pointer_accelerator_filter_touchpad(int dpi,
+       uint64_t event_delta_smooth_threshold,
+       uint64_t event_delta_smooth_value)
+{
+       struct pointer_accelerator *filter;
+       struct pointer_delta_smoothener *smoothener;
+
+       filter = create_default_filter(dpi);
+       if (!filter)
+               return NULL;
+
+       filter->base.interface = &accelerator_interface_touchpad;
+       filter->profile = touchpad_accel_profile_linear;
+
+       smoothener = zalloc(sizeof(*smoothener));
+       smoothener->threshold = event_delta_smooth_threshold,
+       smoothener->value = event_delta_smooth_value,
+       filter->trackers.smoothener = smoothener;
+
+       return &filter->base;
+}
diff --git a/src/filter.c b/src/filter.c
index 291013a1..fef2c835 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -36,12 +36,6 @@
 #include "libinput-util.h"
 #include "filter-private.h"
 
-/* Once normalized, touchpads see the same acceleration as mice. that is
- * technically correct but subjectively wrong, we expect a touchpad to be a
- * lot slower than a mouse. Apply a magic factor to slow down all movements
- */
-#define TP_MAGIC_SLOWDOWN 0.37 /* unitless factor */
-
 struct normalized_coords
 filter_dispatch(struct motion_filter *filter,
                const struct device_float_coords *unaccelerated,
@@ -103,12 +97,6 @@ filter_get_type(struct motion_filter *filter)
 #define DEFAULT_ACCELERATION 2.0               /* unitless factor */
 #define DEFAULT_INCLINE 1.1                    /* unitless factor */
 
-/* Touchpad acceleration */
-#define TOUCHPAD_DEFAULT_THRESHOLD 254         /* mm/s */
-#define TOUCHPAD_THRESHOLD_RANGE 184           /* mm/s */
-#define TOUCHPAD_ACCELERATION 9.0              /* unitless factor */
-#define TOUCHPAD_INCLINE 0.011                 /* unitless factor */
-
 /*
  * Pointer acceleration filter constants
  */
@@ -395,23 +383,6 @@ 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,
@@ -478,44 +449,6 @@ accelerator_filter_noop(struct motion_filter *filter,
        return normalize_for_dpi(unaccelerated, accel->dpi);
 }
 
-static bool
-touchpad_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" */
-
-       /* adjust when accel kicks in */
-       accel_filter->threshold = TOUCHPAD_DEFAULT_THRESHOLD -
-               TOUCHPAD_THRESHOLD_RANGE * speed_adjustment;
-       accel_filter->accel = TOUCHPAD_ACCELERATION;
-       accel_filter->incline = TOUCHPAD_INCLINE;
-       filter->speed_adjustment = speed_adjustment;
-
-       return true;
-}
-
-static struct normalized_coords
-touchpad_constant_filter(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;
-
-       normalized = normalize_for_dpi(unaccelerated, accel->dpi);
-       normalized.x = TP_MAGIC_SLOWDOWN * normalized.x;
-       normalized.y = TP_MAGIC_SLOWDOWN * normalized.y;
-
-       return normalized;
-}
-
 static void
 accelerator_restart(struct motion_filter *filter,
                    void *data,
@@ -684,84 +617,6 @@ pointer_accel_profile_linear(struct motion_filter *filter,
        return factor;
 }
 
-double
-touchpad_accel_profile_linear(struct motion_filter *filter,
-                             void *data,
-                             double speed_in, /* in device 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 */
-
-       /* Convert to mm/s because that's something one can understand */
-       speed_in = v_us2s(speed_in) * 25.4/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 the lower threshold, we decelerate, down to 30%
-          of input speed.
-                  hence 1 = a * 7 + 0.3
-                      0.7 = a * 7  => a := 0.1
-                  deceleration function is thus:
-                       y = 0.1x + 0.3
-
-         Note:
-         * The minimum 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 (speed_in < 7.0) {
-               factor = 0.1 * 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 * (speed_in - threshold) + 1;
-       }
-
-       /* Cap at the maximum acceleration factor */
-       factor = min(max_accel, factor);
-
-       /* Scale everything depending on the acceleration set */
-       factor *= 1 + 0.5 * filter->speed_adjustment;
-
-       return factor * TP_MAGIC_SLOWDOWN;
-}
-
 struct motion_filter_interface accelerator_interface = {
        .type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
        .filter = accelerator_filter_pre_normalized,
@@ -828,38 +683,6 @@ create_pointer_accelerator_filter_linear_low_dpi(int dpi)
        return &filter->base;
 }
 
-struct motion_filter_interface accelerator_interface_touchpad = {
-       .type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
-       .filter = accelerator_filter_post_normalized,
-       .filter_constant = touchpad_constant_filter,
-       .restart = accelerator_restart,
-       .destroy = accelerator_destroy,
-       .set_speed = touchpad_accelerator_set_speed,
-};
-
-struct motion_filter *
-create_pointer_accelerator_filter_touchpad(int dpi,
-       uint64_t event_delta_smooth_threshold,
-       uint64_t event_delta_smooth_value)
-{
-       struct pointer_accelerator *filter;
-       struct pointer_delta_smoothener *smoothener;
-
-       filter = create_default_filter(dpi);
-       if (!filter)
-               return NULL;
-
-       filter->base.interface = &accelerator_interface_touchpad;
-       filter->profile = touchpad_accel_profile_linear;
-
-       smoothener = zalloc(sizeof(*smoothener));
-       smoothener->threshold = event_delta_smooth_threshold,
-       smoothener->value = event_delta_smooth_value,
-       filter->trackers.smoothener = smoothener;
-
-       return &filter->base;
-}
-
 static struct normalized_coords
 accelerator_filter_flat(struct motion_filter *filter,
                        const struct device_float_coords *unaccelerated,
-- 
2.14.3

_______________________________________________
wayland-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to