works
This commit is contained in:
parent
463c6baabb
commit
b739e918c9
4 changed files with 80 additions and 4 deletions
|
|
@ -967,6 +967,16 @@ struct ContentView: View {
|
|||
workspaceHandoffFallbackTask?.cancel()
|
||||
workspaceHandoffFallbackTask = nil
|
||||
let retiring = retiringWorkspaceId
|
||||
|
||||
// Hide terminal portal views for the retiring workspace BEFORE clearing
|
||||
// retiringWorkspaceId. Once cleared, reconcileMountedWorkspaceIds unmounts
|
||||
// the workspace — but dismantleNSView intentionally doesn't hide portal views
|
||||
// (to avoid blackouts during transient bonsplit dismantles). Hiding here
|
||||
// prevents stale portal-hosted terminals from covering browser panes.
|
||||
if let retiring, let workspace = tabManager.tabs.first(where: { $0.id == retiring }) {
|
||||
workspace.hideAllTerminalPortalViews()
|
||||
}
|
||||
|
||||
retiringWorkspaceId = nil
|
||||
tabManager.completePendingWorkspaceUnfocus(reason: reason)
|
||||
#if DEBUG
|
||||
|
|
|
|||
|
|
@ -4089,6 +4089,14 @@ struct GhosttyTerminalView: NSViewRepresentable {
|
|||
coordinator.lastBoundHostId = hostId
|
||||
}
|
||||
TerminalWindowPortalRegistry.synchronizeForAnchor(host)
|
||||
} else {
|
||||
// Bind is deferred until host moves into a window. Update the
|
||||
// existing portal entry's visibleInUI now so that any portal sync
|
||||
// that runs before the deferred bind completes won't hide the view.
|
||||
TerminalWindowPortalRegistry.updateEntryVisibility(
|
||||
for: hostedView,
|
||||
visibleInUI: coordinator.desiredIsVisibleInUI
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,6 +209,29 @@ final class WindowTerminalPortal: NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
/// Hide a portal entry without detaching it. Updates visibleInUI to false and
|
||||
/// sets isHidden = true so subsequent synchronizeHostedView calls keep it hidden.
|
||||
/// Used when a workspace is permanently unmounted (vs. transient bonsplit dismantles).
|
||||
func hideEntry(forHostedId hostedId: ObjectIdentifier) {
|
||||
guard var entry = entriesByHostedId[hostedId] else { return }
|
||||
guard entry.visibleInUI else { return }
|
||||
entry.visibleInUI = false
|
||||
entriesByHostedId[hostedId] = entry
|
||||
entry.hostedView?.isHidden = true
|
||||
#if DEBUG
|
||||
dlog("portal.hideEntry hosted=\(portalDebugToken(entry.hostedView)) reason=workspaceUnmount")
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Update the visibleInUI flag on an existing entry without rebinding.
|
||||
/// Used when a deferred bind is pending — this ensures synchronizeHostedView
|
||||
/// won't hide a view that updateNSView has already marked as visible.
|
||||
func updateEntryVisibility(forHostedId hostedId: ObjectIdentifier, visibleInUI: Bool) {
|
||||
guard var entry = entriesByHostedId[hostedId] else { return }
|
||||
entry.visibleInUI = visibleInUI
|
||||
entriesByHostedId[hostedId] = entry
|
||||
}
|
||||
|
||||
func bind(hostedView: GhosttySurfaceScrollView, to anchorView: NSView, visibleInUI: Bool, zPriority: Int = 0) {
|
||||
guard ensureInstalled() else { return }
|
||||
|
||||
|
|
@ -329,12 +352,17 @@ final class WindowTerminalPortal: NSObject {
|
|||
return
|
||||
}
|
||||
guard let anchorView = entry.anchorView, let window else {
|
||||
// Only hide if the entry is not marked visibleInUI. When a workspace is
|
||||
// remounting, updateNSView sets visibleInUI=true before the deferred bind
|
||||
// provides an anchor — hiding here would race with that and cause a flash.
|
||||
if !entry.visibleInUI {
|
||||
#if DEBUG
|
||||
if !hostedView.isHidden {
|
||||
dlog("portal.hidden hosted=\(portalDebugToken(hostedView)) value=1 reason=missingAnchorOrWindow")
|
||||
}
|
||||
if !hostedView.isHidden {
|
||||
dlog("portal.hidden hosted=\(portalDebugToken(hostedView)) value=1 reason=missingAnchorOrWindow")
|
||||
}
|
||||
#endif
|
||||
hostedView.isHidden = true
|
||||
hostedView.isHidden = true
|
||||
}
|
||||
return
|
||||
}
|
||||
guard anchorView.window === window else {
|
||||
|
|
@ -587,6 +615,23 @@ enum TerminalWindowPortalRegistry {
|
|||
portal.synchronizeHostedViewForAnchor(anchorView)
|
||||
}
|
||||
|
||||
static func hideHostedView(_ hostedView: GhosttySurfaceScrollView) {
|
||||
let hostedId = ObjectIdentifier(hostedView)
|
||||
guard let windowId = hostedToWindowId[hostedId],
|
||||
let portal = portalsByWindowId[windowId] else { return }
|
||||
portal.hideEntry(forHostedId: hostedId)
|
||||
}
|
||||
|
||||
/// Update the visibleInUI flag on an existing portal entry without rebinding.
|
||||
/// Called when a bind is deferred (host not yet in window) to prevent stale
|
||||
/// portal syncs from hiding a view that is about to become visible.
|
||||
static func updateEntryVisibility(for hostedView: GhosttySurfaceScrollView, visibleInUI: Bool) {
|
||||
let hostedId = ObjectIdentifier(hostedView)
|
||||
guard let windowId = hostedToWindowId[hostedId],
|
||||
let portal = portalsByWindowId[windowId] else { return }
|
||||
portal.updateEntryVisibility(forHostedId: hostedId, visibleInUI: visibleInUI)
|
||||
}
|
||||
|
||||
static func viewAtWindowPoint(_ windowPoint: NSPoint, in window: NSWindow) -> NSView? {
|
||||
let portal = portal(for: window)
|
||||
return portal.viewAtWindowPoint(windowPoint)
|
||||
|
|
|
|||
|
|
@ -966,6 +966,19 @@ final class Workspace: Identifiable, ObservableObject {
|
|||
triggerNotificationFocusFlash(panelId: panelId, requiresSplit: false, shouldFocus: true)
|
||||
}
|
||||
|
||||
// MARK: - Portal Lifecycle
|
||||
|
||||
/// Hide all terminal portal views for this workspace.
|
||||
/// Called before the workspace is unmounted to prevent portal-hosted terminal
|
||||
/// views from covering browser panes in the newly selected workspace.
|
||||
func hideAllTerminalPortalViews() {
|
||||
for panel in panels.values {
|
||||
guard let terminal = panel as? TerminalPanel else { continue }
|
||||
terminal.hostedView.setVisibleInUI(false)
|
||||
TerminalWindowPortalRegistry.hideHostedView(terminal.hostedView)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Utility
|
||||
|
||||
/// Create a new terminal panel (used when replacing the last panel)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue