diff options
-rw-r--r-- | CMakeLists.txt | 8 | ||||
-rw-r--r-- | res/iOSBundleInfo.plist.in | 4 | ||||
-rw-r--r-- | src/ios.h | 4 | ||||
-rw-r--r-- | src/ios.m | 81 | ||||
-rw-r--r-- | src/ui/inputwidget.c | 16 |
5 files changed, 90 insertions, 23 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 4200c7c5..2d11e43e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -104,6 +104,12 @@ endif () | |||
104 | set (EMB_BIN ${CMAKE_CURRENT_BINARY_DIR}/resources.lgr) | 104 | set (EMB_BIN ${CMAKE_CURRENT_BINARY_DIR}/resources.lgr) |
105 | make_resources (${EMB_BIN} ${RESOURCES}) | 105 | make_resources (${EMB_BIN} ${RESOURCES}) |
106 | set_source_files_properties (${EMB_BIN} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) | 106 | set_source_files_properties (${EMB_BIN} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) |
107 | if (IOS) | ||
108 | set (EMB_FONTS res/fonts/SourceSans3-Regular.ttf) | ||
109 | set_source_files_properties (${EMB_FONTS} | ||
110 | PROPERTIES MACOSX_PACKAGE_LOCATION Resources | ||
111 | ) | ||
112 | endif () | ||
107 | 113 | ||
108 | # Source files. | 114 | # Source files. |
109 | set (SOURCES | 115 | set (SOURCES |
@@ -287,7 +293,7 @@ else () | |||
287 | endif () | 293 | endif () |
288 | 294 | ||
289 | # Target. | 295 | # Target. |
290 | add_executable (app ${SOURCES} ${RESOURCES}) | 296 | add_executable (app ${SOURCES} ${RESOURCES} ${EMB_FONTS}) |
291 | set_property (TARGET app PROPERTY C_STANDARD 11) | 297 | set_property (TARGET app PROPERTY C_STANDARD 11) |
292 | if (TARGET ext-deps) | 298 | if (TARGET ext-deps) |
293 | add_dependencies (app ext-deps) | 299 | add_dependencies (app ext-deps) |
diff --git a/res/iOSBundleInfo.plist.in b/res/iOSBundleInfo.plist.in index 09af4abf..5a02ed68 100644 --- a/res/iOSBundleInfo.plist.in +++ b/res/iOSBundleInfo.plist.in | |||
@@ -49,6 +49,10 @@ | |||
49 | </array> | 49 | </array> |
50 | <key>UILaunchStoryboardName</key> | 50 | <key>UILaunchStoryboardName</key> |
51 | <string>LaunchScreen</string> | 51 | <string>LaunchScreen</string> |
52 | <key>UIAppFonts</key> | ||
53 | <array> | ||
54 | <string>SourceSans3-Regular.ttf</string> | ||
55 | </array> | ||
52 | <key>UIBackgroundModes</key> | 56 | <key>UIBackgroundModes</key> |
53 | <array> | 57 | <array> |
54 | <string>audio</string> | 58 | <string>audio</string> |
@@ -70,7 +70,9 @@ enum iSystemTextInputFlags { | |||
70 | returnGo_SystemTextInputFlags = iBit(3), | 70 | returnGo_SystemTextInputFlags = iBit(3), |
71 | returnSend_SystemTextInputFlags = iBit(4), | 71 | returnSend_SystemTextInputFlags = iBit(4), |
72 | disableAutocorrect_SystemTextInputFlag = iBit(5), | 72 | disableAutocorrect_SystemTextInputFlag = iBit(5), |
73 | alignRight_SystemTextInputFlag = iBit(6), | 73 | disableAutocapitalize_SystemTextInputFlag = iBit(6), |
74 | alignRight_SystemTextInputFlag = iBit(7), | ||
75 | insertNewlines_SystemTextInputFlag = iBit(8), | ||
74 | }; | 76 | }; |
75 | 77 | ||
76 | iDeclareType(SystemTextInput) | 78 | iDeclareType(SystemTextInput) |
@@ -61,6 +61,7 @@ static UIViewController *viewController_(iWindow *window) { | |||
61 | } | 61 | } |
62 | 62 | ||
63 | static void notifyChange_SystemTextInput_(iSystemTextInput *); | 63 | static void notifyChange_SystemTextInput_(iSystemTextInput *); |
64 | static BOOL isNewlineAllowed_SystemTextInput_(const iSystemTextInput *); | ||
64 | 65 | ||
65 | /*----------------------------------------------------------------------------------------------*/ | 66 | /*----------------------------------------------------------------------------------------------*/ |
66 | 67 | ||
@@ -269,10 +270,19 @@ didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls { | |||
269 | setKeyboardHeight_MainWindow(get_MainWindow(), 0); | 270 | setKeyboardHeight_MainWindow(get_MainWindow(), 0); |
270 | } | 271 | } |
271 | 272 | ||
272 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { | 273 | static void sendReturnKeyPress_(void) { |
273 | SDL_Event ev = { .type = SDL_KEYDOWN }; | 274 | SDL_Event ev = { .type = SDL_KEYDOWN }; |
275 | ev.key.timestamp = SDL_GetTicks(); | ||
274 | ev.key.keysym.sym = SDLK_RETURN; | 276 | ev.key.keysym.sym = SDLK_RETURN; |
277 | ev.key.state = SDL_PRESSED; | ||
278 | SDL_PushEvent(&ev); | ||
279 | ev.type = SDL_KEYUP; | ||
280 | ev.key.state = SDL_RELEASED; | ||
275 | SDL_PushEvent(&ev); | 281 | SDL_PushEvent(&ev); |
282 | } | ||
283 | |||
284 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { | ||
285 | sendReturnKeyPress_(); | ||
276 | return NO; | 286 | return NO; |
277 | } | 287 | } |
278 | 288 | ||
@@ -283,6 +293,17 @@ replacementString:(NSString *)string { | |||
283 | return YES; | 293 | return YES; |
284 | } | 294 | } |
285 | 295 | ||
296 | - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range | ||
297 | replacementText:(NSString *)text { | ||
298 | if ([text isEqualToString:@"\n"]) { | ||
299 | if (!isNewlineAllowed_SystemTextInput_([appState_ systemTextInput])) { | ||
300 | sendReturnKeyPress_(); | ||
301 | return NO; | ||
302 | } | ||
303 | } | ||
304 | return YES; | ||
305 | } | ||
306 | |||
286 | - (void)textViewDidChange:(UITextView *)textView { | 307 | - (void)textViewDidChange:(UITextView *)textView { |
287 | iSystemTextInput *sysCtrl = [appState_ systemTextInput]; | 308 | iSystemTextInput *sysCtrl = [appState_ systemTextInput]; |
288 | notifyChange_SystemTextInput_(sysCtrl); | 309 | notifyChange_SystemTextInput_(sysCtrl); |
@@ -659,14 +680,23 @@ iDefineTypeConstructionArgs(SystemTextInput, (iRect rect, int flags), rect, flag | |||
659 | #define REF_d_field (__bridge UITextField *)d->field | 680 | #define REF_d_field (__bridge UITextField *)d->field |
660 | #define REF_d_view (__bridge UITextView *)d->view | 681 | #define REF_d_view (__bridge UITextView *)d->view |
661 | 682 | ||
662 | static CGRect convertToCGRect_(const iRect *rect) { | 683 | static CGRect convertToCGRect_(const iRect *rect, iBool expanded) { |
663 | const iWindow *win = get_Window(); | 684 | const iWindow *win = get_Window(); |
664 | CGRect frame; | 685 | CGRect frame; |
665 | // TODO: Convert coordinates properly! | 686 | // TODO: Convert coordinates properly! |
666 | frame.origin.x = rect->pos.x / win->pixelRatio; | 687 | frame.origin.x = rect->pos.x / win->pixelRatio; |
667 | frame.origin.y = (rect->pos.y - gap_UI + 2) / win->pixelRatio; | 688 | frame.origin.y = (rect->pos.y - gap_UI + 1) / win->pixelRatio; |
668 | frame.size.width = rect->size.x / win->pixelRatio; | 689 | frame.size.width = rect->size.x / win->pixelRatio; |
669 | frame.size.height = rect->size.y / win->pixelRatio; | 690 | frame.size.height = rect->size.y / win->pixelRatio; |
691 | /* Some padding to account for insets. If we just zero out the insets, the insertion point | ||
692 | may be clipped at the edges. */ | ||
693 | if (expanded) { | ||
694 | const float inset = gap_UI / get_Window()->pixelRatio; | ||
695 | frame.origin.x -= inset + 1; | ||
696 | frame.origin.y -= inset + 1; | ||
697 | frame.size.width += 2 * inset + 2; | ||
698 | frame.size.height += inset + 1; | ||
699 | } | ||
670 | return frame; | 700 | return frame; |
671 | } | 701 | } |
672 | 702 | ||
@@ -682,7 +712,7 @@ void init_SystemTextInput(iSystemTextInput *d, iRect rect, int flags) { | |||
682 | d->flags = flags; | 712 | d->flags = flags; |
683 | d->field = NULL; | 713 | d->field = NULL; |
684 | d->view = NULL; | 714 | d->view = NULL; |
685 | CGRect frame = convertToCGRect_(&rect); | 715 | CGRect frame = convertToCGRect_(&rect, (flags & multiLine_SystemTextInputFlags) != 0); |
686 | if (flags & multiLine_SystemTextInputFlags) { | 716 | if (flags & multiLine_SystemTextInputFlags) { |
687 | d->view = (void *) CFBridgingRetain([[UITextView alloc] initWithFrame:frame textContainer:nil]); | 717 | d->view = (void *) CFBridgingRetain([[UITextView alloc] initWithFrame:frame textContainer:nil]); |
688 | [[viewController_(get_Window()) view] addSubview:REF_d_view]; | 718 | [[viewController_(get_Window()) view] addSubview:REF_d_view]; |
@@ -692,7 +722,9 @@ void init_SystemTextInput(iSystemTextInput *d, iRect rect, int flags) { | |||
692 | [[viewController_(get_Window()) view] addSubview:REF_d_field]; | 722 | [[viewController_(get_Window()) view] addSubview:REF_d_field]; |
693 | } | 723 | } |
694 | UIControl<UITextInputTraits> *traits = (UIControl<UITextInputTraits> *) (d->view ? REF_d_view : REF_d_field); | 724 | UIControl<UITextInputTraits> *traits = (UIControl<UITextInputTraits> *) (d->view ? REF_d_view : REF_d_field); |
695 | // TODO: Use the right font: https://developer.apple.com/documentation/uikit/text_display_and_fonts/adding_a_custom_font_to_your_app?language=objc | 725 | if (~flags & insertNewlines_SystemTextInputFlag) { |
726 | [traits setReturnKeyType:UIReturnKeyDone]; | ||
727 | } | ||
696 | if (flags & returnGo_SystemTextInputFlags) { | 728 | if (flags & returnGo_SystemTextInputFlags) { |
697 | [traits setReturnKeyType:UIReturnKeyGo]; | 729 | [traits setReturnKeyType:UIReturnKeyGo]; |
698 | } | 730 | } |
@@ -701,29 +733,38 @@ void init_SystemTextInput(iSystemTextInput *d, iRect rect, int flags) { | |||
701 | } | 733 | } |
702 | if (flags & disableAutocorrect_SystemTextInputFlag) { | 734 | if (flags & disableAutocorrect_SystemTextInputFlag) { |
703 | [traits setAutocorrectionType:UITextAutocorrectionTypeNo]; | 735 | [traits setAutocorrectionType:UITextAutocorrectionTypeNo]; |
704 | [traits setAutocapitalizationType:UITextAutocapitalizationTypeNone]; | ||
705 | [traits setSpellCheckingType:UITextSpellCheckingTypeNo]; | 736 | [traits setSpellCheckingType:UITextSpellCheckingTypeNo]; |
706 | } | 737 | } |
738 | if (flags & disableAutocapitalize_SystemTextInputFlag) { | ||
739 | [traits setAutocapitalizationType:UITextAutocapitalizationTypeNone]; | ||
740 | } | ||
707 | if (flags & alignRight_SystemTextInputFlag) { | 741 | if (flags & alignRight_SystemTextInputFlag) { |
708 | if (d->field) { | 742 | if (d->field) { |
709 | [REF_d_field setTextAlignment:NSTextAlignmentRight]; | 743 | [REF_d_field setTextAlignment:NSTextAlignmentRight]; |
710 | } | 744 | } |
745 | if (d->view) { | ||
746 | [REF_d_view setTextAlignment:NSTextAlignmentRight]; | ||
747 | } | ||
711 | } | 748 | } |
712 | UIColor *textColor = makeUIColor_(uiInputTextFocused_ColorId); | 749 | UIColor *textColor = makeUIColor_(uiInputTextFocused_ColorId); |
713 | UIColor *backgroundColor = makeUIColor_(uiInputBackgroundFocused_ColorId); | 750 | UIColor *backgroundColor = makeUIColor_(uiInputBackgroundFocused_ColorId); |
714 | [appState_ setSystemTextInput:d]; | 751 | [appState_ setSystemTextInput:d]; |
715 | if (d->field) { | 752 | if (d->field) { |
716 | [REF_d_field setTextColor:textColor]; | 753 | UITextField *field = REF_d_field; |
717 | [REF_d_field setDelegate:appState_]; | 754 | [field setTextColor:textColor]; |
718 | [REF_d_field becomeFirstResponder]; | 755 | [field setDelegate:appState_]; |
756 | [field becomeFirstResponder]; | ||
719 | } | 757 | } |
720 | else { | 758 | else { |
721 | [REF_d_view setTextColor:textColor]; | 759 | UITextView *view = REF_d_view; |
722 | [REF_d_view setBackgroundColor:backgroundColor]; | 760 | [view setTextColor:textColor]; |
723 | [REF_d_view setEditable:YES]; | 761 | [view setBackgroundColor:backgroundColor]; |
762 | [view setEditable:YES]; | ||
724 | // [REF_d_view setSelectable:YES]; | 763 | // [REF_d_view setSelectable:YES]; |
725 | [REF_d_view setDelegate:appState_]; | 764 | const float inset = gap_UI / get_Window()->pixelRatio; |
726 | [REF_d_view becomeFirstResponder]; | 765 | //[view setTextContainerInset:(UIEdgeInsets){ inset - 1, -inset - 1, 0, -inset - 1 }]; |
766 | [view setDelegate:appState_]; | ||
767 | [view becomeFirstResponder]; | ||
727 | } | 768 | } |
728 | d->textChangedFunc = NULL; | 769 | d->textChangedFunc = NULL; |
729 | d->textChangedContext = NULL; | 770 | d->textChangedContext = NULL; |
@@ -774,7 +815,11 @@ void setFont_SystemTextInput(iSystemTextInput *d, int fontId) { | |||
774 | font = [UIFont monospacedSystemFontOfSize:0.8f * height weight:UIFontWeightRegular]; | 815 | font = [UIFont monospacedSystemFontOfSize:0.8f * height weight:UIFontWeightRegular]; |
775 | } | 816 | } |
776 | else { | 817 | else { |
777 | font = [UIFont systemFontOfSize:0.65f * height]; | 818 | // font = [UIFont systemFontOfSize:0.65f * height]; |
819 | // for (NSString *name in [UIFont fontNamesForFamilyName:@"Source Sans 3"]) { | ||
820 | // printf("fontname: %s\n", [name cStringUsingEncoding:NSUTF8StringEncoding]); | ||
821 | // } | ||
822 | font = [UIFont fontWithName:@"SourceSans3-Regular" size:height * 0.7f]; | ||
778 | } | 823 | } |
779 | if (d->field) { | 824 | if (d->field) { |
780 | [REF_d_field setFont:font]; | 825 | [REF_d_field setFont:font]; |
@@ -795,7 +840,7 @@ const iString *text_SystemTextInput(const iSystemTextInput *d) { | |||
795 | } | 840 | } |
796 | 841 | ||
797 | void setRect_SystemTextInput(iSystemTextInput *d, iRect rect) { | 842 | void setRect_SystemTextInput(iSystemTextInput *d, iRect rect) { |
798 | CGRect frame = convertToCGRect_(&rect); | 843 | CGRect frame = convertToCGRect_(&rect, (d->flags & multiLine_SystemTextInputFlags) != 0); |
799 | if (d->field) { | 844 | if (d->field) { |
800 | [REF_d_field setFrame:frame]; | 845 | [REF_d_field setFrame:frame]; |
801 | } | 846 | } |
@@ -816,3 +861,7 @@ static void notifyChange_SystemTextInput_(iSystemTextInput *d) { | |||
816 | d->textChangedFunc(d, d->textChangedContext); | 861 | d->textChangedFunc(d, d->textChangedContext); |
817 | } | 862 | } |
818 | } | 863 | } |
864 | |||
865 | static BOOL isNewlineAllowed_SystemTextInput_(const iSystemTextInput *d) { | ||
866 | return (d->flags & insertNewlines_SystemTextInputFlag) != 0; | ||
867 | } | ||
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index ea7ed523..ad45ed92 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -765,6 +765,12 @@ void deinit_InputWidget(iInputWidget *d) { | |||
765 | deinit_Array(&d->lines); | 765 | deinit_Array(&d->lines); |
766 | } | 766 | } |
767 | 767 | ||
768 | static iBool isAllowedToInsertNewline_InputWidget_(const iInputWidget *d) { | ||
769 | return ~d->inFlags & isSensitive_InputWidgetFlag && | ||
770 | ~d->inFlags & isUrl_InputWidgetFlag && | ||
771 | d->inFlags & lineBreaksEnabled_InputWidgetFlag && d->maxLen == 0; | ||
772 | } | ||
773 | |||
768 | #if defined (LAGRANGE_ENABLE_SYSTEM_INPUT) | 774 | #if defined (LAGRANGE_ENABLE_SYSTEM_INPUT) |
769 | static void updateAfterVisualOffsetChange_InputWidget_(iInputWidget *d, iRoot *root) { | 775 | static void updateAfterVisualOffsetChange_InputWidget_(iInputWidget *d, iRoot *root) { |
770 | iAssert(as_Widget(d)->root == root); | 776 | iAssert(as_Widget(d)->root == root); |
@@ -1062,9 +1068,11 @@ void begin_InputWidget(iInputWidget *d) { | |||
1062 | #if defined (LAGRANGE_ENABLE_SYSTEM_INPUT) | 1068 | #if defined (LAGRANGE_ENABLE_SYSTEM_INPUT) |
1063 | d->sysCtrl = new_SystemTextInput(contentBounds_InputWidget_(d), | 1069 | d->sysCtrl = new_SystemTextInput(contentBounds_InputWidget_(d), |
1064 | (d->maxWrapLines > 1 ? multiLine_SystemTextInputFlags : 0) | | 1070 | (d->maxWrapLines > 1 ? multiLine_SystemTextInputFlags : 0) | |
1065 | (d->inFlags & isUrl_InputWidgetFlag ? disableAutocorrect_SystemTextInputFlag : 0) | | 1071 | (d->inFlags & isUrl_InputWidgetFlag ? (disableAutocorrect_SystemTextInputFlag | |
1072 | disableAutocapitalize_SystemTextInputFlag) : 0) | | ||
1066 | (!cmp_String(id_Widget(w), "url") ? returnGo_SystemTextInputFlags : 0) | | 1073 | (!cmp_String(id_Widget(w), "url") ? returnGo_SystemTextInputFlags : 0) | |
1067 | (flags_Widget(w) & alignRight_WidgetFlag ? alignRight_SystemTextInputFlag : 0)); | 1074 | (flags_Widget(w) & alignRight_WidgetFlag ? alignRight_SystemTextInputFlag : 0) | |
1075 | (isAllowedToInsertNewline_InputWidget_(d) ? insertNewlines_SystemTextInputFlag : 0)); | ||
1068 | setFont_SystemTextInput(d->sysCtrl, d->font); | 1076 | setFont_SystemTextInput(d->sysCtrl, d->font); |
1069 | setText_SystemTextInput(d->sysCtrl, &d->oldText); | 1077 | setText_SystemTextInput(d->sysCtrl, &d->oldText); |
1070 | setTextChangedFunc_SystemTextInput(d->sysCtrl, systemInputChanged_InputWidget_, d); | 1078 | setTextChangedFunc_SystemTextInput(d->sysCtrl, systemInputChanged_InputWidget_, d); |
@@ -2110,9 +2118,7 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
2110 | return iTrue; | 2118 | return iTrue; |
2111 | case SDLK_RETURN: | 2119 | case SDLK_RETURN: |
2112 | case SDLK_KP_ENTER: | 2120 | case SDLK_KP_ENTER: |
2113 | if (~d->inFlags & isSensitive_InputWidgetFlag && | 2121 | if (isAllowedToInsertNewline_InputWidget_(d)) { |
2114 | ~d->inFlags & isUrl_InputWidgetFlag && | ||
2115 | d->inFlags & lineBreaksEnabled_InputWidgetFlag && d->maxLen == 0) { | ||
2116 | if (checkLineBreakMods_InputWidget_(d, mods)) { | 2122 | if (checkLineBreakMods_InputWidget_(d, mods)) { |
2117 | pushUndo_InputWidget_(d); | 2123 | pushUndo_InputWidget_(d); |
2118 | deleteMarked_InputWidget_(d); | 2124 | deleteMarked_InputWidget_(d); |