Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion resources/macos-fast-paste.swift
Original file line number Diff line number Diff line change
@@ -1,14 +1,54 @@
import Cocoa
import Carbon

if !AXIsProcessTrusted() {
exit(2)
}

// Look up which key code produces a given character in the current keyboard
// layout. Hardcoded key codes (0x09 for 'v', 0x08 for 'c') are only correct on
// QWERTY, so Cmd+V / Cmd+C land on the wrong key on Dvorak, Colemak, etc.
func keyCodeForCharacter(_ target: UniChar) -> CGKeyCode? {
guard let sourceRef = TISCopyCurrentKeyboardLayoutInputSource()?.takeRetainedValue(),
let layoutDataRef = TISGetInputSourceProperty(sourceRef, kTISPropertyUnicodeKeyLayoutData) else {
return nil
}
let layoutData = unsafeBitCast(layoutDataRef, to: CFData.self)
let keyLayout = unsafeBitCast(CFDataGetBytePtr(layoutData), to: UnsafePointer<UCKeyboardLayout>.self)

for keyCode: UInt16 in 0..<128 {
var deadKeyState: UInt32 = 0
var chars = [UniChar](repeating: 0, count: 4)
var length = 0

let status = UCKeyTranslate(
keyLayout,
keyCode,
UInt16(kUCKeyActionDown),
0,
UInt32(LMGetKbdType()),
UInt32(kUCKeyTranslateNoDeadKeysBit),
&deadKeyState,
4,
&length,
&chars
)

if status == noErr && length > 0 && chars[0] == target {
return CGKeyCode(keyCode)
}
}
return nil
}

// Selection capture sends ⌘C and reports which app received it, so the caller
// can tell a copied selection from a target that changed underneath it. With no
// arguments this stays what the paste path expects: ⌘V, no output.
let copyMode = CommandLine.arguments.contains("--copy")
let virtualKey: CGKeyCode = copyMode ? 0x08 : 0x09 // kVK_ANSI_C : kVK_ANSI_V
// 0x0063 = 'c', 0x0076 = 'v'. Fall back to the QWERTY key code for the same
// mode if the layout lookup fails, never to the other mode's key.
let virtualKey: CGKeyCode = keyCodeForCharacter(copyMode ? 0x0063 : 0x0076)
?? (copyMode ? 0x08 : 0x09) // kVK_ANSI_C : kVK_ANSI_V

// Resolved before the keystroke is posted: this is the app that will receive it.
let target = copyMode ? NSWorkspace.shared.frontmostApplication : nil
Expand Down