Skip to content

Fix recording shortcuts dropping out during Secure Input - #965

Open
levi wants to merge 3 commits into
altic-dev:mainfrom
levi:fix/registered-keyboard-hotkeys
Open

Fix recording shortcuts dropping out during Secure Input#965
levi wants to merge 3 commits into
altic-dev:mainfrom
levi:fix/registered-keyboard-hotkeys

Conversation

@levi

@levi levi commented Sep 11, 2026

Copy link
Copy Markdown

Description

Option+Space kept stopping working for me on Tahoe. I tracked it down to ChatGPT holding Secure Event Input: FluidVoice's event tap could still report itself as enabled, but it wasn't receiving the shortcut.

This registers recording shortcuts like Option+Space with RegisterEventHotKey and sends press/release events through the existing dictation logic. I tested the patched app on the same Mac with Secure Input still active, and Option+Space now starts recording again.

Registration is exclusive, so a conflicting owner produces an error and keeps the event-tap fallback available. Entering shortcut capture or reinitializing the manager also stops a held Automatic-mode recording, even if the press was short.

The change also handles the bits around registration: avoiding duplicate actions from the event tap, ignoring key repeats, finishing held shortcuts before settings change, and temporarily unregistering shortcuts while editing them. Event-tap recovery leaves active registered shortcuts alone. Secure Input state is logged separately from event-tap health. Sleep/wake and session changes finish interrupted presses and clear stale held-key state, so losing a release callback does not swallow the next press.

Type of Change

  • 🐞 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 🧹 Chore
  • 📝 Documentation update

Related Issue or Discussion

Related to #849, especially the report that Option+Space fails while modifier-only shortcuts still work. I reproduced that symptom, though I can't confirm that report had the same cause.

Also related to the event-tap reliability work in #657. This gives supported key combinations a path that doesn't depend on the tap; it doesn't fix the Function-key failure described there. I'm leaving both as related issues rather than claiming to close them.

Testing

  • Tested on Intel Mac
  • Tested on Apple Silicon Mac
  • Tested on macOS version: 26.6.2 (25G83), Xcode 26.6
  • Ran linter locally: changed Swift files pass strict lint. The full repository check still reports seven existing legacy_swiftui_aspect_ratio violations in unrelated UI files.
  • Ran formatter locally on the changed implementation and test files.
  • Ran tests locally: full app build succeeded; all 103 selected Xcode tests passed (HotkeyShortcutTests and RegisteredHotkeysTests). The standalone 13-test suite also passed.

The new tests cover exclusive registration requests, native conflicts and retry after the owner releases the shortcut, interruption release context, missing key-up recovery across all four sleep/session notifications, registration cleanup against the native API, routing without event-tap events, repeat suppression, modifier-first releases, failed registrations and retry, shortcut editing, stale events, and balancing held shortcuts.

The missing-release test failed before adding the lifecycle observers and passes afterward. It also checks repeated recovery notifications, late releases, and the next complete press.

I checked the regression tests against temporary copies with each fix reverted; both caught the old behavior.

I also launched the debug app and tested physical Option+Space presses with Secure Input active. The shortcut reached the dictation callback; after granting the debug app microphone permission, recording worked. Hold/automatic mode, sleep/wake, and VNC recovery still need hands-on testing.

Screenshots / Video

  • No UI/visual changes; screenshots/video are not applicable.

The ContentView change only hooks shortcut editing into registration cleanup; it doesn't change the layout or controls.

Notes

Plain keys, modifier-only shortcuts, Fn combinations, and mouse buttons keep the existing event-tap path. If native registration fails, the app logs the error and falls back to the tap. Those paths can still be affected by Secure Input.

This doesn't disable Secure Input or override another app's ownership of a shortcut. Cancel and paste-last also keep their existing context-dependent behavior.

docs/REGISTERED_HOTKEYS.md includes the design and remaining acceptance checks. Tests/run_registered_hotkey_tests.sh --live runs a short Option+Space-only probe without recording audio.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 11, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-11T16:47:54.234285Z d2f755d New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@greptile-apps

greptile-apps Bot commented Sep 11, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds a Carbon-based path for eligible recording shortcuts so they continue working while Secure Input suppresses event-tap delivery.

  • Registers supported modifier-key chords exclusively while retaining event-tap fallback after registration failures.
  • Routes native press and release callbacks through the existing dictation state machine and suppresses duplicate event-tap handling.
  • Cleans up held shortcut state during configuration, capture, reinitialization, sleep, wake, and session transitions.
  • Adds focused integration tests, a standalone live probe, and design and acceptance documentation.

Confidence Score: 5/5

The PR appears safe to merge; no actionable new defect or outstanding repository-rule violation was identified.

The lifecycle additions finish each held registered shortcut idempotently, preserve native registrations, clear stale release bookkeeping, and reuse the existing interruption-aware release path. The broader native-registration integration retains event-tap fallback when Carbon registration fails and avoids duplicate routing for successful registrations.

Reviews (3): Last reviewed commit: "Recover held hotkeys across sleep and se..." | Re-trigger Greptile

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 222b8a131c

ℹ️ 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".

Comment on lines +174 to +175
if down {
guard self.pressed.insert(id).inserted else { return } // no autorepeat

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 Badge Recover when a registered key-up is lost

If the machine sleeps, switches sessions, or otherwise loses the release callback while a registered chord is held, its ID remains in pressed, so every subsequent press of that shortcut is rejected here as autorepeat. Event-tap recovery also deliberately preserves state while hasPressedShortcut is true, leaving the shortcut disabled until a settings change or manual reinitialization calls releaseAll; clear or reconcile registered press state during session/wake recovery.

Useful? React with 👍 / 👎.

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