@@ -15,25 +15,41 @@ class KeyboardLayout {
1515
1616 /// Translate a physical keyCode to the character AppKit would use for shortcut matching,
1717 /// preserving command-aware layouts such as "Dvorak - QWERTY Command".
18- /// CJK input sources (Korean, Chinese, Japanese) lack kTISPropertyUnicodeKeyLayoutData,
19- /// so we fall back to TISCopyCurrentASCIICapableKeyboardInputSource() in that case.
18+ /// Some CJK input sources lack kTISPropertyUnicodeKeyLayoutData, and others (Korean
19+ /// 두벌식) have it but UCKeyTranslate still returns non-ASCII characters. In either
20+ /// case we fall back to TISCopyCurrentASCIICapableKeyboardInputSource().
2021 static func character(
2122 forKeyCode keyCode: UInt16 ,
2223 modifierFlags: NSEvent . ModifierFlags = [ ]
2324 ) -> String ? {
2425 if let source = TISCopyCurrentKeyboardInputSource ( ) ? . takeRetainedValue ( ) ,
25- let result = characterFromInputSource ( source, forKeyCode: keyCode, modifierFlags: modifierFlags) {
26+ let result = characterFromInputSource ( source, forKeyCode: keyCode, modifierFlags: modifierFlags) ,
27+ result. allSatisfy ( \. isASCII) {
2628 return result
2729 }
28- // Current input source has no Unicode layout data (e.g. Korean, Chinese, Japanese IME).
29- // Fall back to the ASCII-capable source so shortcut matching still works.
30+ // Current input source has no Unicode layout data or returned a non-ASCII
31+ // character (e.g. Korean 두벌식 has layout data but UCKeyTranslate still
32+ // produces Hangul). Fall back to the ASCII-capable source so shortcut
33+ // matching still works.
3034 if let asciiSource = TISCopyCurrentASCIICapableKeyboardInputSource ( ) ? . takeRetainedValue ( ) ,
3135 let result = characterFromInputSource ( asciiSource, forKeyCode: keyCode, modifierFlags: modifierFlags) {
3236 return result
3337 }
3438 return nil
3539 }
3640
41+ /// Return the ASCII-normalized equivalent of `event.charactersIgnoringModifiers`,
42+ /// falling back through the ASCII-capable input source for non-Latin input methods.
43+ /// Use this wherever code compares raw event characters against Latin shortcut keys.
44+ static func normalizedCharacters( for event: NSEvent ) -> String {
45+ let raw = ( event. charactersIgnoringModifiers ?? " " ) . lowercased ( )
46+ if raw. allSatisfy ( \. isASCII) { return raw }
47+ if let layoutChar = character ( forKeyCode: event. keyCode, modifierFlags: [ ] ) {
48+ return layoutChar
49+ }
50+ return raw
51+ }
52+
3753 private static func characterFromInputSource(
3854 _ source: TISInputSource ,
3955 forKeyCode keyCode: UInt16 ,
0 commit comments