Introduce custom acceleration profile

Merged Yinon Burgansky requested to merge Yinon/libinput:custom-acceleration into main

Introduce a custom acceleration profile (related to #350).

The custom profile allows the user to define a custom acceleration function, giving full control to accelerations behavior on different speeds

libinput supports a user-defined custom acceleration profile, which can be adjusted for different movement types supported by a device. Movement types include pointer movement, scrolling, etc. but the set of supported movement types depends on the device.

The custom pointer acceleration profile gives users full control over the acceleration behavior at different speeds. libinput exposes an acceleration function f(x) where the x axis is the device speed and the y axis is the pointer speed. By supplying the y axis values for this functions, users can control the behavior of the device.

The user should take into account the native device dpi and screen dpi in order to achieve the desired behavior/feel.

The custom acceleration function is defined using n points which are spaced uniformly along the x-axis, starting from 0 and continuing in constant steps. Thus the points defining the custom function are: (0 * step, f[0]), (1 * step, f[1]), ..., ((n-1) * step, f[n-1]) where f is a list of n unitless values defining the acceleration factor for each velocity. When a velocity value does not lie exactly on those points, a linear interpolation of the two closest points will be calculated. When a velocity value is greater than the max point defined, a linear extrapolation of the two biggest points will be calculated.

Supported Movement types:

Movement type Uses supported by devices
Fallback Catch-all default movement type All devices
Motion Used for pointer motion All devices

If a user does not provide the fallback custom acceleration function, a flat acceleration function is used, i.e. no acceleration.

The fallback acceleration may be used for different types of movements, it is strongly recommended that the acceleration function is a constant function.

For example, a physical mouse usually has two movement types: pointer movement and scroll (wheel) movement. As there is no separate movement type for scroll yet, scroll movement is be accelerated using the Fallback acceleration function. Pointer movements is accelerated using the Motion acceleration function. If no Motion acceleration function is set, the Fallback acceleration function is used.

When using custom acceleration profile, any calls to set the speed have no effect on the behavior of the custom acceleration function, but any future calls to get the speed will reflect the updated speed setting.

based on merge request !297 (closed) with a few key changes:
The points are spaced uniformly along the x-axis,
Allowing access in O(1) instead of O(n).
Thus supporting granular control for any transfer functions.
currently the limit is 64 points (arbitrary).

Can be installed for testing on xserver using xinput:

  1. install libinput from this branch
  2. install xorg/driver/xf86-input-libinput!39 (merged)
  3. reboot system
  4. using xinput change profile to custom and set points and step
xinput set-prop <device-id> "libinput Accel Profile Enabled" 0, 0, 1
xinput set-prop <device-id> "libinput Accel Custom Motion Points" 0.0, 1.0 
xinput set-prop <device-id> "libinput Accel Custom Motion Step" 1.0

Or for debug purposes only:

sudo ./builddir/libinput-debug-gui --verbose \
    --set-profile=custom \
    --set-custom-points="0.0;1.0" \
    --set-custom-step=1.0 \

(a flat profile).

You can try creating points from windows acceleration function

Edited by Yinon Burgansky

Merge request reports