Compare commits

...

74 commits
1.31.0 ... main

Author SHA1 Message Date
Peter Hutterer
e53c2141b3 util: add a free_clear() helper to reset after free
Same as e.g. g_clear_pointer(). Switch a number of obvious call sites
over to use this, the rest will come over time.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1472>
2026-04-24 00:24:24 +00:00
Peter Hutterer
c2c8414605 tools: update the tool option parsing test for newer options
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1473>
2026-04-23 23:21:07 +00:00
Peter Hutterer
86a775b3ca tools/debug-tablet: guard against open() failures
This is a debugging tool so we don't expect NDEBUG but let's handle
errors correctly anyway.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1467>
2026-04-22 04:53:14 +00:00
Peter Hutterer
0fa334600d tools: always open with O_CLOEXEC
Doesn't have any effect but it's easy enough and good practice to do.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1467>
2026-04-22 04:53:14 +00:00
Peter Hutterer
a5a9d2d8df tools: guard against zero-length os-release files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1467>
2026-04-22 04:53:14 +00:00
Peter Hutterer
8afdc52eaf tools: Use xclose() over close()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1467>
2026-04-22 04:53:14 +00:00
Peter Hutterer
e53a78f7d7 tools/record: fix missing NULL check on tmpfile() return value
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1467>
2026-04-22 04:53:14 +00:00
Peter Hutterer
a51398cb8d tools: use save_atod instead of atof()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1467>
2026-04-22 04:53:13 +00:00
Peter Hutterer
74b4ca132f tools/debug-tablet-pad: add bounds checks for array accesses
A few not-really-an-issue fixes found by Claude:

1. ctx->buttons_down[number]: the 'number' value comes from
   libinput_event_tablet_pad_get_button_number() and is written into
   a fixed-size array of 32 elements without bounds checking. A crafted
   or malicious device reporting button numbers >= 32 causes a stack
   buffer overflow.

2. ctx->ring[number], ctx->strip[number], ctx->dial[number]: these are
   fixed-size arrays of 2 elements each. Ring/strip/dial numbers from
   libinput events are used as indices without bounds checking. Values
   >= 2 cause out-of-bounds writes.

3. assert()-based error handling for open() and libevdev_new_from_fd():
   assert() is compiled to a no-op in release builds (NDEBUG). This
   means that in release builds, a failed open() returns fd=-1, and
   libevdev_new_from_fd() is called with an invalid fd. The result is
   undefined behavior.

4. Variable-length array (VLA) 'empty[termwidth]' in print_bar():
   termwidth comes from an ioctl(TIOCGWINSZ) call and could be very
   large, causing a stack overflow. Replace with a fixed-size buffer.

None of these really matter for a niche debugging tool.

Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1467>
2026-04-22 04:53:13 +00:00
Peter Hutterer
f899da7552 tools/ptraccel-debug: replace atoi() with safe_atoi()
It's a niche development/debugging tool, argument parsing issues aren't
really something we need to care about but hey, this change is easy.

Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1467>
2026-04-22 04:53:13 +00:00
Peter Hutterer
20b52ffafc udev: use xclose() instead of close()
xclose does the fd == -1 dance which makes analyzers happier.

Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1467>
2026-04-22 04:53:13 +00:00
Peter Hutterer
c276c9579e plugin: use safe_strdup() instead of strdup()
safe_strdup() handles NULL correctly instead of just blowing up. This
shouldn't matter because without a name our plugins won't get here but
let's do this anwyay.

Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1467>
2026-04-22 04:53:13 +00:00
Peter Hutterer
d97983ee5e util: use lstat() instead of stat() in rmdir_r to prevent symlink attacks
stat() follows symbolic links which is definitely something we don't
want. If an attacker can place a symlink inside a directory being
recursively deleted (e.g. a temporary directory), stat() will report the
type of the symlink's target rather than the symlink itself. If the
target is a directory, rmdir_r() will follow the symlink and recursively
delete the target directory's contents outside the intended directory
tree.

This has no real effect, this is only used in the test suite.

Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1467>
2026-04-22 04:53:13 +00:00
Peter Hutterer
b87532dfb5 touchpad: replace sprintf strv_join in the touch state debugging
This is purely to make Claude happy, the function is ifdef'd out and to
actually hit the limit we'd need more than ~25 slots active.

Anyway, the strv helpers make for much nicer code anyway.

Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1467>
2026-04-22 04:53:13 +00:00
Peter Hutterer
75d4acfe94 util: allow for 'e' in safe_atod strings
1.5e2 is a valid string, so let's parse those.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1467>
2026-04-22 04:53:13 +00:00
Peter Hutterer
cc72db48fb doc/user: add an illustration of the touch arbitration rectangle
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1462>
2026-04-21 11:12:59 +10:00
Peter Hutterer
0e4492155f doc: add HOLD_END to libinput_event_gesture_get_cancelled() doc
The implementation accepts LIBINPUT_EVENT_GESTURE_HOLD_END in
require_event_type() but the API documentation only listed SWIPE_END
and PINCH_END. This was likely missed when hold gesture support was
added.

Co-authored-by: Claude <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1469>
2026-04-20 01:10:05 +00:00
Peter Hutterer
2da19a8802 doc: remove ID_INPUT from lua plugin udev properties list
The code in libinput-plugin-lua.c filters udev properties with
strstartswith(key, "ID_INPUT_") which requires a trailing underscore.
The bare 'ID_INPUT' property does not match this filter and is never
included in the properties table provided to plugins.

Co-authored-by: Claude <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1469>
2026-04-20 01:10:05 +00:00
Peter Hutterer
37e1dfd2d1 doc: update multi-device recording docs, --multiple is deprecated
The --multiple flag is deprecated and a no-op in the current code
(libinput-record.c). Multiple devices can simply be specified as
arguments on the commandline. Update the documentation to reflect
the current usage.

Co-authored-by: Claude <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1469>
2026-04-20 01:10:05 +00:00
Peter Hutterer
f87bae4ed2 doc: fix libinput replay output format in tools.rst
The example output showed 'Name: /dev/input/eventN' but the actual code
(libinput-replay.py) prints '/dev/input/eventN: Name'. Update the
example to match the actual output format.

Co-authored-by: Claude <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1469>
2026-04-20 01:10:05 +00:00
Peter Hutterer
20a53db063 doc: fix ClickPad scroll method description in scrolling.rst
ClickPads support both two-finger scrolling and edge scrolling, not
two-finger scrolling only. The code in evdev-mt-touchpad.c always
includes LIBINPUT_CONFIG_SCROLL_EDGE in the supported methods and adds
LIBINPUT_CONFIG_SCROLL_2FG if the touchpad supports 2+ touches.

Co-authored-by: Claude <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1469>
2026-04-20 01:10:05 +00:00
Peter Hutterer
f854eb0515 doc: fix typos and misspellings across documentation
Co-authored-by: Claude <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1469>
2026-04-20 01:10:05 +00:00
Peter Hutterer
60028ea595 doc: fix simplified hold gesture table in gestures.rst
The simplified table showed 'Finger 1 down' producing '<no event>' but
all the detailed examples later in the same document show that a single
finger down triggers a hold begin event with finger count 1, followed by
a cancel and new begin when the second finger arrives. Update the
simplified table to be consistent with the detailed examples and the
actual implementation.

Co-authored-by: Claude <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1469>
2026-04-20 01:10:05 +00:00
Peter Hutterer
2400a5c128 doc: fix reference to non-existent 'hold update' event in gestures.rst
There is no LIBINPUT_EVENT_GESTURE_HOLD_UPDATE event in the API.
When a finger is detected as thumb/palm during a hold and other fingers
remain, the implementation cancels the current hold and starts a new one
with an updated finger count. Update the documentation to describe the
actual behavior.

Co-authored-by: Claude <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1469>
2026-04-20 01:10:05 +00:00
Peter Hutterer
fdd43a4fcd touchpad: time the 3fg fast swipe timeout from the initial contact
We differ between a fast 3fg swipe and a 3fg drag based on whether we
move 5mm within 80ms of contact. Alas, the code started the timeout once
we had enough motion, not on initial contact.

Three fingers down, then resting for >80ms, then moving 5mm within the
subsequent 80ms would thus trigger a fast swipe because the timer wasn't
set until sufficient movement happened. Fix this by setting the timer
based on the initial touch point's time. This requires potentially
setting a negative timer to avoid duplicating parts of the state
machine.

Closes #1266

Fixes: fe1d44637f ("touchpad: add support for fast swipe when 3fg drag is enabled")
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1466>
2026-04-17 02:32:50 +00:00
Peter Hutterer
2bea0f3e4e tablet: extend touch arbitration rect to cover full tablet height
The arbitration rectangle previously only covered a region from 100mm
above the pen tip to 150mm below it (250mm total). This let a few
unintentional touches through such as when some of the fingers are
extended while using the pen. Likewise, a large hand could fall below
the bottom edge of the rectangle.

Change the rect to span the full height and width of the tablet while
keeping the same horizontal logic (200mm wide, starting 20mm from the
pen tip toward the hand side). Simplify a few things too, there is no
need for clipping the rect.

Related: #1276
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1463>
2026-04-16 05:10:53 +00:00
Peter Hutterer
5f29257569 util: use zalloc in stringbuf
zalloc() aborts on allocation failure and it's what we use everywhere
else.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1465>
2026-04-16 04:55:23 +00:00
Peter Hutterer
2ea3fb1d13 tablet-pad: use strdup_printf in sysfs path construction
This simplifies the code and means we don't have to deal with snprintf
return values to ensure we're not truncating.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1465>
2026-04-16 04:55:23 +00:00
Peter Hutterer
9d8a8b4530 util: use snprintf for PID formatting in backtrace helper
Use snprintf to make analyziers happier and bump the buffer size to 16.
That's way larger than we'll need given the kernel's PID_MAX_LIMIT
(4194304) but it doesn't cost us anything.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1465>
2026-04-16 04:55:23 +00:00
Peter Hutterer
e32202eeae util: check for NULL on realloc in _infmask_ensure_size
And abort if that ever happens because it really shouldn't.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1465>
2026-04-16 04:55:23 +00:00
Peter Hutterer
aa04f67b1c plugin: guard against unsigned underflow in plugin_has_mask
nevents should never be zero but let's prevent against an underflow, if
only to make the analyzers happy.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1465>
2026-04-16 04:55:23 +00:00
Peter Hutterer
8c06ceecb2 quirks: add missing modification warning to a quirks file
And add a test to make sure we don't forget this in the future.

Fixes: 488c0c9645 ("quirks: add quirk for the Wareus B15")
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1464>
2026-04-14 09:48:15 +10:00
Peter Hutterer
356c498fd4 lua: force text mode for loading plugins
luaL_loadfile() by default allows for both text files and precompiled
lua files. Precompiled files are not verified on load allowing for a
sandbox escape.

CVE-2026-35093

Fixes: #1271

Found-by: Koen Tange <koen@monokles.eu>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1459>
2026-04-01 23:53:12 +00:00
Peter Hutterer
45dfd0f030 lua: separate the API from the metatables
Previously we had one vtable for the libinputplugin and EvdevDevice
objects. This allowed plugins to call __gc(), a decidedly internal
method.

This fixes a use-after-free: A plugin that called EvdevDevice::__gc()
frees the plugin's copy of device->name but leaves the pointer in-place,
a subsequent call will thus cause a UAF read.

Fix this by separating what is the object's metatable from the public
methods that are accessible to a plugin.

CVE-2026-35094

Fixes: #1272

Found-by: Koen Tange <koen@monokles.eu>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1459>
2026-04-01 23:53:12 +00:00
David Santamaría Rogado
7face63bd5 quirks: add positivo vaio fe15 right button
Signed-off-by: David Santamaría Rogado <howl.nsp@gmail.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1458>
2026-03-30 00:07:52 +02:00
Artem Proskurnev
488c0c9645 quirks: add quirk for the Wareus B15
Fix:
https://gitlab.freedesktop.org/libinput/libinput/-/work_items/1267

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1457>
2026-03-28 12:39:42 +03:00
Richie Roy Jayme
baddf1e2b6 quirks: add support for Goodix touchpad GXTP5400:00 27C6:0F96
This commit adds a specific vendor HWID for Goodix Haptic Touchpad to
improve detection and handling.

Signed-off-by: Richie Roy Jayme <rjayme.jp@gmail.com>
Signed-off-by: Richie Roy Jayme <rjayme2@lenovo.com>
Reviewed-by: Vishnu Sankar <vishnuocv@gmail.com>
Reviewed-by: Vishnu Sankar <vsankar@lenovo.com>
Tested-by: Ameer Ivan Julkarnain <ajulkarnain1@lenovo.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1455>
2026-03-25 18:33:21 +09:00
Peter Hutterer
9baccdf44c touchpad: support automatic drag-lock when releasing at the edge
If drag-lock is disabled but we're in a tap-and-drag state and the
finger is released near the edge (within 5mm), enable automatic drag
lock for 400ms.  This allows a user to quickly reset the finger and
continue with the drag.

The 400ms is a randomly guessed timeout - if you're using tap-and-drag
without draglock, finger dexterity should be high enough that resetting
the single finger can be done quickly but it's also short enough to not
make the occasional delayed button be painful in day-to-day use.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1447>
2026-03-24 05:50:24 +00:00
Peter Hutterer
1486c7ae17 test: change where our finger ends up before releasing
No effect on the test right now but on some small test touchpads
this is close enough to the edge to mess with future tests.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1447>
2026-03-24 05:50:24 +00:00
Peter Hutterer
f97d0e6db1 doc/user: document sticky vs timeout based drag lock a bit better
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1447>
2026-03-24 05:50:23 +00:00
Peter Hutterer
1c4040ffa3 tools/debug-tablet: switch an snprintf to strvs
Less having to think about snprintf's buffer correctness

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1453>
2026-03-24 05:24:35 +00:00
Peter Hutterer
166201d9fc util: fix remaininig usec computation on 32 bits
Follow-up from commit dcbfbc4cf1 ("util: fix usec computation on 32 bits")
which didn't fix all instances, make this consistent.

Fixes: dcbfbc4cf1 ("util: fix usec computation on 32 bits")
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1453>
2026-03-24 05:24:35 +00:00
Peter Hutterer
7d15503b45 evdev: fix rel axis disabling on accelerometers
Copy/paste caused only the abs axes being disabled (REL_X == ABS_X,
etc. so the EV_REL bits had no effect).

Found-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1453>
2026-03-24 05:24:35 +00:00
Peter Hutterer
2dc491de1f Fix various typos
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1452>
2026-03-24 05:09:07 +00:00
Marcin Jahn
bb7aa004f8 quirks: add clevetura clvx s touchpad quirk
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1454>
2026-03-22 20:59:13 +01:00
Freeman Zhang
a1c5f35a69 Add Goodix haptic touchpad 27C6:0F90 support
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1451>
2026-03-22 10:53:44 +00:00
Freeman Zhang
57c71c567f Add Elan haptic touchpad 04F3:3355 support
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1450>
2026-03-22 12:37:19 +08:00
Peter Hutterer
ef9624a16b evdev: store the SYN_REPORT value in the frame
If the SYN_REPORT has a value of nonzero we need to keep that value in
the frame - our upper layers rely on this to detect repeat frames.

Closes #1261

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1449>
2026-03-19 00:09:30 +00:00
GKraats
dcbfbc4cf1 util: fix usec computation on 32 bits
Enforce the needed 64-bit computing on 32 bits.

Signed-off-by: GKraats <vd.kraats@hccnet.nl>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1446>
2026-03-18 00:25:48 +00:00
Peter Hutterer
ad857a51a4 tools/record: fix delta times not being relative
Missing last_time assignment caused the delta time between events to be
the total time.

Fixes: a202ed6115 ("Use a newtype usec_t for timestamps for better type-safety")
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1448>
2026-03-17 05:05:14 +00:00
Peter Hutterer
a521d054d4 tools: fix leak of evdev_prev in libinput-record
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1444>
2026-03-17 00:46:46 +00:00
Peter Hutterer
f86d5ab2ab test: add missing button state assertion for eraser button release
The second 'Expect button event' block in
tablet_eraser_button_different_buttons is missing the button state
assertion that the first block has. This event should be a
BUTTON_STATE_RELEASED (the eraser left proximity), but without the
check the test passes even if the state is wrong.

Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1444>
2026-03-17 00:46:46 +00:00
Peter Hutterer
32fd9ec95f tools: Remove dead eraser_button_button initialization to BTN_STYLUS
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1444>
2026-03-17 00:46:46 +00:00
Peter Hutterer
45150cc6ec tools: fix missing fd assignment in libinput-debug-tablet
The fd opened for the evdev device is never stored in ctx->fds[1].fd
so we never poll for it. Real impact was limited since we do poll for
the libinput fd and we process libevdev events whenever any of the fds
triggers.

Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1444>
2026-03-17 00:46:46 +00:00
Peter Hutterer
c8c1c07a2a tools: fix swapped fread arguments causing DMI modalias to always be "unknown"
fread(buf, sizeof(buf), 1, dmi) reads one block of 2048 bytes,
returning the number of complete blocks (0 or 1). Since DMI modalias
files are always shorter than 2048 bytes, fread returns 0 even when
data was successfully read into buf. The 'if (n > 0)' check then
always fails and the DMI string stays as "unknown".

Swap the size and nmemb arguments so fread returns the number of
bytes read instead.

Fixes: 0ecd08c134 ("tools: use __attribute__(cleanup)")

Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1444>
2026-03-17 00:46:46 +00:00
Peter Hutterer
b1f478b897 tools: fix pencil tablet tool type in libinput-record
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1444>
2026-03-17 00:46:45 +00:00
Peter Hutterer
333d7131ab tools: fix swapped strstartswith arguments in find_device()
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1444>
2026-03-17 00:46:45 +00:00
Peter Hutterer
cd9d6c66fd tablet: fix eraser button get_default_mode/get_default_button return values
Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1444>
2026-03-17 00:46:45 +00:00
Peter Hutterer
a0dc0997f5 meson.build: explicitly convert a boolean to string
Fixes:
  DEPRECATION: Variable substitution with boolean value 'MESON_ENABLED_DEBUG_GUI' is deprecated.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1445>
2026-03-13 12:15:21 +10:00
Peter Hutterer
c6813dc7d8 tools: add --compress-motion-events to the man page and zsh completion
Fixes: dc249b0ffe ("tools/debug-events: add ability to compress motion events")
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1443>
2026-03-11 14:22:40 +10:00
Ilya Kamenko
8dd25ece10 Fold hold-to-scroll into existing scroll button lock mode
Instead of adding a new ENABLED_HOLD enum value, modify the existing
ENABLED lock mode so that hold+scroll+release doesn't engage the lock.

Add a 500ms grace period: if the button was held and used to scroll for
longer than 500ms, releasing the button does not engage the lock
(temporary scroll). If released within 500ms (e.g. shaky hands
triggering accidental motion), the lock still engages as before.

This fixes the unintuitive behavior where the lock engages even after
actively scrolling, without requiring new API surface.

Closes: https://gitlab.freedesktop.org/libinput/libinput/-/issues/1259

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1435>
2026-03-10 23:12:25 +00:00
Mingcong Bai
43547b461b quirks: add Goodix pressure pad quirk for 27C6:01E7
This touchpad is found on the newly released Lenovo ThinkBook G8+ IPH.

Signed-off-by: Mingcong Bai <jeffbai@aosc.io>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1442>
2026-03-10 11:37:34 +08:00
David Santamaría Rogado
2ddc734114 test: set ID_INTEGRATION into test devices
Signed-off-by: David Santamaría Rogado <howl.nsp@gmail.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1429>
2026-03-10 02:27:36 +00:00
David Santamaría Rogado
819e943ab0 evdev: use udev's ID_INTEGRATION
Now we have in udev the ID_INTEGRATION propery that tells us if a device
is internal or external, use it while still allow hwdb and quirks to
override it.

In the future is possible that we could remove quirks for keyboards
integration and hwdb for touchpads and joysticks integration.

Signed-off-by: David Santamaría Rogado <howl.nsp@gmail.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1429>
2026-03-10 02:27:36 +00:00
David Santamaría Rogado
1c82aa1659 quirks: add some more goodix haptic touchpads
Signed-off-by: David Santamaría Rogado <howl.nsp@gmail.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1440>
2026-03-09 09:48:05 +01:00
David Santamaría Rogado
526130fe8d quirks: hp omnibook ultra flip 14 touch pressure
Add pressure attributes to make libinput measure touchpad-pressure
behave right.

Signed-off-by: David Santamaría Rogado <howl.nsp@gmail.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1430>
2026-03-09 01:34:07 +00:00
David Santamaría Rogado
b95840d36e quirks: hp omnibook ultra flip 14 improve rule set
Some initial units had 14t-fh000 instead 14-fh0xxx in their product name
but they are exactly the same model.

We could match both in product version SBKPF or in board product name
8CDE. Match board as seems the way hp-wmi kernel module uses to match.

While at it rewrite the entire huge comment to a little less huge
comment but with more really interesting info.

Signed-off-by: David Santamaría Rogado <howl.nsp@gmail.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1430>
2026-03-09 01:34:07 +00:00
Peter Hutterer
7726350420 tablet: allow for the eraser button to be any button
The previous restriction was BTN_STYLUS* or any button the pen
advertises. This is too restrictive - it works well enough for any pen
with less than 3 buttons (BTN_STYLUS3 is always available on those) but
otherwise it cannot work. A 3-button pen may not advertise any other
buttons, leaving us with the eraser button being a duplicate button. And
events cannot be distinquished between eraser button or real button.

Open up the configuration to effectively any BTN_ event code.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1436>
2026-03-09 01:14:21 +00:00
Peter Hutterer
cdcb827365 Fix the evdev_usage_is_button check for the BTN_STYLUS group
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1436>
2026-03-09 01:14:21 +00:00
Peter Hutterer
0a3ecbea24 tablet: fix missing linebreak after an error message
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1436>
2026-03-09 01:14:21 +00:00
BBaoVanC
db62bf7ab1 quirks/apple: Add AttrSizeHint to Magic Trackpad USB-C
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1437>
2026-03-04 04:53:28 +00:00
David Santamaría Rogado
9eae99d4fe quirks: microsoft surface keyboard event BTN_0
Apply AttrEventCode=-BTN_0 to all surface keyboards.

Fixes: #1251.

Signed-off-by: David Santamaría Rogado <howl.nsp@gmail.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1431>
2026-02-22 08:40:11 +00:00
David Santamaría Rogado
a86b8a0008 doc: list-quirks should be quirks list
while at it replace also a code comment in the same line.

Signed-off-by: David Santamaría Rogado <howl.nsp@gmail.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1432>
2026-02-20 19:56:46 +01:00
Sicelo A. Mhlongo
3428edf1ea doc/user: document keypad slide switch support
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1428>
2026-02-17 12:03:56 +02:00
197 changed files with 2079 additions and 450 deletions

View file

@ -45,6 +45,7 @@ __all_seats()
'--verbose[Use verbose output]' \
'--show-keycodes[Make all keycodes visible]' \
'--grab[Exclusively grab all opened devices]' \
'--compress-motion-events[Compress repeated motion events on a TTY]' \
'--device=[Use the given device with the path backend]:device:_files -W /dev/input/ -P /dev/input/' \
'--udev=[Listen for notifications on the given seat]:seat:__all_seats' \
'--apply-to=[Apply configuration options where the device name matches the pattern]:pattern' \

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 181 KiB

After

Width:  |  Height:  |  Size: 489 KiB

View file

@ -110,7 +110,7 @@ The most common matrices are:
.. math::
\begin{pmatrix}
-1 & 0 & 1 \\
1 & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & 1
\end{pmatrix}

View file

@ -87,7 +87,7 @@ suggested hwdb entry. ::
If there are discrepancies between the coordinate range the kernels
advertises and what what the touchpad sends, the hwdb entry should be added to the
advertises and what the touchpad sends, the hwdb entry should be added to the
``60-evdev.hwdb`` file provided by the `systemd project <https://github.com/systemd/systemd>`_.
An example commit can be found
`here <https://github.com/systemd/systemd/commit/26f667eac1c5e89b689aa0a1daef6a80f473e045>`_.

View file

@ -198,7 +198,7 @@ events is performed within the dispatch method.
evdev [label="evdev_device_dispatch()"]
plugins [label="plugin pipline"]
plugins [label="plugin pipeline"]
fallback [label="fallback_interface_process()"];
touchpad [label="tp_interface_process()"]

View file

@ -13,7 +13,7 @@ Instructions on how to build libinput and its tools and how to build against
libinput.
The build instruction on this page detail how to overwrite your
system-provided libinput with one from the git repository, see
system-provided libinput with one from the git repository,
see :ref:`reverting_install` to revert to the previous state.
.. _distribution_repos:
@ -27,7 +27,7 @@ the latest libinput without building it manually.
.. note:: The list below is provided for convenience. The libinput community
cannot provide any guarantees that the packages in those repositories are
correct, up-to-date and/or unmodified from the git branch. Due dilligence
correct, up-to-date and/or unmodified from the git branch. Due diligence
is recommended.
The following repositories provide an up-to-date package for libinput:

View file

@ -30,7 +30,7 @@ The "bounce" method guarantees that all press events are delivered
immediately and most release events are delivered immediately. The
"spurious" method requires that release events are delayed, libinput thus
does not enable this method unless a faulty event sequence is detected. A
message is printed to the log when spurious deboucing was detected.
message is printed to the log when spurious debouncing was detected.
libinput's debouncing is supposed to correct hardware damage or
substandard hardware. Debouncing also exists as an accessibility feature

View file

@ -60,7 +60,7 @@ is unfortunately not visibly obvious.
available.
If fingers are down in the main area in addition to fingers in the
left or right button area, those fingers are are ignored.
left or right button area, those fingers are ignored.
A release event always releases the buttons logically down, regardless of
the current finger position
@ -77,7 +77,7 @@ The movement of a finger can alter the button area behavior:
- once a finger has moved out of the button area, it cannot move back in and
trigger a right or middle button event
- a finger moving within the software button area does not move the pointer
- once a finger moves out out of the button area it will control the
- once a finger moves out of the button area it will control the
pointer (this only applies if there is no other finger down on the
touchpad)

View file

@ -47,7 +47,7 @@ for those devices it is expected to be implemented by the toolkit.
Three-finger drag
------------------------------------------------------------------------------
Three-finger drag allows emulates the mouse button down while three fingers
Three-finger drag emulates the mouse button down while three fingers
are down on a touchpad without the need to press a physical button or use
:ref:`tapndrag`. See :ref:`drag_3fg` for details on how this feature works.
@ -165,7 +165,7 @@ most touchpads.
Disable while trackpointing
------------------------------------------------------------------------------
DWTP is a form of palm detecion for devices that have a trackpoint (like
DWTP is a form of palm detection for devices that have a trackpoint (like
Thinkpads). While the user is using the trackpoint, the touchpad is disabled,
being enabled again after a timeout. See :ref:`disable-while-trackpointing` for
more info.
@ -205,8 +205,8 @@ Tablet tool pressure range
The pressure range on a :ref:`Tablet tool <tablet-tools>` can be reduced
from the full available hardware range to a subset of that range. The effect
of this is that the tablet will not register pressure below the given
the given threshold is met, and will reach the maximum logical pressure
of this is that the tablet will not register pressure until the given
threshold is met, and will reach the maximum logical pressure
before the maximum hardware-supported pressure is reached.
See :ref:`tablet-pressure-range` for more info.

View file

@ -144,10 +144,9 @@ This test suite can take test names etc. as arguments, have a look at
:ref:`test-suite` for more info. There are a bunch of other tests that are
run by the CI on merge requests, you can run those locally with ::
$> sudo ninja -C builddir check
$> sudo meson test -C builddir
So it always pays to run that before submitting. This will also run the code
through valgrind and pick up any memory leaks.
So it always pays to run that before submitting.
.. _contributing_submitting_code:

View file

@ -64,7 +64,7 @@ MOUSE_DPI
MOUSE_WHEEL_CLICK_ANGLE
The angle in degrees for each click on a mouse wheel. See
**libinput_pointer_get_axis_source()** for details.
**libinput_event_pointer_get_axis_source()** for details.
Below is an example udev rule to assign "seat1" to a device from vendor
@ -94,7 +94,7 @@ type label does not guarantee that the device is initialized by libinput.
If a device fails to meet the requirements for a device type (e.g. a keyboard
labelled as touchpad) the device will not be available through libinput.
Only one device type should be set per device at a type, though libinput can
Only one device type should be set per device at a time, though libinput can
handle some combinations for historical reasons.
Below is an example udev rule to remove an **ID_INPUT_TOUCHPAD** setting

View file

@ -23,7 +23,7 @@ the serial bus (PS/2) as internal keyboards: ::
[Serial Keyboards]
MatchUdevType=keyboard
MatchBus=serial
MatchBus=ps2
AttrKeyboardIntegration=internal
@ -46,7 +46,7 @@ Installing temporary local device quirks
The model quirks are part of the source distribution and should never be
modified. For temporary local workarounds, libinput reads the
``/etc/libinput/local-overrides.quirks`` file. Users may add a sections to
``/etc/libinput/local-overrides.quirks`` file. Users may add sections to
this file to add a device quirk for a local device but beware that **any
modification must be upstreamed** or it may cease to work at any time.
@ -130,7 +130,7 @@ Quirks starting with **Model*** triggers implementation-defined behaviour
for this device not needed for any other device. Only the more
general-purpose **Model*** flags are listed here.
ModelALPSTouchpad, ModelAppleTouchpad, ModelWacomTouchpad, ModelChromebook
ModelALPSSerialTouchpad, ModelAppleTouchpad, ModelWacomTouchpad, ModelChromebook
Reserved for touchpads made by the respective vendors
ModelTouchpadVisibleMarker
Indicates the touchpad has a drawn-on visible marker between the software
@ -162,9 +162,9 @@ ModelScrollOnMiddleClick
Some mice can generate unwanted high-resolution scroll events when the wheel
is pressed. Increases the scroll threshold required to start scrolling to
avoid accidentally scrolling when middle clicking.
AttrSizeHint=NxM, AttrResolutionHint=N
AttrSizeHint=NxM, AttrResolutionHint=NxM
Hints at the width x height of the device in mm, or the resolution
of the x/y axis in units/mm. These may only be used where they apply to
of the x and y axes in units/mm. These may only be used where they apply to
a large proportion of matching devices. They should not be used for any
specific device, override ``EVDEV_ABS_*`` instead, see
:ref:`absolute_coordinate_ranges_fix`.

View file

@ -99,7 +99,7 @@ Hold gestures have three potential logical states:
- **begin**: one or more fingers are placed on the device at the same time
- **end**: all fingers are removed and the device enters a neutral logical state
- **end(cancelled)**: all fingers are part of a known interaction and the
currenthold gesture is no longer active. This may also occurs when
current hold gesture is no longer active. This may also occur when
switching between hold gestures with different finger counts.
.. note:: By definition, a hold gesture does not move and thus no coordinate
@ -108,14 +108,15 @@ Hold gestures have three potential logical states:
For example, a user that puts one finger, then a second finger down and
releases them later may trigger the following event sequence:
============= ============ ============
Action Event Finger count
============= ============ ============
Finger 1 down <no event>
Finger 2 down **begin** 2
Finger 2 up **end** 2
============= ============== ============
Action Event Finger count
============= ============== ============
Finger 1 down **begin** 1
Finger 2 down **cancel** 1
\ **begin** 2
Finger 2 up **end** 2
Finger 1 up <no event>
============= ============ ============
============= ============== ============
A hold gesture may by be **cancelled**. This occurs
when the hold gesture changes into some other interaction and should no
@ -254,7 +255,8 @@ towards an interaction, see :ref:`thumb_detection` and
In the context of hold gestures, thumbs and palms are treated by libinput as
if the finger was removed from the device. Where other non-thumb/non-palm
fingers remain on the device, an **hold update** event is sent. Otherwise,
fingers remain on the device, the current hold gesture is cancelled and a
new **hold begin** event with the updated finger count is sent. Otherwise,
the hold gesture terminates with a **hold cancel** event.
Notably, libinput's thumb and palm detection is not a simple boolean per
@ -359,7 +361,7 @@ Touchpoints are assigned in sequential order and only the first two touch
points are trackable. For libinput this produces an ambiguity where it is
impossible to detect whether a gesture is a pinch gesture or a swipe gesture
whenever a user puts the index and middle finger down first. Since the third
finger does not have positional information, it's location cannot be
finger does not have positional information, its location cannot be
determined.
.. figure:: gesture-2fg-ambiguity.svg

View file

@ -21,7 +21,7 @@ input devices (see :ref:`udev_device_type`) but that should not be used by
libinput. It is recommended that devices that should not be handled as input
devices at all unset the **ID_INPUT** and related properties instead. The
**LIBINPUT_IGNORE_DEVICE** property signals that only libinput should
ignore this property but other parts of the stack (if any) should continue
ignore this device but other parts of the stack (if any) should continue
treating this device normally.
Below is an example udev rule to assign **LIBINPUT_IGNORE_DEVICE** to the

View file

@ -162,7 +162,7 @@ the value can be crafted manually:
.. code-block:: lua
evdev_type = 0x3 -- EV_REL
evdev_type = 0x2 -- EV_REL
evdev_code = 0x1 -- REL_Y
evdev_usage = (evdev_type << 16) | evdev_code
@ -485,7 +485,7 @@ methods will be noops.
Version 1 of the plugin API supports the following udev properties:
- ``ID_INPUT`` and all of ``ID_INPUT_*`` that denote the device type as assigned
- All of ``ID_INPUT_*`` that denote the device type as assigned
by udev. This information is usually used by libinput to determine a
device type. Note that for historical reasons these properties have
varying rules - some properties may be mutually exclusive, others are

View file

@ -131,6 +131,7 @@ src_rst = files(
'svg/tablet-intuos-modes.svg',
'svg/tablet-left-handed.svg',
'svg/tablet-out-of-bounds.svg',
'svg/tablet-touch-arbitration.svg',
'svg/tablet.svg',
'svg/tap-n-drag.svg',
'svg/thumb-detection.svg',

View file

@ -14,7 +14,7 @@ touch the bottom edges of the touchpad during normal interaction.
Interference from a palm depends on the size of the touchpad and the position
of the user's hand. Data from touchpads showed that almost all palm events
during tying on a Lenovo T440 happened in the left-most and right-most 5% of
during typing on a Lenovo T440 happened in the left-most and right-most 5% of
the touchpad. The T440 series has one of the largest touchpads, other
touchpads are less affected by palm touches.
@ -52,7 +52,7 @@ Palm detection based on pressure
The simplest form of palm detection labels a touch as palm when the pressure
value goes above a certain threshold. This threshold is usually high enough
that it cannot be triggered by a finger movement. One a touch is labelled as
that it cannot be triggered by a finger movement. Once a touch is labelled as
palm based on pressure, it will remain so even if the pressure drops below
the threshold again. This ensures that a palm remains a palm even when the
pressure changes as the user is typing.
@ -187,7 +187,7 @@ Stylus-touch arbitration
A special case of palm detection is touch arbitration on devices that
support styli. When interacting with a stylus on the screen, parts of the
hand may touch the surface and trigger touches. As the user is currently
interacting with the stylus, these touches would interfer with the correct
interacting with the stylus, these touches would interfere with the correct
working of the stylus.
libinput employs a method similar to :ref:`disable-while-typing` to detect

View file

@ -39,7 +39,7 @@ Velocity calculation
------------------------------------------------------------------------------
The device's speed of movement is measured across multiple input events
through so-called "trackers". Each event prepends a the tracker item, each
through so-called "trackers". Each event prepends a tracker item, each
subsequent tracker contains the delta of that item to the current position,
the timestamp of the event that created it and the cardinal direction of the
movement at the time. If a device moves into the same direction, the

View file

@ -185,7 +185,7 @@ When you file a bug, please attach the following information:
- a virtual description of your input device, see :ref:`libinput-record`.
This is the most important piece of information, do not forget it!
- the vendor model number of the device (e.g. "Sony Plastation3 controller")
- the vendor model number of the device (e.g. "Sony PlayStation3 controller")
.. _udev_info:
@ -368,7 +368,7 @@ them.
without someone stepping up to do the work. If you do see this tag, do ask
for guidance on how to implement it.
- **hw issue**: an issue that affects a specific device and is a hardware
bug, not a software bug. Often these needs to be worked around in libinput
bug, not a software bug. Often these need to be worked around in libinput
but there are cases where a hw issue ends up as *cantfix*.
- **janitor**: a cleanup task that does not substantially affect how
libinput works. These are usually good bugs for newcomers to start on.
@ -389,7 +389,7 @@ them.
*cantfix*.
- **wontfix**: this issue will not get fixed. This tag is usually assigned
to feature requests that are outside the scope of libinput or would put an
unreasonable maintenance burdern on the maintainers.
unreasonable maintenance burden on the maintainers.
These tags are high-level categories only, always look for the comments in
the issue to get further details.

View file

@ -12,7 +12,7 @@ one can be enabled at a time. As a general overview:
- touchpad devices with physical buttons below the touchpad support edge and
two-finger scrolling
- touchpad devices without physical buttons (:ref:`ClickPads <clickpad_softbuttons>`)
support two-finger scrolling only
support two-finger scrolling and edge scrolling
- pointing sticks provide on-button scrolling by default
- mice and other pointing devices support on-button scrolling but it is not
enabled by default
@ -124,6 +124,12 @@ button lock, the button is now considered logically held down. Pressing and
releasing the button a second time logically releases the button. While the
button is logically held down, motion events are converted to scroll events.
If the button is held and used to scroll for longer than a short grace
period, releasing the button does not engage the lock. This allows
hold-to-scroll for short, precise adjustments without accidentally toggling
the lock. A quick click or a brief scroll within the grace period still
engages the lock as normal.
.. _scroll_sources:
------------------------------------------------------------------------------

View file

@ -43,7 +43,7 @@ Thus, devices "Foo" and "Bar" both reference the same struct
The effect of seat assignment
------------------------------------------------------------------------------
A logical set is interpreted as a group of devices that usually belong to a
A logical seat is interpreted as a group of devices that usually belong to a
single user that interacts with a computer. Thus, the devices are
semantically related. This means for devices within the same logical seat:

View file

@ -0,0 +1,245 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="229.5488mm"
height="86.66362mm"
viewBox="0 0 813.36188 307.07582"
id="svg2"
version="1.1"
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
sodipodi:docname="tablet-touch-arbitration.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4294"
id="linearGradient4300"
x1="465.81339"
y1="666.13727"
x2="454.82117"
y2="658.65521"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
id="linearGradient4294">
<stop
style="stop-color:#1a1a1a;stop-opacity:1;"
offset="0"
id="stop4296" />
<stop
style="stop-color:#808080;stop-opacity:1"
offset="1"
id="stop4298" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4294"
id="linearGradient3"
gradientUnits="userSpaceOnUse"
x1="465.81339"
y1="666.13727"
x2="454.82117"
y2="658.65521" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8"
inkscape:cx="410.71429"
inkscape:cy="188.57143"
inkscape:document-units="px"
inkscape:current-layer="layer2"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="3072"
inkscape:window-height="1629"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="tablet"
inkscape:groupmode="layer"
id="layer1"
style="display:inline"
transform="translate(67.109152,-133.63374)">
<g
id="g4309"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="translate(0,1.0715222)">
<rect
y="134.15933"
x="75.787216"
height="306.02466"
width="522.19733"
id="rect4136"
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:1.05118;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:4.20473, 1.05118;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.748138;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:2.99255, 0.748138;stroke-dashoffset:0;stroke-opacity:1"
id="rect4140"
width="357.34042"
height="226.52563"
x="199.33878"
y="175.42407" />
<rect
y="175.72914"
x="103.10225"
height="22.142857"
width="65"
id="rect4142"
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.989;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.989;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1"
id="rect4148"
width="65"
height="22.142857"
x="103.10225"
y="203.72914" />
<rect
y="231.72913"
x="103.10225"
height="22.142857"
width="65"
id="rect4150"
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.989;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
<rect
y="323.72913"
x="103.10225"
height="22.142857"
width="65"
id="rect4154"
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.989;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.989;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1"
id="rect4156"
width="65"
height="22.142857"
x="103.10225"
y="351.72913" />
<circle
r="22.98097"
cy="287.06125"
cx="135.61298"
id="path4158"
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.989;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
<ellipse
ry="12.608653"
rx="11.5985"
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.520431;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:2.08172, 0.520431;stroke-dashoffset:0;stroke-opacity:1"
id="circle4160"
cx="135.61298"
cy="287.06125" />
<rect
y="379.72913"
x="103.10225"
height="22.142857"
width="65"
id="rect4162"
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.989;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="area">
<rect
style="display:inline;fill:#a44d4d;fill-opacity:1;stroke:none;stroke-width:0.930358"
id="rect1"
width="139.07858"
height="226.89969"
x="485.08383"
y="42.487785" />
<rect
style="display:inline;fill:#a44d4d;fill-opacity:1;stroke:none;stroke-width:1.02823"
id="rect3"
width="169.87961"
height="226.89969"
x="266.07385"
y="42.487785" />
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="stylus"
style="display:inline"
transform="translate(67.109152,-133.63374)">
<g
id="g4304"
transform="matrix(0.37129971,0.09948946,-0.09618892,0.35898192,369.23868,-8.3227001)"
style="display:inline">
<path
sodipodi:nodetypes="czcc"
inkscape:connector-curvature="0"
id="path4286"
d="m 387.83544,799.76093 c -1.1128,3.61694 -3.2211,13.05163 -1.08543,14.07769 2.13567,1.02606 7.81039,-3.72162 10.99756,-6.69095 z"
style="display:inline;fill:#cccccc;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="ssssccssscsssssssssssssssssss"
inkscape:connector-curvature="0"
id="path4283"
d="m 392.64431,804.79039 c -8.52094,-5.90399 -8.49394,-11.01546 0.22879,-43.30647 1.03999,-3.85 2.46829,-9.67602 3.17399,-12.9467 0.99731,-4.62219 2.39455,-7.29497 6.27321,-12 2.74456,-3.32932 5.25157,-6.2783 5.57113,-6.5533 40.78433,-60.97488 80.48307,-125.1652 118.27253,-184 9.86283,-15.675 26.59424,-42.225 37.18089,-59 10.58666,-16.775 34.01422,-53.9 52.06125,-82.5 18.04703,-28.6 35.04505,-55.31677 37.77338,-59.37059 l 4.9606,-7.3706 4.1828,0.57332 c 4.16371,0.5707 4.19706,0.54958 7.30887,-4.62941 3.75631,-6.2516 8.82067,-11.57582 12.2516,-12.88026 5.99391,-2.27888 14.03303,2.9506 14.03303,9.12854 0,3.90203 -2.51704,10.62127 -6.02878,16.09385 -1.63417,2.54664 -2.97122,4.85949 -2.97122,5.13969 0,0.28019 0.9,1.54715 2,2.81546 2.28453,2.63408 2.47267,4.21918 0.86833,7.31574 -1.28218,2.47476 -26.61383,45.18798 -55.85724,94.18426 -10.83283,18.15 -25.72943,43.1137 -33.10357,55.47489 -7.37413,12.3612 -13.69273,23.17153 -14.04131,24.02297 -0.34859,0.85144 -7.50972,12.78774 -15.91363,26.52511 -15.54138,25.40455 -32.24417,52.9052 -70.74345,116.47703 -40.26028,66.47968 -43.66308,72.46026 -49.21634,86.5 -1.74036,4.4 -3.92035,8.675 -4.8444,9.5 -0.92405,0.825 -4.36246,3.75 -7.6409,6.5 -3.27845,2.75 -9.57132,8.3067 -13.98415,12.34823 -10.62726,9.73304 -16.99729,13.87361 -22.52334,14.64034 -3.99187,0.55386 -5.03885,0.251 -9.27207,-2.6821 z"
style="display:inline;fill:#000000" />
<path
sodipodi:nodetypes="scccs"
inkscape:connector-curvature="0"
id="path4292"
d="m 450.89044,688.88586 c 8.71518,5.62513 45.74035,-59.18436 43.57923,-75.43494 l -7.07107,-6.56599 c -29.93081,25.86352 -47.78438,74.72281 -47.78438,74.72281 z"
style="fill:url(#linearGradient4300);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
<g
id="g3"
transform="matrix(-0.37129971,0.09948946,0.09618892,0.35898192,416.04226,-44.344847)"
style="display:inline">
<path
sodipodi:nodetypes="czcc"
inkscape:connector-curvature="0"
id="path1"
d="m 387.83544,799.76093 c -1.1128,3.61694 -3.2211,13.05163 -1.08543,14.07769 2.13567,1.02606 7.81039,-3.72162 10.99756,-6.69095 z"
style="display:inline;fill:#cccccc;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="ssssccssscsssssssssssssssssss"
inkscape:connector-curvature="0"
id="path2"
d="m 392.64431,804.79039 c -8.52094,-5.90399 -8.49394,-11.01546 0.22879,-43.30647 1.03999,-3.85 2.46829,-9.67602 3.17399,-12.9467 0.99731,-4.62219 2.39455,-7.29497 6.27321,-12 2.74456,-3.32932 5.25157,-6.2783 5.57113,-6.5533 40.78433,-60.97488 80.48307,-125.1652 118.27253,-184 9.86283,-15.675 26.59424,-42.225 37.18089,-59 10.58666,-16.775 34.01422,-53.9 52.06125,-82.5 18.04703,-28.6 35.04505,-55.31677 37.77338,-59.37059 l 4.9606,-7.3706 4.1828,0.57332 c 4.16371,0.5707 4.19706,0.54958 7.30887,-4.62941 3.75631,-6.2516 8.82067,-11.57582 12.2516,-12.88026 5.99391,-2.27888 14.03303,2.9506 14.03303,9.12854 0,3.90203 -2.51704,10.62127 -6.02878,16.09385 -1.63417,2.54664 -2.97122,4.85949 -2.97122,5.13969 0,0.28019 0.9,1.54715 2,2.81546 2.28453,2.63408 2.47267,4.21918 0.86833,7.31574 -1.28218,2.47476 -26.61383,45.18798 -55.85724,94.18426 -10.83283,18.15 -25.72943,43.1137 -33.10357,55.47489 -7.37413,12.3612 -13.69273,23.17153 -14.04131,24.02297 -0.34859,0.85144 -7.50972,12.78774 -15.91363,26.52511 -15.54138,25.40455 -32.24417,52.9052 -70.74345,116.47703 -40.26028,66.47968 -43.66308,72.46026 -49.21634,86.5 -1.74036,4.4 -3.92035,8.675 -4.8444,9.5 -0.92405,0.825 -4.36246,3.75 -7.6409,6.5 -3.27845,2.75 -9.57132,8.3067 -13.98415,12.34823 -10.62726,9.73304 -16.99729,13.87361 -22.52334,14.64034 -3.99187,0.55386 -5.03885,0.251 -9.27207,-2.6821 z"
style="display:inline;fill:#000000" />
<path
sodipodi:nodetypes="scccs"
inkscape:connector-curvature="0"
id="path3"
d="m 450.89044,688.88586 c 8.71518,5.62513 45.74035,-59.18436 43.57923,-75.43494 l -7.07107,-6.56599 c -29.93081,25.86352 -47.78438,74.72281 -47.78438,74.72281 z"
style="fill:url(#linearGradient3);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -4,9 +4,9 @@
Switches
==============================================================================
libinput supports the lid and tablet-mode switches. Unlike button events
that come in press and release pairs, switches are usually toggled once and
left at the setting for an extended period of time.
libinput supports the lid, tablet-mode, and keypad slide switches. Unlike
button events that come in press and release pairs, switches are usually
toggled once and left at the setting for an extended period of time.
Only some switches are handled by libinput, see **libinput_switch** for a
list of supported switches. Switch events are exposed to the caller, but
@ -59,3 +59,20 @@ tablet mode is disengaged.
This handling of tablet mode switches is transparent to the user, no
notifications are sent and the device appears as enabled at all times.
.. _switches_keypad_slide:
------------------------------------------------------------------------------
Keypad slide switch handling
------------------------------------------------------------------------------
Where available, libinput listens to devices providing a keypad slide switch.
This is usually available on devices that have an always-attached physical
keyboard which can slide under the screen. An example of such a device is the
Nokia N900.
The event sent by the kernel is ``EV_SW`` ``SW_KEYPAD_SLIDE`` and is provided
as **LIBINPUT_SWITCH_KEYPAD_SLIDE**. The keypad slide switch does not cause any
other input devices to be enabled nor disabled in response, since on some
devices the kernel event is sent while the keyboard is partially visible and
thus usable.

View file

@ -58,7 +58,7 @@ event of type **LIBINPUT_EVENT_TABLET_TOOL_TIP**, and again when the tip
ceases contact with the surface.
Tablet tools may send button events; these are exclusively for extra buttons
unrelated to the tip. A button event is independent of the tip and can while
unrelated to the tip. A button event is independent of the tip and can occur while
the tip is down or up.
Some tablet tools' pressure detection is too sensitive, causing phantom
@ -67,7 +67,7 @@ tools are capable of detecting 1 gram of pressure.
libinput uses a device-specific pressure threshold to determine when the tip
is considered logically down. As a result, libinput may send a nonzero
pressure value while the tip is logically up. Most application can and
pressure value while the tip is logically up. Most applications can and
should ignore pressure information until they receive the event of type
**LIBINPUT_EVENT_TABLET_TOOL_TIP**. Applications that require extremely
fine-grained pressure sensitivity should use the pressure data instead of
@ -100,7 +100,7 @@ all pen-like tools to absolute mode.
If a tool in relative mode must not use pointer acceleration, callers
should use the absolute coordinates returned by
**libinput_event_tablet_tool_get_x()** and libinput_event_tablet_tool_get_y()
**libinput_event_tablet_tool_get_x()** and **libinput_event_tablet_tool_get_y()**
and calculate the delta themselves. Callers that require exact physical
distance should also use these functions to calculate delta movements.
@ -284,7 +284,7 @@ with **libinput_tablet_tool_get_tool_id()** but makes no promises about the
content or format of the ID.
libinput currently supports Wacom-style tool IDs as provided on the Wacom
Intuos 3, 4, 5, Wacon Cintiq and Wacom Intuos Pro series. The tool ID can
Intuos 3, 4, 5, Wacom Cintiq and Wacom Intuos Pro series. The tool ID can
be used to distinguish between e.g. a Wacom Classic Pen or a Wacom Pro Pen.
It is the caller's responsibility to interpret the tool ID.
@ -357,7 +357,7 @@ tablet by 180 degrees to move the tablet pad button area to right side of
the tablet. When left-handed mode is enabled on a tablet device (see
**libinput_device_config_left_handed_set()**) the tablet tool and tablet pad
behavior changes. In left-handed mode, the tools' axes are adjusted
so that the origin of each axis remains the logical north-east of
so that the origin of each axis remains the logical north-west of
the physical tablet. For example, the x and y axes are inverted and the
positive x/y coordinates are down/right of the top-left corner of the tablet
in its current orientation. On a tablet pad, the ring and strip are
@ -401,7 +401,7 @@ caller to decide whether the mode only applies to buttons, rings and strips
or only to rings and strips (this is the case with the Wacom OS X and
Windows driver).
The availability of modes on a touchpad usually depends on visual feedback
The availability of modes on a tablet pad usually depends on visual feedback
such as LEDs around the touch ring. If no visual feedback is available, only
one mode may be available.
@ -466,7 +466,21 @@ devices arbitration has to be done in userspace.
libinput uses the **libinput_device_group** to decide on touch arbitration
and automatically discards touch events whenever a tool is in proximity.
The exact behavior is device-dependent.
The exact behavior is device-dependent but typically comes in two forms: full
tablet touch arbitration and partial arbitration.
.. figure:: tablet-touch-arbitration.svg
:align: center
Partial touch arbitration during a pen interaction for left-handed
and right-handed pen tilt.
Full arbitration simply disables touch on the device while the pen is in
proximity. Partial touch arbitration disables the side of the tablet around the
user's hand, starting slightly to the side of the pen tip. If the pen tilts
to the left (pen held in the left hand), the rectangle is to the left of the
pen tip, if the pen tilts to the right (pen held in the right hand) it is to
the right of the pen tip.
.. _tablet-area:
@ -509,7 +523,7 @@ tip of the tool - inverting the tool brings the eraser into proximity.
.. figure:: tablet-eraser-invert.svg
:align: center
An pen-like tool used as pen and as eraser by inverting it
A pen-like tool used as pen and as eraser by inverting it
Having an eraser as a separate tool is beneficial in many applications as the
eraser tool can be assigned different functionality (colors, paint tools, etc.)
@ -524,7 +538,7 @@ into proximity immediately after - as if the tool was physically inverted.
.. figure:: tablet-eraser-button.svg
:align: center
An pen-like tool used as pen and as eraser by pressing the eraser button
A pen-like tool used as pen and as eraser by pressing the eraser button
Microsoft mandates this behavior (see
`Windows Pen States <https://learn.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states>`_
@ -541,4 +555,4 @@ is disabled, pressing that button will generate a normal tablet tool button
event.
This configuration is only available on pens with an eraser button, not on
with an invert-type eraser.
pens with an invert-type eraser.

View file

@ -59,13 +59,16 @@ tap-and-drag enabled by default.
middle-click drag, tap with three fingers followed by a
single-finger drag.
Also optional is a feature called "drag lock". With drag lock disabled, lifting
the finger will stop any drag process. When enabled, the drag
process continues even after lifting a finger but can be ended
with an additional tap. If timeout-based drag-locks are enabled
the drag process will also automatically end once the finger has
been lifted for an implementation-specific timeout. Drag lock can be
enabled and disabled with **libinput_device_config_tap_set_drag_lock_enabled()**.
Also optional is a feature called "drag lock". With drag lock **disabled**,
lifting the finger will stop any drag process. When **enabled**, the drag
process continues even after lifting a finger, allowing the user to
reset the finger position and keep moving without releasing the drag.
libinput supports two variations of this drag lock: "sticky" and "timeout".
In sticky mode, the drag lock must be ended with an explicit additional tap.
In timeout mode, the drag lock ends automatically if no finger was put back on
the touchpad within a timeout. Drag lock can be enabled and disabled with
**libinput_device_config_tap_set_drag_lock_enabled()**.
Note that drag lock only applies if tap-and-drag is enabled.
.. figure:: tap-n-drag.svg
@ -81,11 +84,13 @@ position can be reset by lifting and quickly setting it down again on the
touchpad (d). This will be interpreted as continuing move and is especially
useful on small touchpads or with slow pointer acceleration.
If drag lock is enabled, the release of the mouse buttons after the finger
release (e) is triggered by a timeout. To release the button immediately,
simply tap again (f).
release (e) is triggered by a timeout (if in timeout mode) or by tapping again (f).
If drag lock is enabled in sticky mode there is no timeout after
releasing a finger and an extra tap is required to release the button.
libinput also supports an "auto drag-lock" feature: if drag lock is **disabled**
but the dragging finger is released at the very edge of the touchpad,
a drag lock automatically activates for a short timeout. This allows a user to
quickly reset the finger to elsewhere on the touchpad and continue the dragging
motion. If the finger is released elsewhere, no drag lock activates.
If two fingers are supported by the hardware, a second finger can be used to
drag while the first is held in-place.

View file

@ -15,7 +15,7 @@ run to check for behavior changes and/or regressions. For quick iteration,
the number of tests to run can be filtered, see :ref:`test-filtering`.
This allows for developers to verify a subset of tests (e.g.
touchpad tap-to-click) while hacking on that specific feature and only run
the full suite when development is done finished.
the full suite when development is finished.
.. note:: The test suite relies on udev and the kernel, specifically uinput.
It creates virtual input devices and replays the events. This may
@ -38,7 +38,7 @@ Job control in the test suite
The test suite runner has a make-like job control enabled by the ``-j`` or
``--jobs`` flag and will fork off as many parallel processes as given by this
flag. The default if unspecified is 8. When debugging a specific test case
failure it is recommended to employ test filtures (see :ref:`test-filtering`)
failure it is recommended to employ test filters (see :ref:`test-filtering`)
and disable parallel tests. The test suite automatically disables parallel
make when run in gdb.
@ -235,7 +235,7 @@ suites as:
::
$ meson test --no-suite=machine # only run container-friendly tests
$ meson test --no-suite=hardware # only run container-friendly tests
$ meson test --suite=valgrind --setup=valgrind # run all valgrind-compatible tests
$ meson test --no-suite=root # run all tests not requiring root

View file

@ -269,7 +269,7 @@ alphanumeric key shows up as letter "a".
The recording can be replayed with the ``libinput replay`` command: ::
$ sudo libinput replay touchpad.yml
SynPS/2 Synaptics TouchPad: /dev/input/event19
/dev/input/event19: SynPS/2 Synaptics TouchPad
Hit enter to start replaying
@ -329,16 +329,13 @@ specific bug. For example, a touchpad may not work in response to keyboard
events. To accurately reproduce this sequence, the timing between multiple
devices must be correct and we need to record the events in one go.
``libinput record`` has a ``--multiple`` argument to record multiple devices at
once. Unlike the normal invocation, this one requires a number of arguments: ::
``libinput record`` can record multiple devices by specifying them on the
commandline. Recording multiple devices requires the ``--output-file``
argument: ::
$ sudo libinput record --multiple --output-file=touchpad-bug.yml /dev/input/event17 /dev/input/event3
$ sudo libinput record --output-file=touchpad-bug.yml /dev/input/event17 /dev/input/event3
recording to 'touchpad-bug.yml'
As seen above, a user must specify ``--multiple`` and the ``--output-file``.
Finally, all devices to be recorded must be specified on the commandline as
well.
Replaying events is the same as for a single recording: ::
$ sudo libinput replay touchpad-bug.yml
@ -365,7 +362,7 @@ The ``libinput analyze`` tool is a multiplexer for various sub-tools that
can analyze input events previously recorded from a device.
Please see the **libinput-analyze(1)** man page for information about what
tools are available and the man page for each respective too.
tools are available and the man page for each respective tool.
.. _libinput-quirks:

View file

@ -8,10 +8,10 @@ Touchpad jitter describes random movement by a few pixels even when the
user's finger is unmoving.
libinput has a mechanism called a **hysteresis** to avoid that jitter. When
active, movement with in the **hysteresis margin** is discarded. If the
active, movement within the **hysteresis margin** is discarded. If the
movement delta is larger than the margin, the movement is passed on as
pointer movement. This is a simplified summary, developers should
read the implementation of the hysteresis in ``src/evdev.c``.
read the implementation of the hysteresis in ``src/evdev.h``.
libinput uses the kernel ``fuzz`` value to determine the size of the
hysteresis. Users should override this with a udev hwdb entry where the

View file

@ -76,8 +76,8 @@ Example output of the tool is below: ::
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 ``down`` column show that each sequence was
considered logically down at some point (see the threholds in the last line),
well as some statistics. The ``down`` column shows that each sequence was
considered logically down at some point (see the thresholds in the last line),
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.
@ -112,7 +112,7 @@ Once the thresholds are decided on (e.g. 10 and 8), they can be enabled with
AttrPalmPressureThreshold=150
AttrThumbPressureThreshold=100
The file name **must** be ``/etc/libinput/local-overrides.quirks``. The
The file name **must** be ``/etc/libinput/local-overrides.quirks``.
The first line is the section name and can be free-form. The ``Match``
directives limit the quirk to your touchpad, make sure the device name
matches your device's name (see ``libinput record``'s output). The dmi
@ -124,7 +124,7 @@ and product name (pn).
Once in place, run the following command to verify the quirk is valid and
works for your device: ::
$ sudo libinput list-quirks /dev/input/event10
$ sudo libinput quirks list /dev/input/event10
AttrPressureRange=10:8
Replace the event node with the one from your device. If the
@ -218,7 +218,7 @@ and product name (pn).
Once in place, run the following command to verify the quirk is valid and
works for your device: ::
$ sudo libinput list-quirks /dev/input/event10
$ sudo libinput quirks list /dev/input/event10
AttrTouchSizeRange=10:8
Replace the event node with the one from your device. If the

View file

@ -50,7 +50,7 @@ touchpads. Some devices can detect multiple fingers but only provide
Some devices provide additional touch size information through
the ``ABS_MT_TOUCH_MAJOR/ABS_MT_TOUCH_MINOR`` axes and/or
the ``ABS_MT_WIDTH_MAJOR/ABS_MT_WIDTH_MINOR`` axes. These axes specifcy
the ``ABS_MT_WIDTH_MAJOR/ABS_MT_WIDTH_MINOR`` axes. These axes specify
the size of the touch ellipse. While the kernel documentation specifies how
these axes are supposed to be mapped, few devices forward reliable
information. libinput uses these values together with a device-specific

View file

@ -25,7 +25,7 @@ Physically separate buttons
Touchpads with physical buttons usually provide two buttons, left and right.
A few touchpads with three buttons exist, and Apple used to have touchpads
with a single physical buttons until ca 2008. Touchpads with only two
with a single physical button until ca 2008. Touchpads with only two
buttons require the software stack to emulate a middle button. libinput does
this when both buttons are pressed simultaneously.

View file

@ -25,7 +25,7 @@ Button scrolling on trackpoints
------------------------------------------------------------------------------
Trackpoint devices have :ref:`button_scrolling` enabled by default. This may
interfer with middle-button dragging, if middle-button dragging is required
interfere with middle-button dragging, if middle-button dragging is required
by a user then button scrolling must be disabled.
.. _trackpoint_range:

View file

@ -131,7 +131,7 @@ Handled device types
- Mice
- Keyboards
- Virtual absolute pointing devices such as those used by QEMU or VirtualBox
- Switches (Lid Switch and Tablet Mode switch)
- Switches (Lid Switch, Tablet Mode switch, and Keypad Slide switch)
- Graphics tablets
- :ref:`Trackpoints`

View file

@ -45,7 +45,7 @@ Both events have their own set of APIs to access the data within:
- ``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL`` available since libinput 1.19.
* ``libinput_event_pointer_get_scroll_value_v120()`` returns a value
normalized into the 0..120 range, see below. Any multiple of 120 should
normalized into multiples of 120, see below. Any multiple of 120 should
be treated as one full wheel click.
.. note:: Where possible, the ``libinput_event_pointer_get_axis_value()``,
@ -77,7 +77,7 @@ wheel:
| 20 | 20 | 1 | 120 |
+-------------+------------+---------------+------+
Fast scrolling may trigger cover than one detent per event and thus each
Fast scrolling may trigger more than one detent per event and thus each
event may contain multiples of the value, discrete or v120 value:
+-------------+------------+---------------+------+

View file

@ -766,7 +766,7 @@ executable('ptraccel-debug',
if is_debug_build
config_tool_option_test = configuration_data()
config_tool_option_test.set('DISABLE_WARNING', 'yes')
config_tool_option_test.set('MESON_ENABLED_DEBUG_GUI', get_option('debug-gui'))
config_tool_option_test.set('MESON_ENABLED_DEBUG_GUI', get_option('debug-gui').to_string())
config_tool_option_test.set('MESON_BUILD_ROOT', meson.current_build_dir())
config_tool_option_test.set('TOOL_PATH', libinput_tool.full_path())
tool_option_test = configure_file(input: 'tools/test_tool_option_parsing.py',

View file

@ -0,0 +1,11 @@
# Do not edit this file, it will be overwritten on update
# Touchpad is not a clickpad but INPUT_PROP_BUTTONPAD is set,
# causing libinput to drop physical button events.
[Clevetura CLVX S Touchpad]
MatchUdevType=touchpad
MatchBus=bluetooth
MatchVendor=0x36F7
MatchProduct=0x5755
AttrInputProp=-INPUT_PROP_BUTTONPAD
AttrEventCode=+BTN_RIGHT

View file

@ -9,3 +9,11 @@ AttrPressureRange=10:8
MatchName=*Elan Touchpad*
AttrResolutionHint=31x31
AttrPressureRange=10:8
# Elan Hapticpad mostly used in Lenovo laptops.
[Elan Haptic Touchpad (04F3:3355)]
MatchBus=i2c
MatchVendor=0x04F3
MatchProduct=0x3355
MatchUdevType=touchpad
AttrInputProp=+INPUT_PROP_PRESSUREPAD

View file

@ -2,6 +2,15 @@
# "GXTP5100 Touchpad": pressure touchpad mostly used in Lenovo laptops.
# Match vid and pid as it can have other names.
[Goodix Haptic Touchpad (27C6:01E7)]
MatchBus=i2c
MatchVendor=0x27C6
MatchProduct=0x01E7
MatchUdevType=touchpad
AttrInputProp=+INPUT_PROP_PRESSUREPAD
# "GXTP5100 Touchpad": pressure touchpad mostly used in Lenovo laptops.
# GXTP5100:00 27C6:01E8 Touchpad
[Goodix Haptic Touchpad (27C6:01E8)]
MatchBus=i2c
MatchVendor=0x27C6
@ -9,6 +18,42 @@ MatchProduct=0x01E8
MatchUdevType=touchpad
AttrInputProp=+INPUT_PROP_PRESSUREPAD
# "GXTP5100 Touchpad": pressure touchpad mostly used in Lenovo laptops.
# GXTP5100:00 27C6:01E9 Touchpad
[Goodix Haptic Touchpad (27C6:01E9)]
MatchBus=i2c
MatchVendor=0x27C6
MatchProduct=0x01E9
MatchUdevType=touchpad
AttrInputProp=+INPUT_PROP_PRESSUREPAD
# "GXTP5100 Touchpad": pressure touchpad mostly used in Lenovo laptops.
# GXTP5100:00 27C6:01EA Touchpad
[Goodix Haptic Touchpad (27C6:01EA)]
MatchBus=i2c
MatchVendor=0x27C6
MatchProduct=0x01EA
MatchUdevType=touchpad
AttrInputProp=+INPUT_PROP_PRESSUREPAD
# "GXTP5100 Touchpad": pressure touchpad mostly used in Lenovo laptops.
# GXTP5100:00 27C6:01EB Touchpad
[Goodix Haptic Touchpad (27C6:01EB)]
MatchBus=i2c
MatchVendor=0x27C6
MatchProduct=0x01EB
MatchUdevType=touchpad
AttrInputProp=+INPUT_PROP_PRESSUREPAD
# "GXTP5400 Touchpad": pressure touchpad mostly used in Lenovo laptops.
# GXTP5400:00 27C6:0F96 Touchpad
[Goodix Haptic Touchpad (27C6:0F96)]
MatchBus=i2c
MatchVendor=0x27C6
MatchProduct=0x0F96
MatchUdevType=touchpad
AttrInputProp=+INPUT_PROP_PRESSUREPAD
# "GXTP5420 Touchpad": pressure touchpad mostly used in Lenovo laptops.
# GXTP5420:00 27C6:0F95 Touchpad
[Goodix Haptic Touchpad (27C6:0F95)]
@ -17,3 +62,11 @@ MatchVendor=0x27C6
MatchProduct=0x0F95
MatchUdevType=touchpad
AttrInputProp=+INPUT_PROP_PRESSUREPAD
# "GXTP5420 Touchpad": pressure touchpad mostly used in Lenovo laptops.
[Goodix Haptic Touchpad (27C6:0F90)]
MatchBus=i2c
MatchVendor=0x27C6
MatchProduct=0x0F90
MatchUdevType=touchpad
AttrInputProp=+INPUT_PROP_PRESSUREPAD

View file

@ -11,15 +11,10 @@ AttrLidSwitchReliability=write_open
# - Surface Laptop 3: Microsoft Surface 045E:09AE Keyboard
# - Surface Book 2: Microsoft Surface Keyboard
[Microsoft Surface Keyboard]
MatchName=*Microsoft Surface *Keyboard*
MatchName=Microsoft Surface *Keyboard
MatchDMIModalias=dmi:*:svnMicrosoftCorporation:*
AttrKeyboardIntegration=internal
[Microsoft Surface Cover]
MatchName=*Microsoft Surface *Cover*
MatchDMIModalias=dmi:*:svnMicrosoftCorporation:*
AttrKeyboardIntegration=internal
AttrEventCode=-BTN_0;
AttrKeyboardIntegration=internal
[Microsoft Surface Laptop Studio Touchpad]
MatchVendor=0x045E

View file

@ -88,6 +88,7 @@ AttrThumbSizeThreshold=700
MatchBus=usb
MatchVendor=0x05AC
MatchProduct=0x0324
AttrSizeHint=162x115
AttrTouchSizeRange=20:10
AttrPressureRange=3:0
AttrPalmSizeThreshold=900

View file

@ -24,28 +24,27 @@ MatchName=*Intel Virtual Button*
MatchDMIModalias=dmi:*:svnHP:pnHPElitex21013G3:*
ModelTabletModeSwitchUnreliable=1
# The HP OmniBook Ultra Flip Laptop 14-fh0xxx's custom Intel ISH firmware
# filters out events from its builtin keyboard and touchpad when the hinge is
# opened little more than 180 degrees but toggles tablet-mode when it's opened
# little less than 180 degrees.
# Do not suspend the keyboard and touchpad to let use the device in flat
# position and also give consistency with some keyboard keys controlled by the
# Video Bus device (brightness down/up), the HP WMI hotkeys device (mic mute and
# hp hubs launcher key) and the backlight getting on and off by the firmware at
# the same time it enables disables the input.
# This one is for the keyboard and...
[HP OmniBook Ultra Flip Laptop 14-fh0xxx Keyboard]
# The HP OmniBook Ultra Flip 14 toggles tablet mode at a little less than 180
# degrees and hardware switches off inputs at a little more than 180 degrees.
# We don't suspend ourselves to allow using them in flat position. It is
# possible that HP fixes this in the future (i.e. so tablet mode toggles
# after 180 degrees) so check before removing these rules.
# This rule is for the keyboard and...
[HP OmniBook Ultra Flip Laptop 14-fh0xxx and 14t-fh000 Keyboard]
MatchBus=ps2
MatchUdevType=keyboard
MatchDMIModalias=dmi:*:svnHP:pnHPOmniBookUltraFlipLaptop14-fh0xxx:*
MatchDMIModalias=dmi:*:svnHP:*:rn8CDE:*
ModelTabletModeNoSuspend=1
# ...this one is for the touchpad.
[HP OmniBook Ultra Flip Laptop 14-fh0xxx Touchpad]
# ...this rule is for the touchpad.
[HP OmniBook Ultra Flip Laptop 14-fh0xxx and 14t-fh000 Touchpad]
MatchBus=i2c
MatchUdevType=touchpad
MatchDMIModalias=dmi:*:svnHP:pnHPOmniBookUltraFlipLaptop14-fh0xxx:*
MatchDMIModalias=dmi:*:svnHP:*:rn8CDE:*
ModelTabletModeNoSuspend=1
AttrPressureRange=15:5
AttrThumbPressureThreshold=80
AttrPalmPressureThreshold=125
[HP Pavilion dm4]
MatchName=*SynPS/2 Synaptics TouchPad

View file

@ -0,0 +1,11 @@
# Do not edit this file, it will be overwritten on update
# Most Pixart Touchpad (093A:0255) devices don't have buttons so we remove right
# button in 30-vendor-pixart.quirks, but this one does.
[Positivo VAIO FE15 Touchpad]
MatchBus=i2c
MatchVendor=0x093A
MatchProduct=0x0255
MatchUdevType=touchpad
MatchDMIModalias=dmi:*:svnPositivoBahia-VAIO:pnVJFE59F11X-*:*
AttrEventCode=+BTN_RIGHT

View file

@ -0,0 +1,8 @@
# Do not edit this file, it will be overwritten on update
# Clickpad that announces BTN_RIGHT
[Wareus B15 Touchpad]
MatchName=HTIX5288:00 36B6:C001 Touchpad
MatchUdevType=touchpad
MatchDMIModalias=dmi:*svnWareus:*pnB15*
AttrEventCode=-BTN_RIGHT

View file

@ -82,10 +82,10 @@ files will not be used.
Debugging
---------
When modifying a data file, use the `libinput list-quirks` tool to
When modifying a data file, use the `libinput quirks list` tool to
verify the changes. The tool can be pointed at the data directory to
analyse, use `--verbose` to get more info. For example:
```
libinput list-quirks --data-dir /path/to/git/repo/quirks/ --verbose /dev/input/event0
libinput quirks list --data-dir /path/to/git/repo/quirks/ --verbose /dev/input/event0
```

View file

@ -332,9 +332,9 @@ evdev_usage_is_button(evdev_usage_t usage)
case EVDEV_BTN_TOOL_FINGER:
case EVDEV_BTN_TOUCH:
return false;
case BTN_STYLUS:
case BTN_STYLUS2:
case BTN_STYLUS3:
case EVDEV_BTN_STYLUS:
case EVDEV_BTN_STYLUS2:
case EVDEV_BTN_STYLUS3:
return true;
case EVDEV_BTN_MISC ... EVDEV_BTN_DIGI - 1:
case EVDEV_BTN_WHEEL ... EVDEV_BTN_GEAR_UP:
@ -550,10 +550,12 @@ evdev_frame_append(struct evdev_frame *frame,
size_t nevents)
{
assert(nevents > 0);
int syn_report_value = 0;
for (size_t i = 0; i < nevents; i++) {
if (evdev_usage_eq(events[i].usage, EVDEV_SYN_REPORT)) {
nevents = i;
syn_report_value = events[i].value;
break;
}
}
@ -568,14 +570,24 @@ evdev_frame_append(struct evdev_frame *frame,
frame->count += nevents;
}
frame->events[frame->count - 1] = (struct evdev_event){
.usage = evdev_usage_from_uint32_t(EVDEV_SYN_REPORT),
.value = syn_report_value,
};
return 0;
}
static inline int
evdev_frame_append_one(struct evdev_frame *frame, evdev_usage_t usage, int32_t value)
{
if (evdev_usage_eq(usage, EVDEV_SYN_REPORT))
if (evdev_usage_eq(usage, EVDEV_SYN_REPORT)) {
frame->events[frame->count - 1] = (struct evdev_event){
.usage = evdev_usage_from_uint32_t(EVDEV_SYN_REPORT),
.value = value,
};
return 0;
}
if (frame->count >= frame->max_size)
return -ENOMEM;

View file

@ -585,8 +585,28 @@ tp_gesture_handle_event_on_state_none(struct tp_dispatch *tp,
static void
tp_gesture_set_3fg_drag_3fg_or_swipe_timer(struct tp_dispatch *tp, usec_t time)
{
libinput_timer_set(&tp->gesture.drag_3fg_or_swipe_timer,
usec_add(time, DRAG_3FG_OR_SWIPE_TIMEOUT));
usec_t expire = usec_add(tp->gesture.initial_time, DRAG_3FG_OR_SWIPE_TIMEOUT);
/* This is a hack to avoid the state machine getting even more complicated.
* For a slow drag/fast swipe we want the time from the *initial* touch point,
* not the time from when we realised the fingers are moving. IOW
* putting 3fg down, resting for 80ms and then moving fast must trigger
* a drag, not a swipe.
*
* In theory we should set the timer in the NONE/UNKNOWN states but that would
* require a whole parallel set of states like
* NONE_BUT_TIMEOUT_FOR_FAST_STATE_EXPIRED. Let's not do that, instead we set a
* negative timer and let the normal state proceed. Either we moved by the
* threshold already (in which case we shouldn't ever get here anyway) or
* we didn't in which case the neg timer will do the right thing too when it
* fires.
*/
if (usec_cmp(expire, time) < 0)
libinput_timer_set_flags(&tp->gesture.drag_3fg_or_swipe_timer,
expire,
TIMER_FLAG_ALLOW_NEGATIVE);
else
libinput_timer_set(&tp->gesture.drag_3fg_or_swipe_timer, expire);
}
static void

View file

@ -178,6 +178,13 @@ tp_tap_clear_timer(struct tp_dispatch *tp)
libinput_timer_cancel(&tp->tap.timer);
}
static bool
tp_touch_near_any_edge(struct tp_dispatch *tp, struct tp_touch *t)
{
return (t->point.x < tp->tap.edges.left || t->point.x > tp->tap.edges.right ||
t->point.y < tp->tap.edges.top || t->point.y > tp->tap.edges.bottom);
}
static void
tp_tap_move_to_dead(struct tp_dispatch *tp, struct tp_touch *t)
{
@ -812,6 +819,7 @@ tp_tap_dragging_handle_event(struct tp_dispatch *tp,
usec_t time,
int nfingers_tapped)
{
bool at_edge = false;
switch (event) {
case TAP_EVENT_TOUCH: {
@ -825,7 +833,8 @@ tp_tap_dragging_handle_event(struct tp_dispatch *tp,
break;
}
case TAP_EVENT_RELEASE:
if (tp->tap.drag_lock != LIBINPUT_CONFIG_DRAG_LOCK_DISABLED) {
if (tp->tap.drag_lock != LIBINPUT_CONFIG_DRAG_LOCK_DISABLED ||
(at_edge = tp_touch_near_any_edge(tp, t))) {
enum tp_tap_state dest[3] = {
TAP_STATE_1FGTAP_DRAGGING_WAIT,
TAP_STATE_2FGTAP_DRAGGING_WAIT,
@ -833,8 +842,9 @@ tp_tap_dragging_handle_event(struct tp_dispatch *tp,
};
assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
tp->tap.state = dest[nfingers_tapped - 1];
if (tp->tap.drag_lock ==
LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_TIMEOUT)
if (at_edge ||
tp->tap.drag_lock ==
LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_TIMEOUT)
tp_tap_set_draglock_timer(tp, time);
} else {
tp_tap_notify(tp,
@ -1579,6 +1589,20 @@ tp_init_tap(struct tp_dispatch *tp)
tp->tap.drag_enabled = tp_drag_default(tp->device);
tp->tap.drag_lock = tp_drag_lock_default(tp->device);
struct evdev_device *device = tp->device;
const struct input_absinfo *absx = device->abs.absinfo_x;
const struct input_absinfo *absy = device->abs.absinfo_y;
assert(absx && absy);
struct phys_coords mm = { 5.0, 5.0 };
struct device_coords edge_margin = evdev_device_mm_to_units(device, &mm);
tp->tap.edges.left = edge_margin.x;
tp->tap.edges.right = (absx->maximum - edge_margin.x + absx->minimum);
tp->tap.edges.top = edge_margin.y;
tp->tap.edges.bottom = (absy->maximum - edge_margin.y + absy->minimum);
snprintf(timer_name,
sizeof(timer_name),
"%s tap",

View file

@ -333,7 +333,7 @@ tp_new_touch(struct tp_dispatch *tp, struct tp_touch *t, usec_t time)
again. That's a kernel bug, so let's complain. */
if (t->state == TOUCH_MAYBE_END) {
evdev_log_bug_kernel(tp->device,
"touch %d ended and began in in same frame.\n",
"touch %d ended and began in same frame.\n",
t->index);
tp->nfingers_down++;
t->state = TOUCH_UPDATE;
@ -1335,7 +1335,7 @@ tp_position_fake_touches(struct tp_dispatch *tp)
return;
/* We have at least one fake touch down. Find the top-most real
* touch and copy its coordinates over to to all fake touches.
* touch and copy its coordinates over to all fake touches.
* This is more reliable than just taking the first touch.
*/
for (i = 0; i < tp->num_slots; i++) {
@ -1837,23 +1837,25 @@ tp_handle_state(struct tp_dispatch *tp, usec_t time)
_unused_ static inline void
tp_debug_touch_state(struct tp_dispatch *tp, struct evdev_device *device)
{
char buf[1024] = { 0 };
_autostrvfree_ char **strv = NULL;
struct tp_touch *t;
size_t i = 0;
tp_for_each_touch(tp, t) {
if (i >= tp->nfingers_down)
break;
sprintf(&buf[strlen(buf)],
"slot %zd: %04d/%04d p%03d %s |",
i++,
t->point.x,
t->point.y,
t->pressure,
tp_touch_active(tp, t) ? "" : "inactive");
strv = strv_append_printf(strv,
"slot %zd: %04d/%04d p%03d %s",
i++,
t->point.x,
t->point.y,
t->pressure,
tp_touch_active(tp, t) ? "" : "inactive");
}
if (buf[0] != '\0')
if (strv) {
_autofree_ char *buf = strv_join(strv, " | ");
evdev_log_debug(device, "touch state: %s\n", buf);
}
}
static void
@ -2678,6 +2680,22 @@ evdev_tag_touchpad(struct evdev_device *device, struct udev_device *udev_device)
int bustype, vendor;
const char *prop;
prop = udev_device_get_property_value(udev_device, "ID_INTEGRATION");
if (prop) {
if (streq(prop, "internal")) {
evdev_tag_touchpad_internal(device);
return;
}
if (streq(prop, "external")) {
evdev_tag_touchpad_external(device);
return;
}
evdev_log_info(device, "tagged with unknown value %s\n", prop);
}
/* Fall back to ID_TOUCHPAD_INTEGRATION if ID_INTEGRATION is missing */
prop = udev_device_get_property_value(udev_device,
"ID_INPUT_TOUCHPAD_INTEGRATION");
if (prop) {

View file

@ -450,6 +450,11 @@ struct tp_dispatch {
unsigned int nfingers_down; /* number of fingers down for tapping (excl.
thumb/palm) */
/* Edges for auto drag-lock, in device coordinates */
struct {
int left, right, top, bottom;
} edges;
} tap;
struct {

View file

@ -237,14 +237,11 @@ pad_led_group_add_toggle_button(struct pad_led_group *group,
return 0;
}
static inline bool
pad_led_get_sysfs_base_path(struct evdev_device *device,
char *path_out,
size_t path_out_sz)
static inline char *
pad_led_get_sysfs_base_path(struct evdev_device *device)
{
struct udev_device *parent, *udev_device;
const char *test_path;
int rc;
udev_device = device->udev_device;
@ -253,24 +250,18 @@ pad_led_get_sysfs_base_path(struct evdev_device *device,
test_path =
udev_device_get_property_value(udev_device,
"LIBINPUT_TEST_TABLET_PAD_SYSFS_PATH");
if (test_path) {
rc = snprintf(path_out, path_out_sz, "%s", test_path);
return rc != -1;
}
if (test_path)
return safe_strdup(test_path);
parent = udev_device_get_parent_with_subsystem_devtype(udev_device,
"input",
NULL);
if (!parent)
return false;
return NULL;
rc = snprintf(path_out,
path_out_sz,
"%s/%s::wacom-",
udev_device_get_syspath(parent),
udev_device_get_sysname(parent));
return rc != -1;
return strdup_printf("%s/%s::wacom-",
udev_device_get_syspath(parent),
udev_device_get_sysname(parent));
}
static int
@ -288,11 +279,12 @@ pad_add_mode_group(struct pad_dispatch *pad,
struct libinput *li = pad_libinput_context(pad);
struct pad_led_group *group = NULL;
int rc = -ENOMEM;
char syspath[PATH_MAX];
_autofree_ char *syspath;
/* syspath is /sys/class/leds/input1234/input12345::wacom-" and
only needs the group + mode appended */
if (!pad_led_get_sysfs_base_path(device, syspath, sizeof(syspath)))
syspath = pad_led_get_sysfs_base_path(device);
if (!syspath)
return -ENOMEM;
group = pad_group_new(pad, group_index, nmodes);

View file

@ -178,7 +178,7 @@ tablet_filter_axis_fuzz(const struct tablet_dispatch *tablet,
fuzz = libevdev_get_abs_fuzz(device->evdev, evdev_usage_code(e->usage));
/* ABS_DISTANCE doesn't have have fuzz set and causes continuous
/* ABS_DISTANCE doesn't have fuzz set and causes continuous
* updates for the cursor/lens tools. Add a minimum fuzz of 2, same
* as the xf86-input-wacom driver
*/
@ -1311,18 +1311,6 @@ eraser_button_get_default_mode(struct libinput_tablet_tool *tool)
static enum libinput_config_status
eraser_button_set_button(struct libinput_tablet_tool *tool, uint32_t button)
{
switch (button) {
case BTN_STYLUS:
case BTN_STYLUS2:
case BTN_STYLUS3:
break;
default:
log_bug_libinput(libinput_device_get_context(tool->last_device),
"Unsupported eraser button 0x%x",
button);
return LIBINPUT_CONFIG_STATUS_INVALID;
}
tool->eraser_button.want_button = button;
eraser_button_toggle(tool);
@ -1878,38 +1866,24 @@ tablet_calculate_arbitration_rect(struct tablet_dispatch *tablet)
{
struct evdev_device *device = tablet->device;
struct phys_rect r = { 0 };
struct phys_coords mm;
const double maxdim = 600; /* 600mm covers all the way to the right/bottom */
mm = evdev_device_units_to_mm(device, &tablet->axes.point);
struct phys_coords mm = evdev_device_units_to_mm(device, &tablet->axes.point);
/* The rect we disable is 20mm left of the tip, 100mm north of the
* tip, and 200x250mm large.
* If the stylus is tilted left (tip further right than the eraser
* end) assume left-handed mode.
*
* Obviously if we'd run out of the boundaries, we clip the rect
* accordingly.
/* The rect we disable is 20mm left of the tip, covering that whole side of the
* tablet. If the stylus is tilted left (tip further right than the eraser end)
* assume left-handed mode.
*/
if (tablet->axes.tilt.x > 0) {
r.x = mm.x - 20;
r.w = 200;
r.w = maxdim;
} else {
r.x = mm.x + 20;
r.w = 200;
r.x -= r.w;
}
if (r.x < 0) {
r.w += r.x;
r.x = 0;
r.w = mm.x + 20;
}
r.y = mm.y - 100;
r.h = 250;
if (r.y < 0) {
r.h += r.y;
r.y = 0;
}
r.y = 0;
r.h = maxdim;
return r;
}
@ -2477,7 +2451,7 @@ tablet_setup_touch_arbitration(struct evdev_device *device,
struct libinput_device_group *group2 =
libinput_device_get_device_group(&new_device->base);
/* same phsical device? -> better, otherwise keep the one we have */
/* same physical device? -> better, otherwise keep the one we have */
if (group1 != group2)
return;

View file

@ -54,6 +54,7 @@
#define DEFAULT_WHEEL_CLICK_ANGLE 15
#define DEFAULT_BUTTON_SCROLL_TIMEOUT usec_from_millis(200)
#define SCROLL_BUTTON_LOCK_GRACE_TIMEOUT usec_from_millis(500)
enum evdev_device_udev_tags {
EVDEV_UDEV_TAG_NONE = 0,
@ -228,6 +229,15 @@ evdev_button_scroll_button(struct evdev_device *device, usec_t time, int is_pres
break; /* handle event */
case BUTTONSCROLL_LOCK_FIRSTDOWN:
assert(!is_press);
if (device->scroll.button_scroll_state == BUTTONSCROLL_SCROLLING &&
usec_cmp(usec_delta(time, device->scroll.button_down_time),
SCROLL_BUTTON_LOCK_GRACE_TIMEOUT) >= 0) {
/* held + scrolled past grace period: temporary scroll,
* no lock engaged */
device->scroll.lock_state = BUTTONSCROLL_LOCK_IDLE;
evdev_log_debug(device, "scroll lock: temp scroll done\n");
break; /* pass release through */
}
device->scroll.lock_state = BUTTONSCROLL_LOCK_FIRSTUP;
evdev_log_debug(device, "scroll lock: first up\n");
return; /* filter release event */
@ -489,6 +499,7 @@ static void
evdev_tag_trackpoint(struct evdev_device *device, struct udev_device *udev_device)
{
char *prop;
const char *udev_prop;
if (!libevdev_has_property(device->evdev, INPUT_PROP_POINTING_STICK) &&
!parse_udev_flag(device, udev_device, "ID_INPUT_POINTINGSTICK"))
@ -496,10 +507,22 @@ evdev_tag_trackpoint(struct evdev_device *device, struct udev_device *udev_devic
device->tags |= EVDEV_TAG_TRACKPOINT;
udev_prop = udev_device_get_property_value(udev_device, "ID_INTEGRATION");
if (udev_prop) {
if (streq(udev_prop, "internal")) {
/* noop, this is the default anyway */
} else if (streq(udev_prop, "external"))
device->tags |= EVDEV_TAG_EXTERNAL_MOUSE;
else
evdev_log_info(device,
"tagged with unknown value %s\n",
udev_prop);
}
_unref_(quirks) *q = libinput_device_get_quirks(&device->base);
if (q && quirks_get_string(q, QUIRK_ATTR_TRACKPOINT_INTEGRATION, &prop)) {
if (streq(prop, "internal")) {
/* noop, this is the default anyway */
device->tags &= ~EVDEV_TAG_EXTERNAL_MOUSE;
} else if (streq(prop, "external")) {
device->tags |= EVDEV_TAG_EXTERNAL_MOUSE;
evdev_log_info(device, "is an external pointing stick\n");
@ -527,6 +550,7 @@ static void
evdev_tag_keyboard(struct evdev_device *device, struct udev_device *udev_device)
{
char *prop;
const char *udev_prop;
int code;
if (!libevdev_has_event_type(device->evdev, EV_KEY))
@ -537,6 +561,18 @@ evdev_tag_keyboard(struct evdev_device *device, struct udev_device *udev_device)
return;
}
udev_prop = udev_device_get_property_value(udev_device, "ID_INTEGRATION");
if (udev_prop) {
if (streq(udev_prop, "internal"))
evdev_tag_keyboard_internal(device);
else if (streq(udev_prop, "external"))
evdev_tag_keyboard_external(device);
else
evdev_log_info(device,
"tagged with unknown value %s\n",
udev_prop);
}
_unref_(quirks) *q = libinput_device_get_quirks(&device->base);
if (q && quirks_get_string(q, QUIRK_ATTR_KEYBOARD_INTEGRATION, &prop)) {
if (streq(prop, "internal")) {
@ -1325,7 +1361,7 @@ evdev_read_wheel_click_count_prop(struct evdev_device *device,
evdev_log_error(device,
"mouse wheel click count is present but invalid, "
"using %d degrees for angle instead instead\n",
"using %d degrees for angle instead\n",
DEFAULT_WHEEL_CLICK_ANGLE);
*angle = DEFAULT_WHEEL_CLICK_ANGLE;
@ -1774,9 +1810,9 @@ evdev_disable_accelerometer_axes(struct evdev_device *device)
libevdev_disable_event_code(evdev, EV_ABS, ABS_Y);
libevdev_disable_event_code(evdev, EV_ABS, ABS_Z);
libevdev_disable_event_code(evdev, EV_ABS, REL_X);
libevdev_disable_event_code(evdev, EV_ABS, REL_Y);
libevdev_disable_event_code(evdev, EV_ABS, REL_Z);
libevdev_disable_event_code(evdev, EV_REL, REL_X);
libevdev_disable_event_code(evdev, EV_REL, REL_Y);
libevdev_disable_event_code(evdev, EV_REL, REL_Z);
}
static bool

View file

@ -168,7 +168,7 @@ lua_push_evdev_device(lua_State *L,
lua_device->bustype = libinput_device_get_id_bustype(device);
lua_device->vid = libinput_device_get_id_vendor(device);
lua_device->pid = libinput_device_get_id_product(device);
lua_device->name = strdup(libinput_device_get_name(device));
lua_device->name = safe_strdup(libinput_device_get_name(device));
lua_device->device_removed_refid = LUA_NOREF;
lua_device->frame_refid = LUA_NOREF;
list_init(&lua_device->udev_properties_list);
@ -375,8 +375,7 @@ remove_device(struct libinput_lua_plugin *plugin, EvdevDevice *evdev)
list_for_each_safe(prop, &evdev->udev_properties_list, link) {
udev_property_destroy(prop);
}
free(evdev->name);
evdev->name = NULL;
free_clear(&evdev->name);
evdev->device = libinput_device_unref(evdev->device);
/* This device no longer exists but our lua code may have a
@ -562,6 +561,12 @@ libinputplugin_unregister(lua_State *L)
return luaL_error(L, "@@unregistering@@");
}
static int
readonly_newindex(lua_State *L)
{
return luaL_error(L, "attempt to modify a read-only table");
}
static int
libinputplugin_gc(lua_State *L)
{
@ -673,7 +678,28 @@ libinputplugin_log_error(lua_State *L)
return libinputplugin_log(L, LIBINPUT_LOG_PRIORITY_ERROR);
}
static const struct luaL_Reg libinputplugin_vtable[] = {
static void
setup_vfuncs(lua_State *L,
const char *metatable_name,
const struct luaL_Reg *vfuncs,
const struct luaL_Reg *public_methods)
{
luaL_newmetatable(L, metatable_name);
luaL_setfuncs(L, vfuncs, 0);
lua_newtable(L);
luaL_setfuncs(L, public_methods, 0);
lua_setfield(L, -2, "__index");
/* set metatable.__metatable = false to prevent a script from getmetatable(),
which is blocked anyway but safe and sorry and whatnot */
lua_pushboolean(L, 0);
lua_setfield(L, -2, "__metatable");
lua_pop(L, 1);
}
static const struct luaL_Reg libinputplugin_methods[] = {
{ "now", libinputplugin_now },
{ "version", libinputplugin_version },
{ "connect", libinputplugin_connect },
@ -685,18 +711,18 @@ static const struct luaL_Reg libinputplugin_vtable[] = {
{ "log_debug", libinputplugin_log_debug },
{ "log_info", libinputplugin_log_info },
{ "log_error", libinputplugin_log_error },
{ "__gc", libinputplugin_gc },
{ NULL, NULL }
};
static const struct luaL_Reg libinputplugin_meta[] = { { "__gc", libinputplugin_gc },
{ "__newindex",
readonly_newindex },
{ NULL, NULL } };
static void
libinputplugin_init(lua_State *L)
{
luaL_newmetatable(L, PLUGIN_METATABLE);
lua_pushstring(L, "__index");
lua_pushvalue(L, -2); /* push metatable */
lua_settable(L, -3); /* metatable.__index = metatable */
luaL_setfuncs(L, libinputplugin_vtable, 0);
setup_vfuncs(L, PLUGIN_METATABLE, libinputplugin_meta, libinputplugin_methods);
}
static int
@ -1073,7 +1099,7 @@ evdevdevice_gc(lua_State *L)
return 0;
}
static const struct luaL_Reg evdevdevice_vtable[] = {
static const struct luaL_Reg evdevdevice_methods[] = {
{ "info", evdevdevice_info },
{ "name", evdevdevice_name },
{ "usages", evdevdevice_usages },
@ -1087,18 +1113,17 @@ static const struct luaL_Reg evdevdevice_vtable[] = {
{ "prepend_frame", evdevdevice_prepend_frame },
{ "append_frame", evdevdevice_append_frame },
{ "disable_feature", evdevdevice_disable_feature },
{ "__gc", evdevdevice_gc },
{ NULL, NULL }
};
static const struct luaL_Reg evdevdevice_meta[] = { { "__gc", evdevdevice_gc },
{ "__newindex", readonly_newindex },
{ NULL, NULL } };
static void
evdevdevice_init(lua_State *L)
{
luaL_newmetatable(L, EVDEV_DEVICE_METATABLE);
lua_pushstring(L, "__index");
lua_pushvalue(L, -2); /* push metatable */
lua_settable(L, -3); /* metatable.__index = metatable */
luaL_setfuncs(L, evdevdevice_vtable, 0);
setup_vfuncs(L, EVDEV_DEVICE_METATABLE, evdevdevice_meta, evdevdevice_methods);
}
static void
@ -1336,7 +1361,7 @@ libinput_lua_plugin_new_from_path(struct libinput *libinput, const char *path)
return NULL;
}
int ret = luaL_loadfile(L, path);
int ret = luaL_loadfilex(L, path, "t");
if (ret == LUA_OK) {
plugin->L = steal(&L);

View file

@ -115,7 +115,7 @@ libinput_plugin_new(struct libinput *libinput,
plugin->refcount = 1;
plugin->interface = interface;
plugin->user_data = user_data;
plugin->name = strdup(name);
plugin->name = safe_strdup(name);
list_init(&plugin->timers);
if (plugin->index >= 32) {
@ -726,6 +726,9 @@ plugin_has_mask(struct libinput_plugin *plugin, struct evdev_frame *frame)
size_t nevents;
struct evdev_event *events = evdev_frame_get_events(frame, &nevents);
if (nevents == 0)
return false;
/* nevents - 1 because we don't check the SYN_REPORT */
for (size_t i = 0; i < nevents - 1; i++) {
struct evdev_event *e = &events[i];

View file

@ -230,7 +230,7 @@ libinput_plugin_enable_evdev_usage(struct libinput_plugin *plugin,
* for P3 the injected event I is received before E.
*
* An example for event injection being harmful:
* A plugin may monitor tablet proximity state and prepent
* A plugin may monitor tablet proximity state and prepend
* proximity-in events if the tablet does not send proximity-in
* events. This plugin stops monitoring events once it sees correct
* proximity-in events.
@ -279,7 +279,7 @@ libinput_plugin_inject_evdev_frame(struct libinput_plugin *libinput,
*
* If called within a plugin's timer callback, any frames generated by
* the plugin will only be seen by plugins after this plugin. These
* frames will be processed in the usual evdev_fame() callback and there
* frames will be processed in the usual evdev_frame() callback and there
* is no indication that the events were queued from within a timer
* callback. Using the above example:
*

View file

@ -5206,7 +5206,7 @@ libinput_tablet_tool_config_eraser_button_get_default_mode(
if (!libinput_tablet_tool_config_eraser_button_get_modes(tool))
return LIBINPUT_CONFIG_ERASER_BUTTON_DEFAULT;
return tool->config.eraser_button.get_mode(tool);
return tool->config.eraser_button.get_default_mode(tool);
}
LIBINPUT_EXPORT enum libinput_config_status
@ -5216,16 +5216,9 @@ libinput_tablet_tool_config_eraser_button_set_button(struct libinput_tablet_tool
if (!libinput_tablet_tool_config_eraser_button_get_modes(tool))
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
switch (button) {
case BTN_STYLUS:
case BTN_STYLUS2:
case BTN_STYLUS3:
break;
default:
if (!libinput_tablet_tool_has_button(tool, button))
return LIBINPUT_CONFIG_STATUS_INVALID;
break;
}
evdev_usage_t usage = evdev_usage_from_code(EV_KEY, button);
if (!evdev_usage_is_button(usage))
return LIBINPUT_CONFIG_STATUS_INVALID;
return tool->config.eraser_button.set_button(tool, button);
}
@ -5246,7 +5239,7 @@ libinput_tablet_tool_config_eraser_button_get_default_button(
if (!libinput_tablet_tool_config_eraser_button_get_modes(tool))
return 0;
return tool->config.eraser_button.get_button(tool);
return tool->config.eraser_button.get_default_button(tool);
}
#ifdef HAVE_LIBWACOM

View file

@ -348,7 +348,7 @@ enum libinput_tablet_pad_strip_axis_source {
* LIBINPUT_TABLET_TOOL_TYPE_PEN.
* Use libinput_tablet_tool_get_tool_id() to get a specific model where applicable.
*
* Note that on some device, the eraser tool is on the tail end of a pen
* Note that on some devices, the eraser tool is on the tail end of a pen
* device. On other devices, e.g. MS Surface 3, the eraser is the pen tip
* while a button is held down.
*
@ -730,7 +730,7 @@ enum libinput_switch {
* If the switch is in state @ref LIBINPUT_SWITCH_STATE_OFF, the
* device is in laptop mode. If the switch is in state @ref
* LIBINPUT_SWITCH_STATE_ON, the device is in tablet mode and the
* keyboard or touchpad may not be accessible.
* keyboard or touchpad may not be accessible.
*
* It is up to the caller to identify which devices are inaccessible
* in tablet mode.
@ -828,7 +828,7 @@ enum libinput_event_type {
LIBINPUT_EVENT_POINTER_AXIS,
/**
* A scroll event from a wheel. This event is sent is sent **in
* A scroll event from a wheel. This event is sent **in
* addition** to the @ref LIBINPUT_EVENT_POINTER_AXIS
* event for all events with a
* libinput_event_pointer_get_axis_source() of @ref
@ -843,7 +843,7 @@ enum libinput_event_type {
/**
* A scroll event caused by the movement of one or more fingers on a
* device. This event is sent is sent **in addition** to the @ref
* device. This event is sent **in addition** to the @ref
* LIBINPUT_EVENT_POINTER_AXIS event for all events with a
* libinput_event_pointer_get_axis_source() of @ref
* LIBINPUT_POINTER_AXIS_SOURCE_FINGER. Ignore @ref
@ -857,7 +857,7 @@ enum libinput_event_type {
/**
* A scroll event from a continuous scroll source, e.g. button
* scrolling. This event is sent is sent **in
* scrolling. This event is sent **in
* addition** to the @ref LIBINPUT_EVENT_POINTER_AXIS
* event for all events with a
* libinput_event_pointer_get_axis_source() of @ref
@ -1932,7 +1932,7 @@ libinput_event_touch_get_base_event(struct libinput_event_touch *event);
*
* Gesture events are generated when a gesture is recognized on a touchpad.
*
* Gesture sequences always start with a LIBINPUT_EVENT_GESTURE_FOO_START
* Gesture sequences always start with a LIBINPUT_EVENT_GESTURE_FOO_BEGIN
* event. All following gesture events will be of the
* LIBINPUT_EVENT_GESTURE_FOO_UPDATE type until a
* LIBINPUT_EVENT_GESTURE_FOO_END is generated which signals the end of the
@ -1994,12 +1994,14 @@ libinput_event_gesture_get_finger_count(struct libinput_event_gesture *event);
*
* Return if the gesture ended normally, or if it was cancelled.
* For gesture events that are not of type
* @ref LIBINPUT_EVENT_GESTURE_SWIPE_END or
* @ref LIBINPUT_EVENT_GESTURE_PINCH_END, this function returns 0.
* @ref LIBINPUT_EVENT_GESTURE_SWIPE_END,
* @ref LIBINPUT_EVENT_GESTURE_PINCH_END, or
* @ref LIBINPUT_EVENT_GESTURE_HOLD_END, this function returns 0.
*
* @note It is an application bug to call this function for events other than
* @ref LIBINPUT_EVENT_GESTURE_SWIPE_END or
* @ref LIBINPUT_EVENT_GESTURE_PINCH_END.
* @ref LIBINPUT_EVENT_GESTURE_SWIPE_END,
* @ref LIBINPUT_EVENT_GESTURE_PINCH_END, or
* @ref LIBINPUT_EVENT_GESTURE_HOLD_END.
*
* @return 0 or 1, with 1 indicating that the gesture was cancelled.
*/
@ -2423,7 +2425,7 @@ libinput_event_tablet_tool_wheel_has_changed(struct libinput_event_tablet_tool *
* width of the device. See the libinput documentation for more details.
*
* @param event The libinput tablet tool event
* @return The current value of the the axis
* @return The current value of the axis
*
* @since 1.2
*/
@ -2446,7 +2448,7 @@ libinput_event_tablet_tool_get_x(struct libinput_event_tablet_tool *event);
* width of the device. See the libinput documentation for more details.
*
* @param event The libinput tablet tool event
* @return The current value of the the axis
* @return The current value of the axis
*
* @since 1.2
*/
@ -2500,7 +2502,7 @@ libinput_event_tablet_tool_get_dy(struct libinput_event_tablet_tool *event);
* If this axis does not exist on the current tool, this function returns 0.
*
* @param event The libinput tablet tool event
* @return The current value of the the axis
* @return The current value of the axis
*
* @since 1.2
*/
@ -2516,7 +2518,7 @@ libinput_event_tablet_tool_get_pressure(struct libinput_event_tablet_tool *event
* If this axis does not exist on the current tool, this function returns 0.
*
* @param event The libinput tablet tool event
* @return The current value of the the axis
* @return The current value of the axis
*
* @since 1.2
*/
@ -2556,7 +2558,7 @@ libinput_event_tablet_tool_get_tilt_x(struct libinput_event_tablet_tool *event);
* If this axis does not exist on the current tool, this function returns 0.
*
* @param event The libinput tablet tool event
* @return The current value of the the axis in degrees
* @return The current value of the axis in degrees
*
* @since 1.2
*/
@ -2578,7 +2580,7 @@ libinput_event_tablet_tool_get_tilt_y(struct libinput_event_tablet_tool *event);
* If this axis does not exist on the current tool, this function returns 0.
*
* @param event The libinput tablet tool event
* @return The current value of the the axis
* @return The current value of the axis
*
* @since 1.2
*/
@ -2596,7 +2598,7 @@ libinput_event_tablet_tool_get_rotation(struct libinput_event_tablet_tool *event
* If this axis does not exist on the current tool, this function returns 0.
*
* @param event The libinput tablet tool event
* @return The current value of the the axis
* @return The current value of the axis
*
* @since 1.2
*/
@ -2630,7 +2632,7 @@ libinput_event_tablet_tool_get_size_major(struct libinput_event_tablet_tool *eve
* rotation must be taken into account.
*
* Where no rotation is available on a tool, or where rotation is zero, the
* minor axis aligns with the y axis and the minor axis with the x axis.
* major axis aligns with the y axis and the minor axis with the x axis.
*
* If this axis does not exist on the current tool, this function returns 0.
*
@ -2823,10 +2825,10 @@ libinput_event_tablet_tool_get_button_state(struct libinput_event_tablet_tool *e
* @ingroup event_tablet
*
* For the button of a @ref LIBINPUT_EVENT_TABLET_TOOL_BUTTON event, return the total
* number of buttons pressed on all devices on the associated seat after the
* number of buttons pressed on all devices on the associated seat after
* the event was triggered.
*
" @note It is an application bug to call this function for events other than
* @note It is an application bug to call this function for events other than
* @ref LIBINPUT_EVENT_TABLET_TOOL_BUTTON. For other events, this function returns 0.
*
* @param event The libinput tablet tool event
@ -3205,7 +3207,7 @@ libinput_event_tablet_pad_get_base_event(struct libinput_event_tablet_pad *event
* returns 0.
*
* @param event The libinput tablet pad event
* @return The current value of the the axis
* @return The current value of the axis
* @retval -1 The finger was lifted
*
* @since 1.3
@ -3259,8 +3261,8 @@ libinput_event_tablet_pad_get_ring_source(struct libinput_event_tablet_pad *even
* logical orientation.
*
* If the source is @ref LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER,
* libinput sends a terminating event with a ring value of -1 when the
* finger is lifted from the ring. A caller may use this information to e.g.
* libinput sends a terminating event with a strip value of -1 when the
* finger is lifted from the strip. A caller may use this information to e.g.
* determine if kinetic scrolling should be triggered.
*
* @note It is an application bug to call this function for events other than
@ -3268,7 +3270,7 @@ libinput_event_tablet_pad_get_ring_source(struct libinput_event_tablet_pad *even
* returns 0.
*
* @param event The libinput tablet pad event
* @return The current value of the the axis
* @return The current value of the axis
* @retval -1 The finger was lifted
*
* @since 1.3
@ -3404,7 +3406,7 @@ libinput_event_tablet_pad_get_key_state(struct libinput_event_tablet_pad *event)
* returns 0.
*
* @param event The libinput tablet pad event
* @return The delta of the the axis
* @return The delta of the axis
*
* @since 1.26
*/
@ -3529,7 +3531,7 @@ libinput_event_tablet_pad_get_time_usec(struct libinput_event_tablet_pad *event)
* @ingroup event_switch
*
* Return the switch that triggered this event.
* For pointer events that are not of type @ref
* For switch events that are not of type @ref
* LIBINPUT_EVENT_SWITCH_TOGGLE, this function returns 0.
*
* @note It is an application bug to call this function for events other than
@ -3665,7 +3667,7 @@ libinput_udev_create_context(const struct libinput_interface *interface,
* available on this seat, or if devices are available but fail to open in
* @ref libinput_interface::open_restricted. Devices that do not have the
* minimum capabilities to be recognized as pointer, keyboard or touch
* device are ignored. Such devices and those that failed to open
* device are ignored. Such devices and those that failed to open are
* ignored until the next call to libinput_resume().
*
* This function may only be called once per context.
@ -3762,7 +3764,7 @@ libinput_path_remove_device(struct libinput_device *device);
* Paths are not traversed recursively.
*
* Plugins that have a 0 byte size shadow any plugins with the same name
* but do not provide any fuctionality. This allows disabling a plugin
* but do not provide any functionality. This allows disabling a plugin
* by simply dropping an empty file in a higher-priority directory.
*
* This function must be called before libinput_plugin_system_load_plugins().
@ -5838,7 +5840,7 @@ libinput_device_config_accel_apply(struct libinput_device *device,
* types (e.g. scrolling) may be added in the future.
*
* The special type @ref LIBINPUT_ACCEL_TYPE_FALLBACK specifies the acceleration
* function to be moved for any movement produced by the device that does not
* function to be used for any movement produced by the device that does not
* have a specific acceleration type defined.
*
* Use to specify the acceleration function type in
@ -5879,7 +5881,7 @@ enum libinput_config_accel_type {
*
* Each custom acceleration function is defined by ``n`` points spaced uniformly
* along the x-axis starting from 0 and continuing in a constant step size.
* There by the function is defined by the following points:
* Thereby the function is defined by the following points:
* (0 * step, f[0]), (1 * step, f[1]), ..., ((n - 1) * step, f[n - 1]).
* The x-axis represents the device-speed in device units per millisecond.
* The y-axis represents the pointer-speed.
@ -6624,7 +6626,9 @@ enum libinput_config_scroll_button_lock_state {
* If the state is
* @ref LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED, the button is considered
* logically down after the first press and release sequence, and logically
* up after the second press and release sequence.
* up after the second press and release sequence. If the button is held
* and used to scroll for longer than a short grace period, releasing the
* button does not engage the lock.
*
* @param device The device to configure
* @param state The state to set the scroll button lock to
@ -7097,7 +7101,7 @@ libinput_device_config_rotation_get_default_angle(struct libinput_device *device
* Check if a tablet tool can have a custom pressure range.
*
* @param tool The libinput tool
* @return Non-zero if a device has an adjustible pressure range, zero otherwise.
* @return Non-zero if a device has an adjustable pressure range, zero otherwise.
*
* @see libinput_tablet_tool_config_pressure_range_set
* @see libinput_tablet_tool_config_pressure_range_get_minimum
@ -7371,14 +7375,9 @@ libinput_tablet_tool_config_eraser_button_get_default_mode(
* the eraser mode to @ref LIBINPUT_CONFIG_ERASER_BUTTON_BUTTON via
* libinput_tablet_tool_config_eraser_button_set_mode().
*
* The buttons BTN_STYLUS, BTN_STYLUS2 and BTN_STYLUS2 are always
* allowed, even if libinput_tablet_tool_has_button() returns zero
* for the button. Otherwise, the button must be one that
* libinput_tablet_tool_has_button() returns a nonzero value for.
*
* @param tool The libinput tool
* @param button The button, usually one of BTN_STYLUS, BTN_STYLUS2 or
* BTN_STYLUS3
* @param button The button code. Must be a valid button (e.g. BTN_STYLUS)
* excluding fake buttons (e.g. BTN_TOOL_*) and keys (KEY_*)
*
* @return A config status code
*

View file

@ -24,7 +24,7 @@
#include "config.h"
/* This has the hallmarks of a library to make it re-usable from the tests
* and from the list-quirks tool. It doesn't have all of the features from a
* and from the quirks list tool. It doesn't have all of the features from a
* library you'd expect though
*/

View file

@ -65,12 +65,12 @@ backtrace_print(FILE *fp,
child = fork();
if (child == 0) {
char pid[8];
char pid[16];
close(pipefd[0]);
dup2(pipefd[1], STDOUT_FILENO);
sprintf(pid, "%d", parent);
snprintf(pid, sizeof(pid), "%d", parent);
execlp("gstack", "gstack", pid, NULL);
exit(errno);

View file

@ -36,6 +36,7 @@
#include <stdlib.h>
#include "util-macros.h"
#include "util-mem.h"
#define bit(x_) (1UL << (x_))
#define NBITS(b) (b * 8)
@ -43,7 +44,7 @@
#define NLONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
#define NCHARS(x) ((size_t)(((x) + 7) / 8))
/* This bitfield helper implementation is taken from from libevdev-util.h,
/* This bitfield helper implementation is taken from libevdev-util.h,
* except that it has been modified to work with arrays of unsigned chars
*/
@ -260,6 +261,8 @@ _nonnull_(1) static inline void _infmask_ensure_size(infmask_t *mask, unsigned i
size_t required = _infmask_size_for_bit(bit);
if (required > mask->nmasks) {
mask->mask = realloc(mask->mask, required * sizeof(bitmask_t));
if (!mask->mask)
abort();
/* Zero out the new memory */
for (size_t i = mask->nmasks; i < required; i++)
mask->mask[i] = bitmask_new();
@ -279,8 +282,7 @@ infmask_new(void)
_nonnull_(1) static inline void infmask_reset(infmask_t *mask)
{
free(mask->mask);
mask->mask = NULL;
free_clear(&mask->mask);
mask->nmasks = 0;
}

View file

@ -48,8 +48,8 @@ file_destroy(struct file *f)
DEFINE_DESTROY_CLEANUP_FUNC(file);
/**
* Appends to the given list all files files in the given directory that end
* with the given with the given suffix.
* Appends to the given list all files in the given directory that end
* with the given suffix.
*/
static void
filenames(const char *directory, const char *suffix, struct list *list)

View file

@ -74,10 +74,12 @@ rmdir_r(const char *dir)
_autofree_ char *path = strdup_printf("%s/%s", dir, entry->d_name);
struct stat st;
if (stat(path, &st) < 0)
if (lstat(path, &st) < 0)
return -errno;
if (S_ISDIR(st.st_mode))
if (S_ISLNK(st.st_mode))
rc = unlink(path) < 0 ? -errno : 0;
else if (S_ISDIR(st.st_mode))
rc = rmdir_r(path);
else
rc = unlink(path) < 0 ? -errno : 0;

View file

@ -186,3 +186,14 @@ steal_fd(int *fd)
*fd = -1;
return copy;
}
/**
* Frees the pointer content and resets the data to NULL.
*/
#define free_clear(ptr_) \
do { \
typeof((ptr_)) _pp = (ptr_); \
typeof(*(ptr_)) _p = *_pp; \
*_pp = NULL; \
free(_p); \
} while(0)

View file

@ -41,7 +41,7 @@ stringbuf_init(struct stringbuf *b)
{
b->len = 0;
b->sz = 64;
b->data = calloc(1, b->sz);
b->data = zalloc(b->sz);
}
static inline bool
@ -53,8 +53,7 @@ stringbuf_is_empty(struct stringbuf *b)
static inline void
stringbuf_reset(struct stringbuf *b)
{
free(b->data);
b->data = NULL;
free_clear(&b->data);
b->sz = 0;
b->len = 0;
}
@ -62,7 +61,7 @@ stringbuf_reset(struct stringbuf *b)
static inline struct stringbuf *
stringbuf_new(void)
{
struct stringbuf *b = calloc(1, sizeof(*b));
struct stringbuf *b = zalloc(sizeof(*b));
stringbuf_init(b);
return b;
}
@ -121,7 +120,7 @@ stringbuf_ensure_space(struct stringbuf *b, size_t sz)
}
/**
* Append the the data from the fd to the string buffer.
* Append the data from the fd to the string buffer.
*/
static inline int
stringbuf_append_from_fd(struct stringbuf *b, int fd, size_t maxlen)

View file

@ -282,6 +282,7 @@ safe_atod(const char *str, double *val)
case '+':
case '-':
case '.':
case 'e':
break;
default:
return false;

View file

@ -41,19 +41,19 @@ DECLARE_NEWTYPE(usec, uint64_t);
static inline usec_t
usec_from_millis(uint32_t millis)
{
return usec_from_uint64_t(millis * 1000);
return usec_from_uint64_t(millis * 1000ULL);
}
static inline usec_t
usec_from_seconds(uint32_t secs)
{
return usec_from_millis(secs * 1000);
return usec_from_uint64_t(secs * 1000000ULL);
}
static inline usec_t
usec_from_hours(uint32_t hours)
{
return usec_from_seconds(hours * 3600);
return usec_from_uint64_t((uint64_t)hours * 3600 * 1000000ULL);
}
static inline uint32_t
@ -83,7 +83,7 @@ usec_to_hours(usec_t us)
static inline usec_t
usec_add_millis(usec_t us, uint32_t millis)
{
return usec_from_uint64_t(usec_as_uint64_t(us) + millis * 1000);
return usec_from_uint64_t(usec_as_uint64_t(us) + millis * 1000ULL);
}
static inline usec_t
@ -101,13 +101,13 @@ us2ms_f(usec_t us)
static inline usec_t
usec_from_timeval(const struct timeval *tv)
{
return usec_from_uint64_t(tv->tv_sec * 1000000 + tv->tv_usec);
return usec_from_uint64_t(tv->tv_sec * 1000000ULL + tv->tv_usec);
}
static inline usec_t
usec_from_timespec(const struct timespec *tp)
{
return usec_from_uint64_t(tp->tv_sec * 1000000 + tp->tv_nsec / 1000);
return usec_from_uint64_t(tp->tv_sec * 1000000ULL + tp->tv_nsec / 1000);
}
static inline usec_t

View file

@ -75,5 +75,6 @@ TEST_DEVICE(LITEST_ABSINFO_OVERRIDE,
{ "EVDEV_ABS_01", "2:2000:200:20" },
{ "EVDEV_ABS_35", "3:3000:300:30" },
{ "EVDEV_ABS_36", "4:4000:400:40" },
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -197,4 +197,8 @@ TEST_DEVICE(LITEST_ACER_HAWAII_KEYBOARD,
.name = "Chicony ACER Hawaii Keyboard",
.id = &input_id,
.events = events,
.absinfo = NULL, )
.absinfo = NULL,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -93,4 +93,8 @@ TEST_DEVICE(LITEST_ACER_HAWAII_TOUCHPAD,
.name = "Chicony ACER Hawaii Keyboard Touchpad",
.id = &input_id,
.events = events,
.absinfo = absinfo, )
.absinfo = absinfo,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -157,4 +157,8 @@ TEST_DEVICE(LITEST_AIPTEK,
.name = "Aiptek",
.id = &input_id,
.events = events,
.absinfo = absinfo, )
.absinfo = absinfo,
.udev_properties = {
{ "ID_INTEGRATION", "external" },
{ NULL },
}, )

View file

@ -173,4 +173,8 @@ TEST_DEVICE(LITEST_ALPS_3FG,
.id = &input_id,
.events = events,
.absinfo = absinfo,
.create = alps_create, )
.create = alps_create,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -120,4 +120,8 @@ TEST_DEVICE(LITEST_ALPS_DUALPOINT,
.id = &input_id,
.events = events,
.absinfo = absinfo,
.quirk_file = quirk_file, )
.quirk_file = quirk_file,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -113,4 +113,8 @@ TEST_DEVICE(LITEST_ALPS_SEMI_MT,
.name = "AlpsPS/2 ALPS GlidePoint",
.id = &input_id,
.events = events,
.absinfo = absinfo, )
.absinfo = absinfo,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -218,4 +218,8 @@ TEST_DEVICE(LITEST_ANKER_MOUSE_KBD,
.name = "USB Laser Game Mouse",
.id = &input_id,
.absinfo = absinfo,
.events = events, )
.events = events,
.udev_properties = {
{ "ID_INTEGRATION", "external" },
{ NULL },
}, )

View file

@ -100,4 +100,8 @@ TEST_DEVICE(LITEST_APPLETOUCH,
.id = &input_id,
.events = events,
.absinfo = absinfo,
.quirk_file = quirk_file, )
.quirk_file = quirk_file,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -226,4 +226,8 @@ TEST_DEVICE(LITEST_APPLE_KEYBOARD,
.name = "Apple Inc. Apple Internal Keyboard / Trackpad",
.id = &input_id,
.events = events,
.absinfo = NULL, )
.absinfo = NULL,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -100,5 +100,6 @@ TEST_DEVICE(LITEST_MAGICMOUSE,
* re-writing those, so let's assume the default */
.udev_properties = {
{ "MOUSE_DPI", "1000" },
{ "ID_INTEGRATION", "external" },
{ NULL },
}, )

View file

@ -323,4 +323,8 @@ TEST_DEVICE(LITEST_MOUSE_GLADIUS,
.name = "ASUS ROG GLADIUS",
.id = &input_id,
.absinfo = absinfo,
.events = events, )
.events = events,
.udev_properties = {
{ "ID_INTEGRATION", "external" },
{ NULL },
}, )

View file

@ -132,4 +132,8 @@ TEST_DEVICE(LITEST_ATMEL_HOVER,
.name = "Atmel maXTouch Touchpad",
.id = &input_id,
.events = events,
.absinfo = absinfo, )
.absinfo = absinfo,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -127,4 +127,8 @@ TEST_DEVICE(LITEST_BCM5974,
.name = "bcm5974",
.id = &input_id,
.events = events,
.absinfo = absinfo, )
.absinfo = absinfo,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -85,5 +85,6 @@ TEST_DEVICE(LITEST_CALIBRATED_TOUCHSCREEN,
.udev_properties = {
{ "LIBINPUT_CALIBRATION_MATRIX", "1.2 3.4 5.6 7.8 9.10 11.12" },
{ "WL_OUTPUT", "myOutput" },
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -58,4 +58,8 @@ TEST_DEVICE(LITEST_CYBORG_RAT,
.name = "Saitek Cyborg R.A.T.5 Mouse",
.id = &input_id,
.absinfo = NULL,
.events = events, )
.events = events,
.udev_properties = {
{ "ID_INTEGRATION", "external" },
{ NULL },
}, )

View file

@ -90,5 +90,6 @@ TEST_DEVICE(LITEST_DELL_CANVAS_TOTEM_TOUCH,
.absinfo = absinfo,
.udev_properties = {
{ "LIBINPUT_DEVICE_GROUP", "dell-canvas-totem-group" },
{ "ID_INTEGRATION", "external" },
{ NULL },
}, )

View file

@ -127,5 +127,6 @@ TEST_DEVICE(LITEST_DELL_CANVAS_TOTEM,
.absinfo = absinfo,
.udev_properties = {
{ "LIBINPUT_DEVICE_GROUP", "dell-canvas-totem-group" },
{ "ID_INTEGRATION", "external" },
{ NULL },
}, )

View file

@ -146,4 +146,8 @@ TEST_DEVICE(LITEST_ELAN_TABLET,
.name = "ELAN2514:00 04F3:23B9",
.id = &input_id,
.events = events,
.absinfo = absinfo, )
.absinfo = absinfo,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -109,4 +109,8 @@ TEST_DEVICE(LITEST_ELANTECH_TOUCHPAD,
.name = "ETPS/2 Elantech Touchpad",
.id = &input_id,
.events = events,
.absinfo = absinfo, )
.absinfo = absinfo,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -53,4 +53,8 @@ TEST_DEVICE(LITEST_MOUSE_FORMAT_STRING,
.name = "Evil %s %d %x Mouse %p %",
.id = &input_id,
.absinfo = NULL,
.events = events, )
.events = events,
.udev_properties = {
{ "ID_INTEGRATION", "external" },
{ NULL },
}, )

View file

@ -123,4 +123,8 @@ TEST_DEVICE(LITEST_GENERIC_PRESSUREPAD,
.name = "Some Generic Pressurepad Touchpad",
.id = &input_id,
.events = events,
.absinfo = absinfo, )
.absinfo = absinfo,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -76,4 +76,8 @@ TEST_DEVICE(LITEST_GENERIC_SINGLETOUCH,
.name = "generic_singletouch",
.id = &input_id,
.events = events,
.absinfo = absinfo, )
.absinfo = absinfo,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

View file

@ -198,4 +198,8 @@ TEST_DEVICE(LITEST_GENERIC_USBCOMBO_KEYBOARD,
.name = "Generic USB KeyTouch Combo",
.id = &input_id,
.events = events,
.absinfo = NULL, )
.absinfo = NULL,
.udev_properties = {
{ "ID_INTEGRATION", "external" },
{ NULL },
}, )

View file

@ -100,7 +100,7 @@ TEST_DEVICE(LITEST_GENERIC_USBCOMBO_TOUCHPAD,
.events = events,
.absinfo = absinfo,
.udev_properties = {
{ "ID_INPUT_TOUCHPAD_INTEGRATION", "external" },
{ "ID_INTEGRATION", "external" },
{ NULL },
},
.quirk_file = quirk_file, )

View file

@ -61,5 +61,6 @@ TEST_DEVICE(LITEST_GPIO_KEYS,
.quirk_file = quirk_file,
.udev_properties = {
{ "ID_INPUT_SWITCH", "1" },
{ "ID_INTEGRATION", "internal" },
{ NULL },
})

View file

@ -60,5 +60,6 @@ TEST_DEVICE(LITEST_HP_WMI_HOTKEYS,
.udev_properties = {
{ "ID_INPUT_SWITCH", "1" },
{ "ID_INTEGRATION", "internal" },
{ NULL },
})

View file

@ -108,4 +108,8 @@ TEST_DEVICE(LITEST_HUION_TABLET,
.name = "HUION PenTablet Pen",
.id = &input_id,
.events = events,
.absinfo = absinfo, )
.absinfo = absinfo,
.udev_properties = {
{ "ID_INTEGRATION", "external" },
{ NULL },
}, )

View file

@ -78,5 +78,6 @@ TEST_DEVICE(LITEST_HUION_Q620M_DIAL,
.absinfo = absinfo,
.udev_properties = {
{ "ID_INPUT_TABLET_PAD", "1" },
{ "ID_INTEGRATION", "external" },
{ NULL },
}, )

View file

@ -54,5 +54,6 @@ TEST_DEVICE(LITEST_IGNORED_MOUSE,
.events = events,
.udev_properties = {
{ "LIBINPUT_IGNORE_DEVICE", "1" },
{ "ID_INTEGRATION", "external" },
{ NULL },
}, )

View file

@ -45,7 +45,11 @@ TEST_DEVICE(LITEST_KEYBOARD_ALL_CODES,
.name = NAME,
.id = &input_id,
.events = NULL,
.absinfo = NULL, )
.absinfo = NULL,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )
static bool
all_codes_create(struct litest_device *d)

View file

@ -250,4 +250,8 @@ TEST_DEVICE(LITEST_KEYBOARD_QUIRKED,
.id = &input_id,
.events = events,
.absinfo = NULL,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
},
.quirk_file = quirk_file, )

View file

@ -343,4 +343,8 @@ TEST_DEVICE(LITEST_KEYBOARD_BLACKWIDOW,
.name = "Razer Razer BlackWidow 2013",
.id = &input_id,
.absinfo = absinfo,
.events = events, )
.events = events,
.udev_properties = {
{ "ID_INTEGRATION", "external" },
{ NULL },
}, )

View file

@ -215,4 +215,8 @@ TEST_DEVICE(LITEST_KEYBOARD_BLADE_STEALTH_VIDEOSWITCH,
.name = "Razer Razer Blade Stealth",
.id = &input_id,
.events = events, )
.events = events,
.udev_properties = {
{ "ID_INTEGRATION", "internal" },
{ NULL },
}, )

Some files were not shown because too many files have changed in this diff Show more