mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-25 03:30:05 +01:00
filter: explain the acceleration function in detail
And switch to a code-flow that's a bit more self-explanatory than the current min/max combinations. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Jonas Ådahl <jadahl@gmail.com>
This commit is contained in:
parent
1cbcc641a0
commit
723dccfd93
1 changed files with 73 additions and 10 deletions
83
src/filter.c
83
src/filter.c
|
|
@ -421,19 +421,26 @@ pointer_accel_profile_linear_low_dpi(struct motion_filter *filter,
|
|||
struct pointer_accelerator *accel_filter =
|
||||
(struct pointer_accelerator *)filter;
|
||||
|
||||
double f1, f2; /* unitless */
|
||||
double max_accel = accel_filter->accel; /* unitless factor */
|
||||
const double threshold = accel_filter->threshold; /* units/us */
|
||||
double threshold = accel_filter->threshold; /* units/us */
|
||||
const double incline = accel_filter->incline;
|
||||
double factor; /* unitless */
|
||||
double dpi_factor = accel_filter->dpi_factor;
|
||||
|
||||
/* dpi_factor is always < 1.0, increase max_accel, reduce
|
||||
the threshold so it kicks in earlier */
|
||||
max_accel /= dpi_factor;
|
||||
threshold *= dpi_factor;
|
||||
|
||||
f1 = min(1, 0.3 + v_us2ms(speed_in) * 10.0);
|
||||
f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold) * dpi_factor) * incline;
|
||||
/* see pointer_accel_profile_linear for a long description */
|
||||
if (v_us2ms(speed_in) < 0.07)
|
||||
factor = 10 * v_us2ms(speed_in) + 0.3;
|
||||
else if (speed_in < threshold)
|
||||
factor = 1;
|
||||
else
|
||||
factor = incline * v_us2ms(speed_in - threshold) + 1;
|
||||
|
||||
factor = min(max_accel, f2 > 1 ? f2 : f1);
|
||||
factor = min(max_accel, factor);
|
||||
|
||||
return factor;
|
||||
}
|
||||
|
|
@ -446,17 +453,67 @@ pointer_accel_profile_linear(struct motion_filter *filter,
|
|||
{
|
||||
struct pointer_accelerator *accel_filter =
|
||||
(struct pointer_accelerator *)filter;
|
||||
|
||||
double f1, f2; /* unitless */
|
||||
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 */
|
||||
|
||||
f1 = min(1, 0.3 + v_us2ms(speed_in) * 10);
|
||||
f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold)) * incline;
|
||||
/*
|
||||
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:
|
||||
|
||||
factor = min(max_accel, f2 > 1 ? f2 : f1);
|
||||
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.3 = a * 0.00 + 0.3 => 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;
|
||||
}
|
||||
|
|
@ -509,6 +566,12 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
|
|||
TP_MAGIC_LOW_RES_FACTOR; /* units/us */
|
||||
const double incline = accel_filter->incline * TP_MAGIC_LOW_RES_FACTOR;
|
||||
|
||||
/* Note: the magic values in this function are obtained by
|
||||
* trial-and-error. No other meaning should be interpreted.
|
||||
* The calculation is a compressed form of
|
||||
* pointer_accel_profile_linear(), look at the git history of that
|
||||
* function for an explaination of what the min/max/etc. does.
|
||||
*/
|
||||
speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
|
||||
|
||||
f1 = min(1, v_us2ms(speed_in) * 5);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue