diff --git a/Sources/Fluid/Services/TypingService.swift b/Sources/Fluid/Services/TypingService.swift index 259c9a05..22e4a58c 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,36 @@ final class TypingService { return Self.isCurrentlyFocusedElement(element, expectedPID: pid) } + private func isGhosttyApplication(pid: pid_t) -> Bool { + guard pid > 0, + let app = NSRunningApplication(processIdentifier: pid) + else { + return false + } + + 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 { @@ -341,6 +372,17 @@ 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, + 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 + } + 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) {