Skip to content

fix(core): stop seeding Back/Forward with a divertable default - #1225

Merged
AprilNEA merged 1 commit into
AprilNEA:masterfrom
litityum:fix/back-forward-default-divert
Sep 9, 2026
Merged

fix(core): stop seeding Back/Forward with a divertable default#1225
AprilNEA merged 1 commit into
AprilNEA:masterfrom
litityum:fix/back-forward-default-divert

Conversation

@litityum

@litityum litityum commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Reseed ButtonId::Back/ButtonId::Forward's default binding from BrowserBack/BrowserForward to MouseBack/MouseForward.

Changes

  • openlogi-core: default_binding now seeds Back/Forward with MouseBack/MouseForward instead of BrowserBack/BrowserForward.
  • openlogi-core: update a config test's expected fallback value to match the new default.
  • openlogi-agent-core: add a regression test asserting a thumb button bound to BrowserBack is diverted, while an untouched Forward stays native.

Why

capture_plan only diverts a button into OpenLogi's dispatch pipeline when its configured binding differs from default_binding. Back/Forward's default was BrowserBack/BrowserForward — so picking that same action in the GUI (the obviously correct choice for "navigate back/forward") matched the default and the button was never diverted. The raw native button-4/5 click went straight to the OS instead.

Chrome/Firefox interpret a native button-4/5 click as back/forward themselves, so this was invisible there. Safari has no native mouse-button navigation binding, so the click did nothing — the action was configured correctly in the GUI but structurally unreachable, regardless of the separate Safari-dispatch-timing work in #1082.

Confirmed on real hardware: with this change alone (on top of current master, which already carries the Safari AXPress navigation code from #363), a Logitech MX Master 3 with Back = "BrowserBack" / Forward = "BrowserForward" correctly navigates back/forward in Safari and Chrome.

Testing

cargo fmt --all -- --check
cargo clippy -p openlogi-core -p openlogi-agent -p openlogi-agent-core -p openlogi-cli \
  -p openlogi-device -p openlogi-hid -p openlogi-hook -p openlogi-inject -p openlogi-ipc \
  -p openlogi-permissions -p openlogi -p xtask --all-targets -- -D warnings
cargo test -p openlogi-core -p openlogi-agent -p openlogi-agent-core -p openlogi-cli \
  -p openlogi-device -p openlogi-hid -p openlogi-hook -p openlogi-inject -p openlogi-ipc \
  -p openlogi-permissions -p openlogi -p xtask
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --document-private-items \
  --exclude openlogi-ui --exclude openlogi-desktop --exclude openlogi-overlay --exclude openlogi-agent
  • GUI crates (openlogi-desktop, openlogi-ui, openlogi-overlay) not built/tested locally — no full Xcode/Metal toolchain available on this machine.
  • Hardware-verified: real-device test on macOS with a Logitech MX Master 3 (Bluetooth-direct), confirmed Back/Forward now navigate in Safari.

Related: #736, #1118, #23, #354, #1018 (stale, proposed the same default reseed among a larger, now-conflicting diff), #1082 (fixes separate Safari-dispatch timing/focus issues once a button is diverted).

Fixes #736
Fixes #1118
Fixes #23
Fixes #354

BrowserBack/BrowserForward were the default binding for Back/Forward,
so picking either in the GUI matched the default and capture_plan
never diverted the button. The action was configured but unreachable,
which is why Back/Forward silently did nothing in Safari (no native
mouse-button navigation to fall back on) while Chrome kept working via
its own native handling of buttons 4/5.

Reseed the default to MouseBack/MouseForward, the actions
is_native_click already treats as native, so an untouched button stays
native and a BrowserBack/BrowserForward binding now differs from the
default and gets diverted.
@litityum
litityum requested a review from AprilNEA as a code owner September 1, 2026 10:03
@greptile-apps

greptile-apps Bot commented Sep 1, 2026

Copy link
Copy Markdown

Greptile Summary

This PR separates native Back/Forward defaults from explicit browser-navigation actions so the latter enter OpenLogi’s dispatch pipeline.

  • Changes Back and Forward defaults to native MouseBack and MouseForward actions.
  • Updates configuration fallback expectations for the new Back default.
  • Adds regression coverage showing explicit BrowserBack is diverted while untouched Forward remains native.

Confidence Score: 5/5

The PR appears safe to merge, with the changed defaults and capture behavior aligned across configuration and regression coverage.

Explicit browser-navigation bindings now differ from native Back/Forward defaults and therefore enter the dispatch path, while untouched controls retain native behavior.

Important Files Changed

Filename Overview
crates/openlogi-core/src/binding/defaults.rs Changes Back/Forward defaults to native mouse actions, allowing explicit browser actions to be distinguished and diverted.
crates/openlogi-agent-core/src/capture_plan.rs Adds focused regression coverage for explicit BrowserBack diversion and native untouched Forward behavior.
crates/openlogi-core/src/config/tests.rs Updates the gesture-mode fallback expectation to the new canonical native Back action.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    A[Thumb button input] --> B{Configured action equals native default?}
    B -->|Yes: MouseBack or MouseForward| C[Keep native button event]
    B -->|No: BrowserBack or BrowserForward| D[Divert into OpenLogi]
    D --> E[Dispatch configured browser action]
Loading

Reviews (1): Last reviewed commit: "fix(core): stop seeding Back/Forward wit..." | Re-trigger Greptile

@davidbudnick davidbudnick added type: bug Something is broken or behaves incorrectly platform: all Cross-platform issue labels Sep 3, 2026
@sandman21vs

Copy link
Copy Markdown

Validated on hardware — this patch fixes the problem here.

Environment: MacBook Air M1 (arm64), macOS 26.6.2, MX Master 3S over
Bluetooth-direct (no Bolt receiver), Brave and Safari. Commit 996486e applied
unchanged on top of current master (d5e2b88), built and run as a dev-channel
bundle.

Before: taken from the stock 0.8.3 agent's own log on this machine (same
code path as current master). With Back = BrowserBack /
Forward = BrowserForward it armed no standard-button CIDs — control capture active … buttons=0 — so the action was configured and unreachable, exactly as
this PR describes. That log also contains zero button → handling binding
lines, i.e. the CGEventTap never remapped these buttons either, so on this
device HID++ diversion is the only path that can reach the action at all.

After: buttons=2 whenever a browser resolving to those actions is
foreground. Verified by driving the foreground app and correlating with the
agent log — four transitions, 1:1, no ambiguity.

Back and Forward now navigate correctly in both Brave and Safari, one page step
per press.

Press-level log with OPENLOGI_LOG=debug, one line per physical press:

HID++ button → binding key="…" button=Back    action=Browser Back
HID++ button → binding key="…" button=Forward action=Browser Forward
  • one dispatch per press across the whole session, including a deliberately
    rapid alternating burst of 8 presses in 2.8 s
  • browser nav debounced — duplicate dispatch path suppressed: 0 — no press
    produced a second dispatch
  • button → handling binding: 0 — the event tap never handled these buttons
    in parallel, so there is no native + injected double delivery
  • no WARN or ERROR during the test

One extra data point that supports the direction of the change: with a per-app
override pinning Brave to MouseBack/MouseForward (native, not diverted,
OpenLogi entirely out of the loop), the raw button 4 did something other than
navigating while button 5 worked normally. So a native binding is not a usable
fallback on this device, which is precisely why the browser actions need to be
divertable. Possibly relevant to #354.

Local gates on the branch, all green: cargo fmt --all -- --check,
cargo clippy --workspace --all-targets -- -D warnings, cargo test --workspace --all-targets (1369 tests), workspace doctests, rustdoc with
RUSTDOCFLAGS=-D warnings, and the wasm portability checks.

Not verified: Linux and Windows, and any device other than the MX Master 3S.

@AprilNEA
AprilNEA merged commit b663491 into AprilNEA:master Sep 9, 2026
27 checks passed
@aprilnea aprilnea Bot mentioned this pull request Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

platform: all Cross-platform issue type: bug Something is broken or behaves incorrectly

Projects

None yet

4 participants