mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-08 11:40:15 +01:00
filter: add a trackpoint multiplier factor
Measuring the trackpoint range has not shown to be sufficient or precise enough to be used as an ingredient for trackpoint acceleration. So let's just switch back to a generic multiplier that we can apply to the input deltas do undo any device-specific lack of scaling. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
1cc9f44e93
commit
27f7a66de4
12 changed files with 320 additions and 173 deletions
|
|
@ -124,6 +124,9 @@ sensitivity in hardware by modifying a sysfs file on the serio node. A
|
|||
higher sensitivity results in higher deltas, thus changing the definition of
|
||||
what is a unit again.
|
||||
|
||||
libinput attempts to normalize unit data to the best of its abilities, see
|
||||
@ref trackpoint_multiplier. Beyond this, it is not possible to have
|
||||
consistent behavior across different touchpad devices.
|
||||
|
||||
@image html ptraccel-trackpoint.svg "Pointer acceleration curves for trackpoints"
|
||||
|
||||
|
|
|
|||
126
doc/svg/trackpoint-delta-illustration.svg
Normal file
126
doc/svg/trackpoint-delta-illustration.svg
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<svg
|
||||
width="600" height="480"
|
||||
viewBox="0 0 600 480"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
|
||||
<title>Gnuplot</title>
|
||||
<desc>Produced by GNUPLOT 5.0 patchlevel 6 </desc>
|
||||
|
||||
<g id="gnuplot_canvas">
|
||||
|
||||
<rect x="0" y="0" width="600" height="480" fill="none"/>
|
||||
<defs>
|
||||
|
||||
<circle id='gpDot' r='0.5' stroke-width='0.5'/>
|
||||
<path id='gpPt0' stroke-width='0.222' stroke='currentColor' d='M-1,0 h2 M0,-1 v2'/>
|
||||
<path id='gpPt1' stroke-width='0.222' stroke='currentColor' d='M-1,-1 L1,1 M1,-1 L-1,1'/>
|
||||
<path id='gpPt2' stroke-width='0.222' stroke='currentColor' d='M-1,0 L1,0 M0,-1 L0,1 M-1,-1 L1,1 M-1,1 L1,-1'/>
|
||||
<rect id='gpPt3' stroke-width='0.222' stroke='currentColor' x='-1' y='-1' width='2' height='2'/>
|
||||
<rect id='gpPt4' stroke-width='0.222' stroke='currentColor' fill='currentColor' x='-1' y='-1' width='2' height='2'/>
|
||||
<circle id='gpPt5' stroke-width='0.222' stroke='currentColor' cx='0' cy='0' r='1'/>
|
||||
<use xlink:href='#gpPt5' id='gpPt6' fill='currentColor' stroke='none'/>
|
||||
<path id='gpPt7' stroke-width='0.222' stroke='currentColor' d='M0,-1.33 L-1.33,0.67 L1.33,0.67 z'/>
|
||||
<use xlink:href='#gpPt7' id='gpPt8' fill='currentColor' stroke='none'/>
|
||||
<use xlink:href='#gpPt7' id='gpPt9' stroke='currentColor' transform='rotate(180)'/>
|
||||
<use xlink:href='#gpPt9' id='gpPt10' fill='currentColor' stroke='none'/>
|
||||
<use xlink:href='#gpPt3' id='gpPt11' stroke='currentColor' transform='rotate(45)'/>
|
||||
<use xlink:href='#gpPt11' id='gpPt12' fill='currentColor' stroke='none'/>
|
||||
<path id='gpPt13' stroke-width='0.222' stroke='currentColor' d='M0,1.330 L1.265,0.411 L0.782,-1.067 L-0.782,-1.076 L-1.265,0.411 z'/>
|
||||
<use xlink:href='#gpPt13' id='gpPt14' fill='currentColor' stroke='none'/>
|
||||
<filter id='textbox' filterUnits='objectBoundingBox' x='0' y='0' height='1' width='1'>
|
||||
<feFlood flood-color='white' flood-opacity='1' result='bgnd'/>
|
||||
<feComposite in='SourceGraphic' in2='bgnd' operator='atop'/>
|
||||
</filter>
|
||||
<filter id='greybox' filterUnits='objectBoundingBox' x='0' y='0' height='1' width='1'>
|
||||
<feFlood flood-color='lightgrey' flood-opacity='1' result='grey'/>
|
||||
<feComposite in='SourceGraphic' in2='grey' operator='atop'/>
|
||||
</filter>
|
||||
</defs>
|
||||
<g fill="none" color="white" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
</g>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
</g>
|
||||
<g fill="none" color="black" stroke="black" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
</g>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
<path stroke='rgb( 0, 0, 0)' d='M20.7,449.4 L575.0,449.4 '/></g>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
<path stroke='rgb( 0, 0, 0)' d='M20.7,449.4 L20.7,16.7 '/> <g transform="translate(325.6,431.7)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
|
||||
<text><tspan font-family="Arial" >minimum possible interval</tspan></text>
|
||||
</g>
|
||||
<g transform="translate(114.9,336.5)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
|
||||
<text><tspan font-family="Arial" >delta is 1</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
<path stroke='rgb( 0, 0, 0)' d='M346.8,414.9 L353.3,410.5 L345.4,411.0 M328.3,419.1 L353.3,410.5 '/></g>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
<path stroke='rgb( 0, 0, 0)' d='M120.6,353.0 L126.0,354.2 L121.9,350.5 M109.4,345.6 L126.0,354.2 '/></g>
|
||||
<g fill="none" color="black" stroke="rgb( 0, 0, 0)" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
</g>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
<g transform="translate(297.8,471.3)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="middle">
|
||||
<text><tspan font-family="Arial" >physical pressure</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
</g>
|
||||
<g id="gnuplot_plot_1" ><title>time between events</title>
|
||||
<g fill="none" color="white" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
</g>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
<g transform="translate(507.9,38.6)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
|
||||
<text><tspan font-family="Arial" >time between events</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
<path stroke='rgb(238, 17, 17)' d='M516.2,34.7 L558.4,34.7 M20.7,16.8 L26.3,25.9 L31.9,33.0 L37.5,40.6 L43.1,52.3 L48.7,57.6
|
||||
L54.3,67.9 L59.9,76.9 L65.5,86.7 L71.1,93.9 L76.7,104.2 L82.3,111.4 L87.9,121.6 L93.5,128.3
|
||||
L99.1,137.5 L104.7,145.9 L110.3,155.0 L115.9,164.1 L121.5,172.6 L127.1,183.2 L132.7,191.6 L138.3,199.0
|
||||
L143.9,209.0 L149.5,217.7 L155.1,225.5 L160.7,235.2 L166.3,243.3 L171.9,253.2 L177.5,260.2 L183.1,269.4
|
||||
L188.7,277.8 L194.3,287.4 L199.9,295.5 L205.5,304.9 L211.1,314.1 L216.7,322.2 L222.3,331.1 L227.9,339.4
|
||||
L233.5,348.9 L239.1,357.3 L244.7,366.0 L250.3,374.7 L255.9,383.9 L261.5,392.4 L267.1,401.3 L272.7,405.9
|
||||
L278.3,406.0 L283.9,405.8 L289.5,406.0 L295.1,405.9 L300.6,406.1 L306.2,406.0 L311.8,406.1 L317.4,406.0
|
||||
L323.0,406.2 L328.6,406.0 L334.2,406.0 L339.8,405.8 L345.4,406.0 L351.0,406.1 L356.6,406.0 L362.2,405.8
|
||||
L367.8,405.9 L373.4,406.2 L379.0,406.0 L384.6,406.0 L390.2,406.1 L395.8,405.8 L401.4,406.0 L407.0,406.1
|
||||
L412.6,405.9 L418.2,406.1 L423.8,406.0 L429.4,405.9 L435.0,406.1 L440.6,406.0 L446.2,406.0 L451.8,405.9
|
||||
L457.4,405.9 L463.0,406.1 L468.6,406.2 L474.2,405.9 L479.8,405.9 L485.4,406.1 L491.0,406.1 L496.6,406.0
|
||||
L502.2,405.9 L507.8,406.0 L513.4,405.8 L519.0,406.0 L524.6,405.9 L530.2,405.8 L535.8,406.2 L541.4,406.2
|
||||
L547.0,405.9 L552.6,406.2 L558.2,406.2 L563.8,406.0 L569.4,405.8 L575.0,406.2 '/></g>
|
||||
</g>
|
||||
<g id="gnuplot_plot_2" ><title>(x, y) delta values</title>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
<g transform="translate(507.9,56.6)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="end">
|
||||
<text><tspan font-family="Arial" >(x, y) delta values</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
<path stroke='rgb( 17, 17, 238)' d='M516.2,52.7 L558.4,52.7 M20.7,362.9 L26.3,362.5 L31.9,362.4 L37.5,362.6 L43.1,363.0 L48.7,362.2
|
||||
L54.3,362.3 L59.9,363.1 L65.5,362.5 L71.1,362.7 L76.7,362.7 L82.3,362.3 L87.9,362.8 L93.5,362.7
|
||||
L99.1,362.7 L104.7,362.9 L110.3,362.2 L115.9,362.4 L121.5,362.6 L127.1,362.5 L132.7,363.0 L138.3,362.9
|
||||
L143.9,362.7 L149.5,362.6 L155.1,362.8 L160.7,363.0 L166.3,362.8 L171.9,362.8 L177.5,362.8 L183.1,363.0
|
||||
L188.7,362.3 L194.3,363.0 L199.9,362.3 L205.5,362.3 L211.1,362.2 L216.7,363.0 L222.3,362.6 L227.9,362.8
|
||||
L233.5,362.6 L239.1,362.8 L244.7,362.8 L250.3,362.5 L255.9,362.6 L261.5,362.7 L267.1,362.4 L272.7,360.9
|
||||
L278.3,358.2 L283.9,355.9 L289.5,352.9 L295.1,349.7 L300.6,346.4 L306.2,343.8 L311.8,341.3 L317.4,338.0
|
||||
L323.0,334.5 L328.6,332.4 L334.2,329.1 L339.8,326.2 L345.4,322.9 L351.0,320.7 L356.6,317.6 L362.2,314.0
|
||||
L367.8,311.4 L373.4,309.0 L379.0,305.1 L384.6,302.3 L390.2,300.7 L395.8,297.0 L401.4,294.2 L407.0,291.7
|
||||
L412.6,288.5 L418.2,284.7 L423.8,282.5 L429.4,279.7 L435.0,275.8 L440.6,274.0 L446.2,271.1 L451.8,267.3
|
||||
L457.4,264.2 L463.0,262.4 L468.6,258.9 L474.2,255.4 L479.8,252.8 L485.4,250.3 L491.0,246.8 L496.6,245.0
|
||||
L502.2,241.2 L507.8,239.3 L513.4,234.8 L519.0,233.1 L524.6,230.0 L530.2,227.6 L535.8,224.9 L541.4,220.6
|
||||
L547.0,218.9 L552.6,214.4 L558.2,212.4 L563.8,210.1 L569.4,206.5 L575.0,203.1 '/></g>
|
||||
</g>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
</g>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
<path stroke='rgb( 0, 0, 0)' d='M561.5,446.6 L575.0,449.4 L561.5,452.2 M547.3,449.4 L575.0,449.4 '/></g>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
<path stroke='rgb( 0, 0, 0)' d='M17.9,27.1 L20.7,16.7 L23.5,27.1 M20.7,38.3 L20.7,16.7 '/></g>
|
||||
<g fill="none" color="black" stroke="rgb( 0, 0, 0)" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
</g>
|
||||
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.9 KiB |
|
|
@ -26,128 +26,144 @@ multiple laptops.
|
|||
|
||||
The values provided by a trackpoint are motion deltas, usually corresponding
|
||||
to the pressure applied to the trackstick. For example, pressure towards the
|
||||
screen on a laptop provides negative y deltas at a fixed rate (e.g. every
|
||||
10ms). As the pressure increases, the delta increases too. As the pressure
|
||||
decreases, the delta decreases until it hits the neutral state.
|
||||
screen on a laptop provides negative y deltas. The reporting rate increases
|
||||
as the pressure increases and once events are reported at the maximum rate,
|
||||
the delta values increase. The figure below shows a rough illustration of
|
||||
this concept. As the pressure
|
||||
decreases, the delta decrease first, then the reporting rate until the
|
||||
trackpoint is in a neutral state and no events are reported. Trackpoint data
|
||||
is hart to generalize, see
|
||||
<a href="https://who-t.blogspot.com/2018/06/observations-on-trackpoint-input-data.html">
|
||||
Observations on trackpoint input data</a> for more details.
|
||||
|
||||
@image html trackpoint-delta-illustration.svg Illustration of the relationship between reporting rate and delta values on a trackpoint
|
||||
|
||||
The delta range itself can vary greatly between laptops, some devices send a
|
||||
maximum delta value of 30, others can go beyond 100. To normalize the motion
|
||||
trackpoint, libinput uses the available delta range and fits its
|
||||
acceleration curve into this range. This requires calibration by the user,
|
||||
see @ref trackpoint_range_measure.
|
||||
maximum delta value of 30, others can go beyond 100. However, the useful
|
||||
delta range is a fraction of the maximum range. It is uncomfortable to exert
|
||||
sufficient pressure to even get close to the maximum ranges.
|
||||
|
||||
@section trackpoint_multiplier The magic trackpoint multiplier
|
||||
|
||||
To accomodate for the wildly different input data on trackpoint, libinput
|
||||
uses a multiplier that is applied to input deltas. Trackpoints that send
|
||||
comparatively high deltas can be "slowed down", trackpoints that send low
|
||||
deltas can be "sped up" to match the expected range. The actual acceleration
|
||||
profile is applied to these pre-multiplied deltas.
|
||||
|
||||
Given a trackpoint delta (dx, dy), a multiplier M and a pointer acceleration
|
||||
function f(dx, dy) → (dx', dy'), the algorithm is effectively:
|
||||
@verbatim
|
||||
f(M * dx, M * dy) → (dx', dy')
|
||||
@endverbatim
|
||||
|
||||
The magic trackpoint multiplier **is not user visible configuration**. It is
|
||||
part of the @ref device-quirks system and provided once per device.
|
||||
User-specific preferences can be adjusted with the pointer acceleration speed
|
||||
setting libinput_device_config_accel_set_speed().
|
||||
|
||||
@subsection trackpoint_multiplier_adjustment Adjusting the magic trackpoint multiplier
|
||||
|
||||
This section only applies if:
|
||||
- the trackpoint default speed (speed setting 0) is unusably slow or
|
||||
unusably fast, **and**
|
||||
- the lowest speed setting (-1) is still too fast **or** the highest speed
|
||||
setting is still too slow, **and**
|
||||
- the @ref device-quirks for this device do not list a trackpoint multiplier
|
||||
(see @ref device-quirks-debugging)
|
||||
|
||||
If the only satisfactory speed settings are less than -0.75 or greater than
|
||||
0.75, a multiplier *may* be required.
|
||||
|
||||
A specific multiplier will apply to **all users with the same laptop
|
||||
model**, so proceed with caution. You must be capable/willing to adjust
|
||||
device quirks, build libinput from source and restart the session frequently
|
||||
to adjust the multiplier. If this does not apply, wait for someone else with
|
||||
the same hardware to do this.
|
||||
|
||||
Finding the correct multiplier is difficult and requires some trial and
|
||||
error. The default multiplier is always 1.0. A value between 0.0 and 1.0
|
||||
slows the trackpoint down, a value above 1.0 speeds the trackpoint up.
|
||||
Values below zero are invalid.
|
||||
|
||||
@note The multiplier is not a configuration to adjust to personal
|
||||
preferences. The multiplier normalizes the input data into a range that can
|
||||
then be configured with the speed setting.
|
||||
|
||||
To adjust the local multiplier, first @ref building_libinput
|
||||
"build libinput from git master". It is not required to install libinput
|
||||
from git. The below assumes that all @ref building_dependencies are already
|
||||
installed.
|
||||
|
||||
@verbatim
|
||||
$ cd path/to/libinput.git
|
||||
|
||||
# Use an approximate multiplier in the quirks file
|
||||
$ cat > data/99-trackpont-override.quirks <<EOF
|
||||
[Trackpoint Override]
|
||||
MatchUdevType=pointingstick
|
||||
AttrTrackpointMultiplier=1.0
|
||||
EOF
|
||||
|
||||
# Use your trackpoint's event node. If the Attr does not show up
|
||||
# then the quirk does not apply to your trackpoint.
|
||||
$ ./builddir/libinput quirks list /dev/input/event18
|
||||
AttrTrackpointMultiplier=1.0
|
||||
|
||||
# Now start a GUI program to debug the trackpoint speed.
|
||||
# ESC closes the debug GUI
|
||||
$ sudo ./builddir/libinput debug-gui
|
||||
@endverbatim
|
||||
|
||||
Replace the multiplier with an approximate value and the event node with
|
||||
your trackpoint's event node. Try to use trackpoint and verify the
|
||||
multiplier is good enough. If not, adjust the `.quirks` file and re-run the
|
||||
`libinput debug-gui`. Note that the `libinput debug-gui` always feels
|
||||
less responsive than libinput would behave in a normal install.
|
||||
|
||||
Once the trackpoint behaves correctly you are ready to test the system
|
||||
libinput:
|
||||
|
||||
@verbatim
|
||||
$ sudo cp data/99-trackpoint-override.quirks /etc/libinput/local-overrides.quirks
|
||||
@endverbatim
|
||||
|
||||
Now verify the override is seen by the system libinput
|
||||
@verbatim
|
||||
$ libinput quirks list
|
||||
AttrTrackpointMultiplier=1.0
|
||||
@endverbatim
|
||||
|
||||
If the multiplier is listed, restart your Wayland session or X server. The
|
||||
new multiplier is now applied to your trackpoint.
|
||||
|
||||
If the trackpoint behavior is acceptable, you are ready to submit this file
|
||||
upstream. First, find add a more precise match for the device so it only
|
||||
applies to the built-in trackpoint on your laptop model. Usually a
|
||||
variation of the following is sufficient:
|
||||
|
||||
@verbatim
|
||||
[Trackpoint Override]
|
||||
MatchUdevType=pointingstick
|
||||
MatchName=*TPPS/2 IBM TrackPoint*
|
||||
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadT440p*
|
||||
AttrTrackpointMultiplier=1.0
|
||||
@endverbatim
|
||||
|
||||
Look at your `/sys/class/dmi/id/modalias` file for the values to add. Verify
|
||||
that `libinput quirks list` still shows the `AttrTrackpointMultiplier`. If
|
||||
it does, then you should @ref reporting_bugs "report a bug" with the contents of
|
||||
the file. Alternatively, file a merge request with the data added.
|
||||
|
||||
|
||||
@section trackpoint_range_measure Measuring the trackpoint range
|
||||
|
||||
This section describes how to measure the trackpoint range and apply @ref
|
||||
device-quirks to make this range known to libinput. libinput provides the tool
|
||||
`libinput measure trackpoint-range` for this task. This is an interactive
|
||||
tool and prints its instructions on the commandline. Example output from
|
||||
this tool is below:
|
||||
This section only applied to libinput version 1.9.x, 1.10.x, and 1.11.x and
|
||||
has been removed. See @ref trackpoint_multiplier for versions 1.12.x and later.
|
||||
|
||||
@verbatim
|
||||
$ sudo libinput measure trackpoint-range
|
||||
This tool measures the commonly used pressure range of the
|
||||
trackpoint. Push the trackpoint:
|
||||
- Four times around the screen edges
|
||||
- From the top left to the bottom right and back, twice
|
||||
- From the top right to the bottom left and back, twice
|
||||
A minimum of 1000 events for each axis is required
|
||||
|
||||
Movements should emulate fast pointer movement on the screen
|
||||
but not use excessive pressure that would not be used
|
||||
during day-to-day movement. For best results, run this tool
|
||||
several times to get an idea of the common range.
|
||||
|
||||
Trackpoint sends: max x: 19, max y: 23 samples [121, 121]
|
||||
@endverbatim
|
||||
|
||||
Once sufficient samples have been collected, the tool prints a simplified
|
||||
histogram for x and y axis deltas. This histogram should be used to
|
||||
<b>estimate</b> the appropriate trackpoint range. For example, let's look at
|
||||
the histogram below:
|
||||
|
||||
@verbatim
|
||||
Histogram for x axis deltas, in counts of 5
|
||||
-30:
|
||||
-29:
|
||||
-28: +
|
||||
-27: +
|
||||
-26: ++
|
||||
-25: ++++
|
||||
-24: +++++
|
||||
-23: ++
|
||||
-22: ++++++
|
||||
-21: +++
|
||||
-20: ++++
|
||||
-19: +++++++
|
||||
-18: ++++++++++++
|
||||
-17: ++++++++++++
|
||||
-16: ++++++++++++
|
||||
-15: ++++
|
||||
-14: +++++
|
||||
-13: +++++
|
||||
-12: ++++++
|
||||
-11: +++++
|
||||
-10: +++
|
||||
-9: ++++
|
||||
-8: +++++++
|
||||
-7: +++++++
|
||||
-6: ++++++++++++
|
||||
-5: ++++++++++++
|
||||
-4: ++++++++++++
|
||||
-3: +++++++++
|
||||
-2: +++++++++
|
||||
-1: ++++++++
|
||||
0: +++++++
|
||||
1: +++++
|
||||
2: +++++
|
||||
3: ++++++
|
||||
4: ++++++
|
||||
5: +++++++
|
||||
6: ++++
|
||||
7: ++
|
||||
8: +++
|
||||
9: +++
|
||||
10: +++
|
||||
11: +++
|
||||
12: +++
|
||||
13: ++++
|
||||
14: ++++++
|
||||
15: ++++
|
||||
16: ++++
|
||||
17: ++++
|
||||
18: ++++++
|
||||
19: +++++++
|
||||
20: ++++
|
||||
21: ++++++
|
||||
22: ++++++
|
||||
23: ++++++
|
||||
24: ++++++
|
||||
25: +++++++++
|
||||
26: +++++++
|
||||
27: ++++++++
|
||||
28: +++++
|
||||
29: ++
|
||||
30: ++
|
||||
31: +
|
||||
32:
|
||||
33:
|
||||
34:
|
||||
@endverbatim
|
||||
|
||||
The 0 delta is the neutral state, each + represents 5 events with that
|
||||
delta value. Note how the curve is distributed, it's not a classic bell
|
||||
curve. That can be a factor of the input provided or the firmware-based
|
||||
pointer acceleration.
|
||||
|
||||
Overall, the majority of events appear to be in the 0-25 range with a few
|
||||
outliers. So the trackpoint range libinput should use for this particular
|
||||
device would be 25. Note how there is a fair bit of guesswork involved, a
|
||||
trackpoint's data is never clean enough to get a definitive value. It is
|
||||
generally better to take a (slightly) smaller range than one too large.
|
||||
|
||||
The device quirk set is `AttrTrackpointRange=25`. See @ref
|
||||
device-quirks for details on how to apply device quirks.
|
||||
If using libinput version 1.11.x or earlier, please see
|
||||
<a href="https://wayland.freedesktop.org/libinput/doc/1.11.0/trackpoints.html#trackpoint_range_measure">
|
||||
the 1.11.0 documentation</a>
|
||||
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -421,6 +421,7 @@ if get_option('documentation')
|
|||
'doc/svg/thumb-detection.svg',
|
||||
'doc/svg/top-software-buttons.svg',
|
||||
'doc/svg/touchscreen-gestures.svg',
|
||||
'doc/svg/trackpoint-delta-illustration.svg',
|
||||
'doc/svg/twofinger-scrolling.svg',
|
||||
# style files
|
||||
'doc/style/header.html',
|
||||
|
|
|
|||
61
src/evdev.c
61
src/evdev.c
|
|
@ -956,7 +956,7 @@ evdev_init_accel(struct evdev_device *device,
|
|||
if (which == LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT)
|
||||
filter = create_pointer_accelerator_filter_flat(device->dpi);
|
||||
else if (device->tags & EVDEV_TAG_TRACKPOINT)
|
||||
filter = create_pointer_accelerator_filter_trackpoint(device->trackpoint_range);
|
||||
filter = create_pointer_accelerator_filter_trackpoint(device->trackpoint_multiplier);
|
||||
else if (device->dpi < DEFAULT_MOUSE_DPI)
|
||||
filter = create_pointer_accelerator_filter_linear_low_dpi(device->dpi);
|
||||
else
|
||||
|
|
@ -1176,59 +1176,36 @@ evdev_read_wheel_tilt_props(struct evdev_device *device)
|
|||
return flags;
|
||||
}
|
||||
|
||||
static inline int
|
||||
evdev_get_trackpoint_range(struct evdev_device *device)
|
||||
static inline double
|
||||
evdev_get_trackpoint_multiplier(struct evdev_device *device)
|
||||
{
|
||||
struct quirks_context *quirks;
|
||||
struct quirks *q;
|
||||
const char *prop;
|
||||
uint32_t range = DEFAULT_TRACKPOINT_RANGE;
|
||||
double multiplier = 1.0;
|
||||
|
||||
if (!(device->tags & EVDEV_TAG_TRACKPOINT))
|
||||
return DEFAULT_TRACKPOINT_RANGE;
|
||||
return 1.0;
|
||||
|
||||
quirks = evdev_libinput_context(device)->quirks;
|
||||
q = quirks_fetch_for_device(quirks, device->udev_device);
|
||||
if (q && quirks_get_uint32(q, QUIRK_ATTR_TRACKPOINT_RANGE, &range)) {
|
||||
goto out;
|
||||
if (q) {
|
||||
quirks_get_double(q, QUIRK_ATTR_TRACKPOINT_MULTIPLIER, &multiplier);
|
||||
quirks_unref(q);
|
||||
}
|
||||
|
||||
evdev_log_info(device,
|
||||
"trackpoint does not have a specified range, "
|
||||
"guessing... see %strackpoints.html\n",
|
||||
HTTP_DOC_LINK);
|
||||
|
||||
prop = udev_device_get_property_value(device->udev_device,
|
||||
"POINTINGSTICK_SENSITIVITY");
|
||||
if (prop) {
|
||||
int sensitivity;
|
||||
|
||||
if (!safe_atoi(prop, &sensitivity) ||
|
||||
(sensitivity < 0.0 || sensitivity > 255)) {
|
||||
evdev_log_error(device,
|
||||
"trackpoint sensitivity property is present but invalid, "
|
||||
"using %d instead\n",
|
||||
DEFAULT_TRACKPOINT_SENSITIVITY);
|
||||
sensitivity = DEFAULT_TRACKPOINT_SENSITIVITY;
|
||||
}
|
||||
range = 1.0 * DEFAULT_TRACKPOINT_RANGE *
|
||||
sensitivity/DEFAULT_TRACKPOINT_SENSITIVITY;
|
||||
|
||||
evdev_log_debug(device,
|
||||
"trackpoint udev sensitivity is %d\n",
|
||||
sensitivity);
|
||||
if (multiplier <= 0.0) {
|
||||
evdev_log_bug_libinput(device,
|
||||
"trackpoint multiplier %.2f is invalid\n",
|
||||
multiplier);
|
||||
multiplier = 1.0;
|
||||
}
|
||||
|
||||
out:
|
||||
quirks_unref(q);
|
||||
if (multiplier != 1.0)
|
||||
evdev_log_info(device,
|
||||
"trackpoint device set to range %.2f\n",
|
||||
multiplier);
|
||||
|
||||
if (range == 0) {
|
||||
evdev_log_bug_libinput(device, "trackpoint range is zero\n");
|
||||
range = DEFAULT_TRACKPOINT_RANGE;
|
||||
}
|
||||
|
||||
evdev_log_info(device, "trackpoint device set to range %d\n", range);
|
||||
return range;
|
||||
return multiplier;
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
|
@ -1749,7 +1726,7 @@ evdev_configure_device(struct evdev_device *device)
|
|||
evdev_tag_external_mouse(device, device->udev_device);
|
||||
evdev_tag_trackpoint(device, device->udev_device);
|
||||
device->dpi = evdev_read_dpi_prop(device);
|
||||
device->trackpoint_range = evdev_get_trackpoint_range(device);
|
||||
device->trackpoint_multiplier = evdev_get_trackpoint_multiplier(device);
|
||||
|
||||
device->seat_caps |= EVDEV_DEVICE_POINTER;
|
||||
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ struct evdev_device {
|
|||
bool is_mt;
|
||||
bool is_suspended;
|
||||
int dpi; /* HW resolution */
|
||||
int trackpoint_range; /* trackpoint max delta */
|
||||
double trackpoint_multiplier; /* trackpoint constant multiplier */
|
||||
struct ratelimit syn_drop_limit; /* ratelimit for SYN_DROPPED logging */
|
||||
struct ratelimit nonpointer_rel_limit; /* ratelimit for REL_* events from non-pointer devices */
|
||||
uint32_t model_flags;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ struct trackpoint_accelerator {
|
|||
|
||||
struct pointer_trackers trackers;
|
||||
double speed_factor;
|
||||
|
||||
double multiplier;
|
||||
};
|
||||
|
||||
double
|
||||
|
|
@ -76,16 +78,20 @@ trackpoint_accelerator_filter(struct motion_filter *filter,
|
|||
{
|
||||
struct trackpoint_accelerator *accel_filter =
|
||||
(struct trackpoint_accelerator *)filter;
|
||||
struct device_float_coords multiplied;
|
||||
struct normalized_coords coords;
|
||||
double f;
|
||||
double velocity;
|
||||
|
||||
trackers_feed(&accel_filter->trackers, unaccelerated, time);
|
||||
multiplied.x = unaccelerated->x * accel_filter->multiplier;
|
||||
multiplied.y = unaccelerated->y * accel_filter->multiplier;
|
||||
|
||||
trackers_feed(&accel_filter->trackers, &multiplied, time);
|
||||
velocity = trackers_velocity(&accel_filter->trackers, time);
|
||||
|
||||
f = trackpoint_accel_profile(filter, data, velocity, time);
|
||||
coords.x = unaccelerated->x * f;
|
||||
coords.y = unaccelerated->y * f;
|
||||
coords.x = multiplied.x * f;
|
||||
coords.y = multiplied.y * f;
|
||||
|
||||
return coords;
|
||||
}
|
||||
|
|
@ -95,11 +101,12 @@ trackpoint_accelerator_filter_noop(struct motion_filter *filter,
|
|||
const struct device_float_coords *unaccelerated,
|
||||
void *data, uint64_t time)
|
||||
{
|
||||
|
||||
struct trackpoint_accelerator *accel_filter =
|
||||
(struct trackpoint_accelerator *)filter;
|
||||
struct normalized_coords coords;
|
||||
|
||||
coords.x = unaccelerated->x;
|
||||
coords.y = unaccelerated->y;
|
||||
coords.x = unaccelerated->x * accel_filter->multiplier;
|
||||
coords.y = unaccelerated->y * accel_filter->multiplier;
|
||||
|
||||
return coords;
|
||||
}
|
||||
|
|
@ -175,27 +182,29 @@ struct motion_filter_interface accelerator_interface_trackpoint = {
|
|||
};
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_trackpoint(int max_hw_delta)
|
||||
create_pointer_accelerator_filter_trackpoint(double multiplier)
|
||||
{
|
||||
struct trackpoint_accelerator *filter;
|
||||
|
||||
assert(multiplier > 0.0);
|
||||
|
||||
/* Trackpoints are special. They don't have a movement speed like a
|
||||
* mouse or a finger, instead they send a stream of events based on
|
||||
* the pressure applied.
|
||||
*
|
||||
* Physical ranges on a trackpoint are the max values for relative
|
||||
* deltas, but these are highly device-specific.
|
||||
* deltas, but these are highly device-specific and unreliable to
|
||||
* measure.
|
||||
*
|
||||
* Instead, we just have a constant multiplier we have in the quirks
|
||||
* system.
|
||||
*/
|
||||
|
||||
filter = zalloc(sizeof *filter);
|
||||
if (!filter)
|
||||
return NULL;
|
||||
|
||||
/* FIXME: should figure out something here to deal with the
|
||||
* trackpoint range/max hw delta. Or we just make it a literal
|
||||
* "magic" number and live with it.
|
||||
*/
|
||||
filter->multiplier = multiplier;
|
||||
|
||||
trackers_init(&filter->trackers);
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ struct motion_filter *
|
|||
create_pointer_accelerator_filter_lenovo_x230(int dpi);
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_trackpoint(int max_delta);
|
||||
create_pointer_accelerator_filter_trackpoint(double multiplier);
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_tablet(int xres, int yres);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@
|
|||
|
||||
/* The HW DPI rate we normalize to before calculating pointer acceleration */
|
||||
#define DEFAULT_MOUSE_DPI 1000
|
||||
#define DEFAULT_TRACKPOINT_RANGE 20
|
||||
#define DEFAULT_TRACKPOINT_SENSITIVITY 128
|
||||
|
||||
#define ANSI_HIGHLIGHT "\x1B[0;1;39m"
|
||||
|
|
|
|||
|
|
@ -265,6 +265,7 @@ quirk_get_name(enum quirk q)
|
|||
case QUIRK_ATTR_PALM_PRESSURE_THRESHOLD: return "AttrPalmPressureThreshold";
|
||||
case QUIRK_ATTR_RESOLUTION_HINT: return "AttrResolutionHint";
|
||||
case QUIRK_ATTR_TRACKPOINT_RANGE: return "AttrTrackpointRange";
|
||||
case QUIRK_ATTR_TRACKPOINT_MULTIPLIER: return "AttrTrackpointMultiplier";
|
||||
case QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD: return "AttrThumbPressureThreshold";
|
||||
default:
|
||||
abort();
|
||||
|
|
@ -642,6 +643,7 @@ parse_attr(struct quirks_context *ctx,
|
|||
struct quirk_dimensions dim;
|
||||
struct quirk_range range;
|
||||
unsigned int v;
|
||||
double d;
|
||||
|
||||
if (streq(key, quirk_get_name(QUIRK_ATTR_SIZE_HINT))) {
|
||||
p->id = QUIRK_ATTR_SIZE_HINT;
|
||||
|
|
@ -714,6 +716,13 @@ parse_attr(struct quirks_context *ctx,
|
|||
p->type = PT_UINT;
|
||||
p->value.u = v;
|
||||
rc = true;
|
||||
} else if (streq(key, quirk_get_name(QUIRK_ATTR_TRACKPOINT_MULTIPLIER))) {
|
||||
p->id = QUIRK_ATTR_TRACKPOINT_MULTIPLIER;
|
||||
if (!safe_atod(value, &d))
|
||||
goto out;
|
||||
p->type = PT_DOUBLE;
|
||||
p->value.d = d;
|
||||
rc = true;
|
||||
} else if (streq(key, quirk_get_name(QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD))) {
|
||||
p->id = QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD;
|
||||
if (!safe_atou(value, &v))
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ enum quirk {
|
|||
QUIRK_ATTR_PALM_PRESSURE_THRESHOLD,
|
||||
QUIRK_ATTR_RESOLUTION_HINT,
|
||||
QUIRK_ATTR_TRACKPOINT_RANGE,
|
||||
QUIRK_ATTR_TRACKPOINT_MULTIPLIER,
|
||||
QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -616,6 +616,7 @@ tools_list_device_quirks(struct quirks_context *ctx,
|
|||
QUIRK_ATTR_PALM_PRESSURE_THRESHOLD,
|
||||
QUIRK_ATTR_RESOLUTION_HINT,
|
||||
QUIRK_ATTR_TRACKPOINT_RANGE,
|
||||
QUIRK_ATTR_TRACKPOINT_MULTIPLIER,
|
||||
QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD,
|
||||
};
|
||||
enum quirk *q;
|
||||
|
|
@ -696,6 +697,11 @@ tools_list_device_quirks(struct quirks_context *ctx,
|
|||
snprintf(buf, sizeof(buf), "%s=%s", name, s);
|
||||
callback(userdata, buf);
|
||||
break;
|
||||
case QUIRK_ATTR_TRACKPOINT_MULTIPLIER:
|
||||
quirks_get_double(quirks, *q, &d);
|
||||
snprintf(buf, sizeof(buf), "%s=%0.2f\n", name, d);
|
||||
callback(userdata, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue