diff --git a/Sources/AppDelegate.swift b/Sources/AppDelegate.swift index 155ecfc9..63db90ac 100644 --- a/Sources/AppDelegate.swift +++ b/Sources/AppDelegate.swift @@ -991,10 +991,15 @@ func browserOmnibarShouldSubmitOnReturn(flags: NSEvent.ModifierFlags) -> Bool { func shouldDispatchBrowserReturnViaFirstResponderKeyDown( keyCode: UInt16, - firstResponderIsBrowser: Bool + firstResponderIsBrowser: Bool, + flags: NSEvent.ModifierFlags ) -> Bool { guard firstResponderIsBrowser else { return false } - return keyCode == 36 || keyCode == 76 + guard keyCode == 36 || keyCode == 76 else { return false } + // Keep browser Return forwarding narrow: only plain/Shift Return should be + // treated as submit-intent. Command-modified Return is reserved for app shortcuts + // like Toggle Pane Zoom (Cmd+Shift+Enter). + return browserOmnibarShouldSubmitOnReturn(flags: flags) } func shouldToggleMainWindowFullScreenForCommandControlFShortcut( @@ -8462,7 +8467,8 @@ private extension NSWindow { // mark handled to avoid the AppKit alert sound path. if shouldDispatchBrowserReturnViaFirstResponderKeyDown( keyCode: event.keyCode, - firstResponderIsBrowser: firstResponderWebView != nil + firstResponderIsBrowser: firstResponderWebView != nil, + flags: event.modifierFlags ) { // Forwarding keyDown can re-enter performKeyEquivalent in WebKit/AppKit internals. // On re-entry, fall back to normal dispatch to avoid an infinite loop. diff --git a/cmuxTests/CmuxWebViewKeyEquivalentTests.swift b/cmuxTests/CmuxWebViewKeyEquivalentTests.swift index dc2ecb6f..cc75f384 100644 --- a/cmuxTests/CmuxWebViewKeyEquivalentTests.swift +++ b/cmuxTests/CmuxWebViewKeyEquivalentTests.swift @@ -1988,7 +1988,8 @@ final class BrowserReturnKeyDownRoutingTests: XCTestCase { XCTAssertTrue( shouldDispatchBrowserReturnViaFirstResponderKeyDown( keyCode: 36, - firstResponderIsBrowser: true + firstResponderIsBrowser: true, + flags: [] ) ) } @@ -1997,7 +1998,8 @@ final class BrowserReturnKeyDownRoutingTests: XCTestCase { XCTAssertTrue( shouldDispatchBrowserReturnViaFirstResponderKeyDown( keyCode: 76, - firstResponderIsBrowser: true + firstResponderIsBrowser: true, + flags: [] ) ) } @@ -2006,7 +2008,8 @@ final class BrowserReturnKeyDownRoutingTests: XCTestCase { XCTAssertFalse( shouldDispatchBrowserReturnViaFirstResponderKeyDown( keyCode: 13, - firstResponderIsBrowser: true + firstResponderIsBrowser: true, + flags: [] ) ) } @@ -2015,7 +2018,58 @@ final class BrowserReturnKeyDownRoutingTests: XCTestCase { XCTAssertFalse( shouldDispatchBrowserReturnViaFirstResponderKeyDown( keyCode: 36, - firstResponderIsBrowser: false + firstResponderIsBrowser: false, + flags: [] + ) + ) + } + + func testRoutesForShiftReturnWhenBrowserFirstResponder() { + XCTAssertTrue( + shouldDispatchBrowserReturnViaFirstResponderKeyDown( + keyCode: 36, + firstResponderIsBrowser: true, + flags: [.shift] + ) + ) + } + + func testDoesNotRouteForCommandShiftReturnWhenBrowserFirstResponder() { + XCTAssertFalse( + shouldDispatchBrowserReturnViaFirstResponderKeyDown( + keyCode: 36, + firstResponderIsBrowser: true, + flags: [.command, .shift] + ) + ) + } + + func testDoesNotRouteForCommandReturnWhenBrowserFirstResponder() { + XCTAssertFalse( + shouldDispatchBrowserReturnViaFirstResponderKeyDown( + keyCode: 36, + firstResponderIsBrowser: true, + flags: [.command] + ) + ) + } + + func testDoesNotRouteForOptionReturnWhenBrowserFirstResponder() { + XCTAssertFalse( + shouldDispatchBrowserReturnViaFirstResponderKeyDown( + keyCode: 36, + firstResponderIsBrowser: true, + flags: [.option] + ) + ) + } + + func testDoesNotRouteForControlReturnWhenBrowserFirstResponder() { + XCTAssertFalse( + shouldDispatchBrowserReturnViaFirstResponderKeyDown( + keyCode: 36, + firstResponderIsBrowser: true, + flags: [.control] ) ) }