libinput: Trackpoints and Pointing Sticks

Trackpoints and Pointing Sticks

This page provides an overview of trackpoint handling in libinput, also refered to as Pointing Stick or Trackstick.

The device itself is usually a round plastic stick between the G, H and B keys with a set of buttons below the space bar.

A trackpoint

libinput always treats the buttons below the space bar as the buttons that belong to the trackpoint even on the few laptops where the buttons are not physically wired to the trackpoint device anyway, see Lenovo *40 series touchpad support.

Trackpoint devices have On-Button scrolling enabled by default. This may interfer with middle-button dragging, if middle-button dragging is required by a user then button scrolling must be disabled.

# Motion range on trackpoints

It is difficult to associate motion on a trackpoint with a physical reference. Unlike mice or touchpads where the motion can be measured in mm, the trackpoint only responds to pressure. Without special equipment it is impossible to measure identical pressure values across 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.

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 Measuring the trackpoint range.

# Measuring the trackpoint range

This section describes how to measure the trackpoint range and apply a hwdb entry 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:

$ 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]

Once sufficient samples have been collected, the tool prints a simplified histogram for x and y axis deltas. This histogram should be used to estimate the appropriate trackpoint range. For example, let's look at the histogram below:

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:

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 udev property to set is `LIBINPUT_ATTR_TRACKPOINT_RANGE=25`. See Modifying the hwdb for details on how to apply this property.