feat(input): switch libinput to udev mode for hotplug support - #10
Conversation
Replace Libinput::new_from_path + one-shot /dev/input/event* scan with
Libinput::new_with_udev + udev_assign_seat("seat0") so that devices
added after startup are picked up automatically:
- USB keyboards/mice plugged in after bcon starts now work
- uinput virtual devices (ydotool, bconmsg injection, etc.) reach bcon
- No more reliance on periodic restarts to rescan /dev/input
Device enumeration for existing devices and hotplug events flow through
a new Event::Device match arm in process_raw_events:
- DeviceEvent::Added applies touchpad config (tap-to-click, natural
scroll, disable-while-typing) via the existing configure_touchpad
helper, so hotplugged touchpads get the same settings as boot-time
ones.
- DeviceEvent::Removed clears held_keys and modifier state. If a
keyboard is unplugged while keys are held down, the corresponding
Released events never arrive, which would otherwise stick keys and
emit phantom key repeats. suspend() performs the same cleanup, so
users already accept this behavior on transient state loss.
To support applying touchpad config in the Added handler, MouseConfig
is cloned into a new struct field.
Both constructors are migrated:
- EvdevKeyboard::new (direct device access)
- EvdevKeyboard::new_with_seat (libseat path)
No Cargo.toml changes — input = "0.8" already enables the udev feature
by default.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Thanks for this! Switching from path to udev mode is the right call — the code is cleaner (net negative lines!) and hotplug support is a real usability win. The device removal cleanup for held keys is a nice touch too. Really appreciate the thorough testing and clear write-up. Also thanks for #9 (Cargo.lock sync) — that saved downstream packagers. |
Switch libinput from path mode to udev mode for automatic device hotplug detection. USB keyboards and mice plugged in after bcon starts now work immediately. Touchpad configuration (tap-to-click, natural scroll, disable-while-typing) is auto-applied to hotplugged devices. Also adds version bump procedure to CLAUDE.md (always sync Cargo.lock with cargo update -p bcon). Contributed by @kay-ws (#10).
|
Thanks for the quick merge and the v1.3.4 release! Upgraded the bcon-test The two items still marked "not yet tested" in the PR description (Separately, I've opened #11 to discuss AUR packaging for Arch users |
|
Post-merge hardware verification on cachy-note (CachyOS, Intel UHD All three "not yet tested" items in the PR body now confirmed:
Additionally confirmed: VT release/acquire (Ctrl+Alt+F1 ↔ F2) cycle Nothing to report as a regression — the udev switch works end-to-end |
New features (contributed by @kay-ws): Config discovery: - Layered XDG-style merge: built-in defaults → /etc/bcon/config.toml (system) → ~/.config/bcon/config.toml (user override) - Tables merge recursively; scalars and arrays replace wholesale - BCON_CONFIG env var for single-file debug bypass - Config::default_template() API for distributors CLI: - --init-config now accepts explicit target: system, user, or path - sudo bcon --init-config=system deterministically writes to /etc/ - Legacy --init-config=vim,jp still writes to ~/.config/ (backward compat) Also includes: - Arch Linux installation docs (#12) - libinput udev hotplug support (#10) - Lenient Kitty graphics base64 decode (#7) Contributors: @kay-ws Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Problem
bconcurrently scans/dev/input/event*once at startup viaLibinput::new_from_path+path_add_device. Devices that appearafter startup are never picked up:
bconstarts don't work.bconstarts don't work.configuration (tap-to-click, natural-scroll, disable-while-typing)
applied.
Fix
Switch both constructors to udev mode:
This makes
libinputmonitor udev for device add/remove and emitDeviceEvent::Added/DeviceEvent::Removed. Existing devices arealso delivered as
Addedafterudev_assign_seat, so the one-shotscan loop is no longer needed.
A new
Event::Devicematch arm inprocess_raw_eventshandles thedevice lifecycle:
DeviceEvent::Added— callconfigure_touchpadon the new device,so hotplugged touchpads get the same tap-to-click / natural-scroll /
disable-while-typing settings as boot-time ones.
DeviceEvent::Removed— clearheld_keysand modifier state. If akeyboard is unplugged while keys are held down, the corresponding
Releasedevents never arrive; without cleanup those keys stay inheld_keysand generate phantom key repeats in the repeat loop.suspend()already performs the same cleanup, so users are alreadyaccustomed to this transient-state-loss behavior.
MouseConfigis cloned into a new struct field so theAddedhandlercan apply touchpad config long after the constructor returns.
Both constructors are migrated:
EvdevKeyboard::new— direct device access path.EvdevKeyboard::new_with_seat— libseat path.No
Cargo.tomlchanges:input = "0.8"already enables theudevfeature by default.
Testing
Verified on Arch Linux (kernel 6.19.11) with
bcon@tty2.service.1. Startup device enumeration via udev
Debug log on service start shows all existing devices delivered as
DeviceEvent::Addedevents:2. Hotplug: uinput device created after startup
To exercise the hotplug path in a QEMU guest where physical USB
hotplug isn't easily simulated, a uinput virtual keyboard was
created after
bconwas already running, andctrl+0(font-resetaction) was injected through it:
The
EmojiAtlas: cache clearedline and the framebuffer redrawconfirm the
font-resetaction fired end-to-end through the newhotplugged device — something the previous code path made impossible.
3. VT switch + suspend/resume
Ctrl+Alt+F1→ tty1 (~27 s) →Ctrl+Alt+F2back to bcon.libinputre-emits Removed + Added for all devices on resume, which re-applies
configure_touchpadcleanly:Pane tree and on-screen state are preserved across the switch.
4. Existing functionality — regression pass
Ctrl+Shift+O,Ctrl+Shift+Enter) ✓Ctrl+Minus) with visible size change ✓5. Unit tests
Not yet tested
follow-up; the test environment is QEMU/KVM which can't trivially
simulate USB hotplug from the guest's point of view).
mid-keypress. The current simple cleanup (clear all held state on
any device removal) is a conservative choice that may very briefly
reset modifier state on uinput-originated short-lived devices too;
a more surgical per-device cleanup could be added later if it
becomes a problem in practice.