fix: add Cmd+Q menu key equivalent as reliable fallback for quit interception#4179
Open
devin-ai-integration[bot] wants to merge 3 commits intomainfrom
Open
fix: add Cmd+Q menu key equivalent as reliable fallback for quit interception#4179devin-ai-integration[bot] wants to merge 3 commits intomainfrom
devin-ai-integration[bot] wants to merge 3 commits intomainfrom
Conversation
The local event monitor (NSEvent.addLocalMonitorForEvents) only receives events dispatched to the app's event stream. When the app is in Accessory activation mode with all windows hidden (after a close via Cmd+Q), there is no key window in the responder chain, so macOS doesn't route keyboard events to the app and the local monitor never fires. Add a global event monitor (NSEvent.addGlobalMonitorForEvents) alongside the existing local one. The global monitor receives events even when the app has no key window, ensuring Cmd+Q works reliably regardless of activation policy state. Co-Authored-By: unknown <>
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
✅ Deploy Preview for hyprnote-storybook canceled.
|
✅ Deploy Preview for hyprnote canceled.
|
Reverts the global event monitor approach (which only fires for events going to other apps, not our own) and instead adds a Cmd+Q menu key equivalent that reliably triggers the quit overlay. When WKWebView has focus, it can intermittently consume keyboard events via performKeyEquivalent before NSEvent.addLocalMonitorForEvents sees them. Menu key equivalents are processed by NSApplication at the same level and serve as a reliable fallback when the local monitor misses the event. The state machine handles double-calls gracefully. Co-Authored-By: unknown <>
Collaborator
|
/staging |
|
When the Cmd+Q menu item fires, there's no physical key release event, so the state machine would progress firstPress → holding → performQuit after 1.2s (force-quitting the app). Fix by adding onMenuCmdQ() that calls onCmdQPressed() followed immediately by onKeyReleased(), which correctly transitions to .awaiting state (showing overlay, waiting for a second press to close). Co-Authored-By: unknown <>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix: add Cmd+Q menu key equivalent as reliable fallback for quit interception
Summary
Adds a native
Cmd+Qmenu item ("Close") to the app menu that triggersQuitInterceptor.onMenuCmdQ(), serving as a reliable fallback whenNSEvent.addLocalMonitorForEventsintermittently fails to receive keyboard events.Symptom: Cmd+Q often doesn't show the quit overlay when the app window is visible and focused. It starts working again after screen recording or reopening the app multiple times.
Root cause: In macOS's event dispatch pipeline,
performKeyEquivalent:on the responder chain runs before local event monitors. When WKWebView'sperformKeyEquivalent:intermittently returns YES for Cmd+Q (depending on internal DOM focus state), it consumes the event and the local monitor never sees it. Focus-disrupting actions (screen recording, reopening) reset WKWebView's internal state, temporarily fixing the problem.Fix: A
Cmd+Qmenu key equivalent is processed byNSApplicationbeforeperformKeyEquivalent:reaches the WKWebView responder chain. This is the standard macOS pattern for app-level keyboard shortcuts with complex view hierarchies. The menu handler callsonMenuCmdQ(), which simulates a quick press-and-release (onCmdQPressed()+onKeyReleased()) to correctly transition to.awaitingstate — since a menu action has no physical key release event.Changes:
AppClosemenu item (Cmd+Q) added to the app menu, before "Quit Completely" (Cmd+Shift+Q)onMenuCmdQ()method inQuitInterceptorthat simulates press-and-release_trigger_cmd_q_pressed→ callsQuitInterceptor.shared.onMenuCmdQ()on main threadhypr_intercept::trigger_cmd_q_pressed()Review & Testing Checklist for Human
onMenuCmdQ()would callonKeyReleased()prematurely, breaking hold detection. Verify that holding Cmd+Q still works correctly..awaiting(not force-quit after 1.2s). This was a bug in an earlier revision that is now fixed viaonMenuCmdQ().Recommended test plan: Build and run on macOS. Use the app normally for a few minutes (interact with the webview, type in text fields, etc. to establish various DOM focus states). Then try Cmd+Q — this is the scenario most likely to reproduce the original bug. Repeat 10+ times across different focus states. Also test hold-to-quit and mouse-clicking "Close" from the app menu.
Notes
performKeyEquivalent: