oviano
2016-12-18 12:11:04 UTC
I needed to tweak the way the screen keyboard works in tvOS.
The problem is that it behaves like the iOS one in that it assumes that the application will be rendering the text so you can see what you are typing. This is not the case with tvOS because the keyboard takes overlays the whole screen and provides its own text input box. This wouldn't be so bad if the text input box wasn't set to invisible/not updating, essentially meaning you are typing blind.
The fix was twofold; firstly for tvOS I've made the text input field visible and allowed it's contents to be updated as the user types the text. Secondly, I've added a function to supply the initial text field so that you can start it from whatever you are expecting the user to edit.
Code:
diff -r 007dfe83abf8 include/SDL_keyboard.h
--- a/include/SDL_keyboard.h Wed Oct 19 20:50:33 2016 -0700
+++ b/include/SDL_keyboard.h Sun Dec 18 14:57:42 2016 +0300
@@ -206,6 +206,13 @@
*/
extern DECLSPEC SDL_bool SDLCALL SDL_IsScreenKeyboardShown(SDL_Window *window);
+/**
+ * \brief Sets the contents of the screen keyboard's text field.
+ *
+ * \sa SDL_StartTextInput()
+ */
+extern DECLSPEC void SDLCALL SDL_SetScreenKeyboardText(const char *a);
+
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
diff -r 007dfe83abf8 src/dynapi/SDL_dynapi_overrides.h
--- a/src/dynapi/SDL_dynapi_overrides.h Wed Oct 19 20:50:33 2016 -0700
+++ b/src/dynapi/SDL_dynapi_overrides.h Sun Dec 18 14:57:42 2016 +0300
@@ -235,6 +235,7 @@
#define SDL_SetTextInputRect SDL_SetTextInputRect_REAL
#define SDL_HasScreenKeyboardSupport SDL_HasScreenKeyboardSupport_REAL
#define SDL_IsScreenKeyboardShown SDL_IsScreenKeyboardShown_REAL
+#define SDL_SetScreenKeyboardText SDL_SetScreenKeyboardText_REAL
#define SDL_LoadObject SDL_LoadObject_REAL
#define SDL_LoadFunction SDL_LoadFunction_REAL
#define SDL_UnloadObject SDL_UnloadObject_REAL
diff -r 007dfe83abf8 src/dynapi/SDL_dynapi_procs.h
--- a/src/dynapi/SDL_dynapi_procs.h Wed Oct 19 20:50:33 2016 -0700
+++ b/src/dynapi/SDL_dynapi_procs.h Sun Dec 18 14:57:42 2016 +0300
@@ -264,6 +264,7 @@
SDL_DYNAPI_PROC(void,SDL_SetTextInputRect,(SDL_Rect *a),(a),)
SDL_DYNAPI_PROC(SDL_bool,SDL_HasScreenKeyboardSupport,(void),(),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_IsScreenKeyboardShown,(SDL_Window *a),(a),return)
+SDL_DYNAPI_PROC(void,SDL_SetScreenKeyboardText,(const char *a),(a),)
SDL_DYNAPI_PROC(void*,SDL_LoadObject,(const char *a),(a),return)
SDL_DYNAPI_PROC(void*,SDL_LoadFunction,(void *a, const char *b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_UnloadObject,(void *a),(a),)
diff -r 007dfe83abf8 src/video/SDL_sysvideo.h
--- a/src/video/SDL_sysvideo.h Wed Oct 19 20:50:33 2016 -0700
+++ b/src/video/SDL_sysvideo.h Sun Dec 18 14:57:42 2016 +0300
@@ -274,6 +274,7 @@
void (*ShowScreenKeyboard) (_THIS, SDL_Window *window);
void (*HideScreenKeyboard) (_THIS, SDL_Window *window);
SDL_bool (*IsScreenKeyboardShown) (_THIS, SDL_Window *window);
+ void (*SetScreenKeyboardText) (_THIS, const char *text);
/* Clipboard */
int (*SetClipboardText) (_THIS, const char *text);
diff -r 007dfe83abf8 src/video/SDL_video.c
--- a/src/video/SDL_video.c Wed Oct 19 20:50:33 2016 -0700
+++ b/src/video/SDL_video.c Sun Dec 18 14:57:42 2016 +0300
@@ -3598,6 +3598,14 @@
return SDL_FALSE;
}
+void
+SDL_SetScreenKeyboardText(const char *text)
+{
+ if (_this && _this->SetScreenKeyboardText) {
+ _this->SetScreenKeyboardText(_this, text);
+ }
+}
+
#if SDL_VIDEO_DRIVER_ANDROID
#include "android/SDL_androidmessagebox.h"
#endif
diff -r 007dfe83abf8 src/video/uikit/SDL_uikitvideo.m
--- a/src/video/uikit/SDL_uikitvideo.m Wed Oct 19 20:50:33 2016 -0700
+++ b/src/video/uikit/SDL_uikitvideo.m Sun Dec 18 14:57:42 2016 +0300
@@ -107,6 +107,7 @@
device->HideScreenKeyboard = UIKit_HideScreenKeyboard;
device->IsScreenKeyboardShown = UIKit_IsScreenKeyboardShown;
device->SetTextInputRect = UIKit_SetTextInputRect;
+ device->SetScreenKeyboardText = UIKit_SetScreenKeyboardText;
#endif
device->SetClipboardText = UIKit_SetClipboardText;
diff -r 007dfe83abf8 src/video/uikit/SDL_uikitviewcontroller.h
--- a/src/video/uikit/SDL_uikitviewcontroller.h Wed Oct 19 20:50:33 2016 -0700
+++ b/src/video/uikit/SDL_uikitviewcontroller.h Sun Dec 18 14:57:42 2016 +0300
@@ -84,4 +84,5 @@
void UIKit_HideScreenKeyboard(_THIS, SDL_Window *window);
SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window);
void UIKit_SetTextInputRect(_THIS, SDL_Rect *rect);
+void UIKit_SetScreenKeyboardText(_THIS, const char *text);
#endif
diff -r 007dfe83abf8 src/video/uikit/SDL_uikitviewcontroller.m
--- a/src/video/uikit/SDL_uikitviewcontroller.m Wed Oct 19 20:50:33 2016 -0700
+++ b/src/video/uikit/SDL_uikitviewcontroller.m Sun Dec 18 14:57:42 2016 +0300
@@ -179,8 +179,9 @@
textField = [[UITextField alloc] initWithFrame:CGRectZero];
textField.delegate = self;
/* placeholder so there is something to delete! */
+#if !TARGET_OS_TV
textField.text = @" ";
-
+#endif
/* set UITextInputTrait properties, mostly to defaults */
textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
textField.autocorrectionType = UITextAutocorrectionTypeNo;
@@ -190,7 +191,9 @@
textField.returnKeyType = UIReturnKeyDefault;
textField.secureTextEntry = NO;
+#if !TARGET_OS_TV
textField.hidden = YES;
+#endif
keyboardVisible = NO;
#if !TARGET_OS_TV
@@ -289,6 +292,11 @@
[self updateKeyboard];
}
+- (void)setKeyboardText:(const char*)text
+{
+ textField.text = [NSString stringWithUTF8String:text];
+}
+
/* UITextFieldDelegate method. Invoked when user types something. */
- (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
@@ -335,7 +343,11 @@
SDL_SendKeyboardText([string UTF8String]);
}
+#if TARGET_OS_TV
+ return YES;
+#else
return NO; /* don't allow the edit! (keep placeholder text there) */
+#endif
}
/* Terminates the editing session */
@@ -423,6 +435,21 @@
}
}
+void
+UIKit_SetScreenKeyboardText(_THIS, const char *text)
+{
+ if (!text) {
+ SDL_InvalidParamError("text");
+ return;
+ }
+
+ @autoreleasepool {
+ SDL_uikitviewcontroller *vc = GetWindowViewController(SDL_GetFocusWindow());
+ if (vc != nil) {
+ [vc setKeyboardText:text];
+ }
+ }
+}
#endif /* SDL_IPHONE_KEYBOARD */
The problem is that it behaves like the iOS one in that it assumes that the application will be rendering the text so you can see what you are typing. This is not the case with tvOS because the keyboard takes overlays the whole screen and provides its own text input box. This wouldn't be so bad if the text input box wasn't set to invisible/not updating, essentially meaning you are typing blind.
The fix was twofold; firstly for tvOS I've made the text input field visible and allowed it's contents to be updated as the user types the text. Secondly, I've added a function to supply the initial text field so that you can start it from whatever you are expecting the user to edit.
Code:
diff -r 007dfe83abf8 include/SDL_keyboard.h
--- a/include/SDL_keyboard.h Wed Oct 19 20:50:33 2016 -0700
+++ b/include/SDL_keyboard.h Sun Dec 18 14:57:42 2016 +0300
@@ -206,6 +206,13 @@
*/
extern DECLSPEC SDL_bool SDLCALL SDL_IsScreenKeyboardShown(SDL_Window *window);
+/**
+ * \brief Sets the contents of the screen keyboard's text field.
+ *
+ * \sa SDL_StartTextInput()
+ */
+extern DECLSPEC void SDLCALL SDL_SetScreenKeyboardText(const char *a);
+
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
diff -r 007dfe83abf8 src/dynapi/SDL_dynapi_overrides.h
--- a/src/dynapi/SDL_dynapi_overrides.h Wed Oct 19 20:50:33 2016 -0700
+++ b/src/dynapi/SDL_dynapi_overrides.h Sun Dec 18 14:57:42 2016 +0300
@@ -235,6 +235,7 @@
#define SDL_SetTextInputRect SDL_SetTextInputRect_REAL
#define SDL_HasScreenKeyboardSupport SDL_HasScreenKeyboardSupport_REAL
#define SDL_IsScreenKeyboardShown SDL_IsScreenKeyboardShown_REAL
+#define SDL_SetScreenKeyboardText SDL_SetScreenKeyboardText_REAL
#define SDL_LoadObject SDL_LoadObject_REAL
#define SDL_LoadFunction SDL_LoadFunction_REAL
#define SDL_UnloadObject SDL_UnloadObject_REAL
diff -r 007dfe83abf8 src/dynapi/SDL_dynapi_procs.h
--- a/src/dynapi/SDL_dynapi_procs.h Wed Oct 19 20:50:33 2016 -0700
+++ b/src/dynapi/SDL_dynapi_procs.h Sun Dec 18 14:57:42 2016 +0300
@@ -264,6 +264,7 @@
SDL_DYNAPI_PROC(void,SDL_SetTextInputRect,(SDL_Rect *a),(a),)
SDL_DYNAPI_PROC(SDL_bool,SDL_HasScreenKeyboardSupport,(void),(),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_IsScreenKeyboardShown,(SDL_Window *a),(a),return)
+SDL_DYNAPI_PROC(void,SDL_SetScreenKeyboardText,(const char *a),(a),)
SDL_DYNAPI_PROC(void*,SDL_LoadObject,(const char *a),(a),return)
SDL_DYNAPI_PROC(void*,SDL_LoadFunction,(void *a, const char *b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_UnloadObject,(void *a),(a),)
diff -r 007dfe83abf8 src/video/SDL_sysvideo.h
--- a/src/video/SDL_sysvideo.h Wed Oct 19 20:50:33 2016 -0700
+++ b/src/video/SDL_sysvideo.h Sun Dec 18 14:57:42 2016 +0300
@@ -274,6 +274,7 @@
void (*ShowScreenKeyboard) (_THIS, SDL_Window *window);
void (*HideScreenKeyboard) (_THIS, SDL_Window *window);
SDL_bool (*IsScreenKeyboardShown) (_THIS, SDL_Window *window);
+ void (*SetScreenKeyboardText) (_THIS, const char *text);
/* Clipboard */
int (*SetClipboardText) (_THIS, const char *text);
diff -r 007dfe83abf8 src/video/SDL_video.c
--- a/src/video/SDL_video.c Wed Oct 19 20:50:33 2016 -0700
+++ b/src/video/SDL_video.c Sun Dec 18 14:57:42 2016 +0300
@@ -3598,6 +3598,14 @@
return SDL_FALSE;
}
+void
+SDL_SetScreenKeyboardText(const char *text)
+{
+ if (_this && _this->SetScreenKeyboardText) {
+ _this->SetScreenKeyboardText(_this, text);
+ }
+}
+
#if SDL_VIDEO_DRIVER_ANDROID
#include "android/SDL_androidmessagebox.h"
#endif
diff -r 007dfe83abf8 src/video/uikit/SDL_uikitvideo.m
--- a/src/video/uikit/SDL_uikitvideo.m Wed Oct 19 20:50:33 2016 -0700
+++ b/src/video/uikit/SDL_uikitvideo.m Sun Dec 18 14:57:42 2016 +0300
@@ -107,6 +107,7 @@
device->HideScreenKeyboard = UIKit_HideScreenKeyboard;
device->IsScreenKeyboardShown = UIKit_IsScreenKeyboardShown;
device->SetTextInputRect = UIKit_SetTextInputRect;
+ device->SetScreenKeyboardText = UIKit_SetScreenKeyboardText;
#endif
device->SetClipboardText = UIKit_SetClipboardText;
diff -r 007dfe83abf8 src/video/uikit/SDL_uikitviewcontroller.h
--- a/src/video/uikit/SDL_uikitviewcontroller.h Wed Oct 19 20:50:33 2016 -0700
+++ b/src/video/uikit/SDL_uikitviewcontroller.h Sun Dec 18 14:57:42 2016 +0300
@@ -84,4 +84,5 @@
void UIKit_HideScreenKeyboard(_THIS, SDL_Window *window);
SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window);
void UIKit_SetTextInputRect(_THIS, SDL_Rect *rect);
+void UIKit_SetScreenKeyboardText(_THIS, const char *text);
#endif
diff -r 007dfe83abf8 src/video/uikit/SDL_uikitviewcontroller.m
--- a/src/video/uikit/SDL_uikitviewcontroller.m Wed Oct 19 20:50:33 2016 -0700
+++ b/src/video/uikit/SDL_uikitviewcontroller.m Sun Dec 18 14:57:42 2016 +0300
@@ -179,8 +179,9 @@
textField = [[UITextField alloc] initWithFrame:CGRectZero];
textField.delegate = self;
/* placeholder so there is something to delete! */
+#if !TARGET_OS_TV
textField.text = @" ";
-
+#endif
/* set UITextInputTrait properties, mostly to defaults */
textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
textField.autocorrectionType = UITextAutocorrectionTypeNo;
@@ -190,7 +191,9 @@
textField.returnKeyType = UIReturnKeyDefault;
textField.secureTextEntry = NO;
+#if !TARGET_OS_TV
textField.hidden = YES;
+#endif
keyboardVisible = NO;
#if !TARGET_OS_TV
@@ -289,6 +292,11 @@
[self updateKeyboard];
}
+- (void)setKeyboardText:(const char*)text
+{
+ textField.text = [NSString stringWithUTF8String:text];
+}
+
/* UITextFieldDelegate method. Invoked when user types something. */
- (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
@@ -335,7 +343,11 @@
SDL_SendKeyboardText([string UTF8String]);
}
+#if TARGET_OS_TV
+ return YES;
+#else
return NO; /* don't allow the edit! (keep placeholder text there) */
+#endif
}
/* Terminates the editing session */
@@ -423,6 +435,21 @@
}
}
+void
+UIKit_SetScreenKeyboardText(_THIS, const char *text)
+{
+ if (!text) {
+ SDL_InvalidParamError("text");
+ return;
+ }
+
+ @autoreleasepool {
+ SDL_uikitviewcontroller *vc = GetWindowViewController(SDL_GetFocusWindow());
+ if (vc != nil) {
+ [vc setKeyboardText:text];
+ }
+ }
+}
#endif /* SDL_IPHONE_KEYBOARD */