diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 4cf0c58cd..ce598641c 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -30,6 +30,7 @@ #include "core_bind.h" +#include "core/config/project_settings.h" #include "core/crypto/crypto_core.h" #include "core/io/file_access_compressed.h" #include "core/io/file_access_encrypted.h" @@ -39,7 +40,6 @@ #include "core/object/method_bind_ext.gen.inc" #include "core/os/keyboard.h" #include "core/os/os.h" -#include "core/config/project_settings.h" /** * Time constants borrowed from loc_time.h @@ -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)); @@ -1553,6 +1554,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 803e463af..3bba6782b 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -30,16 +30,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "core/io/image.h" #include "core/io/compression.h" +#include "core/io/image.h" #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" #include "core/os/dir_access.h" #include "core/os/file_access.h" #include "core/os/os.h" +#include "core/os/safe_refcount.h" #include "core/os/semaphore.h" #include "core/os/thread.h" -#include "core/os/safe_refcount.h" class _ResourceLoader : public Object { GDCLASS(_ResourceLoader, Object); @@ -272,8 +272,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(); @@ -408,6 +423,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 9039668b2..3db9d5e5a 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -337,7 +337,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 8dd93927d..26f22884c 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -31,12 +31,12 @@ /*************************************************************************/ #include "core/config/engine.h" +#include "core/containers/list.h" +#include "core/containers/vector.h" #include "core/io/image.h" #include "core/io/logger.h" -#include "core/containers/list.h" #include "core/os/main_loop.h" #include "core/string/ustring.h" -#include "core/containers/vector.h" #include #include @@ -449,8 +449,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 57a241b2b..1285076cc 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -192,6 +192,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. + @@ -251,6 +254,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 bcdf49546..6269a5033 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. @@ -1204,6 +1216,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/net/relintai/pandemonium/pandemonium/PandemoniumIO.java b/platform/android/java/lib/src/net/relintai/pandemonium/pandemonium/PandemoniumIO.java index 5c836cf08..6f89261f8 100644 --- a/platform/android/java/lib/src/net/relintai/pandemonium/pandemonium/PandemoniumIO.java +++ b/platform/android/java/lib/src/net/relintai/pandemonium/pandemonium/PandemoniumIO.java @@ -203,9 +203,10 @@ public class PandemoniumIO { 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/net/relintai/pandemonium/pandemonium/input/PandemoniumEditText.java b/platform/android/java/lib/src/net/relintai/pandemonium/pandemonium/input/PandemoniumEditText.java index a074181a1..bac91754c 100644 --- a/platform/android/java/lib/src/net/relintai/pandemonium/pandemonium/input/PandemoniumEditText.java +++ b/platform/android/java/lib/src/net/relintai/pandemonium/pandemonium/input/PandemoniumEditText.java @@ -52,6 +52,18 @@ public class PandemoniumEditText 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 PandemoniumEditText 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 PandemoniumEditText 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 PandemoniumEditText 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 PandemoniumEditText 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 PandemoniumEditText 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_pandemonium_io_wrapper.cpp b/platform/android/java_pandemonium_io_wrapper.cpp index f642392fa..b9e9f189d 100644 --- a/platform/android/java_pandemonium_io_wrapper.cpp +++ b/platform/android/java_pandemonium_io_wrapper.cpp @@ -60,7 +60,7 @@ PandemoniumIOJavaWrapper::PandemoniumIOJavaWrapper(JNIEnv *p_env, jobject p_pand _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"); @@ -214,12 +214,12 @@ bool PandemoniumIOJavaWrapper::has_vk() { return (_show_keyboard != 0) && (_hide_keyboard != 0); } -void PandemoniumIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { +void PandemoniumIOJavaWrapper::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_COND(env == nullptr); jstring jStr = env->NewStringUTF(p_existing.utf8().get_data()); - env->CallVoidMethod(pandemonium_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_pandemonium_io_wrapper.h b/platform/android/java_pandemonium_io_wrapper.h index 785acadf1..6dc556d06 100644 --- a/platform/android/java_pandemonium_io_wrapper.h +++ b/platform/android/java_pandemonium_io_wrapper.h @@ -79,7 +79,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 2943edc86..b1c290b2f 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -375,9 +375,9 @@ int OS_Android::get_virtual_keyboard_height() const { // return 0; } -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 (pandemonium_io_java->has_vk()) { - pandemonium_io_java->show_vk(p_existing_text, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end); + pandemonium_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 5f471d188..7bcd3631b 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -132,7 +132,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 59e61b109..2cc99ea4d 100644 --- a/platform/iphone/keyboard_input_view.h +++ b/platform/iphone/keyboard_input_view.h @@ -32,6 +32,6 @@ @interface PandemoniumKeyboardInputView : 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 1ebb0f24b..e988b61a5 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 e5c381e47..04320fa71 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -174,7 +174,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 7e7a0e78d..0b4e29651 100644 --- a/platform/iphone/os_iphone.mm +++ b/platform/iphone/os_iphone.mm @@ -38,10 +38,10 @@ #include "main/main.h" +#include "core/config/project_settings.h" #include "core/io/file_access_pack.h" #include "core/os/dir_access.h" #include "core/os/file_access.h" -#include "core/config/project_settings.h" #include "drivers/unix/syslog_logger.h" #import "app_delegate.h" @@ -439,12 +439,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/js/libs/library_pandemonium_display.js b/platform/javascript/js/libs/library_pandemonium_display.js index d4ee425c7..f6b96ed7d 100644 --- a/platform/javascript/js/libs/library_pandemonium_display.js +++ b/platform/javascript/js/libs/library_pandemonium_display.js @@ -30,101 +30,138 @@ const PandemoniumDisplayVK = { - $PandemoniumDisplayVK__deps: ['$PandemoniumRuntime', '$PandemoniumConfig', '$PandemoniumEventListeners'], - $PandemoniumDisplayVK__postset: 'PandemoniumOS.atexit(function(resolve, reject) { PandemoniumDisplayVK.clear(); resolve(); });', - $PandemoniumDisplayVK: { - textinput: null, - textarea: null, + $PandemoniumDisplayVK__deps: ['$PandemoniumRuntime', '$PandemoniumConfig', '$PandemoniumEventListeners'], + $PandemoniumDisplayVK__postset: 'PandemoniumOS.atexit(function(resolve, reject) { PandemoniumDisplayVK.clear(); resolve(); });', + $PandemoniumDisplayVK: { + textinput: null, + textarea: null, - available: function() { - return PandemoniumConfig.virtual_keyboard && 'ontouchstart' in window; - }, + available: function() { + return PandemoniumConfig.virtual_keyboard && 'ontouchstart' in window; + }, - init: function(input_cb) { - function create(what) { - const elem = document.createElement(what); - elem.style.display = 'none'; - elem.style.position = 'absolute'; - elem.style.zIndex = '-1'; - elem.style.background = 'transparent'; - elem.style.padding = '0px'; - elem.style.margin = '0px'; - elem.style.overflow = 'hidden'; - elem.style.width = '0px'; - elem.style.height = '0px'; - elem.style.border = '0px'; - elem.style.outline = 'none'; - elem.readonly = true; - elem.disabled = true; - PandemoniumEventListeners.add(elem, 'input', function(evt) { - const c_str = PandemoniumRuntime.allocString(elem.value); - input_cb(c_str, elem.selectionEnd); - PandemoniumRuntime.free(c_str); - }, false); - PandemoniumEventListeners.add(elem, 'blur', function(evt) { - elem.style.display = 'none'; - elem.readonly = true; - elem.disabled = true; - }, false); - PandemoniumConfig.canvas.insertAdjacentElement('beforebegin', elem); - return elem; - } - PandemoniumDisplayVK.textinput = create('input'); - PandemoniumDisplayVK.textarea = create('textarea'); - PandemoniumDisplayVK.updateSize(); - }, - show: function(text, multiline, start, end) { - if (!PandemoniumDisplayVK.textinput || !PandemoniumDisplayVK.textarea) { - return; - } - if (PandemoniumDisplayVK.textinput.style.display !== '' || PandemoniumDisplayVK.textarea.style.display !== '') { - PandemoniumDisplayVK.hide(); - } - PandemoniumDisplayVK.updateSize(); - const elem = multiline ? PandemoniumDisplayVK.textarea : PandemoniumDisplayVK.textinput; - elem.readonly = false; - elem.disabled = false; - elem.value = text; - elem.style.display = 'block'; - elem.focus(); - elem.setSelectionRange(start, end); - }, - hide: function() { - if (!PandemoniumDisplayVK.textinput || !PandemoniumDisplayVK.textarea) { - return; - } - [PandemoniumDisplayVK.textinput, PandemoniumDisplayVK.textarea].forEach(function(elem) { - elem.blur(); - elem.style.display = 'none'; - elem.value = ''; - }); - }, - updateSize: function() { - if (!PandemoniumDisplayVK.textinput || !PandemoniumDisplayVK.textarea) { - return; - } - const rect = PandemoniumConfig.canvas.getBoundingClientRect(); + init: function(input_cb) { + function create(what) { + const elem = document.createElement(what); + elem.style.display = 'none'; + elem.style.position = 'absolute'; + elem.style.zIndex = '-1'; + elem.style.background = 'transparent'; + elem.style.padding = '0px'; + elem.style.margin = '0px'; + elem.style.overflow = 'hidden'; + elem.style.width = '0px'; + elem.style.height = '0px'; + elem.style.border = '0px'; + elem.style.outline = 'none'; + elem.readonly = true; + elem.disabled = true; + PandemoniumEventListeners.add(elem, 'input', function(evt) { + const c_str = PandemoniumRuntime.allocString(elem.value); + input_cb(c_str, elem.selectionEnd); + PandemoniumRuntime.free(c_str); + }, false); + PandemoniumEventListeners.add(elem, 'blur', function(evt) { + elem.style.display = 'none'; + elem.readonly = true; + elem.disabled = true; + }, false); + PandemoniumConfig.canvas.insertAdjacentElement('beforebegin', elem); + return elem; + } + PandemoniumDisplayVK.textinput = create('input'); + PandemoniumDisplayVK.textarea = create('textarea'); + PandemoniumDisplayVK.updateSize(); + }, + show: function(text, type, start, end) { + if (!PandemoniumDisplayVK.textinput || !PandemoniumDisplayVK.textarea) { + return; + } + if (PandemoniumDisplayVK.textinput.style.display !== '' || PandemoniumDisplayVK.textarea.style.display !== '') { + PandemoniumDisplayVK.hide(); + } + PandemoniumDisplayVK.updateSize(); + 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; + elem.style.display = 'block'; + elem.focus(); + elem.setSelectionRange(start, end); + }, + hide: function() { + if (!PandemoniumDisplayVK.textinput || !PandemoniumDisplayVK.textarea) { + return; + } + [PandemoniumDisplayVK.textinput, PandemoniumDisplayVK.textarea].forEach(function(elem) { + elem.blur(); + elem.style.display = 'none'; + elem.value = ''; + }); + }, + updateSize: function() { + if (!PandemoniumDisplayVK.textinput || !PandemoniumDisplayVK.textarea) { + return; + } + const rect = PandemoniumConfig.canvas.getBoundingClientRect(); - function update(elem) { - elem.style.left = `${rect.left}px`; - elem.style.top = `${rect.top}px`; - elem.style.width = `${rect.width}px`; - elem.style.height = `${rect.height}px`; - } - update(PandemoniumDisplayVK.textinput); - update(PandemoniumDisplayVK.textarea); + function update(elem) { + elem.style.left = `${rect.left}px`; + elem.style.top = `${rect.top}px`; + elem.style.width = `${rect.width}px`; + elem.style.height = `${rect.height}px`; + } + update(PandemoniumDisplayVK.textinput); + update(PandemoniumDisplayVK.textarea); + }, + clear: function() { + if (PandemoniumDisplayVK.textinput) { + PandemoniumDisplayVK.textinput.remove(); + PandemoniumDisplayVK.textinput = null; + } + if (PandemoniumDisplayVK.textarea) { + PandemoniumDisplayVK.textarea.remove(); + PandemoniumDisplayVK.textarea = null; + } + }, }, - clear: function() { - if (PandemoniumDisplayVK.textinput) { - PandemoniumDisplayVK.textinput.remove(); - PandemoniumDisplayVK.textinput = null; - } - if (PandemoniumDisplayVK.textarea) { - PandemoniumDisplayVK.textarea.remove(); - PandemoniumDisplayVK.textarea = null; - } - }, - }, }; mergeInto(LibraryManager.library, PandemoniumDisplayVK); @@ -133,159 +170,159 @@ mergeInto(LibraryManager.library, PandemoniumDisplayVK); * Keeps track of cursor status and custom shapes. */ const PandemoniumDisplayCursor = { - $PandemoniumDisplayCursor__deps: ['$PandemoniumOS', '$PandemoniumConfig'], - $PandemoniumDisplayCursor__postset: 'PandemoniumOS.atexit(function(resolve, reject) { PandemoniumDisplayCursor.clear(); resolve(); });', - $PandemoniumDisplayCursor: { - shape: 'auto', - visible: true, - cursors: {}, - set_style: function(style) { - PandemoniumConfig.canvas.style.cursor = style; + $PandemoniumDisplayCursor__deps: ['$PandemoniumOS', '$PandemoniumConfig'], + $PandemoniumDisplayCursor__postset: 'PandemoniumOS.atexit(function(resolve, reject) { PandemoniumDisplayCursor.clear(); resolve(); });', + $PandemoniumDisplayCursor: { + shape: 'auto', + visible: true, + cursors: {}, + set_style: function(style) { + PandemoniumConfig.canvas.style.cursor = style; + }, + set_shape: function(shape) { + PandemoniumDisplayCursor.shape = shape; + let css = shape; + if (shape in PandemoniumDisplayCursor.cursors) { + const c = PandemoniumDisplayCursor.cursors[shape]; + css = `url("${c.url}") ${c.x} ${c.y}, auto`; + } + if (PandemoniumDisplayCursor.visible) { + PandemoniumDisplayCursor.set_style(css); + } + }, + clear: function() { + PandemoniumDisplayCursor.set_style(''); + PandemoniumDisplayCursor.shape = 'auto'; + PandemoniumDisplayCursor.visible = true; + Object.keys(PandemoniumDisplayCursor.cursors).forEach(function(key) { + URL.revokeObjectURL(PandemoniumDisplayCursor.cursors[key]); + delete PandemoniumDisplayCursor.cursors[key]; + }); + }, + lockPointer: function() { + const canvas = PandemoniumConfig.canvas; + if (canvas.requestPointerLock) { + canvas.requestPointerLock(); + } + }, + releasePointer: function() { + if (document.exitPointerLock) { + document.exitPointerLock(); + } + }, + isPointerLocked: function() { + return document.pointerLockElement === PandemoniumConfig.canvas; + }, }, - set_shape: function(shape) { - PandemoniumDisplayCursor.shape = shape; - let css = shape; - if (shape in PandemoniumDisplayCursor.cursors) { - const c = PandemoniumDisplayCursor.cursors[shape]; - css = `url("${c.url}") ${c.x} ${c.y}, auto`; - } - if (PandemoniumDisplayCursor.visible) { - PandemoniumDisplayCursor.set_style(css); - } - }, - clear: function() { - PandemoniumDisplayCursor.set_style(''); - PandemoniumDisplayCursor.shape = 'auto'; - PandemoniumDisplayCursor.visible = true; - Object.keys(PandemoniumDisplayCursor.cursors).forEach(function(key) { - URL.revokeObjectURL(PandemoniumDisplayCursor.cursors[key]); - delete PandemoniumDisplayCursor.cursors[key]; - }); - }, - lockPointer: function() { - const canvas = PandemoniumConfig.canvas; - if (canvas.requestPointerLock) { - canvas.requestPointerLock(); - } - }, - releasePointer: function() { - if (document.exitPointerLock) { - document.exitPointerLock(); - } - }, - isPointerLocked: function() { - return document.pointerLockElement === PandemoniumConfig.canvas; - }, - }, }; mergeInto(LibraryManager.library, PandemoniumDisplayCursor); const PandemoniumDisplayScreen = { - $PandemoniumDisplayScreen__deps: ['$PandemoniumConfig', '$PandemoniumOS', '$GL', 'emscripten_webgl_get_current_context'], - $PandemoniumDisplayScreen: { - desired_size: [0, 0], - hidpi: true, - getPixelRatio: function() { - return PandemoniumDisplayScreen.hidpi ? window.devicePixelRatio || 1 : 1; + $PandemoniumDisplayScreen__deps: ['$PandemoniumConfig', '$PandemoniumOS', '$GL', 'emscripten_webgl_get_current_context'], + $PandemoniumDisplayScreen: { + desired_size: [0, 0], + hidpi: true, + getPixelRatio: function() { + return PandemoniumDisplayScreen.hidpi ? window.devicePixelRatio || 1 : 1; + }, + isFullscreen: function() { + const elem = document.fullscreenElement || document.mozFullscreenElement || + document.webkitFullscreenElement || document.msFullscreenElement; + if (elem) { + return elem === PandemoniumConfig.canvas; + } + // But maybe knowing the element is not supported. + return document.fullscreen || document.mozFullScreen || + document.webkitIsFullscreen; + }, + hasFullscreen: function() { + return document.fullscreenEnabled || document.mozFullScreenEnabled || + document.webkitFullscreenEnabled; + }, + requestFullscreen: function() { + if (!PandemoniumDisplayScreen.hasFullscreen()) { + return 1; + } + const canvas = PandemoniumConfig.canvas; + try { + const promise = (canvas.requestFullscreen || canvas.msRequestFullscreen || + canvas.mozRequestFullScreen || canvas.mozRequestFullscreen || + canvas.webkitRequestFullscreen + ).call(canvas); + // Some browsers (Safari) return undefined. + // For the standard ones, we need to catch it. + if (promise) { + promise.catch(function() { + // nothing to do. + }); + } + } catch (e) { + return 1; + } + return 0; + }, + exitFullscreen: function() { + if (!PandemoniumDisplayScreen.isFullscreen()) { + return 0; + } + try { + const promise = document.exitFullscreen(); + if (promise) { + promise.catch(function() { + // nothing to do. + }); + } + } catch (e) { + return 1; + } + return 0; + }, + _updateGL: function() { + const gl_context_handle = _emscripten_webgl_get_current_context(); // eslint-disable-line no-undef + const gl = GL.getContext(gl_context_handle); + if (gl) { + GL.resizeOffscreenFramebuffer(gl); + } + }, + updateSize: function() { + const isFullscreen = PandemoniumDisplayScreen.isFullscreen(); + const wantsFullWindow = PandemoniumConfig.canvas_resize_policy === 2; + const noResize = PandemoniumConfig.canvas_resize_policy === 0; + const wwidth = PandemoniumDisplayScreen.desired_size[0]; + const wheight = PandemoniumDisplayScreen.desired_size[1]; + const canvas = PandemoniumConfig.canvas; + let width = wwidth; + let height = wheight; + if (noResize) { + // Don't resize canvas, just update GL if needed. + if (canvas.width !== width || canvas.height !== height) { + PandemoniumDisplayScreen.desired_size = [canvas.width, canvas.height]; + PandemoniumDisplayScreen._updateGL(); + return 1; + } + return 0; + } + const scale = PandemoniumDisplayScreen.getPixelRatio(); + if (isFullscreen || wantsFullWindow) { + // We need to match screen size. + width = window.innerWidth * scale; + height = window.innerHeight * scale; + } + const csw = `${width / scale}px`; + const csh = `${height / scale}px`; + if (canvas.style.width !== csw || canvas.style.height !== csh || canvas.width !== width || canvas.height !== height) { + // Size doesn't match. + // Resize canvas, set correct CSS pixel size, update GL. + canvas.width = width; + canvas.height = height; + canvas.style.width = csw; + canvas.style.height = csh; + PandemoniumDisplayScreen._updateGL(); + return 1; + } + return 0; + }, }, - isFullscreen: function() { - const elem = document.fullscreenElement || document.mozFullscreenElement || - document.webkitFullscreenElement || document.msFullscreenElement; - if (elem) { - return elem === PandemoniumConfig.canvas; - } - // But maybe knowing the element is not supported. - return document.fullscreen || document.mozFullScreen || - document.webkitIsFullscreen; - }, - hasFullscreen: function() { - return document.fullscreenEnabled || document.mozFullScreenEnabled || - document.webkitFullscreenEnabled; - }, - requestFullscreen: function() { - if (!PandemoniumDisplayScreen.hasFullscreen()) { - return 1; - } - const canvas = PandemoniumConfig.canvas; - try { - const promise = (canvas.requestFullscreen || canvas.msRequestFullscreen || - canvas.mozRequestFullScreen || canvas.mozRequestFullscreen || - canvas.webkitRequestFullscreen - ).call(canvas); - // Some browsers (Safari) return undefined. - // For the standard ones, we need to catch it. - if (promise) { - promise.catch(function() { - // nothing to do. - }); - } - } catch (e) { - return 1; - } - return 0; - }, - exitFullscreen: function() { - if (!PandemoniumDisplayScreen.isFullscreen()) { - return 0; - } - try { - const promise = document.exitFullscreen(); - if (promise) { - promise.catch(function() { - // nothing to do. - }); - } - } catch (e) { - return 1; - } - return 0; - }, - _updateGL: function() { - const gl_context_handle = _emscripten_webgl_get_current_context(); // eslint-disable-line no-undef - const gl = GL.getContext(gl_context_handle); - if (gl) { - GL.resizeOffscreenFramebuffer(gl); - } - }, - updateSize: function() { - const isFullscreen = PandemoniumDisplayScreen.isFullscreen(); - const wantsFullWindow = PandemoniumConfig.canvas_resize_policy === 2; - const noResize = PandemoniumConfig.canvas_resize_policy === 0; - const wwidth = PandemoniumDisplayScreen.desired_size[0]; - const wheight = PandemoniumDisplayScreen.desired_size[1]; - const canvas = PandemoniumConfig.canvas; - let width = wwidth; - let height = wheight; - if (noResize) { - // Don't resize canvas, just update GL if needed. - if (canvas.width !== width || canvas.height !== height) { - PandemoniumDisplayScreen.desired_size = [canvas.width, canvas.height]; - PandemoniumDisplayScreen._updateGL(); - return 1; - } - return 0; - } - const scale = PandemoniumDisplayScreen.getPixelRatio(); - if (isFullscreen || wantsFullWindow) { - // We need to match screen size. - width = window.innerWidth * scale; - height = window.innerHeight * scale; - } - const csw = `${width / scale}px`; - const csh = `${height / scale}px`; - if (canvas.style.width !== csw || canvas.style.height !== csh || canvas.width !== width || canvas.height !== height) { - // Size doesn't match. - // Resize canvas, set correct CSS pixel size, update GL. - canvas.width = width; - canvas.height = height; - canvas.style.width = csw; - canvas.style.height = csh; - PandemoniumDisplayScreen._updateGL(); - return 1; - } - return 0; - }, - }, }; mergeInto(LibraryManager.library, PandemoniumDisplayScreen); @@ -295,366 +332,366 @@ mergeInto(LibraryManager.library, PandemoniumDisplayScreen); * Exposes all the functions needed by DisplayServer implementation. */ const PandemoniumDisplay = { - $PandemoniumDisplay__deps: ['$PandemoniumConfig', '$PandemoniumRuntime', '$PandemoniumDisplayCursor', '$PandemoniumEventListeners', '$PandemoniumDisplayScreen', '$PandemoniumDisplayVK'], - $PandemoniumDisplay: { - window_icon: '', - findDPI: function() { - function testDPI(dpi) { - return window.matchMedia(`(max-resolution: ${dpi}dpi)`).matches; - } + $PandemoniumDisplay__deps: ['$PandemoniumConfig', '$PandemoniumRuntime', '$PandemoniumDisplayCursor', '$PandemoniumEventListeners', '$PandemoniumDisplayScreen', '$PandemoniumDisplayVK'], + $PandemoniumDisplay: { + window_icon: '', + findDPI: function() { + function testDPI(dpi) { + return window.matchMedia(`(max-resolution: ${dpi}dpi)`).matches; + } - function bisect(low, high, func) { - const mid = parseInt(((high - low) / 2) + low, 10); - if (high - low <= 1) { - return func(high) ? high : low; - } - if (func(mid)) { - return bisect(low, mid, func); - } - return bisect(mid, high, func); - } - try { - const dpi = bisect(0, 800, testDPI); - return dpi >= 96 ? dpi : 96; - } catch (e) { - return 96; - } + function bisect(low, high, func) { + const mid = parseInt(((high - low) / 2) + low, 10); + if (high - low <= 1) { + return func(high) ? high : low; + } + if (func(mid)) { + return bisect(low, mid, func); + } + return bisect(mid, high, func); + } + try { + const dpi = bisect(0, 800, testDPI); + return dpi >= 96 ? dpi : 96; + } catch (e) { + return 96; + } + }, }, - }, - // This is implemented as "glGetBufferSubData" in new emscripten versions. - // Since we have to support older (pre 2.0.17) emscripten versions, we add this wrapper function instead. - pandemonium_js_display_glGetBufferSubData__sig: 'viiii', - pandemonium_js_display_glGetBufferSubData__deps: ['$GL', 'emscripten_webgl_get_current_context'], - pandemonium_js_display_glGetBufferSubData: function(target, offset, size, data) { - const gl_context_handle = _emscripten_webgl_get_current_context(); // eslint-disable-line no-undef - const gl = GL.getContext(gl_context_handle); - if (gl) { - gl.GLctx['getBufferSubData'](target, offset, HEAPU8, data, size); - } - }, + // This is implemented as "glGetBufferSubData" in new emscripten versions. + // Since we have to support older (pre 2.0.17) emscripten versions, we add this wrapper function instead. + pandemonium_js_display_glGetBufferSubData__sig: 'viiii', + pandemonium_js_display_glGetBufferSubData__deps: ['$GL', 'emscripten_webgl_get_current_context'], + pandemonium_js_display_glGetBufferSubData: function(target, offset, size, data) { + const gl_context_handle = _emscripten_webgl_get_current_context(); // eslint-disable-line no-undef + const gl = GL.getContext(gl_context_handle); + if (gl) { + gl.GLctx['getBufferSubData'](target, offset, HEAPU8, data, size); + } + }, - pandemonium_js_display_is_swap_ok_cancel__sig: 'i', - pandemonium_js_display_is_swap_ok_cancel: function() { - const win = (['Windows', 'Win64', 'Win32', 'WinCE']); - const plat = navigator.platform || ''; - if (win.indexOf(plat) !== -1) { - return 1; - } - return 0; - }, + pandemonium_js_display_is_swap_ok_cancel__sig: 'i', + pandemonium_js_display_is_swap_ok_cancel: function() { + const win = (['Windows', 'Win64', 'Win32', 'WinCE']); + const plat = navigator.platform || ''; + if (win.indexOf(plat) !== -1) { + return 1; + } + return 0; + }, - pandemonium_js_display_alert__sig: 'vi', - pandemonium_js_display_alert: function(p_text) { - window.alert(PandemoniumRuntime.parseString(p_text)); // eslint-disable-line no-alert - }, + pandemonium_js_display_alert__sig: 'vi', + pandemonium_js_display_alert: function(p_text) { + window.alert(PandemoniumRuntime.parseString(p_text)); // eslint-disable-line no-alert + }, - pandemonium_js_display_screen_dpi_get__sig: 'i', - pandemonium_js_display_screen_dpi_get: function() { - return PandemoniumDisplay.findDPI(); - }, + pandemonium_js_display_screen_dpi_get__sig: 'i', + pandemonium_js_display_screen_dpi_get: function() { + return PandemoniumDisplay.findDPI(); + }, - pandemonium_js_display_pixel_ratio_get__sig: 'f', - pandemonium_js_display_pixel_ratio_get: function() { - return PandemoniumDisplayScreen.getPixelRatio(); - }, + pandemonium_js_display_pixel_ratio_get__sig: 'f', + pandemonium_js_display_pixel_ratio_get: function() { + return PandemoniumDisplayScreen.getPixelRatio(); + }, - pandemonium_js_display_fullscreen_request__sig: 'i', - pandemonium_js_display_fullscreen_request: function() { - return PandemoniumDisplayScreen.requestFullscreen(); - }, + pandemonium_js_display_fullscreen_request__sig: 'i', + pandemonium_js_display_fullscreen_request: function() { + return PandemoniumDisplayScreen.requestFullscreen(); + }, - pandemonium_js_display_fullscreen_exit__sig: 'i', - pandemonium_js_display_fullscreen_exit: function() { - return PandemoniumDisplayScreen.exitFullscreen(); - }, + pandemonium_js_display_fullscreen_exit__sig: 'i', + pandemonium_js_display_fullscreen_exit: function() { + return PandemoniumDisplayScreen.exitFullscreen(); + }, - pandemonium_js_display_desired_size_set__sig: 'vii', - pandemonium_js_display_desired_size_set: function(width, height) { - PandemoniumDisplayScreen.desired_size = [width, height]; - PandemoniumDisplayScreen.updateSize(); - }, + pandemonium_js_display_desired_size_set__sig: 'vii', + pandemonium_js_display_desired_size_set: function(width, height) { + PandemoniumDisplayScreen.desired_size = [width, height]; + PandemoniumDisplayScreen.updateSize(); + }, - pandemonium_js_display_size_update__sig: 'i', - pandemonium_js_display_size_update: function() { - const updated = PandemoniumDisplayScreen.updateSize(); - if (updated) { - PandemoniumDisplayVK.updateSize(); - } - return updated; - }, + pandemonium_js_display_size_update__sig: 'i', + pandemonium_js_display_size_update: function() { + const updated = PandemoniumDisplayScreen.updateSize(); + if (updated) { + PandemoniumDisplayVK.updateSize(); + } + return updated; + }, - pandemonium_js_display_screen_size_get__sig: 'vii', - pandemonium_js_display_screen_size_get: function(width, height) { - const scale = PandemoniumDisplayScreen.getPixelRatio(); - PandemoniumRuntime.setHeapValue(width, window.screen.width * scale, 'i32'); - PandemoniumRuntime.setHeapValue(height, window.screen.height * scale, 'i32'); - }, + pandemonium_js_display_screen_size_get__sig: 'vii', + pandemonium_js_display_screen_size_get: function(width, height) { + const scale = PandemoniumDisplayScreen.getPixelRatio(); + PandemoniumRuntime.setHeapValue(width, window.screen.width * scale, 'i32'); + PandemoniumRuntime.setHeapValue(height, window.screen.height * scale, 'i32'); + }, - pandemonium_js_display_window_size_get__sig: 'vii', - pandemonium_js_display_window_size_get: function(p_width, p_height) { - PandemoniumRuntime.setHeapValue(p_width, PandemoniumConfig.canvas.width, 'i32'); - PandemoniumRuntime.setHeapValue(p_height, PandemoniumConfig.canvas.height, 'i32'); - }, + pandemonium_js_display_window_size_get__sig: 'vii', + pandemonium_js_display_window_size_get: function(p_width, p_height) { + PandemoniumRuntime.setHeapValue(p_width, PandemoniumConfig.canvas.width, 'i32'); + PandemoniumRuntime.setHeapValue(p_height, PandemoniumConfig.canvas.height, 'i32'); + }, - pandemonium_js_display_has_webgl__sig: 'ii', - pandemonium_js_display_has_webgl: function(p_version) { - if (p_version !== 1 && p_version !== 2) { - return false; - } - try { - return !!document.createElement('canvas').getContext(p_version === 2 ? 'webgl2' : 'webgl'); - } catch (e) { - /* Not available */ - } - return false; - }, + pandemonium_js_display_has_webgl__sig: 'ii', + pandemonium_js_display_has_webgl: function(p_version) { + if (p_version !== 1 && p_version !== 2) { + return false; + } + try { + return !!document.createElement('canvas').getContext(p_version === 2 ? 'webgl2' : 'webgl'); + } catch (e) { + /* Not available */ + } + return false; + }, - /* - * Canvas - */ - pandemonium_js_display_canvas_focus__sig: 'v', - pandemonium_js_display_canvas_focus: function() { - PandemoniumConfig.canvas.focus(); - }, + /* + * Canvas + */ + pandemonium_js_display_canvas_focus__sig: 'v', + pandemonium_js_display_canvas_focus: function() { + PandemoniumConfig.canvas.focus(); + }, - pandemonium_js_display_canvas_is_focused__sig: 'i', - pandemonium_js_display_canvas_is_focused: function() { - return document.activeElement === PandemoniumConfig.canvas; - }, + pandemonium_js_display_canvas_is_focused__sig: 'i', + pandemonium_js_display_canvas_is_focused: function() { + return document.activeElement === PandemoniumConfig.canvas; + }, - /* - * Touchscreen - */ - pandemonium_js_display_touchscreen_is_available__sig: 'i', - pandemonium_js_display_touchscreen_is_available: function() { - return 'ontouchstart' in window; - }, + /* + * Touchscreen + */ + pandemonium_js_display_touchscreen_is_available__sig: 'i', + pandemonium_js_display_touchscreen_is_available: function() { + return 'ontouchstart' in window; + }, - /* - * Clipboard - */ - pandemonium_js_display_clipboard_set__sig: 'ii', - pandemonium_js_display_clipboard_set: function(p_text) { - const text = PandemoniumRuntime.parseString(p_text); - if (!navigator.clipboard || !navigator.clipboard.writeText) { - return 1; - } - navigator.clipboard.writeText(text).catch(function(e) { - // Setting OS clipboard is only possible from an input callback. - PandemoniumRuntime.error('Setting OS clipboard is only possible from an input callback for the HTML5 plafrom. Exception:', e); - }); - return 0; - }, + /* + * Clipboard + */ + pandemonium_js_display_clipboard_set__sig: 'ii', + pandemonium_js_display_clipboard_set: function(p_text) { + const text = PandemoniumRuntime.parseString(p_text); + if (!navigator.clipboard || !navigator.clipboard.writeText) { + return 1; + } + navigator.clipboard.writeText(text).catch(function(e) { + // Setting OS clipboard is only possible from an input callback. + PandemoniumRuntime.error('Setting OS clipboard is only possible from an input callback for the HTML5 plafrom. Exception:', e); + }); + return 0; + }, - pandemonium_js_display_clipboard_get__sig: 'ii', - pandemonium_js_display_clipboard_get: function(callback) { - const func = PandemoniumRuntime.get_func(callback); - try { - navigator.clipboard.readText().then(function(result) { - const ptr = PandemoniumRuntime.allocString(result); - func(ptr); - PandemoniumRuntime.free(ptr); - }).catch(function(e) { - // Fail graciously. - }); - } catch (e) { - // Fail graciously. - } - }, + pandemonium_js_display_clipboard_get__sig: 'ii', + pandemonium_js_display_clipboard_get: function(callback) { + const func = PandemoniumRuntime.get_func(callback); + try { + navigator.clipboard.readText().then(function(result) { + const ptr = PandemoniumRuntime.allocString(result); + func(ptr); + PandemoniumRuntime.free(ptr); + }).catch(function(e) { + // Fail graciously. + }); + } catch (e) { + // Fail graciously. + } + }, - /* - * Window - */ - pandemonium_js_display_window_title_set__sig: 'vi', - pandemonium_js_display_window_title_set: function(p_data) { - document.title = PandemoniumRuntime.parseString(p_data); - }, + /* + * Window + */ + pandemonium_js_display_window_title_set__sig: 'vi', + pandemonium_js_display_window_title_set: function(p_data) { + document.title = PandemoniumRuntime.parseString(p_data); + }, - pandemonium_js_display_window_icon_set__sig: 'vii', - pandemonium_js_display_window_icon_set: function(p_ptr, p_len) { - let link = document.getElementById('-gd-engine-icon'); - if (link === null) { - link = document.createElement('link'); - link.rel = 'icon'; - link.id = '-gd-engine-icon'; - document.head.appendChild(link); - } - const old_icon = PandemoniumDisplay.window_icon; - const png = new Blob([PandemoniumRuntime.heapSlice(HEAPU8, p_ptr, p_len)], { - type: 'image/png' - }); - PandemoniumDisplay.window_icon = URL.createObjectURL(png); - link.href = PandemoniumDisplay.window_icon; - if (old_icon) { - URL.revokeObjectURL(old_icon); - } - }, + pandemonium_js_display_window_icon_set__sig: 'vii', + pandemonium_js_display_window_icon_set: function(p_ptr, p_len) { + let link = document.getElementById('-gd-engine-icon'); + if (link === null) { + link = document.createElement('link'); + link.rel = 'icon'; + link.id = '-gd-engine-icon'; + document.head.appendChild(link); + } + const old_icon = PandemoniumDisplay.window_icon; + const png = new Blob([PandemoniumRuntime.heapSlice(HEAPU8, p_ptr, p_len)], { + type: 'image/png' + }); + PandemoniumDisplay.window_icon = URL.createObjectURL(png); + link.href = PandemoniumDisplay.window_icon; + if (old_icon) { + URL.revokeObjectURL(old_icon); + } + }, - /* - * Cursor - */ - pandemonium_js_display_cursor_set_visible__sig: 'vi', - pandemonium_js_display_cursor_set_visible: function(p_visible) { - const visible = p_visible !== 0; - if (visible === PandemoniumDisplayCursor.visible) { - return; - } - PandemoniumDisplayCursor.visible = visible; - if (visible) { - PandemoniumDisplayCursor.set_shape(PandemoniumDisplayCursor.shape); - } else { - PandemoniumDisplayCursor.set_style('none'); - } - }, + /* + * Cursor + */ + pandemonium_js_display_cursor_set_visible__sig: 'vi', + pandemonium_js_display_cursor_set_visible: function(p_visible) { + const visible = p_visible !== 0; + if (visible === PandemoniumDisplayCursor.visible) { + return; + } + PandemoniumDisplayCursor.visible = visible; + if (visible) { + PandemoniumDisplayCursor.set_shape(PandemoniumDisplayCursor.shape); + } else { + PandemoniumDisplayCursor.set_style('none'); + } + }, - pandemonium_js_display_cursor_is_hidden__sig: 'i', - pandemonium_js_display_cursor_is_hidden: function() { - return !PandemoniumDisplayCursor.visible; - }, + pandemonium_js_display_cursor_is_hidden__sig: 'i', + pandemonium_js_display_cursor_is_hidden: function() { + return !PandemoniumDisplayCursor.visible; + }, - pandemonium_js_display_cursor_set_shape__sig: 'vi', - pandemonium_js_display_cursor_set_shape: function(p_string) { - PandemoniumDisplayCursor.set_shape(PandemoniumRuntime.parseString(p_string)); - }, + pandemonium_js_display_cursor_set_shape__sig: 'vi', + pandemonium_js_display_cursor_set_shape: function(p_string) { + PandemoniumDisplayCursor.set_shape(PandemoniumRuntime.parseString(p_string)); + }, - pandemonium_js_display_cursor_set_custom_shape__sig: 'viiiii', - pandemonium_js_display_cursor_set_custom_shape: function(p_shape, p_ptr, p_len, p_hotspot_x, p_hotspot_y) { - const shape = PandemoniumRuntime.parseString(p_shape); - const old_shape = PandemoniumDisplayCursor.cursors[shape]; - if (p_len > 0) { - const png = new Blob([PandemoniumRuntime.heapSlice(HEAPU8, p_ptr, p_len)], { - type: 'image/png' - }); - const url = URL.createObjectURL(png); - PandemoniumDisplayCursor.cursors[shape] = { - url: url, - x: p_hotspot_x, - y: p_hotspot_y, - }; - } else { - delete PandemoniumDisplayCursor.cursors[shape]; - } - if (shape === PandemoniumDisplayCursor.shape) { - PandemoniumDisplayCursor.set_shape(PandemoniumDisplayCursor.shape); - } - if (old_shape) { - URL.revokeObjectURL(old_shape.url); - } - }, + pandemonium_js_display_cursor_set_custom_shape__sig: 'viiiii', + pandemonium_js_display_cursor_set_custom_shape: function(p_shape, p_ptr, p_len, p_hotspot_x, p_hotspot_y) { + const shape = PandemoniumRuntime.parseString(p_shape); + const old_shape = PandemoniumDisplayCursor.cursors[shape]; + if (p_len > 0) { + const png = new Blob([PandemoniumRuntime.heapSlice(HEAPU8, p_ptr, p_len)], { + type: 'image/png' + }); + const url = URL.createObjectURL(png); + PandemoniumDisplayCursor.cursors[shape] = { + url: url, + x: p_hotspot_x, + y: p_hotspot_y, + }; + } else { + delete PandemoniumDisplayCursor.cursors[shape]; + } + if (shape === PandemoniumDisplayCursor.shape) { + PandemoniumDisplayCursor.set_shape(PandemoniumDisplayCursor.shape); + } + if (old_shape) { + URL.revokeObjectURL(old_shape.url); + } + }, - pandemonium_js_display_cursor_lock_set__sig: 'vi', - pandemonium_js_display_cursor_lock_set: function(p_lock) { - if (p_lock) { - PandemoniumDisplayCursor.lockPointer(); - } else { - PandemoniumDisplayCursor.releasePointer(); - } - }, + pandemonium_js_display_cursor_lock_set__sig: 'vi', + pandemonium_js_display_cursor_lock_set: function(p_lock) { + if (p_lock) { + PandemoniumDisplayCursor.lockPointer(); + } else { + PandemoniumDisplayCursor.releasePointer(); + } + }, - pandemonium_js_display_cursor_is_locked__sig: 'i', - pandemonium_js_display_cursor_is_locked: function() { - return PandemoniumDisplayCursor.isPointerLocked() ? 1 : 0; - }, + pandemonium_js_display_cursor_is_locked__sig: 'i', + pandemonium_js_display_cursor_is_locked: function() { + return PandemoniumDisplayCursor.isPointerLocked() ? 1 : 0; + }, - /* - * Listeners - */ - pandemonium_js_display_fullscreen_cb__sig: 'vi', - pandemonium_js_display_fullscreen_cb: function(callback) { - const canvas = PandemoniumConfig.canvas; - const func = PandemoniumRuntime.get_func(callback); + /* + * Listeners + */ + pandemonium_js_display_fullscreen_cb__sig: 'vi', + pandemonium_js_display_fullscreen_cb: function(callback) { + const canvas = PandemoniumConfig.canvas; + const func = PandemoniumRuntime.get_func(callback); - function change_cb(evt) { - if (evt.target === canvas) { - func(PandemoniumDisplayScreen.isFullscreen()); - } - } - PandemoniumEventListeners.add(document, 'fullscreenchange', change_cb, false); - PandemoniumEventListeners.add(document, 'mozfullscreenchange', change_cb, false); - PandemoniumEventListeners.add(document, 'webkitfullscreenchange', change_cb, false); - }, + function change_cb(evt) { + if (evt.target === canvas) { + func(PandemoniumDisplayScreen.isFullscreen()); + } + } + PandemoniumEventListeners.add(document, 'fullscreenchange', change_cb, false); + PandemoniumEventListeners.add(document, 'mozfullscreenchange', change_cb, false); + PandemoniumEventListeners.add(document, 'webkitfullscreenchange', change_cb, false); + }, - pandemonium_js_display_window_blur_cb__sig: 'vi', - pandemonium_js_display_window_blur_cb: function(callback) { - const func = PandemoniumRuntime.get_func(callback); - PandemoniumEventListeners.add(window, 'blur', function() { - func(); - }, false); - }, + pandemonium_js_display_window_blur_cb__sig: 'vi', + pandemonium_js_display_window_blur_cb: function(callback) { + const func = PandemoniumRuntime.get_func(callback); + PandemoniumEventListeners.add(window, 'blur', function() { + func(); + }, false); + }, - pandemonium_js_display_notification_cb__sig: 'viiiii', - pandemonium_js_display_notification_cb: function(callback, p_enter, p_exit, p_in, p_out) { - const canvas = PandemoniumConfig.canvas; - const func = PandemoniumRuntime.get_func(callback); - const notif = [p_enter, p_exit, p_in, p_out]; - ['mouseover', 'mouseleave', 'focus', 'blur'].forEach(function(evt_name, idx) { - PandemoniumEventListeners.add(canvas, evt_name, function() { - func(notif[idx]); - }, true); - }); - }, + pandemonium_js_display_notification_cb__sig: 'viiiii', + pandemonium_js_display_notification_cb: function(callback, p_enter, p_exit, p_in, p_out) { + const canvas = PandemoniumConfig.canvas; + const func = PandemoniumRuntime.get_func(callback); + const notif = [p_enter, p_exit, p_in, p_out]; + ['mouseover', 'mouseleave', 'focus', 'blur'].forEach(function(evt_name, idx) { + PandemoniumEventListeners.add(canvas, evt_name, function() { + func(notif[idx]); + }, true); + }); + }, - pandemonium_js_display_setup_canvas__sig: 'viiii', - pandemonium_js_display_setup_canvas: function(p_width, p_height, p_fullscreen, p_hidpi) { - const canvas = PandemoniumConfig.canvas; - PandemoniumEventListeners.add(canvas, 'contextmenu', function(ev) { - ev.preventDefault(); - }, false); - PandemoniumEventListeners.add(canvas, 'webglcontextlost', function(ev) { - alert('WebGL context lost, please reload the page'); // eslint-disable-line no-alert - ev.preventDefault(); - }, false); - PandemoniumDisplayScreen.hidpi = !!p_hidpi; - switch (PandemoniumConfig.canvas_resize_policy) { - case 0: // None - PandemoniumDisplayScreen.desired_size = [canvas.width, canvas.height]; - break; - case 1: // Project - PandemoniumDisplayScreen.desired_size = [p_width, p_height]; - break; - default: // Full window - // Ensure we display in the right place, the size will be handled by updateSize - canvas.style.position = 'absolute'; - canvas.style.top = 0; - canvas.style.left = 0; - break; - } - PandemoniumDisplayScreen.updateSize(); - if (p_fullscreen) { - PandemoniumDisplayScreen.requestFullscreen(); - } - }, + pandemonium_js_display_setup_canvas__sig: 'viiii', + pandemonium_js_display_setup_canvas: function(p_width, p_height, p_fullscreen, p_hidpi) { + const canvas = PandemoniumConfig.canvas; + PandemoniumEventListeners.add(canvas, 'contextmenu', function(ev) { + ev.preventDefault(); + }, false); + PandemoniumEventListeners.add(canvas, 'webglcontextlost', function(ev) { + alert('WebGL context lost, please reload the page'); // eslint-disable-line no-alert + ev.preventDefault(); + }, false); + PandemoniumDisplayScreen.hidpi = !!p_hidpi; + switch (PandemoniumConfig.canvas_resize_policy) { + case 0: // None + PandemoniumDisplayScreen.desired_size = [canvas.width, canvas.height]; + break; + case 1: // Project + PandemoniumDisplayScreen.desired_size = [p_width, p_height]; + break; + default: // Full window + // Ensure we display in the right place, the size will be handled by updateSize + canvas.style.position = 'absolute'; + canvas.style.top = 0; + canvas.style.left = 0; + break; + } + PandemoniumDisplayScreen.updateSize(); + if (p_fullscreen) { + PandemoniumDisplayScreen.requestFullscreen(); + } + }, - /* - * Virtual Keyboard - */ - pandemonium_js_display_vk_show__sig: 'viiii', - pandemonium_js_display_vk_show: function(p_text, p_multiline, p_start, p_end) { - const text = PandemoniumRuntime.parseString(p_text); - const start = p_start > 0 ? p_start : 0; - const end = p_end > 0 ? p_end : start; - PandemoniumDisplayVK.show(text, p_multiline, start, end); - }, + /* + * Virtual Keyboard + */ + pandemonium_js_display_vk_show__sig: 'viiii', + pandemonium_js_display_vk_show: function(p_text, p_type, p_start, p_end) { + const text = PandemoniumRuntime.parseString(p_text); + const start = p_start > 0 ? p_start : 0; + const end = p_end > 0 ? p_end : start; + PandemoniumDisplayVK.show(text, p_type, start, end); + }, - pandemonium_js_display_vk_hide__sig: 'v', - pandemonium_js_display_vk_hide: function() { - PandemoniumDisplayVK.hide(); - }, + pandemonium_js_display_vk_hide__sig: 'v', + pandemonium_js_display_vk_hide: function() { + PandemoniumDisplayVK.hide(); + }, - pandemonium_js_display_vk_available__sig: 'i', - pandemonium_js_display_vk_available: function() { - return PandemoniumDisplayVK.available(); - }, + pandemonium_js_display_vk_available__sig: 'i', + pandemonium_js_display_vk_available: function() { + return PandemoniumDisplayVK.available(); + }, - pandemonium_js_display_vk_cb__sig: 'vi', - pandemonium_js_display_vk_cb: function(p_input_cb) { - const input_cb = PandemoniumRuntime.get_func(p_input_cb); - if (PandemoniumDisplayVK.available()) { - PandemoniumDisplayVK.init(input_cb); - } - }, + pandemonium_js_display_vk_cb__sig: 'vi', + pandemonium_js_display_vk_cb: function(p_input_cb) { + const input_cb = PandemoniumRuntime.get_func(p_input_cb); + if (PandemoniumDisplayVK.available()) { + PandemoniumDisplayVK.init(input_cb); + } + }, }; autoAddDeps(PandemoniumDisplay, '$PandemoniumDisplay'); -mergeInto(LibraryManager.library, PandemoniumDisplay); +mergeInto(LibraryManager.library, PandemoniumDisplay); \ No newline at end of file diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index aee29a367..581e0920a 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -785,8 +785,8 @@ bool OS_JavaScript::has_virtual_keyboard() const { return pandemonium_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) { - pandemonium_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 acdc76360..af120d3e3 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -124,7 +124,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/javascript/pandemonium_js.h b/platform/javascript/pandemonium_js.h index 2c75efe3a..4cc970666 100644 --- a/platform/javascript/pandemonium_js.h +++ b/platform/javascript/pandemonium_js.h @@ -110,7 +110,7 @@ extern void pandemonium_js_display_notification_cb(void (*p_callback)(int p_noti // Display Virtual Keyboard extern int pandemonium_js_display_vk_available(); extern void pandemonium_js_display_vk_cb(void (*p_input)(const char *p_text, int p_cursor)); -extern void pandemonium_js_display_vk_show(const char *p_text, int p_multiline, int p_start, int p_end); +extern void pandemonium_js_display_vk_show(const char *p_text, int p_type, int p_start, int p_end); extern void pandemonium_js_display_vk_hide(); #ifdef __cplusplus diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index e1ceab18a..da5f7a1fd 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -30,15 +30,15 @@ #include "line_edit.h" -#include "core/object/message_queue.h" #include "core/input/input.h" +#include "core/input/shortcut.h" +#include "core/object/message_queue.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "core/string/print_string.h" #include "core/string/translation.h" #include "label.h" #include "scene/gui/popup_menu.h" -#include "core/input/shortcut.h" #include "scene/main/timer.h" #include "scene/main/viewport.h" @@ -1391,9 +1391,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); } } } @@ -1807,6 +1807,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_selecting_enabled(bool p_enabled) { selecting_enabled = p_enabled; @@ -1982,6 +1990,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); @@ -2011,6 +2021,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"); @@ -2020,6 +2039,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, "selecting_enabled"), "set_selecting_enabled", "is_selecting_enabled"); @@ -2054,6 +2074,7 @@ LineEdit::LineEdit() { deselect_on_focus_loss_enabled = true; popup_show = false; virtual_keyboard_enabled = true; + virtual_keyboard_type = KEYBOARD_TYPE_DEFAULT; drag_action = false; drag_caret_force_displayed = false; diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 062f4fc63..fe3cf83d5 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; + VirtualKeyboardType virtual_keyboard_type; bool drag_action; bool drag_caret_force_displayed; @@ -243,6 +255,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_selecting_enabled(bool p_enabled); bool is_selecting_enabled() const; @@ -262,5 +277,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 558027b53..e7e1b8bba 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1877,7 +1877,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: {