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 3 commits into
Conversation
Greptile SummaryThis PR fixes the Linux hook grabbing touchpads (and pointing sticks) by replacing the single
Confidence Score: 5/5Safe to merge; the device-selection logic is correct and well-covered by tests, and the new config flag is cleanly isolated to the startup path. The core fix — No files require special attention. The Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[evdev::enumerate] --> B{name starts with OPENLOGI_DEVICE_PREFIX?}
B -- yes --> SKIP[skip device]
B -- no --> C{BTN_LEFT in supported_keys?}
C -- no --> SKIP
C -- yes --> D{REL_X AND REL_Y in rel_axes?}
D -- no --> SKIP
D -- yes --> E{Touch surface? BTN_TOUCH / BTN_TOOL_FINGER / ABS_MT_POSITION_X / BUTTONPAD / SEMI_MT / DIRECT}
E -- yes --> SKIP
E -- no --> F{POINTING_STICK property?}
F -- yes --> SKIP
F -- no --> HOOK[grab device & build virtual uinput device]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[evdev::enumerate] --> B{name starts with OPENLOGI_DEVICE_PREFIX?}
B -- yes --> SKIP[skip device]
B -- no --> C{BTN_LEFT in supported_keys?}
C -- no --> SKIP
C -- yes --> D{REL_X AND REL_Y in rel_axes?}
D -- no --> SKIP
D -- yes --> E{Touch surface? BTN_TOUCH / BTN_TOOL_FINGER / ABS_MT_POSITION_X / BUTTONPAD / SEMI_MT / DIRECT}
E -- yes --> SKIP
E -- no --> F{POINTING_STICK property?}
F -- yes --> SKIP
F -- no --> HOOK[grab device & build virtual uinput device]
Reviews (3): Last reviewed commit: "fix(agent): skip the accessibility promp..." | 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.