Skip to content

Add macOS support and use the SDK's key names - #1

Merged
PyFlat-JR merged 4 commits into
mainfrom
feature/macos-support
Oct 14, 2026
Merged

PyFlat-JR merged 4 commits into
mainfrom
feature/macos-support

Conversation

@PyFlat-JR

Copy link
Copy Markdown
Member

What does this PR do?

Adds macOS on Apple silicon as a second platform next to Windows, and moves to Macro Deck SDK 3.0.0-beta.17 so both platforms publish exactly the key names the combo editor stores.

macOS hook

  • A Quartz event tap on its own CFRunLoop thread. With Accessibility it can swallow a suppressed combo's key; with only Input Monitoring it falls back to listen-only, so hotkeys still fire but the key also reaches the focused app.
  • Granting or revoking either permission takes effect without a restart: without access it retries every 5 seconds, and it swaps between the active and the listen-only tap when Accessibility changes. Revoking Accessibility no longer freezes all input.
  • Modifiers are read from each event's flags, so a modifier released while macOS hid the keys (a password field) never sticks.
  • A missing permission shows a notification that says which one and where to turn it on. The Accessibility one only appears once a trigger actually asks for suppression.

Shared core

  • KeyboardHook holds the platform-neutral half (held keys, combo detection, what a suppressed combo swallows) and picks the backend for the OS. The Windows WH_KEYBOARD_LL hook moved into Windows/ unchanged in behaviour.
  • An OS without a backend only logs a warning, so the plugin never fails to start.

Key names from the SDK

  • The plugin's own key tables are gone. Both hooks translate native codes with MacroDeck.Sdk.Input.NativeKeys (Macro-Deck#1289) and name them with KeyNames, following ADR 0104 from Macro-Deck#1287: letters follow the active layout, digits and punctuation the key position (Minus, IntlBackslash), plus NumpadEnter and NumLock.
  • On Windows punctuation now goes by scan code, so the German ß key is Minus like in the recorder. On macOS letters go through the active input source, so the Z key on a German Mac is Z.
  • Right-hand modifiers still publish Ctrl, Shift, Alt and Meta, because the editor never stores RightCtrl for event triggers.
  • Suppression resolves the spelling a trigger was stored with (-, Esc, Cmd, ...) the same way the host's trigger matching does.

Build and release

  • manifest.json gets an osx-arm64 entrypoint and the host:notifications permission, macrodeck-build.json a matching target, and CI also runs on macos-latest.
  • All Macro Deck packages and the release workflow's cli-version are on 3.0.0-beta.17, the Store's current minimum.

Docs

  • README has a macOS section (permissions, Cmd as Meta, password fields, keys macOS never reports). AGENTS.md describes the backends and the SDK key lookup.

Checklist

  • I have read AGENTS.md.
  • dotnet build and dotnet test pass locally (0 warnings, 63 tests).
  • macrodeck-plugin test passes against the packed artifact (0 failed).
  • I updated README.md / AGENTS.md where this changes what they describe.

Tested on

  • Windows 11: hotkeys, suppression, punctuation on a German layout.
  • macOS on Apple silicon with a German input source: permission prompts and notifications, granting and revoking Accessibility while running, letters following the input source, ß as Minus, right-hand modifiers, suppression of Ctrl+ß.

@PyFlat-JR
PyFlat-JR merged commit 9ac482e into main Oct 14, 2026
2 checks passed
@PyFlat-JR
PyFlat-JR deleted the feature/macos-support branch October 14, 2026 21:54
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