Skip to content

fix(macos): capture side-button gestures over HID++ - #722

Open
juan-apa wants to merge 6 commits into
AprilNEA:masterfrom
juan-apa:fix/bluetooth-button-source
Open

fix(macos): capture side-button gestures over HID++#722
juan-apa wants to merge 6 commits into
AprilNEA:masterfrom
juan-apa:fix/bluetooth-button-source

Conversation

@juan-apa

@juan-apa juan-apa commented Aug 20, 2026

Copy link
Copy Markdown

Summary

I ran into this while configuring gestures on the Forward button of my MX Master 3. The configuration looked valid, but clicking Forward only performed the normal browser action, and holding the button while moving the mouse never triggered a gesture.

While debugging it, I captured the macOS Back/Forward events directly and found that every Forward press and release arrived with device=None. OpenLogi correctly rejects unattributed events in its global macOS hook to avoid remapping input from unrelated devices, so the gesture hold never began.

My first attempt allowed senderless Back/Forward events through that hook. Review feedback pointed out the important flaw in that approach: without a source identity, OpenLogi cannot prove that the event came from the configured Logitech mouse.

I then moved the Forward button lifecycle to the mouse's device-specific HID++ channel while continuing to use macOS pointer movement for the swipe. A second review caught another source-mixing case: while Forward was held, movement from a trackpad or another mouse could contribute to the Logitech gesture.

To investigate that, I logged macOS movement senders. The trackpad and MX Master were distinguishable during normal movement, but movement became senderless while Forward was held; moving the trackpad during that hold stayed in the same anonymous stream. I also dumped the mouse's HID++ control capabilities and confirmed that Forward (CID 0x0056) advertises raw-XY support.

The final implementation therefore gets both the button lifecycle and swipe movement from the same device-specific HID++ control. The global macOS hook is no longer involved in these side-button gestures.

Changes

  • Request raw-XY HID++ capture for gesture-mode Back/Forward controls on macOS.
  • Arm only controls that advertise both diversion and raw-XY support; unsupported controls remain native.
  • Resolve side-button clicks and swipes through the existing HID++ gesture accumulator.
  • Keep unattributed events blocked in the global macOS hook.
  • Dispatch through the originating device's effective per-app gesture bindings.
  • Remove the host-side state that combined HID++ button edges with global OS movement.
  • Share the inventory-owned HID++ channel, restart capture when inventory replaces it, and re-arm volatile diversion after reconnect notifications.
  • Preserve the mouse-capture opt-out and native fallback behavior.

Testing

I built and ran the agent against an isolated copy of my real configuration on a physical MX Master 3. I verified:

  • Click → Mission Control
  • Up → Show Desktop
  • Down → App Exposé
  • Left → Previous Desktop
  • Right → Next Desktop
  • Holding Forward while moving only the trackpad does not produce a swipe; releasing Forward still produces the configured click
  • Turning the mouse off and back on twice restores all Forward gestures after the capture session reconnects

The hardware diagnostics also confirmed:

  • Normal trackpad and MX Master movement have distinct macOS sender identities
  • Movement from either device is senderless while Forward is held, so OS movement cannot be safely attributed
  • Forward CID 0x0056 reports divertable=true and raw_xy=true

Repository validation:

  • cargo fmt --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --workspace
  • rustdoc with warnings denied for openlogi-hid, openlogi-agent-core, and openlogi-agent

Fixes #716

@juan-apa
juan-apa requested a review from AprilNEA as a code owner August 20, 2026 15:38
@greptile-apps

greptile-apps Bot commented Aug 20, 2026

Copy link
Copy Markdown

Greptile Summary

This PR moves macOS Back/Forward gesture capture entirely onto each mouse’s HID++ channel, preserving source isolation and native fallback.

  • Requests raw-XY diversion only for capable side-button controls.
  • Resolves button lifecycle and movement through the same device-specific gesture accumulator.
  • Couples side-button diversion to hook availability and preserves the mouse-capture opt-out.
  • Shares inventory-owned channels, detects channel replacement, and re-arms diversion after reconnects.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
crates/openlogi-agent-core/src/capture_plan.rs Adds macOS HID++ side-gesture plans, capability-gated diversion requests, hook-availability gating, and capture opt-out enforcement.
crates/openlogi-agent-core/src/hook_runtime.rs Restores fail-closed handling for senderless macOS button events now that side gestures no longer depend on the global hook.
crates/openlogi-agent-core/src/orchestrator.rs Publishes per-device side-gesture ownership, removes duplicate global-hook dispatch, and notifies capture reconciliation immediately.
crates/openlogi-agent-core/src/watchers/gesture.rs Reconciles notified per-device sessions, uses inventory-owned channels, and dispatches HID++ side gestures through originating-device plans.
crates/openlogi-agent/src/main.rs Coordinates hook availability with HID++ side-button diversion so controls are restored before hook teardown.
crates/openlogi-hid/src/session/gesture.rs Adds capability-checked raw-XY side-button capture, registry replacement detection, reconnect re-arming, and device-local gesture accumulation.
crates/openlogi-hid/src/session/gesture/tests.rs Covers side-button click/swipe resolution and volatile diversion re-arming behavior.

Sequence Diagram

sequenceDiagram
  participant Mouse as Logitech mouse
  participant HID as HID++ capture session
  participant Acc as Gesture accumulator
  participant Plan as Per-device capture plan
  participant Dispatch as Action dispatcher
  participant OS as macOS
  Mouse->>HID: Back/Forward press + raw XY
  HID->>Acc: Device-specific button edge
  HID->>Acc: Device-specific movement
  Acc->>Plan: Click or swipe direction
  Plan->>Dispatch: Originating device's effective binding
  Dispatch->>OS: Execute configured action
Loading

Reviews (9): Last reviewed commit: "fix(agent): source side-button gestures ..." | Re-trigger Greptile

Comment thread crates/openlogi-agent-core/src/hook_runtime.rs Outdated
@juan-apa juan-apa changed the title fix(macos): allow senderless side-button gestures fix(macos): capture side-button gestures over HID++ Aug 20, 2026
Comment thread crates/openlogi-agent/src/main.rs Outdated
Comment thread crates/openlogi-agent-core/src/hook_runtime.rs Outdated
Comment thread crates/openlogi-agent/src/main.rs Outdated
@juan-apa

Copy link
Copy Markdown
Author

@greptileai The remaining summary concern about dropping the macOS movement hook during Accessibility revocation no longer applies to the latest implementation in e3e6196.

Back/Forward gestures now receive both the button lifecycle and swipe deltas from the same device-specific HID++ raw-XY control; the OS movement hook is not involved. When hook availability changes, the capture plan retains side_gesture_bindings while the existing HID++ session drains, so captured input can still resolve during teardown before the control is restored to its native mapping.

Could you please re-review the latest commit with the source-safe raw-XY path in mind?

@davidbudnick davidbudnick added type: bug Something is broken or behaves incorrectly platform: macos macOS-specific issue labels Aug 20, 2026
@juan-apa
juan-apa requested a review from davidbudnick as a code owner August 20, 2026 19:51
Comment thread crates/openlogi-agent/src/main.rs
@juan-apa
juan-apa force-pushed the fix/bluetooth-button-source branch from f598049 to 345aa0f Compare August 20, 2026 19:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

platform: macos macOS-specific issue type: bug Something is broken or behaves incorrectly

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: gestures are not working + no option to activate theAction ring (MX Anywhere 3)

2 participants