Skip to content

Fix keyboard shortcuts while macOS Secure Input is active#1127

Closed
wolph wants to merge 1 commit into
mrkai77:developfrom
wolph:fix/secure-input-hotkeys
Closed

Fix keyboard shortcuts while macOS Secure Input is active#1127
wolph wants to merge 1 commit into
mrkai77:developfrom
wolph:fix/secure-input-hotkeys

Conversation

@wolph

@wolph wolph commented Jul 22, 2026

Copy link
Copy Markdown

Summary

  • keep Loop shortcuts working while macOS Secure Input is active
  • retain the existing event-tap path for the radial menu and shortcuts that Carbon cannot represent
  • add a focused 15-test unit-test target for the fallback and its integration

Root cause

Loop currently discovers keyboard shortcuts through a CGEventTap. When an application enables macOS Secure Input, ordinary keyboard events are no longer delivered to that event tap. Loop keeps running and the radial menu can still work, but keyboard shortcuts appear completely dead because their key-down events never reach KeybindTrigger.

This is why the same shortcuts can continue to work in window managers that register global system hotkeys instead of relying exclusively on an event tap.

Fix

For shortcuts that can be represented as one ordinary key plus side-independent base modifiers, Loop now also registers a Carbon hotkey through RegisterEventHotKey.

The existing CGEventTap remains the primary path for all other input. In particular, this PR does not move the radial menu, multi-key chords, or side-dependent modifier chords to Carbon. Those inputs retain their current behavior and limitations.

The fallback is deliberately narrow:

  • registrations rebuild when the trigger key, keybinds, modifier-side behavior, or reverse-cycle setting changes
  • successful Carbon registrations are deferred by the event-tap path, preventing duplicate actions when Secure Input is off
  • Carbon callbacks are scheduled onto EventTapThread, preserving the existing keybind execution context
  • an active-press set preserves repeat and release behavior
  • a small generation counter rejects callbacks queued before a rebuild or stop
  • failed or unsupported registrations fall back to the existing event-tap behavior

AppDelegate also skips normal application startup when loaded as an XCTest host. This prevents unit tests from showing Accessibility prompts or mutating the running applications TCC state.

Scope

The production change is limited to:

  • the Carbon shortcut value/resolver
  • the Carbon registration monitor
  • the integration points in KeybindTrigger
  • the XCTest-host startup guard

There are no changes to LoopManager, trigger timers, general event-monitor classes, or application lifecycle coordination.

Verification

  • 15 focused tests passed, covering shortcut conversion, unsupported and side-dependent chords, duplicate registration handling, rebuild/stop behavior, repeat and release behavior, reverse-cycle Shift bindings, event-tap deduplication, settings rebuilds, and stale callback rejection
  • Xcode static analyzer completed successfully
  • Development configuration built successfully as a thin arm64 app from fresh DerivedData
  • strict deep code-signature verification passed for the ad-hoc build
  • manually enabled Secure Input, confirmed it was active, and verified Loop screen/cycle shortcuts in the installed build
  • manually confirmed the radial menu still works

Limitations

Carbon cannot represent every chord accepted by Loop. Shortcuts with multiple ordinary keys or side-dependent modifiers therefore remain on the event-tap path and can still be unavailable while Secure Input is active. This preserves existing semantics instead of silently broadening or changing those shortcuts.

@wolph
wolph force-pushed the fix/secure-input-hotkeys branch 2 times, most recently from b5df9b7 to 81bb47e Compare July 22, 2026 17:43
@wolph
wolph force-pushed the fix/secure-input-hotkeys branch from 81bb47e to 89a57e6 Compare July 22, 2026 18:05
@wolph
wolph marked this pull request as ready for review July 22, 2026 23:28
Copilot AI review requested due to automatic review settings July 22, 2026 23:28

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@mrkai77

mrkai77 commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Hey @wolph, thanks for the PR! Unfortunately, we won't be able to review it until it complies with our AI Policy and follows our PR template.

Historically, we've been more lenient with smaller PRs, but for larger ones like this, which require extensive testing and can take hours of maintainer time to review, we ask that contributors follow both requirements.

Feel free to reopen the PR once those have been addressed. Thanks!

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.

4 participants