Synchronize on-screen keyboard state with text input active state

When a hardware keyboard is attached to an iPad, you can easily trigger a set of on-screen keyboard transitions that will take place over time, and we need to track whether we're currently showing or hiding the keyboard and make sure we don't clobber the existing state during those transitions.

Testing:
* Connected a hardware keyboard to an iPad
* Launched checkkeys
* Noted the keyboard bar was active at the bottom of the screen and text input was active
* Tapped with both fingers to quickly toggle text input off and back on
* Noted the keyboard bar slid down and then back up, and text input was active
* Tapped on the keyboard bar to bring up the full on-screen keyboard and then closed it so the keyboard bar was still active, and text input was still active
* Tapped on the screen to turn text input off, noted the keyboard bar slid down
* Tapped with both fingers to quickly toggle text input on and back off
* Noted that the keyboard bar slid up and then back down, and text input was inactive
* Tapped on the screen to turn text input on, tapped on the keyboard bar to bring up the full on-screen keyboard, and text input was active
* Pressed a key on the physical keyboard, the on-screen keyboard closed, the key press and release was delivered (with no text input) and then the keyboard bar slid up, and text input was active again

Fixes https://github.com/libsdl-org/SDL/issues/7979
main
Sam Lantinga 2023-08-01 23:56:04 -07:00
parent 5fb92ef2f7
commit c3288d113e
1 changed files with 66 additions and 6 deletions

View File

@ -82,6 +82,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
SDLUITextField *textField;
BOOL hardwareKeyboard;
BOOL showingKeyboard;
BOOL hidingKeyboard;
BOOL rotatingOrientation;
NSString *committedText;
NSString *obligateForBackspace;
@ -99,6 +100,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
[self initKeyboard];
hardwareKeyboard = NO;
showingKeyboard = NO;
hidingKeyboard = NO;
rotatingOrientation = NO;
#endif
@ -292,7 +294,18 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[center addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
[center addObserver:self
selector:@selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:nil];
[center addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
[center addObserver:self
selector:@selector(keyboardDidHide:)
name:UIKeyboardDidHideNotification
object:nil];
#endif
[center addObserver:self
selector:@selector(textFieldTextDidChange:)
@ -363,7 +376,15 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
[center removeObserver:self
name:UIKeyboardWillShowNotification
object:nil];
[center removeObserver:self name:UIKeyboardWillHideNotification object:nil];
[center removeObserver:self
name:UIKeyboardDidShowNotification
object:nil];
[center removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
[center removeObserver:self
name:UIKeyboardDidHideNotification
object:nil];
#endif
[center removeObserver:self
name:UITextFieldTextDidChangeNotification
@ -373,23 +394,40 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
/* reveal onscreen virtual keyboard */
- (void)showKeyboard
{
if (keyboardVisible) {
return;
}
keyboardVisible = YES;
if (textField.window) {
showingKeyboard = YES;
[textField becomeFirstResponder];
showingKeyboard = NO;
}
}
/* hide onscreen virtual keyboard */
- (void)hideKeyboard
{
if (!keyboardVisible) {
return;
}
keyboardVisible = NO;
[textField resignFirstResponder];
if (textField.window) {
hidingKeyboard = YES;
[textField resignFirstResponder];
}
}
- (void)keyboardWillShow:(NSNotification *)notification
{
BOOL shouldStartTextInput = NO;
if (!SDL_TextInputActive() && !hidingKeyboard && !rotatingOrientation) {
shouldStartTextInput = YES;
}
showingKeyboard = YES;
#if !TARGET_OS_TV
CGRect kbrect = [[notification userInfo][UIKeyboardFrameEndUserInfoKey] CGRectValue];
@ -399,14 +437,36 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
[self setKeyboardHeight:(int)kbrect.size.height];
#endif
if (shouldStartTextInput) {
SDL_StartTextInput();
}
}
- (void)keyboardDidShow:(NSNotification *)notification
{
showingKeyboard = NO;
}
- (void)keyboardWillHide:(NSNotification *)notification
{
if (!showingKeyboard && !rotatingOrientation) {
BOOL shouldStopTextInput = NO;
if (SDL_TextInputActive() && !showingKeyboard && !rotatingOrientation) {
shouldStopTextInput = YES;
}
hidingKeyboard = YES;
[self setKeyboardHeight:0];
if (shouldStopTextInput) {
SDL_StopTextInput();
}
[self setKeyboardHeight:0];
}
- (void)keyboardDidHide:(NSNotification *)notification
{
hidingKeyboard = NO;
}
- (void)textFieldTextDidChange:(NSNotification *)notification