From 5ced3134d3840f0c18b5f8b7bd88d7fc76c667be Mon Sep 17 00:00:00 2001 From: Apptah Date: Mon, 23 Mar 2026 09:05:39 +0800 Subject: [PATCH] Fix browser freeze after pane split by reattaching WKWebView rendering state (#1852) When a pane split occurs, SwiftUI recreates host views and the portal system rebinds the WKWebView to a new container. However, the bind path never called BrowserWindowPortalRegistry.refresh(), so WebKit's internal rendering state (_exitInWindow/_enterInWindow) was never cycled. This left the WKWebView frozen in the original pane after a split. Add refresh() calls after every portal bind that changes the host, in three code paths: the main update path (shouldBindNow), onDidMoveToWindow, and onGeometryChanged. The refresh is a no-op when no reattach is needed (browserPortalNeedsRenderingStateReattach == false), so normal rendering is unaffected. Co-authored-by: Claude Opus 4.6 (1M context) --- Sources/Panels/BrowserPanelView.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Sources/Panels/BrowserPanelView.swift b/Sources/Panels/BrowserPanelView.swift index c30124a7..95716b7b 100644 --- a/Sources/Panels/BrowserPanelView.swift +++ b/Sources/Panels/BrowserPanelView.swift @@ -6098,6 +6098,10 @@ struct WebViewRepresentable: NSViewRepresentable { visibleInUI: coordinator.desiredPortalVisibleInUI, zPriority: coordinator.desiredPortalZPriority ) + BrowserWindowPortalRegistry.refresh( + webView: webView, + reason: "portalHostBind.didMoveToWindow" + ) BrowserWindowPortalRegistry.updatePaneTopChromeHeight( for: webView, height: coordinator.desiredPortalVisibleInUI ? paneTopChromeHeight : 0 @@ -6129,6 +6133,10 @@ struct WebViewRepresentable: NSViewRepresentable { visibleInUI: coordinator.desiredPortalVisibleInUI, zPriority: coordinator.desiredPortalZPriority ) + BrowserWindowPortalRegistry.refresh( + webView: webView, + reason: "portalHostBind.geometryChanged" + ) BrowserWindowPortalRegistry.updatePaneTopChromeHeight( for: webView, height: coordinator.desiredPortalVisibleInUI ? paneTopChromeHeight : 0 @@ -6166,6 +6174,14 @@ struct WebViewRepresentable: NSViewRepresentable { visibleInUI: coordinator.desiredPortalVisibleInUI, zPriority: coordinator.desiredPortalZPriority ) + // Force a rendering-state reattach after portal host replacement + // (e.g. after a pane split). Without this, WKWebView can freeze + // because _exitInWindow/_enterInWindow are never cycled when the + // web view is reparented to a new container during bind. + BrowserWindowPortalRegistry.refresh( + webView: webView, + reason: "portalHostBind" + ) coordinator.lastPortalHostId = hostId coordinator.lastSynchronizedHostGeometryRevision = geometryRevision }