From 111dc85afca8014caed5b4dd0fb965e51fb408b1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 26 Jul 2024 09:22:38 -0700 Subject: [PATCH] Don't send keys consumed by the IME on macOS This makes the macOS behavior match other platforms where the IME eats keys that are used for composing text. --- src/video/cocoa/SDL_cocoakeyboard.m | 53 ++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/src/video/cocoa/SDL_cocoakeyboard.m b/src/video/cocoa/SDL_cocoakeyboard.m index f7fd6f1f3b04b..685d6752df7e7 100644 --- a/src/video/cocoa/SDL_cocoakeyboard.m +++ b/src/video/cocoa/SDL_cocoakeyboard.m @@ -39,9 +39,15 @@ @interface SDL3TranslatorResponder : NSView NSRange _markedRange; NSRange _selectedRange; SDL_Rect _inputRect; + int _pendingRawCode; + SDL_Scancode _pendingScancode; + Uint64 _pendingTimestamp; } - (void)doCommandBySelector:(SEL)myselector; - (void)setInputRect:(const SDL_Rect *)rect; +- (void)setPendingKey:(int)rawcode scancode:(SDL_Scancode)scancode timestamp:(Uint64)timestamp; +- (void)sendPendingKey; +- (void)clearPendingKey; @end @implementation SDL3TranslatorResponder @@ -72,6 +78,9 @@ - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange [self unmarkText]; } + // Deliver the raw key event that generated this text + [self sendPendingKey]; + SDL_SendKeyboardText(str); } @@ -116,6 +125,9 @@ - (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replaceme _selectedRange = selectedRange; _markedRange = NSMakeRange(0, [aString length]); + // This key event was consumed by the IME + [self clearPendingKey]; + SDL_SendEditingText([aString UTF8String], (int)selectedRange.location, (int)selectedRange.length); @@ -127,6 +139,9 @@ - (void)unmarkText { _markedText = nil; + // This key event was consumed by the IME + [self clearPendingKey]; + SDL_SendEditingText("", 0, 0); } @@ -181,6 +196,28 @@ - (NSArray *)validAttributesForMarkedText return [NSArray array]; } +- (void)setPendingKey:(int)rawcode scancode:(SDL_Scancode)scancode timestamp:(Uint64)timestamp +{ + _pendingRawCode = rawcode; + _pendingScancode = scancode; + _pendingTimestamp = timestamp; +} + +- (void)sendPendingKey; +{ + if (_pendingRawCode < 0) { + return; + } + + SDL_SendKeyboardKey(_pendingTimestamp, SDL_DEFAULT_KEYBOARD_ID, _pendingRawCode, _pendingScancode, SDL_PRESSED); + [self clearPendingKey]; +} + +- (void)clearPendingKey; +{ + _pendingRawCode = -1; +} + @end static bool IsModifierKeyPressed(unsigned int flags, @@ -404,9 +441,6 @@ void Cocoa_HandleKeyEvent(SDL_VideoDevice *_this, NSEvent *event) } scancode = [event keyCode]; -#if 0 - const char *text; -#endif if ((scancode == 10 || scancode == 50) && KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) { /* see comments in scancodes_darwin.h */ @@ -427,22 +461,17 @@ void Cocoa_HandleKeyEvent(SDL_VideoDevice *_this, NSEvent *event) UpdateKeymap(data, SDL_TRUE); } - SDL_SendKeyboardKey(Cocoa_GetEventTimestamp([event timestamp]), SDL_DEFAULT_KEYBOARD_ID, scancode, code, SDL_PRESSED); #ifdef DEBUG_SCANCODES if (code == SDL_SCANCODE_UNKNOWN) { SDL_Log("The key you just pressed is not recognized by SDL. To help get this fixed, report this to the SDL forums/mailing list or to Christian Walther . Mac virtual key code is %d.\n", scancode); } #endif if (SDL_TextInputActive(SDL_GetKeyboardFocus())) { - /* FIXME CW 2007-08-16: only send those events to the field editor for which we actually want text events, not e.g. esc or function keys. Arrow keys in particular seem to produce crashes sometimes. */ + [data.fieldEdit setPendingKey:scancode scancode:code timestamp:Cocoa_GetEventTimestamp([event timestamp])]; [data.fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]]; -#if 0 - text = [[event characters] UTF8String]; - if(text && *text) { - SDL_SendKeyboardText(text); - [data->fieldEdit setString:@""]; - } -#endif + [data.fieldEdit sendPendingKey]; + } else { + SDL_SendKeyboardKey(Cocoa_GetEventTimestamp([event timestamp]), SDL_DEFAULT_KEYBOARD_ID, scancode, code, SDL_PRESSED); } break; case NSEventTypeKeyUp: