Fixed delayed text entry for OTP codes on iOS (thanks @pipiwoaini!)

Fixes https://github.com/libsdl-org/SDL/issues/13717
This commit is contained in:
Sam Lantinga
2025-09-14 08:06:24 -07:00
parent 4561be89a5
commit 113c7e8a58

View File

@@ -79,6 +79,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
BOOL rotatingOrientation; BOOL rotatingOrientation;
NSString *committedText; NSString *committedText;
NSString *obligateForBackspace; NSString *obligateForBackspace;
BOOL isOTPMode;
#endif #endif
} }
@@ -280,6 +281,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
textField.hidden = YES; textField.hidden = YES;
textFieldFocused = NO; textFieldFocused = NO;
isOTPMode = NO;
NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
#ifndef SDL_PLATFORM_TVOS #ifndef SDL_PLATFORM_TVOS
@@ -477,6 +479,10 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
if (SDL_TextInputActive(window)) { if (SDL_TextInputActive(window)) {
[textField becomeFirstResponder]; [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. /* 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; return true;
} }
if (isOTPMode) {
if (textField.text.length == 64 && [textField.text isEqualToString:[@"" stringByPaddingToLength:64 withString:@" " startingAtIndex:0]]) {
textField.text = @"";
committedText = @"";
}
}
return [textField becomeFirstResponder]; return [textField becomeFirstResponder];
} }
@@ -554,14 +566,6 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
- (void)textFieldTextDidChange:(NSNotification *)notification - (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) { if (textField.markedTextRange == nil) {
NSUInteger compareLength = SDL_min(textField.text.length, committedText.length); NSUInteger compareLength = SDL_min(textField.text.length, committedText.length);
NSUInteger matchLength; NSUInteger matchLength;
@@ -596,9 +600,6 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
} }
committedText = textField.text; committedText = textField.text;
} }
if (startTextInputMomentarily)
SDL_StopTextInput(window);
} }
- (void)updateKeyboard - (void)updateKeyboard
@@ -643,8 +644,8 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
// UITextFieldDelegate method. Invoked when user types something. // UITextFieldDelegate method. Invoked when user types something.
- (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{ {
if (textField.markedTextRange == nil) { if (!isOTPMode) {
if ([string length] == 0 && textField.text.length < 16) { if (textField.markedTextRange == nil && textField.text.length < 16) {
[self resetTextState]; [self resetTextState];
} }
} }
@@ -664,9 +665,11 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
- (void)resetTextState - (void)resetTextState
{ {
if (!isOTPMode) {
textField.text = obligateForBackspace; textField.text = obligateForBackspace;
committedText = textField.text; committedText = textField.text;
} }
}
#endif #endif