fix(hook): grab only relative pointer devices, never touchpads or pointing sticks - #401
fix(hook): grab only relative pointer devices, never touchpads or pointing sticks#401kesleyfort wants to merge 4 commits into
Conversation
Greptile SummaryThis PR fixes the Linux evdev hook incorrectly grabbing touchpads and pointing sticks by tightening device selection to require real relative-pointer capabilities (
Confidence Score: 4/5Safe to merge after removing the doubled doc comment on The Files Needing Attention: crates/openlogi-core/src/config/settings.rs — the doubled doc comment on
|
| Filename | Overview |
|---|---|
| crates/openlogi-hook/src/linux.rs | Adds is_hookable_mouse with multi-layer touch/pointing-stick exclusion guards and exhaustive unit tests; fixes the touchpad-kill bug correctly. |
| crates/openlogi-core/src/config/settings.rs | Adds capture_mouse_events field correctly, but the old doc comment for auto_download_assets was not removed, leaving a doubled and inconsistent description in rustdoc output. |
| crates/openlogi-agent/src/main.rs | Gates the accessibility prompt and hook installation behind capture_mouse_events; the accessibility watcher only emits on state transitions so no log spam occurs. |
| docs/CONFIGURATION.md | Documents the new capture_mouse_events setting accurately alongside the existing options. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[evdev::enumerate all /dev/input/ devices] --> B[is_hookable_mouse?]
B --> C{Name starts with 'OpenLogi '?}
C -- yes --> SKIP[Skip device]
C -- no --> D{Has BTN_LEFT + REL_X + REL_Y?}
D -- no --> SKIP
D -- yes --> E{Touch keys / ABS_MT / BUTTONPAD / SEMI_MT / DIRECT?}
E -- yes --> SKIP
E -- no --> F{POINTING_STICK prop?}
F -- yes --> SKIP
F -- no --> HOOK[Grab & hook device]
HOOK --> G[Create paired uinput virtual mouse]
G --> H[Re-inject PassThrough events / Swallow Suppress events]
Reviews (4): Last reviewed commit: "Merge branch 'master' into fix/hook-touc..." | Re-trigger Greptile
| if !hookable | ||
| && d.supported_keys() | ||
| .is_some_and(|keys| keys.contains(KeyCode::BTN_LEFT)) | ||
| { | ||
| debug!( | ||
| "not hooking {} ({}): has mouse buttons but is not a plain relative-pointer mouse", | ||
| path.display(), | ||
| d.name().unwrap_or("unnamed"), | ||
| ); | ||
| } |
There was a problem hiding this comment.
Redundant
supported_keys() call in debug guard
d.supported_keys() is already called (and its result consumed) inside is_hookable_mouse, but the debug logging condition calls it again on the same Device. Because Device does not cache individual capability tables, this triggers a second parse of the same bitfield. For the fast path (devices that are hookable) no second call happens, but for every non-mouse device that advertises BTN_LEFT the key set is parsed twice. Capturing the keys reference once (or simply accepting the minor duplication) keeps intent clear.
…nting sticks The Linux hook selected every evdev device advertising BTN_LEFT, which includes touchpads: they got an exclusive grab whose multitouch EV_ABS stream the relative-only virtual mouse cannot re-inject, so the built-in touchpad went dead the moment the agent started. Device selection now requires a real relative pointer (BTN_LEFT plus REL_X/REL_Y) and refuses anything touch-driven (BTN_TOUCH/BTN_TOOL_FINGER, ABS_MT_POSITION_X, or the BUTTONPAD/SEMI_MT/DIRECT input properties) as well as pointing sticks, whose POINTING_STICK-derived libinput behaviors a re-injected stream would lose. Our own uinput devices are excluded by the shared "OpenLogi " name prefix, covering the action injector too.
… hook app_settings.capture_mouse_events (default true) is an escape hatch for users who want OpenLogi purely for HID++ device configuration: set to false, the agent never installs the OS-level mouse hook, so no input device is grabbed or intercepted on any platform. DPI, SmartShift, gesture-button, and thumb-wheel features are unaffected. Read once at agent startup, like show_in_menu_bar; flipping it requires an agent restart, as documented.
…bled With capture_mouse_events = false the agent never installs the CGEventTap, so it has no use for the Accessibility permission — firing the TCC prompt at startup contradicts the setting's hands-off intent. Read the toggle first and prompt only when the hook is actually wanted.
460b0fa to
f9bc554
Compare
Summary
The Linux hook selected every evdev device advertising
BTN_LEFT, whichincludes touchpads: they got an exclusive grab whose multitouch
EV_ABSstream the relative-only virtual mouse cannot re-inject, so the built-in
touchpad went dead the moment the agent started. This tightens device
selection and adds an opt-out for users who only want HID++ configuration.
Changes
src/linux.rs): device selection now requires a realrelative pointer (
BTN_LEFT+REL_X/REL_Y) and refuses anythingtouch-driven (
BTN_TOUCH/BTN_TOOL_FINGER,ABS_MT_POSITION_X, or theBUTTONPAD/SEMI_MT/DIRECTinput properties) as well as pointing sticks(
POINTING_STICK, whose libinput behaviors a re-injected stream would lose).Our own uinput devices are excluded by the shared
OpenLoginame prefix,covering the action injector too.
src/config.rs) + openlogi-agent (src/main.rs): addapp_settings.capture_mouse_events(defaulttrue). Whenfalse, the agentnever installs the OS-level mouse hook, so no input device is grabbed or
intercepted on any platform; DPI, SmartShift, gesture-button, and thumb-wheel
features are unaffected. Read once at agent startup (like
show_in_menu_bar);flipping it requires an agent restart.
Testing
cargo build/cargo clippyon the hook, agent, and core crates.maintainer verification that the touchpad stays live while a relative mouse is
still hooked, and that
capture_mouse_events = falseleaves no device grabbed.Fixes #355
Related: #356 (contributor draft targeting the same issue via device selection)
— overlapping; left open for the maintainer to compare/adopt.