diff --git a/macos/Ghostty.xcodeproj/project.pbxproj b/macos/Ghostty.xcodeproj/project.pbxproj index 77e95db04..55d973db6 100644 --- a/macos/Ghostty.xcodeproj/project.pbxproj +++ b/macos/Ghostty.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ A5CEAFFF29C2410700646FDA /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CEAFFE29C2410700646FDA /* Backport.swift */; }; A5D495A2299BEC7E00DD1313 /* GhosttyKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5D495A1299BEC7E00DD1313 /* GhosttyKit.xcframework */; }; A5FECBD729D1FC3900022361 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FECBD629D1FC3900022361 /* ContentView.swift */; }; + A5FECBD929D2010400022361 /* WindowAccessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FECBD829D2010400022361 /* WindowAccessor.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -40,6 +41,7 @@ A5CEAFFE29C2410700646FDA /* Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Backport.swift; sourceTree = ""; }; A5D495A1299BEC7E00DD1313 /* GhosttyKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = GhosttyKit.xcframework; sourceTree = ""; }; A5FECBD629D1FC3900022361 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + A5FECBD829D2010400022361 /* WindowAccessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowAccessor.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -66,6 +68,7 @@ A59444F629A2ED5200725BBA /* SettingsView.swift */, A5CEAFFE29C2410700646FDA /* Backport.swift */, A5FECBD629D1FC3900022361 /* ContentView.swift */, + A5FECBD829D2010400022361 /* WindowAccessor.swift */, ); path = Sources; sourceTree = ""; @@ -201,6 +204,7 @@ A55B7BB629B6F47F0055DE60 /* AppState.swift in Sources */, A5CEAFDC29B8009000646FDA /* SplitView.swift in Sources */, A55685E029A03A9F004303CE /* AppError.swift in Sources */, + A5FECBD929D2010400022361 /* WindowAccessor.swift in Sources */, A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */, A5B30535299BEAAA0047F10C /* GhosttyApp.swift in Sources */, A5CEAFFF29C2410700646FDA /* Backport.swift in Sources */, diff --git a/macos/Sources/ContentView.swift b/macos/Sources/ContentView.swift index 387ab948d..afe833a13 100644 --- a/macos/Sources/ContentView.swift +++ b/macos/Sources/ContentView.swift @@ -4,8 +4,13 @@ import GhosttyKit struct ContentView: View { let ghostty: Ghostty.AppState + // We need access to our app delegate to know if we're quitting or not. @EnvironmentObject private var appDelegate: AppDelegate + // We need access to our window to know if we're the key window to determine + // if we show the quit confirmation or not. + @State private var window: NSWindow? + var body: some View { switch ghostty.readiness { case .loading: @@ -21,11 +26,18 @@ struct ContentView: View { NSApplication.shared.reply(toApplicationShouldTerminate: true) } case .ready: + let confirmQuitting = Binding(get: { + self.appDelegate.confirmQuit && (self.window?.isKeyWindow ?? false) + }, set: { + self.appDelegate.confirmQuit = $0 + }) + Ghostty.TerminalSplit(onClose: Self.closeWindow) .ghosttyApp(ghostty.app!) + .background(WindowAccessor(window: $window)) .confirmationDialog( "Quit Ghostty?", - isPresented: $appDelegate.confirmQuit) { + isPresented: confirmQuitting) { Button("Close Ghostty", role: .destructive) { NSApplication.shared.reply(toApplicationShouldTerminate: true) } diff --git a/macos/Sources/WindowAccessor.swift b/macos/Sources/WindowAccessor.swift new file mode 100644 index 000000000..f12e841bd --- /dev/null +++ b/macos/Sources/WindowAccessor.swift @@ -0,0 +1,16 @@ +import SwiftUI + +/// Allows accessing the window that this view is a part of. +struct WindowAccessor: NSViewRepresentable { + @Binding var window: NSWindow? + + func makeNSView(context: Context) -> NSView { + let view = NSView() + DispatchQueue.main.async { + self.window = view.window + } + return view + } + + func updateNSView(_ nsView: NSView, context: Context) {} +}