diff --git a/macos/Ghostty.xcodeproj/project.pbxproj b/macos/Ghostty.xcodeproj/project.pbxproj index cdedbb5e1..e38e33c42 100644 --- a/macos/Ghostty.xcodeproj/project.pbxproj +++ b/macos/Ghostty.xcodeproj/project.pbxproj @@ -66,6 +66,7 @@ isa = PBXFileSystemSynchronizedBuildFileExceptionSet; membershipExceptions = ( App/macOS/AppDelegate.swift, + "App/macOS/AppDelegate+Ghostty.swift", App/macOS/main.swift, App/macOS/MainMenu.xib, Features/About/About.xib, diff --git a/macos/Sources/App/macOS/AppDelegate+Ghostty.swift b/macos/Sources/App/macOS/AppDelegate+Ghostty.swift new file mode 100644 index 000000000..7cc74ba7d --- /dev/null +++ b/macos/Sources/App/macOS/AppDelegate+Ghostty.swift @@ -0,0 +1,18 @@ +import AppKit + +extension AppDelegate: Ghostty.Delegate { + func ghosttySurface(id: UUID) -> Ghostty.SurfaceView? { + for window in NSApp.windows { + guard let controller = window.windowController as? BaseTerminalController else { + continue + } + for surface in controller.surfaceTree { + if surface.id == id { + return surface + } + } + } + + return nil + } +} diff --git a/macos/Sources/Ghostty/GhosttyDelegate.swift b/macos/Sources/Ghostty/GhosttyDelegate.swift new file mode 100644 index 000000000..0ce3dced4 --- /dev/null +++ b/macos/Sources/Ghostty/GhosttyDelegate.swift @@ -0,0 +1,8 @@ +extension Ghostty { + /// This is a delegate that should be applied to your global app delegate for GhosttyKit + /// to perform app-global operations. + protocol Delegate { + /// Look up a surface within the application by ID. + func ghosttySurface(id: UUID) -> SurfaceView? + } +} diff --git a/macos/Sources/Ghostty/Surface View/SurfaceView+Transferable.swift b/macos/Sources/Ghostty/Surface View/SurfaceView+Transferable.swift index da3050eae..d5d47f601 100644 --- a/macos/Sources/Ghostty/Surface View/SurfaceView+Transferable.swift +++ b/macos/Sources/Ghostty/Surface View/SurfaceView+Transferable.swift @@ -4,6 +4,7 @@ import AppKit import CoreTransferable import UniformTypeIdentifiers +/// Conformance to `Transferable` enables drag-and-drop. extension Ghostty.SurfaceView: Transferable { static var transferRepresentation: some TransferRepresentation { DataRepresentation(contentType: .ghosttySurfaceId) { surface in @@ -32,22 +33,19 @@ extension Ghostty.SurfaceView: Transferable { @MainActor static func find(uuid: UUID) -> Self? { #if canImport(AppKit) - for window in NSApp.windows { - guard let controller = window.windowController as? BaseTerminalController else { - continue - } - for surface in controller.surfaceTree { - if surface.id == uuid { - return surface as? Self - } - } - } - #endif - + guard let del = NSApp.delegate as? Ghostty.Delegate else { return nil } + return del.ghosttySurface(id: uuid) as? Self + #elseif canImport(UIKit) + // We should be able to use UIApplication here. return nil + #else + return nil + #endif } } extension UTType { + /// A format that encodes the bare UUID only for the surface. This can be used if you have + /// a way to look up a surface by ID. static let ghosttySurfaceId = UTType(exportedAs: "com.mitchellh.ghosttySurfaceId") }