From 28572702bfc77f799ccb5eddd3ae5982f402f042 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 30 Sep 2022 17:25:57 -0700 Subject: [PATCH] Properly backspace over text that was entered when autocorrect updates text with the iPhone on-screen keyboard --- Android.mk | 0 src/video/uikit/SDL_uikitviewcontroller.m | 51 ++++++++++++++--------- 2 files changed, 31 insertions(+), 20 deletions(-) mode change 100644 => 100755 Android.mk diff --git a/Android.mk b/Android.mk old mode 100644 new mode 100755 diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index d0dd863f6..4aa2d287e 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -75,7 +75,7 @@ SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *o BOOL hardwareKeyboard; BOOL showingKeyboard; BOOL rotatingOrientation; - NSString *changeText; + NSString *committedText; NSString *obligateForBackspace; #endif } @@ -263,12 +263,12 @@ SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *o /* Set ourselves up as a UITextFieldDelegate */ - (void)initKeyboard { - changeText = nil; obligateForBackspace = @" "; /* 64 space */ textField = [[UITextField alloc] initWithFrame:CGRectZero]; textField.delegate = self; /* placeholder so there is something to delete! */ textField.text = obligateForBackspace; + committedText = textField.text; /* set UITextInputTrait properties, mostly to defaults */ textField.autocapitalizationType = UITextAutocapitalizationTypeNone; @@ -408,21 +408,39 @@ SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *o - (void)textFieldTextDidChange:(NSNotification *)notification { - if (changeText!=nil && textField.markedTextRange == nil) - { - NSUInteger len = changeText.length; - if (len > 0) { + if (textField.markedTextRange == nil) { + NSUInteger compareLength = SDL_min(textField.text.length, committedText.length); + NSUInteger matchLength; + + /* Backspace over characters that are no longer in the string */ + for (matchLength = 0; matchLength < compareLength; ++matchLength) { + if ([committedText characterAtIndex:matchLength] != [textField.text characterAtIndex:matchLength]) { + break; + } + } + if (matchLength < committedText.length) { + size_t deleteLength = SDL_utf8strlen([[committedText substringFromIndex:matchLength] UTF8String]); + while (deleteLength > 0) { + /* Send distinct down and up events for each backspace action */ + SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_BACKSPACE); + SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_BACKSPACE); + --deleteLength; + } + } + + if (matchLength < textField.text.length) { + NSString *pendingText = [textField.text substringFromIndex:matchLength]; if (!SDL_HardwareKeyboardKeyPressed()) { /* Go through all the characters in the string we've been sent and * convert them to key presses */ - int i; - for (i = 0; i < len; i++) { - SDL_SendKeyboardUnicodeKey([changeText characterAtIndex:i]); + NSUInteger i; + for (i = 0; i < pendingText.length; i++) { + SDL_SendKeyboardUnicodeKey([pendingText characterAtIndex:i]); } } - SDL_SendKeyboardText([changeText UTF8String]); + SDL_SendKeyboardText([pendingText UTF8String]); } - changeText = nil; + committedText = textField.text; } } @@ -463,18 +481,11 @@ SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *o /* UITextFieldDelegate method. Invoked when user types something. */ - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { - NSUInteger len = string.length; - if (len == 0) { - changeText = nil; - if (textField.markedTextRange == nil) { - /* it wants to replace text with nothing, ie a delete */ - SDL_SendKeyboardKeyAutoRelease(SDL_SCANCODE_BACKSPACE); - } + if (textField.markedTextRange == nil) { if (textField.text.length < 16) { textField.text = obligateForBackspace; + committedText = textField.text; } - } else { - changeText = string; } return YES; }