diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-12-04 17:55:38 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-12-04 17:55:38 +0200 |
commit | 368eddea42200ec95faa4f4767a72b2b3cf7bdff (patch) | |
tree | 5de42312f4ff697d7a141e926be41731e957d043 /src/ios.m | |
parent | f8c0c817c2ce1919f71ef333439c9f4742fc6a12 (diff) |
iOS: Setting up a system-provided text input control
Diffstat (limited to 'src/ios.m')
-rw-r--r-- | src/ios.m | 111 |
1 files changed, 110 insertions, 1 deletions
@@ -60,6 +60,8 @@ static UIViewController *viewController_(iWindow *window) { | |||
60 | return NULL; | 60 | return NULL; |
61 | } | 61 | } |
62 | 62 | ||
63 | static void notifyChange_SystemTextInput_(iSystemTextInput *); | ||
64 | |||
63 | /*----------------------------------------------------------------------------------------------*/ | 65 | /*----------------------------------------------------------------------------------------------*/ |
64 | 66 | ||
65 | API_AVAILABLE(ios(13.0)) | 67 | API_AVAILABLE(ios(13.0)) |
@@ -159,9 +161,10 @@ API_AVAILABLE(ios(13.0)) | |||
159 | 161 | ||
160 | /*----------------------------------------------------------------------------------------------*/ | 162 | /*----------------------------------------------------------------------------------------------*/ |
161 | 163 | ||
162 | @interface AppState : NSObject<UIDocumentPickerDelegate> { | 164 | @interface AppState : NSObject<UIDocumentPickerDelegate, UITextFieldDelegate> { |
163 | iString *fileBeingSaved; | 165 | iString *fileBeingSaved; |
164 | iString *pickFileCommand; | 166 | iString *pickFileCommand; |
167 | iSystemTextInput *sysCtrl; | ||
165 | } | 168 | } |
166 | @property (nonatomic, assign) BOOL isHapticsAvailable; | 169 | @property (nonatomic, assign) BOOL isHapticsAvailable; |
167 | @property (nonatomic, strong) NSObject *haptic; | 170 | @property (nonatomic, strong) NSObject *haptic; |
@@ -175,9 +178,18 @@ static AppState *appState_; | |||
175 | self = [super init]; | 178 | self = [super init]; |
176 | fileBeingSaved = NULL; | 179 | fileBeingSaved = NULL; |
177 | pickFileCommand = NULL; | 180 | pickFileCommand = NULL; |
181 | sysCtrl = NULL; | ||
178 | return self; | 182 | return self; |
179 | } | 183 | } |
180 | 184 | ||
185 | -(void)setSystemTextInput:(iSystemTextInput *)sys { | ||
186 | sysCtrl = sys; | ||
187 | } | ||
188 | |||
189 | -(iSystemTextInput *)systemTextInput { | ||
190 | return sysCtrl; | ||
191 | } | ||
192 | |||
181 | -(void)setPickFileCommand:(const char *)command { | 193 | -(void)setPickFileCommand:(const char *)command { |
182 | if (!pickFileCommand) { | 194 | if (!pickFileCommand) { |
183 | pickFileCommand = new_String(); | 195 | pickFileCommand = new_String(); |
@@ -256,6 +268,21 @@ didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls { | |||
256 | -(void)keyboardOffScreen:(NSNotification *)notification { | 268 | -(void)keyboardOffScreen:(NSNotification *)notification { |
257 | setKeyboardHeight_MainWindow(get_MainWindow(), 0); | 269 | setKeyboardHeight_MainWindow(get_MainWindow(), 0); |
258 | } | 270 | } |
271 | |||
272 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { | ||
273 | SDL_Event ev = { .type = SDL_KEYDOWN }; | ||
274 | ev.key.keysym.sym = SDLK_RETURN; | ||
275 | SDL_PushEvent(&ev); | ||
276 | printf("Return pressed\n"); | ||
277 | return NO; | ||
278 | } | ||
279 | |||
280 | - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { | ||
281 | iSystemTextInput *sysCtrl = [appState_ systemTextInput]; | ||
282 | notifyChange_SystemTextInput_(sysCtrl); | ||
283 | return YES; | ||
284 | } | ||
285 | |||
259 | @end | 286 | @end |
260 | 287 | ||
261 | static void enableMouse_(iBool yes) { | 288 | static void enableMouse_(iBool yes) { |
@@ -607,3 +634,85 @@ iBool isStarted_AVFAudioPlayer(const iAVFAudioPlayer *d) { | |||
607 | iBool isPaused_AVFAudioPlayer(const iAVFAudioPlayer *d) { | 634 | iBool isPaused_AVFAudioPlayer(const iAVFAudioPlayer *d) { |
608 | return d->state == paused_AVFAudioPlayerState; | 635 | return d->state == paused_AVFAudioPlayerState; |
609 | } | 636 | } |
637 | |||
638 | /*----------------------------------------------------------------------------------------------*/ | ||
639 | |||
640 | struct Impl_SystemTextInput { | ||
641 | void *ctrl; | ||
642 | void (*textChangedFunc)(iSystemTextInput *, void *); | ||
643 | void *textChangedContext; | ||
644 | }; | ||
645 | |||
646 | iDefineTypeConstructionArgs(SystemTextInput, (int flags), flags) | ||
647 | |||
648 | #define REF_d_ctrl (__bridge UITextField *)d->ctrl | ||
649 | |||
650 | void init_SystemTextInput(iSystemTextInput *d, int flags) { | ||
651 | d->ctrl = (void *) CFBridgingRetain([[UITextField alloc] init]); | ||
652 | UITextField *field = REF_d_ctrl; | ||
653 | // TODO: Use the right font: https://developer.apple.com/documentation/uikit/text_display_and_fonts/adding_a_custom_font_to_your_app?language=objc | ||
654 | [[viewController_(get_Window()) view] addSubview:REF_d_ctrl]; | ||
655 | if (flags & returnGo_SystemTextInputFlags) { | ||
656 | [field setReturnKeyType:UIReturnKeyGo]; | ||
657 | } | ||
658 | if (flags & returnSend_SystemTextInputFlags) { | ||
659 | [field setReturnKeyType:UIReturnKeySend]; | ||
660 | } | ||
661 | if (flags & disableAutocorrect_SystemTextInputFlag) { | ||
662 | [field setAutocorrectionType:UITextAutocorrectionTypeNo]; | ||
663 | [field setAutocapitalizationType:UITextAutocapitalizationTypeNone]; | ||
664 | [field setSpellCheckingType:UITextSpellCheckingTypeNo]; | ||
665 | } | ||
666 | if (flags & alignRight_WidgetFlag) { | ||
667 | [field setTextAlignment:NSTextAlignmentRight]; | ||
668 | } | ||
669 | [field setDelegate:appState_]; | ||
670 | [field becomeFirstResponder]; | ||
671 | d->textChangedFunc = NULL; | ||
672 | d->textChangedContext = NULL; | ||
673 | [appState_ setSystemTextInput:d]; | ||
674 | } | ||
675 | |||
676 | void deinit_SystemTextInput(iSystemTextInput *d) { | ||
677 | [appState_ setSystemTextInput:nil]; | ||
678 | [REF_d_ctrl removeFromSuperview]; | ||
679 | d->ctrl = nil; // TODO: Does this need to be released?? | ||
680 | } | ||
681 | |||
682 | void setText_SystemTextInput(iSystemTextInput *d, const iString *text) { | ||
683 | [REF_d_ctrl setText:[NSString stringWithUTF8String:cstr_String(text)]]; | ||
684 | [REF_d_ctrl selectAll:nil]; | ||
685 | } | ||
686 | |||
687 | void setFont_SystemTextInput(iSystemTextInput *d, int fontId) { | ||
688 | int height = lineHeight_Text(fontId); | ||
689 | UIFont *font = [UIFont systemFontOfSize:0.65f * height / get_Window()->pixelRatio]; | ||
690 | [REF_d_ctrl setFont:font]; | ||
691 | } | ||
692 | |||
693 | const iString *text_SystemTextInput(const iSystemTextInput *d) { | ||
694 | return collectNewCStr_String([[REF_d_ctrl text] cStringUsingEncoding:NSUTF8StringEncoding]);; | ||
695 | } | ||
696 | |||
697 | void setRect_SystemTextInput(iSystemTextInput *d, iRect rect) { | ||
698 | const iWindow *win = get_Window(); | ||
699 | CGRect frame; | ||
700 | frame.origin.x = rect.pos.x / win->pixelRatio; | ||
701 | frame.origin.y = (rect.pos.y - gap_UI + 2) / win->pixelRatio; | ||
702 | frame.size.width = rect.size.x / win->pixelRatio; | ||
703 | frame.size.height = rect.size.y / win->pixelRatio; | ||
704 | [REF_d_ctrl setFrame:frame]; | ||
705 | } | ||
706 | |||
707 | void setTextChangedFunc_SystemTextInput(iSystemTextInput *d, | ||
708 | void (*textChangedFunc)(iSystemTextInput *, void *), | ||
709 | void *context) { | ||
710 | d->textChangedFunc = textChangedFunc; | ||
711 | d->textChangedContext = context; | ||
712 | } | ||
713 | |||
714 | static void notifyChange_SystemTextInput_(iSystemTextInput *d) { | ||
715 | if (d && d->textChangedFunc) { | ||
716 | d->textChangedFunc(d, d->textChangedContext); | ||
717 | } | ||
718 | } | ||