From 4b1c0c8c509766cf3e36d6d771fc324b176397bd Mon Sep 17 00:00:00 2001 From: grohith327 Date: Tue, 30 Jun 2026 21:54:36 -0700 Subject: [PATCH 1/2] add fallback paste for ghostty --- Sources/Fluid/Services/TypingService.swift | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Sources/Fluid/Services/TypingService.swift b/Sources/Fluid/Services/TypingService.swift index 259c9a05..c7c8342d 100644 --- a/Sources/Fluid/Services/TypingService.swift +++ b/Sources/Fluid/Services/TypingService.swift @@ -54,6 +54,7 @@ final class TypingService { private static let pasteboardSessionSemaphore = DispatchSemaphore(value: 1) private static let pasteboardRestoreQueue = DispatchQueue(label: "TypingService.PasteboardRestore", qos: .utility) private static var focusSnapshot: FocusSnapshot? + private static let ghosttyBundleIdentifier = "com.mitchellh.ghostty" private var textInsertionMode: SettingsStore.TextInsertionMode { SettingsStore.shared.textInsertionMode @@ -224,6 +225,16 @@ final class TypingService { return Self.isCurrentlyFocusedElement(element, expectedPID: pid) } + private func isGhosttyTarget(preferredTargetPID: pid_t?) -> Bool { + guard let preferredTargetPID, preferredTargetPID > 0, + let app = NSRunningApplication(processIdentifier: preferredTargetPID) + else { + return false + } + + return app.bundleIdentifier == Self.ghosttyBundleIdentifier + } + /// Best-effort: activates the app with the given PID, unless it's Fluid itself. @discardableResult static func activateApp(pid: pid_t) -> Bool { @@ -341,6 +352,15 @@ final class TypingService { self.log("[TypingService] insertTextInstantly called with \(text.count) characters") self.log("[TypingService] Attempting to type text: \"\(text.prefix(50))\(text.count > 50 ? "..." : "")\"") + if self.textInsertionMode == .standard, self.isGhosttyTarget(preferredTargetPID: preferredTargetPID) { + self.log("[TypingService] Ghostty target detected in standard mode; forcing Reliable Paste path") + if self.tryReliablePasteInsertion(text, preferredTargetPID: preferredTargetPID) { + self.log("[TypingService] SUCCESS: Ghostty Reliable Paste path completed") + return + } + self.log("[TypingService] Ghostty Reliable Paste path fell through to direct-typing fallbacks") + } + if self.textInsertionMode == .reliablePaste { self.log("[TypingService] Reliable Paste mode enabled") if self.tryReliablePasteInsertion(text, preferredTargetPID: preferredTargetPID) { From 32ab04d7f6fc4ba383edbcfee69dc4c6e09bd97e Mon Sep 17 00:00:00 2001 From: grohith327 Date: Tue, 30 Jun 2026 23:06:57 -0700 Subject: [PATCH 2/2] add best effort extraction for ghostty pid --- Sources/Fluid/Services/TypingService.swift | 34 ++++++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/Sources/Fluid/Services/TypingService.swift b/Sources/Fluid/Services/TypingService.swift index c7c8342d..22e4a58c 100644 --- a/Sources/Fluid/Services/TypingService.swift +++ b/Sources/Fluid/Services/TypingService.swift @@ -225,9 +225,9 @@ final class TypingService { return Self.isCurrentlyFocusedElement(element, expectedPID: pid) } - private func isGhosttyTarget(preferredTargetPID: pid_t?) -> Bool { - guard let preferredTargetPID, preferredTargetPID > 0, - let app = NSRunningApplication(processIdentifier: preferredTargetPID) + private func isGhosttyApplication(pid: pid_t) -> Bool { + guard pid > 0, + let app = NSRunningApplication(processIdentifier: pid) else { return false } @@ -235,6 +235,26 @@ final class TypingService { return app.bundleIdentifier == Self.ghosttyBundleIdentifier } + private func ghosttyTargetPID(preferredTargetPID: pid_t?) -> pid_t? { + if let preferredTargetPID, preferredTargetPID > 0 { + return self.isGhosttyApplication(pid: preferredTargetPID) ? preferredTargetPID : nil + } + + if let focusedPID = self.getSystemFocusedElementAndPID()?.pid, + self.isGhosttyApplication(pid: focusedPID) + { + return focusedPID + } + + if let frontmostPID = NSWorkspace.shared.frontmostApplication?.processIdentifier, + self.isGhosttyApplication(pid: frontmostPID) + { + return frontmostPID + } + + return nil + } + /// Best-effort: activates the app with the given PID, unless it's Fluid itself. @discardableResult static func activateApp(pid: pid_t) -> Bool { @@ -352,9 +372,11 @@ final class TypingService { self.log("[TypingService] insertTextInstantly called with \(text.count) characters") self.log("[TypingService] Attempting to type text: \"\(text.prefix(50))\(text.count > 50 ? "..." : "")\"") - if self.textInsertionMode == .standard, self.isGhosttyTarget(preferredTargetPID: preferredTargetPID) { - self.log("[TypingService] Ghostty target detected in standard mode; forcing Reliable Paste path") - if self.tryReliablePasteInsertion(text, preferredTargetPID: preferredTargetPID) { + if self.textInsertionMode == .standard, + let ghosttyTargetPID = self.ghosttyTargetPID(preferredTargetPID: preferredTargetPID) + { + self.log("[TypingService] Ghostty target detected in standard mode (PID \(ghosttyTargetPID)); forcing Reliable Paste path") + if self.tryReliablePasteInsertion(text, preferredTargetPID: ghosttyTargetPID) { self.log("[TypingService] SUCCESS: Ghostty Reliable Paste path completed") return }