summaryrefslogtreecommitdiff
path: root/src/filter.c
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2015-06-23 12:45:16 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2015-07-02 13:03:43 +1000
commit3928f3228105f65e4ee6186572e3f95f78c96113 (patch)
tree5f1a4c7bd66c09a88bb1d01997e447c4c874baba /src/filter.c
parent4df1a9b66e437a191fab0ef4fc48511e993c4680 (diff)
filter: add a custom low-dpi acceleration
Motion normalization does not work well for devices below the default 1000dpi rate. A 400dpi mouse's minimum movement generates a 2.5 normalized motion, causing it to skip pixels at low speeds even when unaccelerated. Likewise, we don't want 1000dpi mice to be normalized to a 400dpi mouse, it feels sluggish even at higher acceleration speeds. Instead, add a custom acceleration method for lower-dpi mice. At low-speeds, one device unit results in a one-pixel movement. Depending on the DPI factor, the acceleration kicks in earlier and goes to higher acceleration so faster movements with a low-dpi mouse feel approximately the same as the same movement on a higher-dpi mouse. https://bugzilla.redhat.com/show_bug.cgi?id=1231304 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'src/filter.c')
-rw-r--r--src/filter.c54
1 files changed, 49 insertions, 5 deletions
diff --git a/src/filter.c b/src/filter.c
index 23e33495..35449f56 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -264,8 +264,16 @@ accelerator_filter(struct motion_filter *filter,
double velocity; /* units/ms */
double accel_value; /* unitless factor */
struct normalized_coords accelerated;
+ struct normalized_coords unnormalized;
+ double dpi_factor = accel->dpi_factor;
- feed_trackers(accel, unaccelerated, time);
+ /* For low-dpi mice, use device units, everything else uses
+ 1000dpi normalized */
+ dpi_factor = min(1.0, dpi_factor);
+ unnormalized.x = unaccelerated->x * dpi_factor;
+ unnormalized.y = unaccelerated->y * dpi_factor;
+
+ feed_trackers(accel, &unnormalized, time);
velocity = calculate_velocity(accel, time);
accel_value = calculate_acceleration(accel,
data,
@@ -273,10 +281,10 @@ accelerator_filter(struct motion_filter *filter,
accel->last_velocity,
time);
- accelerated.x = accel_value * unaccelerated->x;
- accelerated.y = accel_value * unaccelerated->y;
+ accelerated.x = accel_value * unnormalized.x;
+ accelerated.y = accel_value * unnormalized.y;
- accel->last = *unaccelerated;
+ accel->last = unnormalized;
accel->last_velocity = velocity;
@@ -377,10 +385,46 @@ create_pointer_accelerator_filter(accel_profile_func_t profile,
return &filter->base;
}
+/**
+ * Custom acceleration function for mice < 1000dpi.
+ * At slow motion, a single device unit causes a one-pixel movement.
+ * The threshold/max accel depends on the DPI, the smaller the DPI the
+ * earlier we accelerate and the higher the maximum acceleration is. Result:
+ * at low speeds we get pixel-precision, at high speeds we get approx. the
+ * same movement as a high-dpi mouse.
+ *
+ * Note: data fed to this function is in device units, not normalized.
+ */
+double
+pointer_accel_profile_linear_low_dpi(struct motion_filter *filter,
+ void *data,
+ double speed_in, /* in device units */
+ uint64_t time)
+{
+ struct pointer_accelerator *accel_filter =
+ (struct pointer_accelerator *)filter;
+
+ double s1, s2;
+ double max_accel = accel_filter->accel; /* unitless factor */
+ const double threshold = accel_filter->threshold; /* units/ms */
+ const double incline = accel_filter->incline;
+ double factor;
+ double dpi_factor = accel_filter->dpi_factor;
+
+ max_accel /= dpi_factor;
+
+ s1 = min(1, 0.3 + speed_in * 10);
+ s2 = 1 + (speed_in - threshold * dpi_factor) * incline;
+
+ factor = min(max_accel, s2 > 1 ? s2 : s1);
+
+ return factor;
+}
+
double
pointer_accel_profile_linear(struct motion_filter *filter,
void *data,
- double speed_in,
+ double speed_in, /* 1000-dpi normalized */
uint64_t time)
{
struct pointer_accelerator *accel_filter =