Repository navigation
Driverless media keys, part 2: the session reads them as inputs (phase 6) - #1332
Conversation
…e 6) Apple keyboards deliver their media keys as macOS system-defined events, which the worker's tap never asked for, so a rule with a media key as its input could not fire. The bridge's physical-input rule now admits the same ten consumer-page keys it posts; the worker adds NX_SYSDEFINED to its tap mask, decodes subtype-8 events (SessionKeyMap.mediaInput) and hands a mapped key to Kanata as a consumer-page input, consuming it. Unmapped media keys pass through untouched. Held media inputs have their own ledger (usage numbers overlap across pages), a release whose press predates the tap passes through, and hardware repeats of a held mapped key are swallowed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Review of PR 1332 (media keys as session inputs): no blocking issues. Two things worth a look.
Minor: a duplicate down ( 🤖 Generated with Claude Code |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 32e2338615
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| private static let mediaKeyTypeToConsumerUsage = Dictionary( | ||
| uniqueKeysWithValues: consumerUsageToMediaKeyType.map { ($0.value, $0.key) } |
There was a problem hiding this comment.
Exclude media inputs that cannot be named in Kanata
When hardware sends NX_KEYTYPE_FAST or NX_KEYTYPE_REWIND (19/20), reversing the entire output table decodes them as newly supported inputs, but KeyboardCapture.mediaKeyCodeToString produces fastforward/rewind and KeyMappingFormatter explicitly leaves those unchanged because they have no Kanata name. The Mapper therefore cannot generate a valid defsrc token for these two inputs, despite the bridge admitting their usages; either add a valid lowering or omit them from the input table.
Useful? React with 👍 / 👎.
| **Part 2 (inputs, 2026-10-20).** The bridge's physical-input rule | ||
| (`physical_input_supported`) admits the same ten consumer codes. The worker adds | ||
| NX_SYSDEFINED (14) to its tap mask; `SessionKeyMap.mediaInput(subtype:data1:)` decodes a |
There was a problem hiding this comment.
Update the published guides before declaring media inputs shipped
This is a user-visible feature, but the commit updates only developer architecture documents. The published guides still tell users that media and brightness remapping is unavailable in driverless mode (guides/fun-layer.md and guides/driverless-caps-lock.md) and provide no instructions or limitations for using media keys as inputs, so users receive directly contradictory guidance. Update the relevant guides/ content along with this shipped status.
AGENTS.md reference: AGENTS.md:L382-L383
Useful? React with 👍 / 👎.
Completes phase 6 (review §4.5): media keys on Apple keyboards work as rule inputs, not only outputs.
What
physical_input_supportedadmits the ten consumer-page codes the worker handles (same table as outputs), in plain and managed-Caps validation and for chord participants.SessionKeyMap.mediaInput(subtype:data1:)decodes a subtype-8 event to Kanata's (usage, value); a key the profile maps is sent as a consumer-page input and consumed, anything else passes through untouched (so unmapped volume/brightness behave exactly as before). Held media inputs have their own ledger (mediaInputs— 0xE2 is Mute on page 12 but Left Alt on page 7); a release whose press predates the tap passes through; hardware repeats of a held mapped key are swallowed (Kanata repeats itself).Tests
Rust 24 (media keys are inputs;
calcisn't; managed-Caps case). Swift: decode table incl. repeat/up/unknown/subtype, input↔output table agreement, andtestCapturedMediaKeyIsAnAdmittedInput(captured Mute as input → saved → defsrc containsmute→ real bridge admits it).KEYPATH_TEST_ENFORCE_CLEAN_SUMMARY=1 Scripts/run-tests-safe.sh: 5,805 passed, 0 app warnings/errors, 0 build warnings.Hardware (Air) — pending
Rule with physical F10 (Mute) as input → fires; unmapped F11/F12 still change volume; held mapped key doesn't double-fire.
🤖 Generated with Claude Code