Prevent window title reset when command palette opens

This commit is contained in:
Bryan Lee
2025-05-02 05:27:34 +08:00
parent e79bf71f23
commit 75cba1d50d
3 changed files with 72 additions and 19 deletions

View File

@ -40,6 +40,21 @@ protocol TerminalViewModel: ObservableObject {
var commandPaletteIsShowing: Bool { get set } var commandPaletteIsShowing: Bool { get set }
} }
struct WindowAccessor: NSViewRepresentable {
@Binding var window: NSWindow?
func makeNSView(context: Context) -> NSView {
let view = NSView()
DispatchQueue.main.async {
// Ensure view is in hierarchy
self.window = view.window
}
return view
}
func updateNSView(_ nsView: NSView, context: Context) {}
}
/// The main terminal view. This terminal view supports splits. /// The main terminal view. This terminal view supports splits.
struct TerminalView<ViewModel: TerminalViewModel>: View { struct TerminalView<ViewModel: TerminalViewModel>: View {
@ObservedObject var ghostty: Ghostty.App @ObservedObject var ghostty: Ghostty.App
@ -64,19 +79,12 @@ struct TerminalView<ViewModel: TerminalViewModel>: View {
@FocusedValue(\.ghosttySurfaceZoomed) private var zoomedSplit @FocusedValue(\.ghosttySurfaceZoomed) private var zoomedSplit
@FocusedValue(\.ghosttySurfaceCellSize) private var cellSize @FocusedValue(\.ghosttySurfaceCellSize) private var cellSize
// The title for our window // State to hold the last known valid title from the focused surface
private var title: String { @State private var lastKnownSurfaceTitle: String = "👻"
if let surfaceTitle, !surfaceTitle.isEmpty { // State to hold the last known valid PWD URL
return surfaceTitle @State private var lastKnownPwdURL: URL?
} // State to hold the NSWindow reference
return "👻" @State private var hostingWindow: NSWindow?
}
// The pwd of the focused surface as a URL
private var pwdURL: URL? {
guard let surfacePwd, surfacePwd != "" else { return nil }
return URL(fileURLWithPath: surfacePwd)
}
var body: some View { var body: some View {
switch ghostty.readiness { switch ghostty.readiness {
@ -105,11 +113,11 @@ struct TerminalView<ViewModel: TerminalViewModel>: View {
self.delegate?.focusedSurfaceDidChange(to: newValue) self.delegate?.focusedSurfaceDidChange(to: newValue)
} }
} }
.onChange(of: title) { newValue in .onChange(of: surfaceTitle) { newValue in
self.delegate?.titleDidChange(to: newValue) updateWindowTitle(newValue)
} }
.onChange(of: pwdURL) { newValue in .onChange(of: surfacePwd) { newValue in
self.delegate?.pwdDidChange(to: newValue) updatePwdURL(from: newValue)
} }
.onChange(of: cellSize) { newValue in .onChange(of: cellSize) { newValue in
guard let size = newValue else { return } guard let size = newValue else { return }
@ -137,6 +145,53 @@ struct TerminalView<ViewModel: TerminalViewModel>: View {
} }
} }
} }
// Use WindowAccessor to get a reference to the hosting NSWindow
.background(WindowAccessor(window: $hostingWindow))
// Ensure the title is set via delegate once the window reference is available
.onChange(of: hostingWindow) { newWindow in
if newWindow != nil {
DispatchQueue.main.async {
self.delegate?.titleDidChange(to: self.lastKnownSurfaceTitle)
}
}
}
// Set initial title and PWD when the view first appears
.onAppear {
updateWindowTitle(surfaceTitle)
updatePwdURL(from: surfacePwd)
}
}
}
private func updateWindowTitle(_ currentSurfaceTitle: String?) {
guard let newTitle = currentSurfaceTitle, !newTitle.isEmpty else {
// If the new title is nil or empty (e.g., focus lost to command palette),
// *do not* change the title. We simply do nothing here, preserving the last known title
return
}
if newTitle != lastKnownSurfaceTitle {
lastKnownSurfaceTitle = newTitle
DispatchQueue.main.async {
self.delegate?.titleDidChange(to: self.lastKnownSurfaceTitle)
}
}
}
private func updatePwdURL(from newPwdString: String?) {
guard let path = newPwdString, !path.isEmpty,
path.starts(with: "/") else {
// If newPwdString is nil, empty, or not an absolute path, do nothing
return
}
let newURL = URL(fileURLWithPath: path)
// If the newly created URL is different from the last known one, update and notify
if newURL != lastKnownPwdURL {
lastKnownPwdURL = newURL
DispatchQueue.main.async {
self.delegate?.pwdDidChange(to: self.lastKnownPwdURL)
}
} }
} }
} }

View File

@ -77,7 +77,6 @@ extension Ghostty {
.onReceive(pubZoom) { onZoom(notification: $0) } .onReceive(pubZoom) { onZoom(notification: $0) }
} }
} }
.navigationTitle(surfaceTitle ?? "Ghostty")
.id(node) // Needed for change detection on node .id(node) // Needed for change detection on node
} else { } else {
// On these events we want to reset the split state and call it. // On these events we want to reset the split state and call it.

View File

@ -13,7 +13,6 @@ extension Ghostty {
SurfaceForApp(app) { surfaceView in SurfaceForApp(app) { surfaceView in
SurfaceWrapper(surfaceView: surfaceView) SurfaceWrapper(surfaceView: surfaceView)
} }
.navigationTitle(surfaceTitle ?? "Ghostty")
} }
} }
} }