Conversation
hidpp_side_gesture_maps_for hands gesture-mode buttons to device-owned HID++ raw-XY capture because macOS 26 delivers aux-button CGEvents with no backing IOHIDEvent, but it filters to Back | Forward — so a MiddleClick gesture map still rides the OS hook, whose fail-closed attribution gate drops those unattributed events. Result: on macOS 26, side-button gestures work while wheel-button gestures (and their Click action) are silently dead. Include MiddleClick in the filter. Its CID (0x0052) is already in DIVERTABLE_STANDARD_BUTTONS, and the capture/dispatch path is button-generic, so no other change is needed. Verified on an ERGO M575 (Unifying receiver, macOS 26.6, arm64): 0x0052 reports `divertable, raw-xy` in `openlogi diag controls`; with this change the capture session arms `gesture_buttons=3` (was 2) and a five-slot wheel gesture map (click/up/down/left/right) works end to end, alongside unchanged Back/Forward gestures. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
| oshook_gestures_for(config, Some(config_key), app) | ||
| .into_iter() | ||
| .filter(|(button, _)| matches!(button, ButtonId::Back | ButtonId::Forward)) | ||
| .filter(|(button, _)| matches!(button, ButtonId::MiddleClick | ButtonId::Back | ButtonId::Forward)) |
There was a problem hiding this comment.
Capture capability fallback missing
If a device's middle-click control does not support raw XY, adding MiddleClick here removes its gesture map from the macOS hook, while HID++ capture silently skips the unsupported control. Gesture mode is available without checking that capability, so the configured click and swipe actions are handled by neither path and stop working. Keep the OS-hook fallback unless the control can actually be armed.
There was a problem hiding this comment.
Fair point in principle, but note the same property holds for the existing Back | Forward ownership: the transfer is unconditional there too, with no raw-XY capability check before the hook gives the button up. This PR deliberately follows that established pattern rather than introducing a divergent policy for one button. A capability-aware fallback (restoring hook ownership when the raw-XY divert can't actually arm) would need the capture session's arm result fed back into the capture plan — a design change that should cover all three buttons together; happy to take a swing at it as a follow-up if the maintainer wants that direction. Test coverage for the MiddleClick branch added in eb6e746.
There was a problem hiding this comment.
Agreed. Since Back/Forward already use unconditional ownership transfer, requiring a capability check only for MiddleClick would introduce an inconsistent policy. A correct fallback needs the capture arm result fed back into planning for all three buttons, so that is appropriately scoped as a follow-up. The added test covers MiddleClick’s hook-availability transitions and raw-XY ownership. This comment is resolved.
Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.
| oshook_gestures_for(config, Some(config_key), app) | ||
| .into_iter() | ||
| .filter(|(button, _)| matches!(button, ButtonId::Back | ButtonId::Forward)) | ||
| .filter(|(button, _)| matches!(button, ButtonId::MiddleClick | ButtonId::Back | ButtonId::Forward)) |
There was a problem hiding this comment.
MiddleClick branch lacks coverage
The new MiddleClick ownership branch has no capture-plan regression test, although nearby tests verify the same behavior for Forward. Add a MiddleClick gesture-mode case that checks side_gesture_bindings, the (0x0052, MiddleClick) capture request, and the platform and opt-out behavior; otherwise this macOS fix can regress without failing the test suite.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Generalize macos_side_gesture_capture_follows_mouse_hook_availability into a per-button helper and run it for Forward and MiddleClick, so the new MiddleClick ownership branch cannot regress silently: the test checks the raw-XY capture request, the hook-map exclusion on macOS, and the hook-availability opt-in/opt-out transitions for both buttons. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Problem
Since 0.8.x, gesture-mode Back/Forward are owned by device-specific HID++ raw-XY capture on macOS (
hidpp_side_gesture_maps_for), which correctly sidesteps macOS 26 delivering aux-button CGEvents with no backing IOHIDEvent (CGEventCopyIOHIDEventreturns null, so the hook's fail-closed attribution gate drops them — context in #733).But the filter is
Back | Forwardonly, so a MiddleClick gesture map still rides the OS hook and is silently dead on macOS 26 — no swipes, and its Click action doesn't fire either (the plain click passes through natively). Side buttons work, the wheel button doesn't, which makes it look device-specific when it isn't.Fix
Include
ButtonId::MiddleClickin the filter. Its CID (0x0052) is already inDIVERTABLE_STANDARD_BUTTONS, and the capture spec / gesture dispatch (side_gesture_bindings.get(&button)) are button-generic, so this one line is the whole change.Testing
ERGO M575 (Unifying receiver, macOS 26.6, arm64):
openlogi diag controlsreports 0x0052 asdivertable, raw-xycontrol capture active … gesture_buttons=2; wheel gesture map dead (all five slots), Back/Forward gestures finegesture_buttons=3; a five-slot wheel map (Click/Up/Down/Left/Right → shortcut actions) works end to end, Back/Forward unchanged🤖 Generated with Claude Code