Skip to content

Optionally send media keys to Omarchy while it is focused - #314

Draft
NimbleAINinja wants to merge 13 commits into
omacom:mainfrom
NimbleAINinja:host-key-routing-media
Draft

NimbleAINinja wants to merge 13 commits into
omacom:mainfrom
NimbleAINinja:host-key-routing-media

Conversation

@NimbleAINinja

Copy link
Copy Markdown
Contributor

What changed and why

Stacked on #313 — the first seven commits here are that PR; only the last six are new. Draft until it merges.

Second part of the follow-up to #249 ("defaults for display brightness and media controls"). The Keyboard sheet gains a Media row: previous, play/pause and next (F7–F9) can go to Omarchy while its window has the keyboard. It defaults to macOS, so nothing changes unless someone opts in. Volume, mute, brightness and keyboard backlight always stay with macOS.

  • The media keys arrive as NX_SYSDEFINED aux-control events, which full grab's tap does not capture. A new Cocoa patch, qemu-cocoa-media-keys.patch (applied right after the host-keys patch), adds a media-keys=on|off display option. When on, the tap also takes those events, decodes the three transport keys and sends them through the keyboard state tracker as audioprev / audioplay / audionext; everything else is returned to macOS. With the option off the tap's event mask is unchanged.
  • Going through the keyboard state tracker means QEMU's existing release on focus loss lifts a held media key.
  • KeyboardRoutingLaunchConfiguration publishes OMARCHY_QEMU_GPU_MEDIA_KEYS (0/1); run-qemu-gpu.sh validates it, checks the capability and appends ,media-keys=on only when enabled.
  • The guest needs no change: Omarchy's Hyprland bindings already map XF86AudioPlay/Next/Prev to omarchy-shell media.
  • The setting applies on the next VM start, like the other rows. Older saved preferences without the field load as macOS.

I first tried this in the --bridge-command-super helper, but nothing launches that helper any more and it would hold QEMU's single QMP client, so it lives in the Cocoa tap instead.

As with the first PR, #279's Cocoa patch overlaps this one's context and whichever merges second needs a mechanical refresh.

Testing

Run on the branch as submitted plus two local planning documents (no code difference), on an M1 Max MacBook Pro, macOS 27:

  • make test: exit 0.
  • QEMU patch stack: all 22 patches apply in build-script order, exit 0, checksums match their pins; the media-keys patch applies with no offset or fuzz, and the host-keys patch is byte-identical to the first PR's.
  • make build: exit 0. The bundled QEMU's -help lists [,host-keys=code:code...][,media-keys=on|off].
  • git diff --check origin/main: clean.
  • New tests: the decoder compiled from the patch text and exercised for every transport key, state, and the ignored volume/mute/brightness/backlight types (test-cocoa-media-keys.py); launch environment; launcher scenarios for on, off and an invalid value; preference migration; sheet and row.
  • Key events were measured with a listen-only HID tap on both keyboards: F7/F8/F9 send aux key types 20/16/19, F10–F12 send 7/1/0.
  • Manual, installed build, built-in keyboard and Magic Keyboard (A1843): with Media set to Omarchy and the VM restarted, F7–F9 control a player in the guest while Omarchy is focused and the Mac's Now Playing once a Mac app is focused; holding F9 and clicking a Mac window leaves no stuck key; volume always controls the Mac. With Media set to macOS, F7–F9 always control the Mac.

Not done: no screenshots attached yet. Not tested on macOS 15.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DP6vwz7aaUNRSuNGLgRqTB

NimbleAINinja and others added 13 commits October 4, 2026 13:26
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A listen-only HID tap on the M1 Max built-in keyboard and a Magic
Keyboard A1843 confirmed the F4-F6 keycodes. F4 sends 177 on built-in
keyboards (Spotlight) and 131 on the Magic Keyboard (Launchpad), so the
Spotlight / Launchpad row now matches both. F5 and F6 on built-in
keyboards are dedicated Dictation/Siri (176) and Do Not Disturb (178)
caps rather than plain function keys, so they get their own rows,
defaulting to macOS like every other row. The new default host-key list
is 131,144,145,160,176,177,178.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DP6vwz7aaUNRSuNGLgRqTB
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DP6vwz7aaUNRSuNGLgRqTB
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DP6vwz7aaUNRSuNGLgRqTB
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DP6vwz7aaUNRSuNGLgRqTB
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant