import Cocoa import ApplicationServices import CoreGraphics public struct MacInputState: Codable { public let source: String public let app: String public let text: String public let cursor: Int public let selection: Int public let revision: Int64 public let timestamp: Double public init(app: String, text: String, cursor: Int, selection: Int, revision: Int64) { self.source = "mac" self.app = app self.text = text self.cursor = cursor self.selection = selection self.revision = revision self.timestamp = Date().timeIntervalSince1970 } } public final class FocusedInputSync { public static let shared = FocusedInputSync() private let systemWideElement: AXUIElement private var isApplyingRemoteChange: Bool = false private var lastObservedText: String = "" private var lastObservedCursor: Int = -1 private var lastObservedApp: String = "" private var localRevision: Int64 = 0 private var remoteChangeExpiryTime: Double = 0 private init() { self.systemWideElement = AXUIElementCreateSystemWide() enableGlobalAccessibility() } private func enableGlobalAccessibility() { AXUIElementSetAttributeValue(systemWideElement, "AXEnhancedUserInterface" as CFString, kCFBooleanTrue) AXUIElementSetAttributeValue(systemWideElement, "AXManualAccessibility" as CFString, kCFBooleanTrue) } /// Resolves the actual user-facing application, bypassing system overlays public func getRealFrontmostApp() -> NSRunningApplication? { if let front = NSWorkspace.shared.frontmostApplication, front.activationPolicy == .regular, let bundleId = front.bundleIdentifier, !bundleId.contains("notificationcenter"), !bundleId.contains("controlcenter"), !bundleId.contains("WindowManager"), !bundleId.contains("Soniox") { return front } let windowList = CGWindowListCopyWindowInfo([.optionOnScreenOnly, .excludeDesktopElements], kCGNullWindowID) as? [[String: Any]] ?? [] for win in windowList { let layer = win[kCGWindowLayer as String] as? Int ?? -1 let pid = win[kCGWindowOwnerPID as String] as? pid_t ?? 0 let bounds = win[kCGWindowBounds as String] as? [String: Any] ?? [:] let width = bounds["Width"] as? CGFloat ?? 0 let height = bounds["Height"] as? CGFloat ?? 0 if layer == 0 && width > 100 && height > 100 { if let app = NSRunningApplication(processIdentifier: pid), app.activationPolicy == .regular, let bundleId = app.bundleIdentifier, !bundleId.contains("notificationcenter"), !bundleId.contains("controlcenter"), !bundleId.contains("WindowManager"), !bundleId.contains("Soniox") { return app } } } return NSWorkspace.shared.frontmostApplication } private func findFocusedDescendant(_ elem: AXUIElement, depth: Int = 0) -> AXUIElement? { if depth > 12 { return nil } var isFocusedObj: CFTypeRef? if AXUIElementCopyAttributeValue(elem, kAXFocusedAttribute as CFString, &isFocusedObj) == .success, let isFocused = isFocusedObj as? Bool, isFocused { var roleObj: CFTypeRef? AXUIElementCopyAttributeValue(elem, kAXRoleAttribute as CFString, &roleObj) let role = (roleObj as? String) ?? "" if role != "AXWindow" && role != "AXApplication" && role != "AXGroup" && role != "AXSplitGroup" && role != "AXScrollArea" { return elem } } var childrenObj: CFTypeRef? if AXUIElementCopyAttributeValue(elem, kAXChildrenAttribute as CFString, &childrenObj) == .success, let children = childrenObj as? [AXUIElement] { for child in children { if let found = findFocusedDescendant(child, depth: depth + 1) { return found } } } return nil } public func getFocusedElement() -> (AXUIElement?, String) { guard let frontApp = getRealFrontmostApp() else { return (nil, "App") } let appName = frontApp.localizedName ?? "App" let appElem = AXUIElementCreateApplication(frontApp.processIdentifier) AXUIElementSetAttributeValue(appElem, "AXEnhancedUserInterface" as CFString, kCFBooleanTrue) AXUIElementSetAttributeValue(appElem, "AXManualAccessibility" as CFString, kCFBooleanTrue) var targetElem: AXUIElement? // 1. System-wide focused element var focusedObj: CFTypeRef? if AXUIElementCopyAttributeValue(systemWideElement, kAXFocusedUIElementAttribute as CFString, &focusedObj) == .success, let obj = focusedObj { let elem = obj as! AXUIElement var roleObj: CFTypeRef? AXUIElementCopyAttributeValue(elem, kAXRoleAttribute as CFString, &roleObj) let role = (roleObj as? String) ?? "" if role != "AXWindow" && role != "AXApplication" { targetElem = elem } } // 2. App focused element if targetElem == nil { if AXUIElementCopyAttributeValue(appElem, kAXFocusedUIElementAttribute as CFString, &focusedObj) == .success, let obj = focusedObj { let elem = obj as! AXUIElement var roleObj: CFTypeRef? AXUIElementCopyAttributeValue(elem, kAXRoleAttribute as CFString, &roleObj) let role = (roleObj as? String) ?? "" if role != "AXWindow" && role != "AXApplication" { targetElem = elem } } } // 3. App focused window element if targetElem == nil { var focusedWinObj: CFTypeRef? if AXUIElementCopyAttributeValue(appElem, kAXFocusedWindowAttribute as CFString, &focusedWinObj) == .success, let win = focusedWinObj { var winFocObj: CFTypeRef? if AXUIElementCopyAttributeValue((win as! AXUIElement), kAXFocusedUIElementAttribute as CFString, &winFocObj) == .success, let obj = winFocObj { targetElem = (obj as! AXUIElement) } } } // 4. Recursive search in tree if targetElem == nil { targetElem = findFocusedDescendant(appElem) } return (targetElem, appName) } /// Inspects current focused element on Mac and returns state snapshot if user typed on Mac public func inspectCurrentState() -> MacInputState? { let now = Date().timeIntervalSince1970 if isApplyingRemoteChange || now < remoteChangeExpiryTime { return nil } let (elemOpt, appName) = getFocusedElement() let appChanged = (appName != lastObservedApp) if appChanged { lastObservedApp = appName } guard let elem = elemOpt else { if appChanged && !lastObservedText.isEmpty { localRevision += 1 return MacInputState(app: appName, text: lastObservedText, cursor: lastObservedCursor, selection: 0, revision: localRevision) } return nil } var roleObj: CFTypeRef? AXUIElementCopyAttributeValue(elem, kAXRoleAttribute as CFString, &roleObj) let role = roleObj as? String ?? "" let isTextRole = (role == "AXTextField" || role == "AXTextArea" || role == "AXComboBox" || role == "AXSearchField") var text = "" var valObj: CFTypeRef? if AXUIElementCopyAttributeValue(elem, kAXValueAttribute as CFString, &valObj) == .success, let val = valObj { if let str = val as? String { text = str } else if let attrStr = val as? NSAttributedString { text = attrStr.string } } if text.isEmpty && isTextRole { var countObj: CFTypeRef? if AXUIElementCopyAttributeValue(elem, kAXNumberOfCharactersAttribute as CFString, &countObj) == .success, let count = countObj as? Int, count > 0 { var range = CFRange(location: 0, length: count) if let axRange = AXValueCreate(.cfRange, &range) { var strObj: CFTypeRef? if AXUIElementCopyParameterizedAttributeValue(elem, kAXStringForRangeParameterizedAttribute as CFString, axRange, &strObj) == .success, let str = strObj as? String { text = str } } } } // Ghost empty suppression for non-native containers if text.isEmpty && !lastObservedText.isEmpty && !isTextRole { return nil } var cursor = text.count var selLen = 0 var rangeObj: CFTypeRef? if AXUIElementCopyAttributeValue(elem, kAXSelectedTextRangeAttribute as CFString, &rangeObj) == .success, let axRange = rangeObj { var range = CFRange() if AXValueGetValue(axRange as! AXValue, .cfRange, &range) { cursor = range.location selLen = range.length } } if text == lastObservedText && cursor == lastObservedCursor && !appChanged { return nil } lastObservedText = text lastObservedCursor = cursor lastObservedApp = appName localRevision += 1 return MacInputState(app: appName, text: text, cursor: cursor, selection: selLen, revision: localRevision) } /// Perfectly mirrors the full text to the active Mac input box in real-time @discardableResult public func applyRemoteUpdate(text: String, cursor: Int? = nil, isFullReplace: Bool = true) -> Bool { isApplyingRemoteChange = true remoteChangeExpiryTime = Date().timeIntervalSince1970 + 0.25 defer { DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { self.isApplyingRemoteChange = false } } // Normalize line endings and preserve intentional multiline text (\n) var cleanText = text.replacingOccurrences(of: "\r\n", with: "\n").replacingOccurrences(of: "\r", with: "\n") cleanText = cleanText.trimmingCharacters(in: .whitespacesAndNewlines) let targetCursor = cursor ?? cleanText.count lastObservedText = cleanText lastObservedCursor = targetCursor let (_, appName) = getFocusedElement() lastObservedApp = appName // Universal Quartz CGEvent Keystroke Engine (Cmd+A -> Cmd+V / Backspace or pure Cmd+V) // Works 100% reliably across native, web, and Electron/Chromium apps (e.g. Antigravity, VS Code, Slack, Firefox) print("FocusedInputSync: 🚀 Injecting text into '\(appName)' (replace: \(isFullReplace), len: \(cleanText.count), lines: \(cleanText.components(separatedBy: "\n").count))") if isFullReplace { return executeCleanFullReplace(cleanText) } else { return pasteOnlyViaCleanKeystroke(cleanText) } } /** * Inserts speech directly at active cursor via clean Cmd+V */ private func pasteOnlyViaCleanKeystroke(_ text: String) -> Bool { guard !text.isEmpty else { return true } let pasteboard = NSPasteboard.general pasteboard.clearContents() pasteboard.setString(text, forType: .string) let src = CGEventSource(stateID: .hidSystemState) let kVK_ANSI_V: CGKeyCode = 9 // Paste: Cmd + V if let vDown = CGEvent(keyboardEventSource: src, virtualKey: kVK_ANSI_V, keyDown: true) { vDown.flags = .maskCommand vDown.post(tap: .cghidEventTap) vDown.post(tap: .cgSessionEventTap) } usleep(12000) if let vUp = CGEvent(keyboardEventSource: src, virtualKey: kVK_ANSI_V, keyDown: false) { vUp.flags = .maskCommand vUp.post(tap: .cghidEventTap) vUp.post(tap: .cgSessionEventTap) } usleep(10000) return true } /** * Replaces the entire content of active input box cleanly in real-time. * If text is empty: Cmd+A -> Backspace. * If text is non-empty: Cmd+A -> Cmd+V. */ private func executeCleanFullReplace(_ text: String) -> Bool { let src = CGEventSource(stateID: .hidSystemState) let kVK_ANSI_A: CGKeyCode = 0 let kVK_ANSI_V: CGKeyCode = 9 let kVK_Delete: CGKeyCode = 51 if text.isEmpty { // Select all: Cmd + A if let aDown = CGEvent(keyboardEventSource: src, virtualKey: kVK_ANSI_A, keyDown: true) { aDown.flags = .maskCommand aDown.post(tap: .cghidEventTap) aDown.post(tap: .cgSessionEventTap) } usleep(8000) if let aUp = CGEvent(keyboardEventSource: src, virtualKey: kVK_ANSI_A, keyDown: false) { aUp.flags = .maskCommand aUp.post(tap: .cghidEventTap) aUp.post(tap: .cgSessionEventTap) } usleep(15000) // Backspace to clear if let delDown = CGEvent(keyboardEventSource: src, virtualKey: kVK_Delete, keyDown: true) { delDown.post(tap: .cghidEventTap) delDown.post(tap: .cgSessionEventTap) } usleep(8000) if let delUp = CGEvent(keyboardEventSource: src, virtualKey: kVK_Delete, keyDown: false) { delUp.post(tap: .cghidEventTap) delUp.post(tap: .cgSessionEventTap) } return true } // Set clipboard let pasteboard = NSPasteboard.general pasteboard.clearContents() pasteboard.setString(text, forType: .string) // 1. Select all: Cmd + A if let aDown = CGEvent(keyboardEventSource: src, virtualKey: kVK_ANSI_A, keyDown: true) { aDown.flags = .maskCommand aDown.post(tap: .cghidEventTap) aDown.post(tap: .cgSessionEventTap) } usleep(8000) if let aUp = CGEvent(keyboardEventSource: src, virtualKey: kVK_ANSI_A, keyDown: false) { aUp.flags = .maskCommand aUp.post(tap: .cghidEventTap) aUp.post(tap: .cgSessionEventTap) } usleep(18000) // 18ms for selection to settle // 2. Paste: Cmd + V if let vDown = CGEvent(keyboardEventSource: src, virtualKey: kVK_ANSI_V, keyDown: true) { vDown.flags = .maskCommand vDown.post(tap: .cghidEventTap) vDown.post(tap: .cgSessionEventTap) } usleep(12000) if let vUp = CGEvent(keyboardEventSource: src, virtualKey: kVK_ANSI_V, keyDown: false) { vUp.flags = .maskCommand vUp.post(tap: .cghidEventTap) vUp.post(tap: .cgSessionEventTap) } return true } }