From ce24b48e50ae13a794650b6009fcc0d3e81c11a8 Mon Sep 17 00:00:00 2001 From: Brian Semrau Date: Thu, 7 Jul 2022 14:22:28 -0400 Subject: [PATCH] Add support for multiple virtual keyboard types --- core/bind/core_bind.cpp | 16 ++++-- core/bind/core_bind.h | 18 ++++++- core/os/os.cpp | 2 +- core/os/os.h | 13 ++++- doc/classes/LineEdit.xml | 28 ++++++++++ doc/classes/OS.xml | 39 +++++++++++++- .../src/org/godotengine/godot/GodotIO.java | 7 +-- .../godot/input/GodotEditText.java | 51 ++++++++++++++++--- platform/android/java_godot_io_wrapper.cpp | 6 +-- platform/android/java_godot_io_wrapper.h | 2 +- platform/android/os_android.cpp | 4 +- platform/android/os_android.h | 2 +- platform/iphone/keyboard_input_view.h | 2 +- platform/iphone/keyboard_input_view.mm | 2 +- platform/iphone/os_iphone.h | 2 +- platform/iphone/os_iphone.mm | 38 +++++++++++++- platform/javascript/godot_js.h | 2 +- .../js/libs/library_godot_display.js | 46 +++++++++++++++-- platform/javascript/os_javascript.cpp | 4 +- platform/javascript/os_javascript.h | 2 +- platform/uwp/os_uwp.cpp | 2 +- platform/uwp/os_uwp.h | 2 +- scene/gui/line_edit.cpp | 24 ++++++++- scene/gui/line_edit.h | 16 ++++++ scene/gui/text_edit.cpp | 2 +- 25 files changed, 291 insertions(+), 41 deletions(-) diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 6b13bef93d8..5a382f9b9a2 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -1086,8 +1086,8 @@ bool _OS::has_virtual_keyboard() const { return OS::get_singleton()->has_virtual_keyboard(); } -void _OS::show_virtual_keyboard(const String &p_existing_text, bool p_multiline) { - OS::get_singleton()->show_virtual_keyboard(p_existing_text, Rect2(), p_multiline); +void _OS::show_virtual_keyboard(const String &p_existing_text, _OS::VirtualKeyboardType p_type) { + OS::get_singleton()->show_virtual_keyboard(p_existing_text, Rect2(), OS::VirtualKeyboardType(p_type)); } void _OS::hide_virtual_keyboard() { @@ -1403,7 +1403,8 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("dump_memory_to_file", "file"), &_OS::dump_memory_to_file); ClassDB::bind_method(D_METHOD("dump_resources_to_file", "file"), &_OS::dump_resources_to_file); ClassDB::bind_method(D_METHOD("has_virtual_keyboard"), &_OS::has_virtual_keyboard); - ClassDB::bind_method(D_METHOD("show_virtual_keyboard", "existing_text", "multiline"), &_OS::show_virtual_keyboard, DEFVAL(""), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("show_virtual_keyboard", "existing_text", "multiline"), &_OS::_show_virtual_keyboard, DEFVAL(""), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("show_virtual_keyboard_type", "existing_text", "type"), &_OS::show_virtual_keyboard, DEFVAL(""), DEFVAL(_OS::KEYBOARD_TYPE_DEFAULT)); ClassDB::bind_method(D_METHOD("hide_virtual_keyboard"), &_OS::hide_virtual_keyboard); ClassDB::bind_method(D_METHOD("get_virtual_keyboard_height"), &_OS::get_virtual_keyboard_height); ClassDB::bind_method(D_METHOD("print_resources_in_use", "short"), &_OS::print_resources_in_use, DEFVAL(false)); @@ -1554,6 +1555,15 @@ void _OS::_bind_methods() { BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_SENSOR_PORTRAIT); BIND_ENUM_CONSTANT(SCREEN_ORIENTATION_SENSOR); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_DEFAULT); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_MULTILINE); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER_DECIMAL); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PHONE); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_EMAIL_ADDRESS); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PASSWORD); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_URL); + BIND_ENUM_CONSTANT(SYSTEM_DIR_DESKTOP); BIND_ENUM_CONSTANT(SYSTEM_DIR_DCIM); BIND_ENUM_CONSTANT(SYSTEM_DIR_DOCUMENTS); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index a8207e6f221..680a3a0b96a 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -274,8 +274,23 @@ public: void dump_memory_to_file(const String &p_file); void dump_resources_to_file(const String &p_file); + enum VirtualKeyboardType { + KEYBOARD_TYPE_DEFAULT, + KEYBOARD_TYPE_MULTILINE, + KEYBOARD_TYPE_NUMBER, + KEYBOARD_TYPE_NUMBER_DECIMAL, + KEYBOARD_TYPE_PHONE, + KEYBOARD_TYPE_EMAIL_ADDRESS, + KEYBOARD_TYPE_PASSWORD, + KEYBOARD_TYPE_URL + }; + + void _show_virtual_keyboard(const String &p_existing_text = "", bool p_multiline = false) { + show_virtual_keyboard(p_existing_text, p_multiline ? KEYBOARD_TYPE_MULTILINE : KEYBOARD_TYPE_DEFAULT); + } + bool has_virtual_keyboard() const; - void show_virtual_keyboard(const String &p_existing_text = "", bool p_multiline = false); + void show_virtual_keyboard(const String &p_existing_text = "", VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT); void hide_virtual_keyboard(); int get_virtual_keyboard_height(); @@ -410,6 +425,7 @@ VARIANT_ENUM_CAST(_OS::VideoDriver); VARIANT_ENUM_CAST(_OS::PowerState); VARIANT_ENUM_CAST(_OS::Weekday); VARIANT_ENUM_CAST(_OS::Month); +VARIANT_ENUM_CAST(_OS::VirtualKeyboardType); VARIANT_ENUM_CAST(_OS::SystemDir); VARIANT_ENUM_CAST(_OS::ScreenOrientation); VARIANT_ENUM_CAST(_OS::HandleType); diff --git a/core/os/os.cpp b/core/os/os.cpp index 385ebfa5485..5d2f2339901 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -222,7 +222,7 @@ bool OS::has_virtual_keyboard() const { return false; } -void OS::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { +void OS::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) { } void OS::hide_virtual_keyboard() { diff --git a/core/os/os.h b/core/os/os.h index b46063c8d3c..28272a7e29e 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -437,8 +437,19 @@ public: CURSOR_MAX }; + enum VirtualKeyboardType { + KEYBOARD_TYPE_DEFAULT, + KEYBOARD_TYPE_MULTILINE, + KEYBOARD_TYPE_NUMBER, + KEYBOARD_TYPE_NUMBER_DECIMAL, + KEYBOARD_TYPE_PHONE, + KEYBOARD_TYPE_EMAIL_ADDRESS, + KEYBOARD_TYPE_PASSWORD, + KEYBOARD_TYPE_URL + }; + virtual bool has_virtual_keyboard() const; - virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1); + virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1); virtual void hide_virtual_keyboard(); // returns height of the currently shown virtual keyboard (0 if keyboard is hidden) diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index dc2d6be4f14..2644db3a9d3 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -196,6 +196,9 @@ If [code]true[/code], the native virtual keyboard is shown when focused on platforms that support it. + + Specifies the type of virtual keyboard to show. + @@ -255,6 +258,31 @@ Represents the size of the [enum MenuItems] enum. + + Default text virtual keyboard. + + + Multiline virtual keyboard. + + + Virtual number keypad, useful for PIN entry. + + + Virtual number keypad, useful for entering fractional numbers. + + + Virtual phone number keypad. + + + Virtual keyboard with additional keys to assist with typing email addresses. + + + Virtual keyboard for entering a password. On most platforms, this should disable autocomplete and autocapitalization. + [b]Note:[/b] This is not supported on HTML5 or below iOS version 11.0. Instead, this will behave identically to [constant KEYBOARD_TYPE_DEFAULT]. + + + Virtual keyboard with additional keys to assist with typing URLs. + diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index fe7ed82a58f..dc49fc79331 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -1017,7 +1017,19 @@ Shows the virtual keyboard if the platform has one. The [code]existing_text[/code] parameter is useful for implementing your own [LineEdit] or [TextEdit], as it tells the virtual keyboard what text has already been typed (the virtual keyboard uses it for auto-correct and predictions). The [code]multiline[/code] parameter needs to be set to [code]true[/code] to be able to enter multiple lines of text, as in [TextEdit]. - [b]Note:[/b] This method is implemented on Android, iOS and UWP. + [b]Note:[/b] This method is equivalent to calling [method show_virtual_keyboard_type] with either default or multiline keyboard type. It is kept for compatibility with previous Godot releases and should be considered [i]deprecated[/i] and replaced by [method show_virtual_keyboard_type]. + [b]Note:[/b] This method is implemented on Android, iOS, UWP, and HTML5. + + + + + + + + Shows the virtual keyboard if the platform has one. + The [code]existing_text[/code] parameter is useful for implementing your own [LineEdit] or [TextEdit], as it tells the virtual keyboard what text has already been typed (the virtual keyboard uses it for auto-correct and predictions). + The [code]type[/code] parameter allows selecting which virtual keyboard to show. + [b]Note:[/b] This method is implemented on Android, iOS, UWP, and HTML5. @@ -1207,6 +1219,31 @@ Uses most suitable orientation based on the hardware sensor. + + Default text virtual keyboard. + + + Multiline virtual keyboard. + + + Virtual number keypad, useful for PIN entry. + + + Virtual number keypad, useful for entering fractional numbers. + + + Virtual phone number keypad. + + + Virtual keyboard with additional keys to assist with typing email addresses. + + + Virtual keyboard for entering a password. On most platforms, this should disable autocomplete and autocapitalization. + [b]Note:[/b] This is not supported on HTML5 or below iOS version 11.0. Instead, this will behave identically to [constant KEYBOARD_TYPE_DEFAULT]. + + + Virtual keyboard with additional keys to assist with typing URLs. + Desktop directory path. diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java index b482a29f258..940b1546ed8 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java @@ -203,9 +203,10 @@ public class GodotIO { return result; } - public void showKeyboard(String p_existing_text, boolean p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { - if (edit != null) - edit.showKeyboard(p_existing_text, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end); + public void showKeyboard(String p_existing_text, int p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) { + if (edit != null) { + edit.showKeyboard(p_existing_text, GodotEditText.VirtualKeyboardType.values()[p_type], p_max_input_length, p_cursor_start, p_cursor_end); + } //InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE); //inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java index 4e7996e350c..d2350a635d7 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java @@ -52,6 +52,18 @@ public class GodotEditText extends EditText { private final static int HANDLER_OPEN_IME_KEYBOARD = 2; private final static int HANDLER_CLOSE_IME_KEYBOARD = 3; + // Enum must be kept up-to-date with OS::VirtualKeyboardType + public enum VirtualKeyboardType { + KEYBOARD_TYPE_DEFAULT, + KEYBOARD_TYPE_MULTILINE, + KEYBOARD_TYPE_NUMBER, + KEYBOARD_TYPE_NUMBER_DECIMAL, + KEYBOARD_TYPE_PHONE, + KEYBOARD_TYPE_EMAIL_ADDRESS, + KEYBOARD_TYPE_PASSWORD, + KEYBOARD_TYPE_URL + } + // =========================================================== // Fields // =========================================================== @@ -60,7 +72,7 @@ public class GodotEditText extends EditText { private EditHandler sHandler = new EditHandler(this); private String mOriginText; private int mMaxInputLength = Integer.MAX_VALUE; - private boolean mMultiline = false; + private VirtualKeyboardType mKeyboardType = VirtualKeyboardType.KEYBOARD_TYPE_DEFAULT; private static class EditHandler extends Handler { private final WeakReference mEdit; @@ -101,7 +113,11 @@ public class GodotEditText extends EditText { } public boolean isMultiline() { - return mMultiline; + return mKeyboardType == VirtualKeyboardType.KEYBOARD_TYPE_MULTILINE; + } + + public VirtualKeyboardType getKeyboardType() { + return mKeyboardType; } private void handleMessage(final Message msg) { @@ -122,8 +138,31 @@ public class GodotEditText extends EditText { } int inputType = InputType.TYPE_CLASS_TEXT; - if (edit.isMultiline()) { - inputType |= InputType.TYPE_TEXT_FLAG_MULTI_LINE; + switch (edit.getKeyboardType()) { + case KEYBOARD_TYPE_DEFAULT: + inputType = InputType.TYPE_CLASS_TEXT; + break; + case KEYBOARD_TYPE_MULTILINE: + inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE; + break; + case KEYBOARD_TYPE_NUMBER: + inputType = InputType.TYPE_CLASS_NUMBER; + break; + case KEYBOARD_TYPE_NUMBER_DECIMAL: + inputType = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED; + break; + case KEYBOARD_TYPE_PHONE: + inputType = InputType.TYPE_CLASS_PHONE; + break; + case KEYBOARD_TYPE_EMAIL_ADDRESS: + inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; + break; + case KEYBOARD_TYPE_PASSWORD: + inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD; + break; + case KEYBOARD_TYPE_URL: + inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI; + break; } edit.setInputType(inputType); @@ -197,7 +236,7 @@ public class GodotEditText extends EditText { // =========================================================== // Methods // =========================================================== - public void showKeyboard(String p_existing_text, boolean p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { + public void showKeyboard(String p_existing_text, VirtualKeyboardType p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) { int maxInputLength = (p_max_input_length <= 0) ? Integer.MAX_VALUE : p_max_input_length; if (p_cursor_start == -1) { // cursor position not given this.mOriginText = p_existing_text; @@ -210,7 +249,7 @@ public class GodotEditText extends EditText { this.mMaxInputLength = maxInputLength - (p_existing_text.length() - p_cursor_end); } - this.mMultiline = p_multiline; + this.mKeyboardType = p_type; final Message msg = new Message(); msg.what = HANDLER_OPEN_IME_KEYBOARD; diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp index 0c61219fe74..9fdde9281ef 100644 --- a/platform/android/java_godot_io_wrapper.cpp +++ b/platform/android/java_godot_io_wrapper.cpp @@ -61,7 +61,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc _get_screen_refresh_rate = p_env->GetMethodID(cls, "getScreenRefreshRate", "(D)D"); _get_window_safe_area = p_env->GetMethodID(cls, "getWindowSafeArea", "()[I"), _get_unique_id = p_env->GetMethodID(cls, "getUniqueID", "()Ljava/lang/String;"); - _show_keyboard = p_env->GetMethodID(cls, "showKeyboard", "(Ljava/lang/String;ZIII)V"); + _show_keyboard = p_env->GetMethodID(cls, "showKeyboard", "(Ljava/lang/String;IIII)V"); _hide_keyboard = p_env->GetMethodID(cls, "hideKeyboard", "()V"); _set_screen_orientation = p_env->GetMethodID(cls, "setScreenOrientation", "(I)V"); _get_screen_orientation = p_env->GetMethodID(cls, "getScreenOrientation", "()I"); @@ -215,12 +215,12 @@ bool GodotIOJavaWrapper::has_vk() { return (_show_keyboard != nullptr) && (_hide_keyboard != nullptr); } -void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { +void GodotIOJavaWrapper::show_vk(const String &p_existing, int p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) { if (_show_keyboard) { JNIEnv *env = get_jni_env(); ERR_FAIL_NULL(env); jstring jStr = env->NewStringUTF(p_existing.utf8().get_data()); - env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end); + env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_type, p_max_input_length, p_cursor_start, p_cursor_end); } } diff --git a/platform/android/java_godot_io_wrapper.h b/platform/android/java_godot_io_wrapper.h index 48320cdbd74..dfb8132b1b0 100644 --- a/platform/android/java_godot_io_wrapper.h +++ b/platform/android/java_godot_io_wrapper.h @@ -80,7 +80,7 @@ public: float get_screen_refresh_rate(float p_fallback); String get_unique_id(); bool has_vk(); - void show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end); + void show_vk(const String &p_existing, int p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end); void hide_vk(); int get_vk_height(); void set_vk_height(int p_height); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index a18cc7a572b..26488e82334 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -387,9 +387,9 @@ int OS_Android::get_virtual_keyboard_height() const { return godot_io_java->get_vk_height(); } -void OS_Android::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { +void OS_Android::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) { if (godot_io_java->has_vk()) { - godot_io_java->show_vk(p_existing_text, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end); + godot_io_java->show_vk(p_existing_text, (int)p_type, p_max_input_length, p_cursor_start, p_cursor_end); } else { ERR_PRINT("Virtual keyboard not available"); } diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 4820d6c8b42..cd8237db037 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -128,7 +128,7 @@ public: virtual bool has_touchscreen_ui_hint() const; virtual bool has_virtual_keyboard() const; - virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1); + virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1); virtual void hide_virtual_keyboard(); virtual int get_virtual_keyboard_height() const; diff --git a/platform/iphone/keyboard_input_view.h b/platform/iphone/keyboard_input_view.h index 33fa5d571a4..fc34e6a11b1 100644 --- a/platform/iphone/keyboard_input_view.h +++ b/platform/iphone/keyboard_input_view.h @@ -32,6 +32,6 @@ @interface GodotKeyboardInputView : UITextView -- (BOOL)becomeFirstResponderWithString:(NSString *)existingString multiline:(BOOL)flag cursorStart:(NSInteger)start cursorEnd:(NSInteger)end; +- (BOOL)becomeFirstResponderWithString:(NSString *)existingString cursorStart:(NSInteger)start cursorEnd:(NSInteger)end; @end diff --git a/platform/iphone/keyboard_input_view.mm b/platform/iphone/keyboard_input_view.mm index a7760f73e17..393a2e7c5b3 100644 --- a/platform/iphone/keyboard_input_view.mm +++ b/platform/iphone/keyboard_input_view.mm @@ -83,7 +83,7 @@ return YES; } -- (BOOL)becomeFirstResponderWithString:(NSString *)existingString multiline:(BOOL)flag cursorStart:(NSInteger)start cursorEnd:(NSInteger)end { +- (BOOL)becomeFirstResponderWithString:(NSString *)existingString cursorStart:(NSInteger)start cursorEnd:(NSInteger)end { self.text = existingString; self.previousText = existingString; diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index c2fdd1bcd0b..ebdfb4bb5f5 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -175,7 +175,7 @@ public: virtual bool can_draw() const; virtual bool has_virtual_keyboard() const; - virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1); + virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1); virtual void hide_virtual_keyboard(); virtual int get_virtual_keyboard_height() const; diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm index 87dea7698d5..c36de41da5c 100644 --- a/platform/iphone/os_iphone.mm +++ b/platform/iphone/os_iphone.mm @@ -451,12 +451,46 @@ bool OSIPhone::has_virtual_keyboard() const { return true; }; -void OSIPhone::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { +void OSIPhone::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) { NSString *existingString = [[NSString alloc] initWithUTF8String:p_existing_text.utf8().get_data()]; + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault; + AppDelegate.viewController.keyboardView.textContentType = nil; + switch (p_type) { + case KEYBOARD_TYPE_DEFAULT: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault; + } break; + case KEYBOARD_TYPE_MULTILINE: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault; + } break; + case KEYBOARD_TYPE_NUMBER: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeNumberPad; + } break; + case KEYBOARD_TYPE_NUMBER_DECIMAL: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDecimalPad; + } break; + case KEYBOARD_TYPE_PHONE: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypePhonePad; + AppDelegate.viewController.keyboardView.textContentType = UITextContentTypeTelephoneNumber; + } break; + case KEYBOARD_TYPE_EMAIL_ADDRESS: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeEmailAddress; + AppDelegate.viewController.keyboardView.textContentType = UITextContentTypeEmailAddress; + } break; + case KEYBOARD_TYPE_PASSWORD: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeDefault; + if (@available(iOS 11.0, *)) { + AppDelegate.viewController.keyboardView.textContentType = UITextContentTypePassword; + } + } break; + case KEYBOARD_TYPE_URL: { + AppDelegate.viewController.keyboardView.keyboardType = UIKeyboardTypeWebSearch; + AppDelegate.viewController.keyboardView.textContentType = UITextContentTypeURL; + } break; + } + [AppDelegate.viewController.keyboardView becomeFirstResponderWithString:existingString - multiline:p_multiline cursorStart:p_cursor_start cursorEnd:p_cursor_end]; }; diff --git a/platform/javascript/godot_js.h b/platform/javascript/godot_js.h index 2cb5c3025c9..d000f13fbd7 100644 --- a/platform/javascript/godot_js.h +++ b/platform/javascript/godot_js.h @@ -110,7 +110,7 @@ extern void godot_js_display_notification_cb(void (*p_callback)(int p_notificati // Display Virtual Keyboard extern int godot_js_display_vk_available(); extern void godot_js_display_vk_cb(void (*p_input)(const char *p_text, int p_cursor)); -extern void godot_js_display_vk_show(const char *p_text, int p_multiline, int p_start, int p_end); +extern void godot_js_display_vk_show(const char *p_text, int p_type, int p_start, int p_end); extern void godot_js_display_vk_hide(); #ifdef __cplusplus diff --git a/platform/javascript/js/libs/library_godot_display.js b/platform/javascript/js/libs/library_godot_display.js index 2085a4c6e1d..22ffb1629fc 100644 --- a/platform/javascript/js/libs/library_godot_display.js +++ b/platform/javascript/js/libs/library_godot_display.js @@ -73,7 +73,7 @@ const GodotDisplayVK = { GodotDisplayVK.textarea = create('textarea'); GodotDisplayVK.updateSize(); }, - show: function (text, multiline, start, end) { + show: function (text, type, start, end) { if (!GodotDisplayVK.textinput || !GodotDisplayVK.textarea) { return; } @@ -81,7 +81,45 @@ const GodotDisplayVK = { GodotDisplayVK.hide(); } GodotDisplayVK.updateSize(); - const elem = multiline ? GodotDisplayVK.textarea : GodotDisplayVK.textinput; + + let elem = GodotDisplayVK.textinput; + switch (type) { + case 0: // KEYBOARD_TYPE_DEFAULT + elem.type = 'text'; + elem.inputmode = ''; + break; + case 1: // KEYBOARD_TYPE_MULTILINE + elem = GodotDisplayVK.textarea; + break; + case 2: // KEYBOARD_TYPE_NUMBER + elem.type = 'text'; + elem.inputmode = 'numeric'; + break; + case 3: // KEYBOARD_TYPE_NUMBER_DECIMAL + elem.type = 'text'; + elem.inputmode = 'decimal'; + break; + case 4: // KEYBOARD_TYPE_PHONE + elem.type = 'tel'; + elem.inputmode = ''; + break; + case 5: // KEYBOARD_TYPE_EMAIL_ADDRESS + elem.type = 'email'; + elem.inputmode = ''; + break; + case 6: // KEYBOARD_TYPE_PASSWORD + elem.type = 'password'; + elem.inputmode = ''; + break; + case 7: // KEYBOARD_TYPE_URL + elem.type = 'url'; + elem.inputmode = ''; + break; + default: + elem.type = 'text'; + elem.inputmode = ''; + break; + } elem.readonly = false; elem.disabled = false; elem.value = text; @@ -621,11 +659,11 @@ const GodotDisplay = { * Virtual Keyboard */ godot_js_display_vk_show__sig: 'viiii', - godot_js_display_vk_show: function (p_text, p_multiline, p_start, p_end) { + godot_js_display_vk_show: function (p_text, p_type, p_start, p_end) { const text = GodotRuntime.parseString(p_text); const start = p_start > 0 ? p_start : 0; const end = p_end > 0 ? p_end : start; - GodotDisplayVK.show(text, p_multiline, start, end); + GodotDisplayVK.show(text, p_type, start, end); }, godot_js_display_vk_hide__sig: 'v', diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 991b7a65147..7d57fceae7d 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -801,8 +801,8 @@ bool OS_JavaScript::has_virtual_keyboard() const { return godot_js_display_vk_available() != 0; } -void OS_JavaScript::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { - godot_js_display_vk_show(p_existing_text.utf8().get_data(), p_multiline, p_cursor_start, p_cursor_end); +void OS_JavaScript::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) { + godot_js_display_vk_show(p_existing_text.utf8().get_data(), p_type, p_cursor_start, p_cursor_end); } void OS_JavaScript::hide_virtual_keyboard() { diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index fc646a026ba..6104065a167 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -125,7 +125,7 @@ public: static OS_JavaScript *get_singleton(); virtual bool has_virtual_keyboard() const; - virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1); + virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1); virtual void hide_virtual_keyboard(); virtual bool get_swap_ok_cancel(); diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index a5731120dc2..ee81f2ee0ac 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -741,7 +741,7 @@ bool OS_UWP::has_virtual_keyboard() const { return UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Touch; } -void OS_UWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { +void OS_UWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_input_length, int p_cursor_start, int p_cursor_end) { InputPane ^ pane = InputPane::GetForCurrentView(); pane->TryShow(); } diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index de279074d64..ce7faedd657 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -235,7 +235,7 @@ public: virtual bool has_touchscreen_ui_hint() const; virtual bool has_virtual_keyboard() const; - virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1); + virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1); virtual void hide_virtual_keyboard(); virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index c3cf6504700..9a654ed4163 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -1407,9 +1407,9 @@ void LineEdit::clear() { void LineEdit::show_virtual_keyboard() { if (OS::get_singleton()->has_virtual_keyboard() && virtual_keyboard_enabled) { if (selection.enabled) { - OS::get_singleton()->show_virtual_keyboard(text, get_global_rect(), false, max_length, selection.begin, selection.end); + OS::get_singleton()->show_virtual_keyboard(text, get_global_rect(), (OS::VirtualKeyboardType)virtual_keyboard_type, max_length, selection.begin, selection.end); } else { - OS::get_singleton()->show_virtual_keyboard(text, get_global_rect(), false, max_length, cursor_pos); + OS::get_singleton()->show_virtual_keyboard(text, get_global_rect(), (OS::VirtualKeyboardType)virtual_keyboard_type, max_length, cursor_pos); } } } @@ -1822,6 +1822,14 @@ bool LineEdit::is_virtual_keyboard_enabled() const { return virtual_keyboard_enabled; } +void LineEdit::set_virtual_keyboard_type(VirtualKeyboardType p_type) { + virtual_keyboard_type = p_type; +} + +LineEdit::VirtualKeyboardType LineEdit::get_virtual_keyboard_type() const { + return virtual_keyboard_type; +} + void LineEdit::set_middle_mouse_paste_enabled(bool p_enabled) { middle_mouse_paste_enabled = p_enabled; } @@ -2005,6 +2013,8 @@ void LineEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("is_context_menu_enabled"), &LineEdit::is_context_menu_enabled); ClassDB::bind_method(D_METHOD("set_virtual_keyboard_enabled", "enable"), &LineEdit::set_virtual_keyboard_enabled); ClassDB::bind_method(D_METHOD("is_virtual_keyboard_enabled"), &LineEdit::is_virtual_keyboard_enabled); + ClassDB::bind_method(D_METHOD("set_virtual_keyboard_type", "type"), &LineEdit::set_virtual_keyboard_type); + ClassDB::bind_method(D_METHOD("get_virtual_keyboard_type"), &LineEdit::get_virtual_keyboard_type); ClassDB::bind_method(D_METHOD("set_clear_button_enabled", "enable"), &LineEdit::set_clear_button_enabled); ClassDB::bind_method(D_METHOD("is_clear_button_enabled"), &LineEdit::is_clear_button_enabled); ClassDB::bind_method(D_METHOD("set_shortcut_keys_enabled", "enable"), &LineEdit::set_shortcut_keys_enabled); @@ -2036,6 +2046,15 @@ void LineEdit::_bind_methods() { BIND_ENUM_CONSTANT(MENU_REDO); BIND_ENUM_CONSTANT(MENU_MAX); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_DEFAULT); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_MULTILINE); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER_DECIMAL); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PHONE); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_EMAIL_ADDRESS); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PASSWORD); + BIND_ENUM_CONSTANT(KEYBOARD_TYPE_URL); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text"); ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_length", PROPERTY_HINT_RANGE, "0,1000,1,or_greater"), "set_max_length", "get_max_length"); @@ -2045,6 +2064,7 @@ void LineEdit::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand_to_text_length"), "set_expand_to_text_length", "get_expand_to_text_length"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "virtual_keyboard_enabled"), "set_virtual_keyboard_enabled", "is_virtual_keyboard_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "virtual_keyboard_type", PROPERTY_HINT_ENUM, "Default,Multiline,Number,Decimal,Phone,Email,Password,URL"), "set_virtual_keyboard_type", "get_virtual_keyboard_type"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clear_button_enabled"), "set_clear_button_enabled", "is_clear_button_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "middle_mouse_paste_enabled"), "set_middle_mouse_paste_enabled", "is_middle_mouse_paste_enabled"); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 14c3f4795c0..458a4e40dd6 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -58,6 +58,17 @@ public: }; + enum VirtualKeyboardType { + KEYBOARD_TYPE_DEFAULT, + KEYBOARD_TYPE_MULTILINE, + KEYBOARD_TYPE_NUMBER, + KEYBOARD_TYPE_NUMBER_DECIMAL, + KEYBOARD_TYPE_PHONE, + KEYBOARD_TYPE_EMAIL_ADDRESS, + KEYBOARD_TYPE_PASSWORD, + KEYBOARD_TYPE_URL + }; + private: Align align; @@ -93,6 +104,7 @@ private: bool shortcut_keys_enabled; bool virtual_keyboard_enabled = true; + VirtualKeyboardType virtual_keyboard_type = KEYBOARD_TYPE_DEFAULT; bool drag_action = false; bool drag_caret_force_displayed = false; @@ -244,6 +256,9 @@ public: void set_virtual_keyboard_enabled(bool p_enable); bool is_virtual_keyboard_enabled() const; + void set_virtual_keyboard_type(VirtualKeyboardType p_type); + VirtualKeyboardType get_virtual_keyboard_type() const; + void set_middle_mouse_paste_enabled(bool p_enabled); bool is_middle_mouse_paste_enabled() const; @@ -266,5 +281,6 @@ public: VARIANT_ENUM_CAST(LineEdit::Align); VARIANT_ENUM_CAST(LineEdit::MenuItems); +VARIANT_ENUM_CAST(LineEdit::VirtualKeyboardType); #endif diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 5d092e6c0df..ce43de25afb 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1880,7 +1880,7 @@ void TextEdit::_notification(int p_what) { cursor_end = cursor_start + post_text.length(); } - OS::get_singleton()->show_virtual_keyboard(get_text(), get_global_rect(), true, -1, cursor_start, cursor_end); + OS::get_singleton()->show_virtual_keyboard(get_text(), get_global_rect(), OS::KEYBOARD_TYPE_MULTILINE, -1, cursor_start, cursor_end); } } break; case NOTIFICATION_FOCUS_EXIT: {