From 85cba70c2e2a0459ddea8d337d4fd0f97809d54a Mon Sep 17 00:00:00 2001 From: Tobias Pape Date: Tue, 15 Jul 2025 18:12:39 +0200 Subject: [PATCH 1/2] Work around strange SwiftUI behavior in "older" macOSen. The Quick Terminal would not appear anymore, as somewhere in the framework the Quick Terminal Window's geometry gets corrupted when the window is added to the UI. This works around by caching the windows geometry and reusing it afterwards --- .../QuickTerminal/QuickTerminalController.swift | 12 ++++++++++++ .../Features/QuickTerminal/QuickTerminalWindow.swift | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift b/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift index 3bd8bc18f..b9f879a30 100644 --- a/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift +++ b/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift @@ -111,12 +111,24 @@ class QuickTerminalController: BaseTerminalController { // Setup our initial size based on our configured position position.setLoaded(window) + // Upon first adding this Window to its host view, older SwiftUI + // seems to have a "hiccup" and corrupts the frameRect, + // sometimes setting the size to zero, sometimes corrupting it. + // We pass the actual window's frame as "inital" frame directly + // to the window, so it can use that instead of the frameworks + // "interpretation" + if let qtWindow = window as? QuickTerminalWindow { + qtWindow.initialFrame = window.frame + } // Setup our content window.contentView = NSHostingView(rootView: TerminalView( ghostty: self.ghostty, viewModel: self, delegate: self )) + if let qtWindow = window as? QuickTerminalWindow { + qtWindow.initialFrame = nil + } // Animate the window in animateIn() diff --git a/macos/Sources/Features/QuickTerminal/QuickTerminalWindow.swift b/macos/Sources/Features/QuickTerminal/QuickTerminalWindow.swift index 005808a23..663f868f9 100644 --- a/macos/Sources/Features/QuickTerminal/QuickTerminalWindow.swift +++ b/macos/Sources/Features/QuickTerminal/QuickTerminalWindow.swift @@ -29,4 +29,14 @@ class QuickTerminalWindow: NSPanel { // We don't want to activate the owning app when quick terminal is triggered. self.styleMask.insert(.nonactivatingPanel) } + var initialFrame: NSRect? = nil + override func setFrame(_ frameRect: NSRect, display flag: Bool) { + // Upon first adding this Window to its host view, older SwiftUI + // seems to have a "hiccup" and corrupts the frameRect, + // sometimes setting the size to zero, sometimes corrupting it. + // If we find we have cached the "initial" frame, use that instead + // the propagated one throught the framework + super.setFrame(initialFrame ?? frameRect, display: flag) + } + } From 4fdf0b687e6512c3effccaa713fd0fcfa98ab7aa Mon Sep 17 00:00:00 2001 From: Tobias Pape Date: Tue, 22 Jul 2025 23:04:24 +0200 Subject: [PATCH 2/2] typo found typos, typo may keep them --- .../Features/QuickTerminal/QuickTerminalController.swift | 5 ++++- .../Features/QuickTerminal/QuickTerminalWindow.swift | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift b/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift index b9f879a30..1f608f767 100644 --- a/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift +++ b/macos/Sources/Features/QuickTerminal/QuickTerminalController.swift @@ -114,18 +114,21 @@ class QuickTerminalController: BaseTerminalController { // Upon first adding this Window to its host view, older SwiftUI // seems to have a "hiccup" and corrupts the frameRect, // sometimes setting the size to zero, sometimes corrupting it. - // We pass the actual window's frame as "inital" frame directly + // We pass the actual window's frame as "initial" frame directly // to the window, so it can use that instead of the frameworks // "interpretation" if let qtWindow = window as? QuickTerminalWindow { qtWindow.initialFrame = window.frame } + // Setup our content window.contentView = NSHostingView(rootView: TerminalView( ghostty: self.ghostty, viewModel: self, delegate: self )) + + // Clear out our frame at this point, the fixup from above is complete. if let qtWindow = window as? QuickTerminalWindow { qtWindow.initialFrame = nil } diff --git a/macos/Sources/Features/QuickTerminal/QuickTerminalWindow.swift b/macos/Sources/Features/QuickTerminal/QuickTerminalWindow.swift index 663f868f9..1a4170dbc 100644 --- a/macos/Sources/Features/QuickTerminal/QuickTerminalWindow.swift +++ b/macos/Sources/Features/QuickTerminal/QuickTerminalWindow.swift @@ -29,14 +29,19 @@ class QuickTerminalWindow: NSPanel { // We don't want to activate the owning app when quick terminal is triggered. self.styleMask.insert(.nonactivatingPanel) } + + /// This is set to the frame prior to setting `contentView`. This is purely a hack to workaround + /// bugs in older macOS versions (Ventura): https://github.com/ghostty-org/ghostty/pull/8026 var initialFrame: NSRect? = nil + override func setFrame(_ frameRect: NSRect, display flag: Bool) { // Upon first adding this Window to its host view, older SwiftUI // seems to have a "hiccup" and corrupts the frameRect, // sometimes setting the size to zero, sometimes corrupting it. // If we find we have cached the "initial" frame, use that instead - // the propagated one throught the framework + // the propagated one through the framework + // + // https://github.com/ghostty-org/ghostty/pull/8026 super.setFrame(initialFrame ?? frameRect, display: flag) } - }