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 (cherry picked from commit c3288d113e434b20d2f0dda73210d3a52504d199) (cherry picked from commit 030bb7282a8c93caf15fd023e02de888def7f582)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m
index 3baadd8..604de7d 100644
--- a/src/video/uikit/SDL_uikitviewcontroller.m
+++ b/src/video/uikit/SDL_uikitviewcontroller.m
@@ -74,6 +74,7 @@ SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *o
UITextField *textField;
BOOL hardwareKeyboard;
BOOL showingKeyboard;
+ BOOL hidingKeyboard;
BOOL rotatingOrientation;
NSString *committedText;
NSString *obligateForBackspace;
@@ -91,6 +92,7 @@ SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *o
[self initKeyboard];
hardwareKeyboard = NO;
showingKeyboard = NO;
+ hidingKeyboard = NO;
rotatingOrientation = NO;
#endif
@@ -277,8 +279,22 @@ SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *o
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
#if !TARGET_OS_TV
- [center addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
- [center addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
+ [center addObserver:self
+ selector:@selector(keyboardWillShow:)
+ name:UIKeyboardWillShowNotification
+ 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:) name:UITextFieldTextDidChangeNotification object:nil];
}
@@ -341,8 +357,18 @@ SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *o
{
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
#if !TARGET_OS_TV
- [center removeObserver:self name:UIKeyboardWillShowNotification object:nil];
- [center removeObserver:self name:UIKeyboardWillHideNotification object:nil];
+ [center removeObserver:self
+ name:UIKeyboardWillShowNotification
+ 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 object:nil];
}
@@ -350,23 +376,40 @@ SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *o
/* 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];
@@ -376,14 +419,36 @@ SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *o
[self setKeyboardHeight:(int)kbrect.size.height];
#endif
+
+ if (shouldStartTextInput) {
+ SDL_StartTextInput();
+ }
+}
+
+- (void)keyboardDidShow:(NSNotification *)notification
+{
+ showingKeyboard = NO;
}
- (void)keyboardWillHide:(NSNotification *)notification
{
- if (!showingKeyboard && !rotatingOrientation) {
- SDL_StopTextInput();
+ BOOL shouldStopTextInput = NO;
+
+ if (SDL_TextInputActive() && !showingKeyboard && !rotatingOrientation) {
+ shouldStopTextInput = YES;
}
+
+ hidingKeyboard = YES;
[self setKeyboardHeight:0];
+
+ if (shouldStopTextInput) {
+ SDL_StopTextInput();
+ }
+}
+
+- (void)keyboardDidHide:(NSNotification *)notification
+{
+ hidingKeyboard = NO;
}
- (void)textFieldTextDidChange:(NSNotification *)notification