From 113c7e8a5801c54dd17f9caedd6712929f7cfbd2 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 14 Sep 2025 08:06:24 -0700 Subject: [PATCH] Fixed delayed text entry for OTP codes on iOS (thanks @pipiwoaini!) Fixes https://github.com/libsdl-org/SDL/issues/13717 --- src/video/uikit/SDL_uikitviewcontroller.m | 33 ++++++++++++----------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index c5b27c0700..99a0b67d65 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -79,6 +79,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char BOOL rotatingOrientation; NSString *committedText; NSString *obligateForBackspace; + BOOL isOTPMode; #endif } @@ -280,6 +281,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char textField.hidden = YES; textFieldFocused = NO; + isOTPMode = NO; NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; #ifndef SDL_PLATFORM_TVOS @@ -477,6 +479,10 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char if (SDL_TextInputActive(window)) { [textField becomeFirstResponder]; } + + isOTPMode = + (SDL_GetTextInputType(props) == SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_HIDDEN) || + (SDL_GetTextInputType(props) == SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_VISIBLE); } /* requests the SDL text field to become focused and accept text input. @@ -490,6 +496,12 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char return true; } + if (isOTPMode) { + if (textField.text.length == 64 && [textField.text isEqualToString:[@"" stringByPaddingToLength:64 withString:@" " startingAtIndex:0]]) { + textField.text = @""; + committedText = @""; + } + } return [textField becomeFirstResponder]; } @@ -554,14 +566,6 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char - (void)textFieldTextDidChange:(NSNotification *)notification { - // When opening a password manager overlay to select a password and have it auto-filled, - // text input becomes stopped as a result of the keyboard being hidden or the text field losing focus. - // As a workaround, ensure text input is activated on any changes to the text field. - bool startTextInputMomentarily = !SDL_TextInputActive(window); - - if (startTextInputMomentarily) - SDL_StartTextInput(window); - if (textField.markedTextRange == nil) { NSUInteger compareLength = SDL_min(textField.text.length, committedText.length); NSUInteger matchLength; @@ -596,9 +600,6 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char } committedText = textField.text; } - - if (startTextInputMomentarily) - SDL_StopTextInput(window); } - (void)updateKeyboard @@ -643,8 +644,8 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char // UITextFieldDelegate method. Invoked when user types something. - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { - if (textField.markedTextRange == nil) { - if ([string length] == 0 && textField.text.length < 16) { + if (!isOTPMode) { + if (textField.markedTextRange == nil && textField.text.length < 16) { [self resetTextState]; } } @@ -664,8 +665,10 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char - (void)resetTextState { - textField.text = obligateForBackspace; - committedText = textField.text; + if (!isOTPMode) { + textField.text = obligateForBackspace; + committedText = textField.text; + } } #endif