Skip to content

feat(gui): bind a custom shortcut from the button picker - #784

Open
AalmanSadath wants to merge 2 commits into
AprilNEA:masterfrom
AalmanSadath:feat/gui-custom-shortcut-buttons
Open

feat(gui): bind a custom shortcut from the button picker#784
AalmanSadath wants to merge 2 commits into
AprilNEA:masterfrom
AalmanSadath:feat/gui-custom-shortcut-buttons

Conversation

@AalmanSadath

Copy link
Copy Markdown

Summary

Action::CustomShortcut is deliberately excluded from Action::catalog, so the
mouse button picker had no way to reach it — binding a chord to a button meant
hand-editing config.toml. The Actions Ring editor already had the field, so
this adds the same one to each button's popover and to a gesture button's
per-direction flyout.

Two deliberate differences from the ring's editor:

Changes

  • openlogi-desktop
    • features/mouse/picker.rs: new shortcut_rows helper — the chord already
      bound (if any), the text field, and an Add button committing through the
      existing PickFn. Prepended to the action list in both action_picker and
      the gesture flyout_card. The bound chord has no catalog row to check, so
      the section states it explicitly; without that the picker looks unbound
      whenever a shortcut is in use.
    • features/mouse/view.rs: MouseModelView owns one lazily-created
      InputState, threaded to both popovers. One field for the view, not one per
      popover — only one is open at a time, and a per-render entity would clear
      the field on every repaint. It resets on commit and on every popover
      open/close, so a chord typed for one button does not follow the user to the
      next. Reset lives in set_binding_popover_open, which runs outside paint
      for the same reason gesture_active_dir does.
    • features/action_ring.rs: moved to the shortened placeholder key.
  • openlogi-ui: "Shortcut, e.g. Cmd+Shift+P""e.g. Cmd+Shift+P" in all
    21 catalogs, same position, real translations rather than English fill-in. The
    longer string did not fit the popover, and both call sites move together so
    the catalogs carry one placeholder instead of two near-identical ones.

No wire types changed — Action::CustomShortcut already round-trips through
config and IPC — so PROTOCOL_VERSION is untouched.

Testing

cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --document-private-items \
  --exclude openlogi-ui --exclude openlogi-desktop --exclude openlogi-overlay --exclude openlogi-agent
cargo test -p openlogi-ui locale
cargo test -p openlogi-desktop i18n
cargo xtask ci   # 8 passed, 1 skipped

All run on Linux with RUSTFLAGS="-D warnings". cargo xtask ci's skipped job
is tests (macos) — not reproducible on this host, so not claimed green.

Exercised in a dev GUI build against openlogi-agent-mock on Fedora 44 /
Wayland: entering a chord on a button and on a gesture direction, Add disabled
until the text parses, the field clearing on commit and when switching buttons,
and the bound chord showing in the section. Not runtime-tested on hardware
this is GUI-side only, and whether the agent then fires the chord is the
injector path, which this PR does not touch. Worth noting #514 reports the agent
ignoring a CustomShortcut on a button; if that is still live it is a separate
agent-side bug, not something this change would fix.

gui-custom-shorcut-buttons

Fixes #573

Action::CustomShortcut is deliberately absent from Action::catalog, so the
mouse button picker had no way to reach it: binding a chord to a button
meant hand-editing config.toml. The Actions Ring editor already had the
field, so this puts the same one in each button's popover and in a gesture
button's per-direction flyout.

Two differences from the ring's editor. Add stays disabled until the text
parses as a KeyCombo, rather than the ring's silent `if let Ok(..)` that
commits nothing and says nothing when the chord is malformed. And the field
drops `cleanable`, whose glyph took enough of the row to truncate the
placeholder, now that it clears itself anyway.

One InputState serves every binding popover, since only one is open at a
time. It is owned by MouseModelView rather than created per render, which
would clear the field on every repaint, and it resets on commit and on every
popover open so a chord typed for one button does not follow the user to the
next.

The placeholder lost its "Shortcut, " prefix to fit the popover; the ring
editor moves to the shortened key too, so the catalogs carry one string
instead of two near-identical ones.
@AalmanSadath
AalmanSadath requested a review from AprilNEA as a code owner August 22, 2026 02:49
@greptile-apps

greptile-apps Bot commented Aug 22, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds custom-shortcut entry to mouse-button and gesture-direction pickers while sharing and resetting one persistent input field across popovers.

  • Adds validated custom-shortcut rows and commit actions to both picker variants.
  • Clears shortcut text on commit, popover transitions, and gesture-direction changes.
  • Replaces the longer shortcut placeholder key across the action-ring editor and locale catalogs.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
crates/openlogi-desktop/src/features/mouse/picker.rs Adds custom-shortcut input, validation, bound-state display, and commit behavior to button and gesture pickers.
crates/openlogi-desktop/src/features/mouse/view.rs Owns the shared shortcut input and clears it across commits, popover transitions, and gesture-direction changes.
crates/openlogi-desktop/src/features/action_ring.rs Moves the action-ring shortcut editor to the shortened localized placeholder.
crates/openlogi-ui/locales/en.yml Replaces the long shortcut placeholder translation key, with equivalent updates across all locale catalogs.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    A[Open button or gesture picker] --> B[Clear shared shortcut input]
    B --> C[Enter key combination]
    C --> D{Parses as KeyCombo?}
    D -- No --> E[Add remains disabled]
    D -- Yes --> F[Commit CustomShortcut]
    F --> G[Clear shared input]
    C --> H[Switch gesture direction]
    H --> B
Loading

Reviews (2): Last reviewed commit: "fix(gui): clear the shortcut field when ..." | Re-trigger Greptile

Switching direction leaves the same popover open, so it never runs through
set_binding_popover_open and the shared field kept whatever had been typed.
The flyout is rebuilt with on_pick aimed at the newly selected direction, so
pressing Add committed the retained chord to the wrong one.

Both paths now reset through a single clear_shortcut_input helper.
@davidbudnick davidbudnick added type: feature New feature request area: gui Graphical user interface platform: all Cross-platform issue labels Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: gui Graphical user interface platform: all Cross-platform issue type: feature New feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Keyboard shortcuts can't be set to mouse buttons

2 participants