From 2e03e0305caf851e305a7d73af1efe4a4fdf693a Mon Sep 17 00:00:00 2001 From: der richter Date: Sun, 21 Apr 2024 17:02:36 +0200 Subject: [PATCH] mac/input: add support for dead key reporting dead keys like tilde and accents were not reported because they returned an empty string from the NSEvent. try to retrieve dead key with alternative Carbon API when an empty key is reported. --- osdep/mac/input_helper.swift | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/osdep/mac/input_helper.swift b/osdep/mac/input_helper.swift index 0e4ec1f55c7bf..e5268ade4c6a3 100644 --- a/osdep/mac/input_helper.swift +++ b/osdep/mac/input_helper.swift @@ -107,7 +107,9 @@ class InputHelper: NSObject { } guard let chars = event.characters, let charsNoMod = event.charactersIgnoringModifiers else { return false } - let key = (useAltGr() && event.modifierFlags.contains(.optionRight)) ? chars : charsNoMod + var key = (useAltGr() && event.modifierFlags.contains(.optionRight)) ? chars : charsNoMod + if key.isEmpty { key = mapDeadKey(event) } + if key.isEmpty { return false } key.withCString { var bstr = bstr0($0) putKey(bstr_decode_utf8(bstr, &bstr), modifiers: event.modifierFlags, type: event.type) @@ -230,6 +232,23 @@ class InputHelper: NSObject { return Int32(buttonMapping[button] ?? SWIFT_MBTN9 + Int32(button - 5)); } + func mapDeadKey(_ event: NSEvent) -> String { + let keyboard = TISCopyCurrentKeyboardInputSource().takeRetainedValue() + let layoutPtr = TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData) + let layoutData = unsafeBitCast(layoutPtr, to: CFData.self) + let layout = unsafeBitCast(CFDataGetBytePtr(layoutData), to: UnsafePointer.self) + let maxLength = 2 + let modifiers: UInt32 = UInt32(event.modifierFlags.rawValue >> 16) & 0xff + var deadKeyState: UInt32 = 0 + var length = 0 + var chars = [UniChar](repeating: 0, count: maxLength) + let err = UCKeyTranslate(layout, event.keyCode, UInt16(kUCKeyActionDisplay), modifiers, + UInt32(LMGetKbdType()), 0, &deadKeyState, maxLength, &length, &chars) + + if err != noErr || length < 1 { return "" } + return String(utf16CodeUnits: chars, count: length) + } + @objc func open(files: [String], append: Bool = false) { lock.withLock { guard let input = input else { return }