fix: support keyboard shortcuts with CJK input sources (Korean, Chinese, Japanese) (#1649)

When a non-Latin input source is active, event.charactersIgnoringModifiers
returns CJK characters that cannot match Latin shortcut keys. This adds
ASCII-capable input source fallback in KeyboardLayout and updates the
matchShortcut guard to skip early-return when event chars are non-ASCII.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
이수민 2026-03-20 18:47:19 +09:00 committed by GitHub
parent 22689d5e0d
commit 8b49d66763
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 3 deletions

View file

@ -15,12 +15,31 @@ class KeyboardLayout {
/// Translate a physical keyCode to the character AppKit would use for shortcut matching,
/// preserving command-aware layouts such as "Dvorak - QWERTY Command".
/// CJK input sources (Korean, Chinese, Japanese) lack kTISPropertyUnicodeKeyLayoutData,
/// so we fall back to TISCopyCurrentASCIICapableKeyboardInputSource() in that case.
static func character(
forKeyCode keyCode: UInt16,
modifierFlags: NSEvent.ModifierFlags = []
) -> String? {
guard let source = TISCopyCurrentKeyboardInputSource()?.takeRetainedValue(),
let layoutDataPointer = TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData) else {
if let source = TISCopyCurrentKeyboardInputSource()?.takeRetainedValue(),
let result = characterFromInputSource(source, forKeyCode: keyCode, modifierFlags: modifierFlags) {
return result
}
// Current input source has no Unicode layout data (e.g. Korean, Chinese, Japanese IME).
// Fall back to the ASCII-capable source so shortcut matching still works.
if let asciiSource = TISCopyCurrentASCIICapableKeyboardInputSource()?.takeRetainedValue(),
let result = characterFromInputSource(asciiSource, forKeyCode: keyCode, modifierFlags: modifierFlags) {
return result
}
return nil
}
private static func characterFromInputSource(
_ source: TISInputSource,
forKeyCode keyCode: UInt16,
modifierFlags: NSEvent.ModifierFlags
) -> String? {
guard let layoutDataPointer = TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData) else {
return nil
}