Prevent background webview autofocus from stealing focus
This commit is contained in:
parent
0dbe95b797
commit
a369cf4419
3 changed files with 55 additions and 0 deletions
|
|
@ -3112,6 +3112,11 @@ struct WebViewRepresentable: NSViewRepresentable {
|
|||
let webView = panel.webView
|
||||
context.coordinator.panel = panel
|
||||
context.coordinator.webView = webView
|
||||
Self.applyWebViewFirstResponderPolicy(
|
||||
panel: panel,
|
||||
webView: webView,
|
||||
isPanelFocused: isPanelFocused
|
||||
)
|
||||
|
||||
let shouldUseWindowPortal = panel.shouldPreserveWebViewAttachmentDuringTransientHide()
|
||||
if shouldUseWindowPortal {
|
||||
|
|
@ -3359,6 +3364,15 @@ struct WebViewRepresentable: NSViewRepresentable {
|
|||
}
|
||||
}
|
||||
|
||||
private static func applyWebViewFirstResponderPolicy(
|
||||
panel: BrowserPanel,
|
||||
webView: WKWebView,
|
||||
isPanelFocused: Bool
|
||||
) {
|
||||
guard let cmuxWebView = webView as? CmuxWebView else { return }
|
||||
cmuxWebView.allowsFirstResponderAcquisition = isPanelFocused && !panel.shouldSuppressWebViewFocus()
|
||||
}
|
||||
|
||||
static func dismantleNSView(_ nsView: NSView, coordinator: Coordinator) {
|
||||
coordinator.attachRetryWorkItem?.cancel()
|
||||
coordinator.attachRetryWorkItem = nil
|
||||
|
|
|
|||
|
|
@ -22,6 +22,14 @@ final class CmuxWebView: WKWebView {
|
|||
var onContextMenuDownloadStateChanged: ((Bool) -> Void)?
|
||||
var contextMenuLinkURLProvider: ((CmuxWebView, NSPoint, @escaping (URL?) -> Void) -> Void)?
|
||||
var contextMenuDefaultBrowserOpener: ((URL) -> Bool)?
|
||||
/// Guard against background panes stealing first responder (e.g. page autofocus).
|
||||
/// BrowserPanelView updates this as pane focus state changes.
|
||||
var allowsFirstResponderAcquisition: Bool = true
|
||||
|
||||
override func becomeFirstResponder() -> Bool {
|
||||
guard allowsFirstResponderAcquisition else { return false }
|
||||
return super.becomeFirstResponder()
|
||||
}
|
||||
|
||||
override func performKeyEquivalent(with event: NSEvent) -> Bool {
|
||||
// Preserve Cmd+Return/Enter for web content (e.g. editors/forms). Do not
|
||||
|
|
|
|||
|
|
@ -99,6 +99,39 @@ final class CmuxWebViewKeyEquivalentTests: XCTestCase {
|
|||
XCTAssertTrue(spy.invoked)
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func testCanBlockFirstResponderAcquisitionWhenPaneIsUnfocused() {
|
||||
_ = NSApplication.shared
|
||||
|
||||
let window = NSWindow(
|
||||
contentRect: NSRect(x: 0, y: 0, width: 640, height: 420),
|
||||
styleMask: [.titled, .closable],
|
||||
backing: .buffered,
|
||||
defer: false
|
||||
)
|
||||
let container = NSView(frame: window.contentRect(forFrameRect: window.frame))
|
||||
window.contentView = container
|
||||
|
||||
let webView = CmuxWebView(frame: container.bounds, configuration: WKWebViewConfiguration())
|
||||
webView.autoresizingMask = [.width, .height]
|
||||
container.addSubview(webView)
|
||||
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
defer { window.orderOut(nil) }
|
||||
|
||||
webView.allowsFirstResponderAcquisition = true
|
||||
XCTAssertTrue(window.makeFirstResponder(webView))
|
||||
|
||||
_ = window.makeFirstResponder(nil)
|
||||
webView.allowsFirstResponderAcquisition = false
|
||||
XCTAssertFalse(webView.becomeFirstResponder())
|
||||
|
||||
_ = window.makeFirstResponder(webView)
|
||||
if let firstResponderView = window.firstResponder as? NSView {
|
||||
XCTAssertFalse(firstResponderView === webView || firstResponderView.isDescendant(of: webView))
|
||||
}
|
||||
}
|
||||
|
||||
private func installMenu(spy: ActionSpy, key: String, modifiers: NSEvent.ModifierFlags) {
|
||||
let mainMenu = NSMenu()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue