From ab1a6d9f272c7416a55c62d4d13db3b3f163304e Mon Sep 17 00:00:00 2001 From: BillionClaw Date: Wed, 18 Mar 2026 19:25:25 +0800 Subject: [PATCH 1/2] fix(keyboard): forward unbound Cmd+Shift combinations to terminal Unbound Cmd+Shift+ combinations were being silently swallowed by the AppKit key-routing layer and never reached the terminal via the kitty keyboard protocol. The root cause was in performKeyEquivalent's two-pass mechanism: 1. First pass returned false, expecting AppKit to redispatch 2. When no menu item matched, AppKit never redispatched the event The fix checks on the first pass if any menu item would handle the event. If not, the key is processed directly instead of relying on AppKit redispatch. Fixes manaflow-ai/cmux#1718 --- Sources/GhosttyTerminalView.swift | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Sources/GhosttyTerminalView.swift b/Sources/GhosttyTerminalView.swift index ded6ac00679f..dab91a3e12d3 100644 --- a/Sources/GhosttyTerminalView.swift +++ b/Sources/GhosttyTerminalView.swift @@ -4886,8 +4886,15 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { } } + // First pass: check if a menu item would handle this event. + // If not, process the key directly instead of relying on AppKit redispatch, + // which silently drops unbound Cmd+Shift combinations. lastPerformKeyEvent = event.timestamp - return false + if let menu = NSApp.mainMenu, menu.performKeyEquivalent(with: event) { + return true + } + equivalent = event.characters ?? "" + break } let finalEvent = NSEvent.keyEvent( From e0802e944340220ff754036d2a9f5c4a9ed32340 Mon Sep 17 00:00:00 2001 From: BillionClaw <267901332+BillionClaw@users.noreply.github.com> Date: Thu, 19 Mar 2026 00:46:15 +0800 Subject: [PATCH 2/2] fix(keyboard): check shouldRouteCommandEquivalentDirectlyToMainMenu before menu routing - Only route to NSApp.mainMenu if shouldRouteCommandEquivalentDirectlyToMainMenu permits it; otherwise fall through to terminal handling - Preserves intended exclusion for Cmd+` (keyCode 50) and non-menu command paths - Addresses reviewer feedback that unconditional main-menu routing bypasses command-routing filtering and can regress intentionally excluded shortcuts --- Sources/GhosttyTerminalView.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Sources/GhosttyTerminalView.swift b/Sources/GhosttyTerminalView.swift index dab91a3e12d3..504303ebc72f 100644 --- a/Sources/GhosttyTerminalView.swift +++ b/Sources/GhosttyTerminalView.swift @@ -4889,6 +4889,12 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { // First pass: check if a menu item would handle this event. // If not, process the key directly instead of relying on AppKit redispatch, // which silently drops unbound Cmd+Shift combinations. + // Only route to main menu if shouldRouteCommandEquivalentDirectlyToMainMenu + // permits it (e.g., Cmd+` is intentionally excluded). + if !shouldRouteCommandEquivalentDirectlyToMainMenu(event) { + lastPerformKeyEvent = nil + return false + } lastPerformKeyEvent = event.timestamp if let menu = NSApp.mainMenu, menu.performKeyEquivalent(with: event) { return true