feat: add Linux support (evdev + HID++ + uinput)#33
feat: add Linux support (evdev + HID++ + uinput)#33thisislvca merged 17 commits intoTomBadash:masterfrom
Conversation
Add full Linux platform support for Mouser, including mouse event interception, keyboard action simulation, HID++ device communication, and per-app profile detection. Linux implementation: - mouse_hook.py: evdev grab + uinput forwarding for button/scroll blocking, gesture tracking with threading lock, crash guard (atexit + signal handlers) to release grab on abnormal exit - key_simulator.py: evdev UInput virtual keyboard, 22 actions with thread-safe lazy initialization - app_detector.py: xdotool + /proc for foreground app detection (X11) - config.py: XDG-compliant config path (~/.config/Mouser) - requirements.txt: evdev>=1.6 Linux dependency Cross-platform fixes: - hid_gesture.py: support both "pip install hid" and "pip install hidapi" via _HidDeviceCompat wrapper; cap HID++ control discovery at 32 with circuit breaker to prevent DoS from malicious devices - config.py: atomic config writes (tempfile + os.replace) to prevent data loss on crash; restrictive file permissions (0o600 on POSIX); type validation on config load Note: Cross-platform changes (config.py, hid_gesture.py) were reviewed against Windows/macOS code paths but only runtime-tested on Linux (Nobara/Fedora, Bluetooth MX Master 3S). Tested: 27/27 unit tests pass. Manual verification on Nobara Linux with Logitech MX Master 3S over Bluetooth. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hey, thanks so much for contributing! I pushed a few follow-up commits directly onto this PR to add some missing features:
Before we merge, could you please test this on Linux and confirm:
Thanks again 🙏 |
|
Thanks for adding these features! I tested everything on Linux (Nobara 43, Wayland, Logitech MX Test Results:
Per-app auto-switching issue: The profile for Firefox is saved with This is not Nobara-specific. On most Linux distros, many apps use wrapper scripts in Additional findings:
Heads up: I'll also be pushing a fix for a separate issue I found during long-running sessions |
|
Ok awesome, thanks! Will fix all of these tomorrow morning, feel free to add your commit for that fix thanks again 💪 |
|
Just pushed fixes for both of the issues you found:
If you get a chance, could you pull the latest on this PR and re-test:
The reconnect issue you mentioned can stay as a separate follow-up if that’s easier, happy to review that too once you push it. Thanks again |
When the Bluetooth mouse disconnects (e.g. screen-off power management), the evdev hook falls back to another input device. Previously it stayed stuck on that fallback even after the Logitech reconnected via HID++. Now _on_hid_connect signals a rescan so the evdev loop switches back to the Logitech device automatically. Also suppress duplicate log lines: - Battery level only printed when it changes - "No compatible device" retry only printed once per disconnect cycle Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously the engine read the mouse's current DPI on startup and overwrote the saved config value, discarding the user's preference. Now it applies the saved DPI to the mouse instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The existing app detector relied on xdotool, which only works on X11. On KDE Wayland, native windows are invisible to xdotool and per-app profile switching silently failed. Add session-type detection with fallback: - KDE Wayland: use kdotool (requires `dnf install kdotool`) - X11: existing xdotool logic (unchanged) - GNOME and other Wayland compositors: not yet supported (returns None) Tested on Nobara 43 (KDE Plasma 6 + Wayland). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Thank you for addressing those two issues. Re-test results
The root cause is in To summarize the two layers:
My previous report only identified Layer 2. After your fix, testing revealed Layer 1 was the actual blocker. Commits I'm pushing
Other observations
All tests were done on Nobara 43 (KDE Plasma 6 + Wayland) with Logitech MX Master 3S via Bluetooth. |
Add space_left and space_right actions to the Linux key_simulator, matching the Windows and macOS implementations. Uses Ctrl+Super+Left/Right which is standard across GNOME and KDE. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Just pushed two last follow-up fixes:
If you get a chance, could you do one last quick pass before we merge just to confirm:
If all good after that I think we should be good to merge, thanks again |
|
Thanks for reviewing! All three are tested postive. I also have a follow-up PR ready (feat/mode-shift-mapping) that adds mode shift button remapping, a wheel toggle (ratchet/free spin), and custom keyboard shortcut mapping. I'll open it once this PR is merged. |
|
Appreciate it, just fixed a failing test and merged! Looking forward to reviewing your next PR too :) |
|
@hieshima i am trying this on ubuntu. But the mouse does not appear in the UI and is not "handled". Any idea why? EDIT: it seems it is because evdev is picking up the mouse but no _on_hid_connect is triggered. |
|
@farfromrefug Thanks again for reporting this. I put together a follow-up in PR #55 that should address the two Linux symptoms you described:
If HID++ still does not come up on your Ubuntu setup, Mouser now logs HID connection failures more explicitly as well (for example, when a HID candidate opens but feature discovery fails, or when no Logitech HID interface is found yet). If you’re willing to retest, that would be very helpful. |
|
@hieshima awesome. I tested your PR and it seems much better. The only issue i have is that the DPI slider is not visible in the settings. Normal? |
Add Linux platform support for Mouser, including mouse event interception, keyboard action simulation, HID++ device communication, and per-app profile detection.
Linux implementation:
mouse_hook.py: evdev grab + uinput forwarding for button/scroll blocking, gesture tracking with threading lock, crash guard (atexit + signal handlers) to release grab on abnormal exitkey_simulator.py: evdev UInput virtual keyboard, 22 actions with thread-safe lazy initializationapp_detector.py: xdotool + /proc for foreground app detection (X11)config.py: XDG-compliant config path (~/.config/Mouser)requirements.txt: evdev>=1.6 Linux dependencyCross-platform fixes:
hid_gesture.py: support both "pip install hid" and "pip install hidapi" via _HidDeviceCompat wrapper; cap HID++ control discovery at 32 with circuit breaker to prevent DoS from malicious devicesconfig.py: atomic config writes (tempfile + os.replace) to prevent data loss on crash; restrictive file permissions (0o600 on POSIX); type validation on config loadNote: Cross-platform changes (
config.py,hid_gesture.py) were reviewed against Windows/macOS code paths but only runtime-tested on Linux (Nobara/Fedora, Bluetooth MX Master 3S).Tested: 27/27 unit tests pass. Manual verification on Nobara Linux with Logitech MX Master 3S over Bluetooth.