From a0a71544f4b3589a8740455cc9b286825d1d2b6f Mon Sep 17 00:00:00 2001 From: Tamil Iniyan Date: Mon, 10 Aug 2026 14:19:08 +0530 Subject: [PATCH] Fix text injection landing nowhere: post to cgAnnotatedSessionEventTap TextInjector posted synthetic keystrokes to .cgSessionEventTap, the same event-pipeline location HotkeyMonitor installs its listen-only tap at (.headInsertEventTap on .cgSessionEventTap). The synthetic keyDown/keyUp events collided with that tap and were silently dropped before reaching the focused application - transcription and the fn-hotkey worked fine, but nothing ever got typed anywhere. Confirmed empirically with a standalone harness posting the same event via all three CGEventTapLocation options: cghidEventTap and cgSessionEventTap both no-op, cgAnnotatedSessionEventTap reliably lands in the focused text field. Related upstream: digimata/parrot#13, digimata/parrot#17 --- Sources/parrot/Input/TextInjector.swift | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Sources/parrot/Input/TextInjector.swift b/Sources/parrot/Input/TextInjector.swift index dc6f790b..8b6a559f 100644 --- a/Sources/parrot/Input/TextInjector.swift +++ b/Sources/parrot/Input/TextInjector.swift @@ -28,12 +28,20 @@ enum TextInjector { let length = chunk.count guard length > 0 else { return } + // NOTE: posting to `.cgSessionEventTap` collides with HotkeyMonitor's + // own listen-only tap, which is installed at `.headInsertEventTap` on + // that same `.cgSessionEventTap` location — the synthetic keystrokes + // get silently swallowed before reaching the focused app. Posting to + // `.cgAnnotatedSessionEventTap` (further down the pipeline, past that + // tap) delivers reliably. Confirmed empirically: cghidEventTap and + // cgSessionEventTap both silently no-op here; cgAnnotatedSessionEventTap + // lands in the focused text field every time. let down = CGEvent(keyboardEventSource: nil, virtualKey: 0, keyDown: true) down?.keyboardSetUnicodeString(stringLength: length, unicodeString: &chunk) - down?.post(tap: .cgSessionEventTap) + down?.post(tap: .cgAnnotatedSessionEventTap) let up = CGEvent(keyboardEventSource: nil, virtualKey: 0, keyDown: false) up?.keyboardSetUnicodeString(stringLength: length, unicodeString: &chunk) - up?.post(tap: .cgSessionEventTap) + up?.post(tap: .cgAnnotatedSessionEventTap) } }