touchpad: don't feed 0/0 deltas into the accel filters
[platform/upstream/libinput.git] / src / filter.c
index 3221d19..5b0b877 100644 (file)
@@ -38,26 +38,34 @@ filter_dispatch(struct motion_filter *filter,
        filter->interface->filter(filter, motion, data, time);
 }
 
+void
+filter_destroy(struct motion_filter *filter)
+{
+       if (!filter)
+               return;
+
+       filter->interface->destroy(filter);
+}
+
 /*
  * Default parameters for pointer acceleration profiles.
  */
 
-#define DEFAULT_CONSTANT_ACCELERATION 10.0
-#define DEFAULT_THRESHOLD 4.0
-#define DEFAULT_ACCELERATION 2.0
+#define DEFAULT_THRESHOLD 0.4                  /* in units/ms */
+#define DEFAULT_ACCELERATION 2.0               /* unitless factor */
 
 /*
  * Pointer acceleration filter constants
  */
 
-#define MAX_VELOCITY_DIFF      1.0
+#define MAX_VELOCITY_DIFF      1.0 /* units/ms */
 #define MOTION_TIMEOUT         300 /* (ms) */
 #define NUM_POINTER_TRACKERS   16
 
 struct pointer_tracker {
-       double dx;
-       double dy;
-       uint64_t time;
+       double dx;      /* delta to most recent event, in device units */
+       double dy;      /* delta to most recent event, in device units */
+       uint64_t time;  /* ms */
        int dir;
 };
 
@@ -67,10 +75,10 @@ struct pointer_accelerator {
 
        accel_profile_func_t profile;
 
-       double velocity;
-       double last_velocity;
-       int last_dx;
-       int last_dy;
+       double velocity;        /* units/ms */
+       double last_velocity;   /* units/ms */
+       int last_dx;            /* device units */
+       int last_dy;            /* device units */
 
        struct pointer_tracker *trackers;
        int cur_tracker;
@@ -174,7 +182,7 @@ calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time)
        dx = tracker->dx;
        dy = tracker->dy;
        distance = sqrt(dx*dx + dy*dy);
-       return distance / (double)(time - tracker->time);
+       return distance / (double)(time - tracker->time); /* units/ms */
 }
 
 static double
@@ -218,7 +226,7 @@ calculate_velocity(struct pointer_accelerator *accel, uint64_t time)
                }
        }
 
-       return result;
+       return result; /* units/ms */
 }
 
 static double
@@ -245,28 +253,7 @@ calculate_acceleration(struct pointer_accelerator *accel,
 
        factor = factor / 6.0;
 
-       return factor;
-}
-
-static double
-soften_delta(double last_delta, double delta)
-{
-       if (delta < -1.0 || delta > 1.0) {
-               if (delta > last_delta)
-                       return delta - 0.5;
-               else if (delta < last_delta)
-                       return delta + 0.5;
-       }
-
-       return delta;
-}
-
-static void
-apply_softening(struct pointer_accelerator *accel,
-               struct motion_params *motion)
-{
-       motion->dx = soften_delta(accel->last_dx, motion->dx);
-       motion->dy = soften_delta(accel->last_dy, motion->dy);
+       return factor; /* unitless factor */
 }
 
 static void
@@ -276,8 +263,8 @@ accelerator_filter(struct motion_filter *filter,
 {
        struct pointer_accelerator *accel =
                (struct pointer_accelerator *) filter;
-       double velocity;
-       double accel_value;
+       double velocity; /* units/ms */
+       double accel_value; /* unitless factor */
 
        feed_trackers(accel, motion->dx, motion->dy, time);
        velocity = calculate_velocity(accel, time);
@@ -286,8 +273,6 @@ accelerator_filter(struct motion_filter *filter,
        motion->dx = accel_value * motion->dx;
        motion->dy = accel_value * motion->dy;
 
-       apply_softening(accel, motion);
-
        accel->last_dx = motion->dx;
        accel->last_dy = motion->dy;
 
@@ -332,15 +317,6 @@ create_pointer_accelator_filter(accel_profile_func_t profile)
        return &filter->base;
 }
 
-void
-motion_filter_destroy(struct motion_filter *filter)
-{
-       if (!filter)
-               return;
-
-       filter->interface->destroy(filter);
-}
-
 static inline double
 calc_penumbral_gradient(double x)
 {
@@ -352,27 +328,32 @@ calc_penumbral_gradient(double x)
 double
 pointer_accel_profile_smooth_simple(struct motion_filter *filter,
                                    void *data,
-                                   double velocity,
+                                   double velocity, /* units/ms */
                                    uint64_t time)
 {
-       double threshold = DEFAULT_THRESHOLD;
-       double accel = DEFAULT_ACCELERATION;
-       double smooth_accel_coefficient;
+       double threshold = DEFAULT_THRESHOLD; /* units/ms */
+       double accel = DEFAULT_ACCELERATION; /* unitless factor */
+       double smooth_accel_coefficient; /* unitless factor */
+       double factor; /* unitless factor */
+
+       if (threshold < 0.1)
+               threshold = 0.1;
+       if (accel < 1.0)
+               accel = 1.0;
+
 
-       velocity *= DEFAULT_CONSTANT_ACCELERATION;
+       if (velocity < (threshold / 2.0))
+               return calc_penumbral_gradient(0.5 + velocity / threshold) * 2.0 - 1.0;
 
-       if (velocity < 1.0)
-               return calc_penumbral_gradient(0.5 + velocity * 0.5) * 2.0 - 1.0;
-       if (threshold < 1.0)
-               threshold = 1.0;
        if (velocity <= threshold)
-               return 1;
-       velocity /= threshold;
-       if (velocity >= accel) {
+               return 1.0;
+
+       factor = velocity/threshold;
+       if (factor >= accel)
                return accel;
-       } else {
-               smooth_accel_coefficient =
-                       calc_penumbral_gradient(velocity / accel);
-               return 1.0 + (smooth_accel_coefficient * (accel - 1.0));
-       }
+
+       /* 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));
 }