Commit ef5204fd authored by Peter Hutterer's avatar Peter Hutterer

tools: revamp the touchpad-pressure measuring tool

Let's hope this one is more obvious to use for users.
Signed-off-by: Peter Hutterer's avatarPeter Hutterer <peter.hutterer@who-t.net>
parent 9351f54d
......@@ -38,27 +38,43 @@ statistics, including whether a touch is/was considered logically down.
Example output of the tool is below: ::
$ sudo libinput measure touchpad-pressure
Ready for recording data.
Pressure range used: 8:10
Palm pressure range used: 65535
Place a single finger on the touchpad to measure pressure values.
Ctrl+C to exit
&nbsp;
Sequence 1190 pressure: min: 39 max: 48 avg: 43 median: 44 tags: down
Sequence 1191 pressure: min: 49 max: 65 avg: 62 median: 64 tags: down
Sequence 1192 pressure: min: 40 max: 78 avg: 64 median: 66 tags: down
Sequence 1193 pressure: min: 36 max: 83 avg: 70 median: 73 tags: down
Sequence 1194 pressure: min: 43 max: 76 avg: 72 median: 74 tags: down
Touchpad pressure: 47 min: 47 max: 86 tags: down
$ sudo libinput measure touchpad-pressure
Using Synaptics TM2668-002: /dev/input/event21
This is an interactive tool
Place a single finger on the touchpad to measure pressure values.
Check that:
- touches subjectively perceived as down are tagged as down
- touches with a thumb are tagged as thumb
- touches with a palm are tagged as palm
If the touch states do not match the interaction, re-run
with --touch-thresholds=down:up using observed pressure values.
See --help for more options.
Press Ctrl+C to exit
+-------------------------------------------------------------------------------+
| Thresh | 70 | 60 | 130 | 100 | |
+-------------------------------------------------------------------------------+
| Touch | down | up | palm | thumb | min | max | p | avg | median |
+-------------------------------------------------------------------------------+
| 178 | x | x | | | 75 | 75 | 0 | 75 | 75 |
| 179 | x | x | | | 35 | 88 | 0 | 77 | 81 |
| 180 | x | x | | x | 65 | 113 | 0 | 98 | 98 |
| 181 | x | x | | x | 50 | 101 | 0 | 86 | 90 |
| 182 | x | x | | | 40 | 80 | 0 | 66 | 70 |
| 183 | x | | | | 43 | 78 | 78 | |
...
The example output shows five completed touch sequences and one ongoing one.
For each, the respective minimum and maximum pressure values are printed as
well as some statistics. The ``tags`` show that sequence was considered
logically down at some point. This is an interactive tool and its output may
change frequently. Refer to the **libinput-measure-touchpad-pressure(1)** man
page for more details.
well as some statistics. The ``down`` column show that each sequence was
considered logically down at some point, two of the sequences were considered
thumbs. This is an interactive tool and its output may change frequently. Refer
to the **libinput-measure-touchpad-pressure(1)** man page for more details.
By default, this tool uses the :ref:`device-quirks` for the pressure range. To
narrow down on the best values for your device, specify the 'logically down'
......
......@@ -37,6 +37,51 @@ except ModuleNotFoundError as e:
sys.exit(1)
class TableFormatter(object):
ALIGNMENT = 3
def __init__(self):
self.colwidths = []
@property
def width(self):
return sum(self.colwidths) + 1
def headers(self, args):
s = '|'
align = self.ALIGNMENT - 1 # account for |
for arg in args:
# +2 because we want space left/right of text
w = ((len(arg) + 2 + align) // align) * align
self.colwidths.append(w + 1)
s += ' {:^{width}s} |'.format(arg, width=w - 2)
return s
def values(self, args):
s = '|'
for w, arg in zip(self.colwidths, args):
w -= 1 # width includes | separator
if type(arg) == str:
# We want space margins for strings
s += ' {:{width}s} |'.format(arg, width=w - 2)
elif type(arg) == bool:
s += '{:^{width}s}|'.format('x' if arg else ' ', width=w)
else:
s += '{:^{width}d}|'.format(arg, width=w)
if len(args) < len(self.colwidths):
s += '|'.rjust(self.width - len(s), ' ')
return s
def separator(self):
return '+' + '-' * (self.width - 2) + '+'
fmt = TableFormatter()
class Range(object):
"""Class to keep a min/max of a value around"""
def __init__(self):
......@@ -112,36 +157,19 @@ class TouchSequence(object):
def _str_summary(self):
if not self.points:
return "{:78s}".format("Sequence: no pressure values recorded")
s = "Sequence {} pressure: "\
"min: {:3d} max: {:3d} avg: {:3d} median: {:3d} tags:" \
.format(
self.tracking_id,
self.prange.min,
self.prange.max,
self.avg(),
self.median()
)
if self.was_down:
s += " down"
if self.was_palm:
s += " palm"
if self.was_thumb:
s += " thumb"
return fmt.values([self.tracking_id, False, False, False, False,
'No pressure values recorded'])
s = fmt.values([self.tracking_id, self.was_down, True, self.was_palm,
self.was_thumb, self.prange.min, self.prange.max, 0,
self.avg(), self.median()])
return s
def _str_state(self):
s = "Touchpad pressure: {:3d} min: {:3d} max: {:3d} tags: {} {} {}" \
.format(
self.points[-1].pressure,
self.prange.min,
self.prange.max,
"down" if self.is_down else " ",
"palm" if self.is_palm else " ",
"thumb" if self.is_thumb else " "
)
s = fmt.values([self.tracking_id, self.is_down, not self.is_down,
self.is_palm, self.is_thumb, self.prange.min,
self.prange.max, self.points[-1].pressure])
return s
......@@ -227,8 +255,8 @@ def handle_key(device, event):
libevdev.EV_KEY.BTN_TOOL_QUINTTAP
]
if event.code in tapcodes and event.value > 0:
print("\rThis tool cannot handle multiple fingers, "
"output will be invalid", file=sys.stderr)
print('\r\033[2KThis tool cannot handle multiple fingers, '
'output will be invalid')
def handle_abs(device, event):
......@@ -239,7 +267,7 @@ def handle_abs(device, event):
try:
s = device.current_sequence()
s.finalize()
print("\r{}".format(s))
print("\r\033[2K{}".format(s))
except IndexError:
# If the finger was down at startup
pass
......@@ -248,7 +276,7 @@ def handle_abs(device, event):
try:
s = device.current_sequence()
s.append(Touch(pressure=event.value))
print("\r{}".format(s), end="")
print("\r\033[2K{}".format(s), end="")
except IndexError:
# If the finger was down at startup
pass
......@@ -262,12 +290,27 @@ def handle_event(device, event):
def loop(device):
print("Ready for recording data.")
print("Pressure range used: {}:{}".format(device.down, device.up))
print("Palm pressure range used: {}".format(device.palm))
print("Thumb pressure range used: {}".format(device.thumb))
print("Place a single finger on the touchpad to measure pressure values.\n"
"Ctrl+C to exit\n")
print('This is an interactive tool')
print()
print("Place a single finger on the touchpad to measure pressure values.")
print('Check that:')
print('- touches subjectively perceived as down are tagged as down')
print('- touches with a thumb are tagged as thumb')
print('- touches with a palm are tagged as palm')
print()
print('If the touch states do not match the interaction, re-run')
print('with --touch-thresholds=down:up using observed pressure values.')
print('See --help for more options.')
print()
print("Press Ctrl+C to exit")
print()
headers = fmt.headers(['Touch', 'down', 'up', 'palm', 'thumb', 'min', 'max', 'p', 'avg', 'median'])
print(fmt.separator())
print(fmt.values(['Thresh', device.down, device.up, device.palm, device.thumb]))
print(fmt.separator())
print(headers)
print(fmt.separator())
while True:
for event in device.events():
......@@ -316,7 +359,9 @@ def main(args):
loop(device)
except KeyboardInterrupt:
pass
print('\r\033[2K{}'.format(fmt.separator()))
print()
except (PermissionError, OSError):
print("Error: failed to open device")
except InvalidDeviceError as e:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment