mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-06 11:28:39 +02: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 *accel_filter =
|
||||||
(struct pointer_accelerator *)filter;
|
(struct pointer_accelerator *)filter;
|
||||||
|
|
||||||
double f1, f2; /* unitless */
|
|
||||||
double max_accel = accel_filter->accel; /* unitless factor */
|
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;
|
const double incline = accel_filter->incline;
|
||||||
double factor; /* unitless */
|
double factor; /* unitless */
|
||||||
double dpi_factor = accel_filter->dpi_factor;
|
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;
|
max_accel /= dpi_factor;
|
||||||
|
threshold *= dpi_factor;
|
||||||
|
|
||||||
f1 = min(1, 0.3 + v_us2ms(speed_in) * 10.0);
|
/* see pointer_accel_profile_linear for a long description */
|
||||||
f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold) * dpi_factor) * incline;
|
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;
|
return factor;
|
||||||
}
|
}
|
||||||
|
|
@ -446,17 +453,67 @@ pointer_accel_profile_linear(struct motion_filter *filter,
|
||||||
{
|
{
|
||||||
struct pointer_accelerator *accel_filter =
|
struct pointer_accelerator *accel_filter =
|
||||||
(struct pointer_accelerator *)filter;
|
(struct pointer_accelerator *)filter;
|
||||||
|
|
||||||
double f1, f2; /* unitless */
|
|
||||||
const double max_accel = accel_filter->accel; /* unitless factor */
|
const double max_accel = accel_filter->accel; /* unitless factor */
|
||||||
const double threshold = accel_filter->threshold; /* units/us */
|
const double threshold = accel_filter->threshold; /* units/us */
|
||||||
const double incline = accel_filter->incline;
|
const double incline = accel_filter->incline;
|
||||||
double factor; /* unitless */
|
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;
|
return factor;
|
||||||
}
|
}
|
||||||
|
|
@ -509,6 +566,12 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
|
||||||
TP_MAGIC_LOW_RES_FACTOR; /* units/us */
|
TP_MAGIC_LOW_RES_FACTOR; /* units/us */
|
||||||
const double incline = accel_filter->incline * TP_MAGIC_LOW_RES_FACTOR;
|
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;
|
speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
|
||||||
|
|
||||||
f1 = min(1, v_us2ms(speed_in) * 5);
|
f1 = min(1, v_us2ms(speed_in) * 5);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue