Skip to content

fix(gui): map MX Keys Mini controls to HID++ bindings - #1337

Closed
gmpandolfo wants to merge 4 commits into
AprilNEA:masterfrom
gmpandolfo:fix/mx-keys-mini-hidpp-mapping
Closed

gmpandolfo wants to merge 4 commits into
AprilNEA:masterfrom
gmpandolfo:fix/mx-keys-mini-hidpp-mapping

Conversation

@gmpandolfo

@gmpandolfo gmpandolfo commented Sep 10, 2026 •

Copy link
Copy Markdown

Summary

Applies the same fix as #1258 ("map MX Mechanical Mini controls to HID++
bindings") to the MX Keys Mini (mx_keys_mini depot, model id 0xb369).

Before, the Keys view drew a generic, evenly-spaced Esc/F1–F19 overlay (20
slots) on top of a keyboard that physically has ~14 keys in its top row, so
unbound keys looked bindable and the callouts did not line up with the real
key-caps. This rebuilds the row from the depot's semantic slot metadata and
routes the dedicated media keys through per-device HID++ bindings, exactly like
#1258 does for the Mechanical Mini.

The reconstructed row (14 hotspots):
Esc | F1–F3 (EasySwitch) | F4/F5 (backlight −/+) | Dictation | Emoji | Screen Capture | Mic Mute | Play/Pause | Mute | Volume Down | Volume Up

Backlight down/up have no HID++ control ID, so they stay native F-keys next to
Esc and the EasySwitch keys. The eight media keys already have CIDs in
KEYBOARD_KEY_CIDS and translation keys in every locale, so this needs no
openlogi-core change, no KEYBOARD_KEY_CIDS change, no locale change, and no
PROTOCOL_VERSION bump
— it is contained to the desktop GUI.

Depends on #1258 — draft, do not merge yet

This is built on top of #1258, whose infrastructure it uses in full
(BindingTarget, key_definitions, commit_target, per-device editor reset).
The two commits 79d9ca80 and f615b03d on this branch are @aztkgeek's #1258,
included only so the branch compiles; once #1258 merges I will rebase this onto
master so the diff is just the MX Keys Mini commit(s).

Changes

  • openlogi-desktop: mx_keys_mini_definitions() in
    features/keyboard/function_row.rs — recognises model id 0xb369, rebuilds
    the top row from device_easyswitch_image + device_keys_image slots, maps
    the eight divertable media slots to their ButtonId, keeps Esc / EasySwitch /
    backlight as global F-keys. New mx_keys_mini_control() slot→ButtonId map
    (kept separate from fix(gui): map MX Mechanical Mini controls to HID++ bindings #1258's semantic_top_row_button so the Mechanical Mini is
    untouched). Short callout labels for the newly device-targeted buttons. Three
    tests + a synthetic mx_keys_mini_asset() mirroring the shipped depot
    metadata.
  • openlogi-ui: register action-icons/moon.svg in ACTION_ICONS — the file
    was vendored and referenced by Action::Sleep in the picker but never
    registered, so every picker frame showing Sleep logged
    could not find asset at path "action-icons/moon.svg". (Also on its way via a
    separate PR; harmless if it lands there first.)

Screenshots

Before — generic 20-slot Esc/F1–F19 overlay, keys don't match the hardware:

before

After — 14 real keys; the eight media keys are per-device HID++ controls,
Esc / EasySwitch / backlight stay native:

after

Testing

Local gate, on the #1258 base:

export RUSTFLAGS="-D warnings"
cargo fmt --all -- --check                                              # clean
cargo clippy -p openlogi-ui -p openlogi-desktop -p openlogi-overlay --all-targets -- -D warnings   # clean
cargo test  -p openlogi-ui -p openlogi-desktop -p openlogi-overlay      # 200 + 17 + 3 + 1 passed (incl. 3 new)
cargo clippy --workspace --all-targets -- -D warnings                   # clean
RUSTDOCFLAGS=-D warnings cargo doc --workspace --no-deps --document-private-items \
  --exclude openlogi-ui --exclude openlogi-desktop --exclude openlogi-overlay --exclude openlogi-agent   # clean

No wire-type, locale, or cfg-gated change, so those gates don't apply.

Runtime-verified on real hardware (MX Keys Mini, Bluetooth, Linux): the Keys
view renders the 14-key row aligned to the physical key-caps; binding Volume
Down / Screen Capture / etc. commits per-device and the HID++ divert takes
effect; unbinding restores native behaviour; switching devices clears stale
selection.

elalecs and others added 4 commits September 3, 2026 12:29
Mirror the MX Mechanical Mini fix (AprilNEA#1258) for the MX Keys Mini: rebuild the
physical top row from the depot's semantic slots instead of overlaying a
positional Esc/F1-F19 row, and route the dedicated media keys through
per-device HID++ bindings.

The Keys Mini has no navigation column and 10 top-row markers (backlight
down/up, dictation, emoji, screen capture, mic mute, play/pause, mute,
volume down/up). Backlight has no HID++ CID so it stays a native F-key
alongside Esc and the three EasySwitch keys; the eight media keys, which
already carry CIDs in KEYBOARD_KEY_CIDS, become rebindable per-device
controls.

No core/IPC/locale change: every ButtonId, CID, and translation key this
needs already landed with AprilNEA#1258.
`Action::Sleep` maps to `action-icons/moon.svg` in the binding picker, but
that file was never added to `ACTION_ICONS`, so every picker frame showing
the Sleep entry logged `could not find asset at path "action-icons/moon.svg"`.
The file was already vendored; only the registration was missing.
@gmpandolfo
gmpandolfo marked this pull request as ready for review September 10, 2026 16:20
@greptile-apps

greptile-apps Bot commented Sep 10, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

The PR appears safe to merge after hardening the MX Keys Mini metadata validation; the remaining finding is a non-blocking robustness issue.

Fix All in CodexFindings

  1. P2 Loose Slot Count Validation ▶

Summary

  • Reconstructs compact keyboard hotspots from depot assignment metadata.
  • Separates global Esc/F-key bindings from per-device HID++ control bindings.
  • Adds five Mechanical Mini control identifiers and their HID++ capture mappings.
  • Resets editor state when navigating away or switching devices.
  • Registers the previously missing Sleep action icon and adds control labels to locale catalogs.
  • Includes the required IPC version update for the dependency changes.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Selected keyboard and depot metadata] --> B{Recognized Mini model and valid slots?}
  B -->|No| C[Generic global Esc/F-key layout]
  B -->|Yes| D[Semantic physical hotspots]
  D --> E{Hotspot type}
  E -->|Esc, EasySwitch, backlight| F[Global keyboard binding]
  E -->|Dedicated HID++ control| G[Per-device button binding]
  F --> H[OS keyboard capture path]
  G --> I[Agent HID++ keyboard session]
  H --> J[Configured action]
  I --> J
Loading

Reviews (1) · Last reviewed commit: "fix(gui): register moon.svg so the Sleep..."


let mut top_row: Vec<&Assignment> = assignments_for(asset, "device_keys_image").collect();
top_row.sort_by(|a, b| a.marker.x.total_cmp(&b.marker.x));
if easy_switch.len() != 3 || !(8..=12).contains(&top_row.len()) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Loose Slot Count Validation

The MX Keys Mini has a fixed 10-slot device_keys_image row, but this check accepts any count from 8 through 12 without validating the expected semantic slots or their uniqueness. Because every accepted assignment is rendered, incomplete metadata can omit physical controls, while duplicate or unknown slots can become duplicate HID++ targets or positional global F-key bindings. Validating the expected 10-slot semantic set before enabling this layout would avoid misleading or incorrectly targeted hotspots.

Knowledge Base Used: Desktop application shell

Fix in Codex Fix in Claude Code

@davidbudnick davidbudnick added type: bug Something is broken or behaves incorrectly area: gui Graphical user interface platform: all Cross-platform issue labels Sep 14, 2026
@AprilNEA

Copy link
Copy Markdown
Owner

Thanks for digging into this! It's superseded by #1604 (now on master), which keys keyboard controls by their HID++ control ID instead of adding one variant per key. The Keys tab now places keys by the control IDs in the device render's markers. Closing, but shout if something here isn't covered.

@AprilNEA AprilNEA closed this Sep 29, 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: bug Something is broken or behaves incorrectly

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants