AprilNEA / AprilNEA/OpenLogi

[Feature]: Add macOS system-wide left/right mouse button swap

Open
#1,062 1 comment 0 reactions 0 assignees View on GitHub
needs: triage type: feature
Dominant language
Rust
Stars
21k
Forks
675
Avg merge
2d 5h
Merged PRs (30d)
172

Description

### Pre-flight checklist

- [x] I searched existing issues and the [Roadmap](https://github.com/AprilNEA/OpenLogi#roadmap), and this isn't already tracked.

### Problem / motivation

OpenLogi currently has no way to change which physical mouse button macOS treats as the primary click.

Logitech Options+ exposes this setting and keeps it synchronized with `System Settings → Mouse → Secondary click`. Providing the same capability would make OpenLogi a more complete local-first replacement and let users manage the setting without switching applications.

This is a host-wide macOS setting, distinct from per-device HID++ firmware swapping.

### Proposed solution

Add a macOS-only toggle under `Settings → General`:

> Swap left and right mouse buttons

The implementation should:

- Use the background agent for all platform I/O; the GUI remains an IPC client.
- Update the live `HIDPointerButtonMode` value so click behavior changes immediately.
- Persist `com.apple.mouse.swapLeftRightButton` through CFPreferences.
- Read both values back after writing and report success only when verified.
- Observe external changes made through System Settings or other applications and update the OpenLogi toggle automatically.
- Model the setting semantically as `PrimaryMouseButton::{Left, Right}` rather than an inverted Boolean.
- Keep it host-wide: do not store it in OpenLogi TOML, device settings, per-application profiles, or button bindings.

### Alternatives considered

- Implement HID++ `0x2001` first: This is a different, firmware-level feature that may follow the mouse between computers. Its wire protocol is not sufficiently verified and it should eventually be presented separately for devices that actually support it.

- Swap clicks through OpenLogi’s input hook: This would emulate the behavior instead of changing the macOS setting, require the hook to remain active, and could disagree with System Settings or other applications.

- Direct users to System Settings: This works, but leaves a common Options+ feature outside OpenLogi and provides no synchronized status inside the application.

### Related area(s)

- [x] GUI
- [ ] CLI
- [x] Button actions / remapping
- [ ] DPI
- [ ] SmartShift
- [ ] Per-application profiles
- [ ] Configuration (TOML)
- [ ] Auto-update
- [x] Other

### Additional context

Testing with Logitech Options+ 2.6.944893 showed that enabling or disabling its left/right swap also changes the macOS Secondary click setting.

Investigation of the installed Options+ agent found that it:

- Reads and writes the live `HIDPointerButtonMode` IOHIDSystem parameter.
- Uses mode `1` for right-button primary and mode `2` for left-button primary.
- Persists `com.apple.mouse.swapLeftRightButton` for the current user and host.
- Updates both the live value and persistent preference.

This behavior is evidence for the macOS host-level route, not for HID++ feature `0x2001`. Firmware-level support should remain a separate follow-up pending confirmed protocol captures or documentation.

Related HID++ reference: https://openlogi.org/hidpp/features/x2001-swap-left-right-button

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by tracing the background agent, GUI General settings, and their existing IPC path, then identify the platform I/O boundary for macOS mouse settings. The work is done when the toggle uses the semantic primary-button model, updates live behavior, verifies CFPreferences reads and writes, and follows external System Settings changes without storing the value in OpenLogi configuration.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, rust
Domain
desktop
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.