summaryrefslogtreecommitdiff
path: root/platform/android
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android')
-rw-r--r--platform/android/android_input_handler.cpp53
-rw-r--r--platform/android/android_input_handler.h2
-rw-r--r--platform/android/android_keys_utils.cpp47
-rw-r--r--platform/android/android_keys_utils.h251
-rw-r--r--platform/android/display_server_android.cpp10
-rw-r--r--platform/android/display_server_android.h2
-rw-r--r--platform/android/export/export.cpp4
-rw-r--r--platform/android/export/export_plugin.cpp6
-rw-r--r--platform/android/export/export_plugin.h6
-rw-r--r--platform/android/export/gradle_export_util.h8
-rw-r--r--platform/android/file_access_android.h36
-rw-r--r--platform/android/file_access_filesystem_jandroid.cpp48
-rw-r--r--platform/android/file_access_filesystem_jandroid.h1
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotIO.java7
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotLib.java2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java49
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java19
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java22
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt33
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/directory/FilesystemDirectoryAccess.kt9
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt3
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt19
-rw-r--r--platform/android/java_godot_io_wrapper.cpp6
-rw-r--r--platform/android/java_godot_io_wrapper.h2
-rw-r--r--platform/android/java_godot_lib_jni.cpp5
-rw-r--r--platform/android/java_godot_lib_jni.h2
-rw-r--r--platform/android/java_godot_view_wrapper.h6
27 files changed, 397 insertions, 261 deletions
diff --git a/platform/android/android_input_handler.cpp b/platform/android/android_input_handler.cpp
index 81802298d9..6427346365 100644
--- a/platform/android/android_input_handler.cpp
+++ b/platform/android/android_input_handler.cpp
@@ -56,10 +56,10 @@ void AndroidInputHandler::_set_key_modifier_state(Ref<InputEventWithModifiers> e
ev->set_ctrl_pressed(control_mem);
}
-void AndroidInputHandler::process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed) {
+void AndroidInputHandler::process_key_event(int p_keycode, int p_physical_keycode, int p_unicode, bool p_pressed) {
static char32_t prev_wc = 0;
- char32_t unicode = p_unicode_char;
- if ((p_unicode_char & 0xfffffc00) == 0xd800) {
+ char32_t unicode = p_unicode;
+ if ((p_unicode & 0xfffffc00) == 0xd800) {
if (prev_wc != 0) {
ERR_PRINT("invalid utf16 surrogate input");
}
@@ -78,39 +78,38 @@ void AndroidInputHandler::process_key_event(int p_keycode, int p_scancode, int p
Ref<InputEventKey> ev;
ev.instantiate();
- int val = unicode;
- Key keycode = android_get_keysym(p_keycode);
- Key phy_keycode = android_get_keysym(p_scancode);
- if (keycode == Key::SHIFT) {
- shift_mem = p_pressed;
+ Key physical_keycode = godot_code_from_android_code(p_physical_keycode);
+ Key keycode = physical_keycode;
+ if (p_keycode != 0) {
+ keycode = godot_code_from_unicode(p_keycode);
}
- if (keycode == Key::ALT) {
- alt_mem = p_pressed;
- }
- if (keycode == Key::CTRL) {
- control_mem = p_pressed;
- }
- if (keycode == Key::META) {
- meta_mem = p_pressed;
+
+ switch (physical_keycode) {
+ case Key::SHIFT: {
+ shift_mem = p_pressed;
+ } break;
+ case Key::ALT: {
+ alt_mem = p_pressed;
+ } break;
+ case Key::CTRL: {
+ control_mem = p_pressed;
+ } break;
+ case Key::META: {
+ meta_mem = p_pressed;
+ } break;
+ default:
+ break;
}
ev->set_keycode(keycode);
- ev->set_physical_keycode(phy_keycode);
- ev->set_unicode(val);
+ ev->set_physical_keycode(physical_keycode);
+ ev->set_unicode(unicode);
ev->set_pressed(p_pressed);
_set_key_modifier_state(ev);
- if (val == '\n') {
- ev->set_keycode(Key::ENTER);
- } else if (val == 61448) {
- ev->set_keycode(Key::BACKSPACE);
- ev->set_unicode((char32_t)Key::BACKSPACE);
- } else if (val == 61453) {
- ev->set_keycode(Key::ENTER);
- ev->set_unicode((char32_t)Key::ENTER);
- } else if (p_keycode == 4) {
+ if (p_physical_keycode == AKEYCODE_BACK) {
if (DisplayServerAndroid *dsa = Object::cast_to<DisplayServerAndroid>(DisplayServer::get_singleton())) {
dsa->send_window_event(DisplayServer::WINDOW_EVENT_GO_BACK_REQUEST, true);
}
diff --git a/platform/android/android_input_handler.h b/platform/android/android_input_handler.h
index 1397ca59e4..6dfab7def8 100644
--- a/platform/android/android_input_handler.h
+++ b/platform/android/android_input_handler.h
@@ -83,7 +83,7 @@ public:
void process_mouse_event(int input_device, int event_action, int event_android_buttons_mask, Point2 event_pos, float event_vertical_factor = 0, float event_horizontal_factor = 0);
void process_double_tap(int event_android_button_mask, Point2 p_pos);
void process_joy_event(JoypadEvent p_event);
- void process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed);
+ void process_key_event(int p_keycode, int p_physical_keycode, int p_unicode, bool p_pressed);
};
#endif // ANDROID_INPUT_HANDLER_H
diff --git a/platform/android/android_keys_utils.cpp b/platform/android/android_keys_utils.cpp
index 885e4ff145..d2c5fdfd6c 100644
--- a/platform/android/android_keys_utils.cpp
+++ b/platform/android/android_keys_utils.cpp
@@ -30,12 +30,49 @@
#include "android_keys_utils.h"
-Key android_get_keysym(unsigned int p_code) {
- for (int i = 0; _ak_to_keycode[i].keysym != Key::UNKNOWN; i++) {
- if (_ak_to_keycode[i].keycode == p_code) {
- return _ak_to_keycode[i].keysym;
+Key godot_code_from_android_code(unsigned int p_code) {
+ for (int i = 0; android_godot_code_pairs[i].android_code != AKEYCODE_MAX; i++) {
+ if (android_godot_code_pairs[i].android_code == p_code) {
+ return android_godot_code_pairs[i].godot_code;
}
}
-
return Key::UNKNOWN;
}
+
+Key godot_code_from_unicode(unsigned int p_code) {
+ unsigned int code = p_code;
+ if (code > 0xFF) {
+ return Key::UNKNOWN;
+ }
+ // Known control codes.
+ if (code == '\b') { // 0x08
+ return Key::BACKSPACE;
+ }
+ if (code == '\t') { // 0x09
+ return Key::TAB;
+ }
+ if (code == '\n') { // 0x0A
+ return Key::ENTER;
+ }
+ if (code == 0x1B) {
+ return Key::ESCAPE;
+ }
+ if (code == 0x1F) {
+ return Key::KEY_DELETE;
+ }
+ // Unknown control codes.
+ if (code <= 0x1F || (code >= 0x80 && code <= 0x9F)) {
+ return Key::UNKNOWN;
+ }
+ // Convert to uppercase.
+ if (code >= 'a' && code <= 'z') { // 0x61 - 0x7A
+ code -= ('a' - 'A');
+ }
+ if (code >= u'à' && code <= u'ö') { // 0xE0 - 0xF6
+ code -= (u'à' - u'À'); // 0xE0 - 0xC0
+ }
+ if (code >= u'ø' && code <= u'þ') { // 0xF8 - 0xFF
+ code -= (u'ø' - u'Ø'); // 0xF8 - 0xD8
+ }
+ return Key(code);
+}
diff --git a/platform/android/android_keys_utils.h b/platform/android/android_keys_utils.h
index 24a6589fba..5ec3ee17aa 100644
--- a/platform/android/android_keys_utils.h
+++ b/platform/android/android_keys_utils.h
@@ -34,129 +34,140 @@
#include <android/input.h>
#include <core/os/keyboard.h>
-struct _WinTranslatePair {
- Key keysym = Key::NONE;
- unsigned int keycode = 0;
+#define AKEYCODE_MAX 0xFFFF
+
+struct AndroidGodotCodePair {
+ unsigned int android_code = 0;
+ Key godot_code = Key::NONE;
};
-static _WinTranslatePair _ak_to_keycode[] = {
- { Key::TAB, AKEYCODE_TAB },
- { Key::ENTER, AKEYCODE_ENTER },
- { Key::SHIFT, AKEYCODE_SHIFT_LEFT },
- { Key::SHIFT, AKEYCODE_SHIFT_RIGHT },
- { Key::ALT, AKEYCODE_ALT_LEFT },
- { Key::ALT, AKEYCODE_ALT_RIGHT },
- { Key::MENU, AKEYCODE_MENU },
- { Key::PAUSE, AKEYCODE_MEDIA_PLAY_PAUSE },
- { Key::ESCAPE, AKEYCODE_BACK },
- { Key::SPACE, AKEYCODE_SPACE },
- { Key::PAGEUP, AKEYCODE_PAGE_UP },
- { Key::PAGEDOWN, AKEYCODE_PAGE_DOWN },
- { Key::HOME, AKEYCODE_HOME }, //(0x24)
- { Key::LEFT, AKEYCODE_DPAD_LEFT },
- { Key::UP, AKEYCODE_DPAD_UP },
- { Key::RIGHT, AKEYCODE_DPAD_RIGHT },
- { Key::DOWN, AKEYCODE_DPAD_DOWN },
- { Key::PERIODCENTERED, AKEYCODE_DPAD_CENTER },
- { Key::BACKSPACE, AKEYCODE_DEL },
- { Key::KEY_0, AKEYCODE_0 },
- { Key::KEY_1, AKEYCODE_1 },
- { Key::KEY_2, AKEYCODE_2 },
- { Key::KEY_3, AKEYCODE_3 },
- { Key::KEY_4, AKEYCODE_4 },
- { Key::KEY_5, AKEYCODE_5 },
- { Key::KEY_6, AKEYCODE_6 },
- { Key::KEY_7, AKEYCODE_7 },
- { Key::KEY_8, AKEYCODE_8 },
- { Key::KEY_9, AKEYCODE_9 },
- { Key::A, AKEYCODE_A },
- { Key::B, AKEYCODE_B },
- { Key::C, AKEYCODE_C },
- { Key::D, AKEYCODE_D },
- { Key::E, AKEYCODE_E },
- { Key::F, AKEYCODE_F },
- { Key::G, AKEYCODE_G },
- { Key::H, AKEYCODE_H },
- { Key::I, AKEYCODE_I },
- { Key::J, AKEYCODE_J },
- { Key::K, AKEYCODE_K },
- { Key::L, AKEYCODE_L },
- { Key::M, AKEYCODE_M },
- { Key::N, AKEYCODE_N },
- { Key::O, AKEYCODE_O },
- { Key::P, AKEYCODE_P },
- { Key::Q, AKEYCODE_Q },
- { Key::R, AKEYCODE_R },
- { Key::S, AKEYCODE_S },
- { Key::T, AKEYCODE_T },
- { Key::U, AKEYCODE_U },
- { Key::V, AKEYCODE_V },
- { Key::W, AKEYCODE_W },
- { Key::X, AKEYCODE_X },
- { Key::Y, AKEYCODE_Y },
- { Key::Z, AKEYCODE_Z },
- { Key::HOMEPAGE, AKEYCODE_EXPLORER },
- { Key::LAUNCH0, AKEYCODE_BUTTON_A },
- { Key::LAUNCH1, AKEYCODE_BUTTON_B },
- { Key::LAUNCH2, AKEYCODE_BUTTON_C },
- { Key::LAUNCH3, AKEYCODE_BUTTON_X },
- { Key::LAUNCH4, AKEYCODE_BUTTON_Y },
- { Key::LAUNCH5, AKEYCODE_BUTTON_Z },
- { Key::LAUNCH6, AKEYCODE_BUTTON_L1 },
- { Key::LAUNCH7, AKEYCODE_BUTTON_R1 },
- { Key::LAUNCH8, AKEYCODE_BUTTON_L2 },
- { Key::LAUNCH9, AKEYCODE_BUTTON_R2 },
- { Key::LAUNCHA, AKEYCODE_BUTTON_THUMBL },
- { Key::LAUNCHB, AKEYCODE_BUTTON_THUMBR },
- { Key::LAUNCHC, AKEYCODE_BUTTON_START },
- { Key::LAUNCHD, AKEYCODE_BUTTON_SELECT },
- { Key::LAUNCHE, AKEYCODE_BUTTON_MODE },
- { Key::VOLUMEMUTE, AKEYCODE_MUTE },
- { Key::VOLUMEDOWN, AKEYCODE_VOLUME_DOWN },
- { Key::VOLUMEUP, AKEYCODE_VOLUME_UP },
- { Key::BACK, AKEYCODE_MEDIA_REWIND },
- { Key::FORWARD, AKEYCODE_MEDIA_FAST_FORWARD },
- { Key::MEDIANEXT, AKEYCODE_MEDIA_NEXT },
- { Key::MEDIAPREVIOUS, AKEYCODE_MEDIA_PREVIOUS },
- { Key::MEDIASTOP, AKEYCODE_MEDIA_STOP },
- { Key::PLUS, AKEYCODE_PLUS },
- { Key::EQUAL, AKEYCODE_EQUALS }, // the '+' key
- { Key::COMMA, AKEYCODE_COMMA }, // the ',' key
- { Key::MINUS, AKEYCODE_MINUS }, // the '-' key
- { Key::SLASH, AKEYCODE_SLASH }, // the '/?' key
- { Key::BACKSLASH, AKEYCODE_BACKSLASH },
- { Key::BRACKETLEFT, AKEYCODE_LEFT_BRACKET },
- { Key::BRACKETRIGHT, AKEYCODE_RIGHT_BRACKET },
- { Key::CTRL, AKEYCODE_CTRL_LEFT },
- { Key::CTRL, AKEYCODE_CTRL_RIGHT },
- { Key::UNKNOWN, 0 }
+static AndroidGodotCodePair android_godot_code_pairs[] = {
+ { AKEYCODE_UNKNOWN, Key::UNKNOWN }, // (0) Unknown key code.
+ { AKEYCODE_HOME, Key::HOME }, // (3) Home key.
+ { AKEYCODE_BACK, Key::BACK }, // (4) Back key.
+ { AKEYCODE_0, Key::KEY_0 }, // (7) '0' key.
+ { AKEYCODE_1, Key::KEY_1 }, // (8) '1' key.
+ { AKEYCODE_2, Key::KEY_2 }, // (9) '2' key.
+ { AKEYCODE_3, Key::KEY_3 }, // (10) '3' key.
+ { AKEYCODE_4, Key::KEY_4 }, // (11) '4' key.
+ { AKEYCODE_5, Key::KEY_5 }, // (12) '5' key.
+ { AKEYCODE_6, Key::KEY_6 }, // (13) '6' key.
+ { AKEYCODE_7, Key::KEY_7 }, // (14) '7' key.
+ { AKEYCODE_8, Key::KEY_8 }, // (15) '8' key.
+ { AKEYCODE_9, Key::KEY_9 }, // (16) '9' key.
+ { AKEYCODE_STAR, Key::ASTERISK }, // (17) '*' key.
+ { AKEYCODE_POUND, Key::NUMBERSIGN }, // (18) '#' key.
+ { AKEYCODE_DPAD_UP, Key::UP }, // (19) Directional Pad Up key.
+ { AKEYCODE_DPAD_DOWN, Key::DOWN }, // (20) Directional Pad Down key.
+ { AKEYCODE_DPAD_LEFT, Key::LEFT }, // (21) Directional Pad Left key.
+ { AKEYCODE_DPAD_RIGHT, Key::RIGHT }, // (22) Directional Pad Right key.
+ { AKEYCODE_VOLUME_UP, Key::VOLUMEUP }, // (24) Volume Up key.
+ { AKEYCODE_VOLUME_DOWN, Key::VOLUMEDOWN }, // (25) Volume Down key.
+ { AKEYCODE_CLEAR, Key::CLEAR }, // (28) Clear key.
+ { AKEYCODE_A, Key::A }, // (29) 'A' key.
+ { AKEYCODE_B, Key::B }, // (30) 'B' key.
+ { AKEYCODE_C, Key::C }, // (31) 'C' key.
+ { AKEYCODE_D, Key::D }, // (32) 'D' key.
+ { AKEYCODE_E, Key::E }, // (33) 'E' key.
+ { AKEYCODE_F, Key::F }, // (34) 'F' key.
+ { AKEYCODE_G, Key::G }, // (35) 'G' key.
+ { AKEYCODE_H, Key::H }, // (36) 'H' key.
+ { AKEYCODE_I, Key::I }, // (37) 'I' key.
+ { AKEYCODE_J, Key::J }, // (38) 'J' key.
+ { AKEYCODE_K, Key::K }, // (39) 'K' key.
+ { AKEYCODE_L, Key::L }, // (40) 'L' key.
+ { AKEYCODE_M, Key::M }, // (41) 'M' key.
+ { AKEYCODE_N, Key::N }, // (42) 'N' key.
+ { AKEYCODE_O, Key::O }, // (43) 'O' key.
+ { AKEYCODE_P, Key::P }, // (44) 'P' key.
+ { AKEYCODE_Q, Key::Q }, // (45) 'Q' key.
+ { AKEYCODE_R, Key::R }, // (46) 'R' key.
+ { AKEYCODE_S, Key::S }, // (47) 'S' key.
+ { AKEYCODE_T, Key::T }, // (48) 'T' key.
+ { AKEYCODE_U, Key::U }, // (49) 'U' key.
+ { AKEYCODE_V, Key::V }, // (50) 'V' key.
+ { AKEYCODE_W, Key::W }, // (51) 'W' key.
+ { AKEYCODE_X, Key::X }, // (52) 'X' key.
+ { AKEYCODE_Y, Key::Y }, // (53) 'Y' key.
+ { AKEYCODE_Z, Key::Z }, // (54) 'Z' key.
+ { AKEYCODE_COMMA, Key::COMMA }, // (55) ',’ key.
+ { AKEYCODE_PERIOD, Key::PERIOD }, // (56) '.' key.
+ { AKEYCODE_ALT_LEFT, Key::ALT }, // (57) Left Alt modifier key.
+ { AKEYCODE_ALT_RIGHT, Key::ALT }, // (58) Right Alt modifier key.
+ { AKEYCODE_SHIFT_LEFT, Key::SHIFT }, // (59) Left Shift modifier key.
+ { AKEYCODE_SHIFT_RIGHT, Key::SHIFT }, // (60) Right Shift modifier key.
+ { AKEYCODE_TAB, Key::TAB }, // (61) Tab key.
+ { AKEYCODE_SPACE, Key::SPACE }, // (62) Space key.
+ { AKEYCODE_ENTER, Key::ENTER }, // (66) Enter key.
+ { AKEYCODE_DEL, Key::BACKSPACE }, // (67) Backspace key.
+ { AKEYCODE_GRAVE, Key::QUOTELEFT }, // (68) '`' (backtick) key.
+ { AKEYCODE_MINUS, Key::MINUS }, // (69) '-'.
+ { AKEYCODE_EQUALS, Key::EQUAL }, // (70) '=' key.
+ { AKEYCODE_LEFT_BRACKET, Key::BRACKETLEFT }, // (71) '[' key.
+ { AKEYCODE_RIGHT_BRACKET, Key::BRACKETRIGHT }, // (72) ']' key.
+ { AKEYCODE_BACKSLASH, Key::BACKSLASH }, // (73) '\' key.
+ { AKEYCODE_SEMICOLON, Key::SEMICOLON }, // (74) ';' key.
+ { AKEYCODE_APOSTROPHE, Key::APOSTROPHE }, // (75) ''' (apostrophe) key.
+ { AKEYCODE_SLASH, Key::SLASH }, // (76) '/' key.
+ { AKEYCODE_AT, Key::AT }, // (77) '@' key.
+ { AKEYCODE_PLUS, Key::PLUS }, // (81) '+' key.
+ { AKEYCODE_MENU, Key::MENU }, // (82) Menu key.
+ { AKEYCODE_SEARCH, Key::SEARCH }, // (84) Search key.
+ { AKEYCODE_MEDIA_STOP, Key::MEDIASTOP }, // (86) Stop media key.
+ { AKEYCODE_MEDIA_PREVIOUS, Key::MEDIAPREVIOUS }, // (88) Play Previous media key.
+ { AKEYCODE_PAGE_UP, Key::PAGEUP }, // (92) Page Up key.
+ { AKEYCODE_PAGE_DOWN, Key::PAGEDOWN }, // (93) Page Down key.
+ { AKEYCODE_ESCAPE, Key::ESCAPE }, // (111) Escape key.
+ { AKEYCODE_FORWARD_DEL, Key::KEY_DELETE }, // (112) Forward Delete key.
+ { AKEYCODE_CTRL_LEFT, Key::CTRL }, // (113) Left Control modifier key.
+ { AKEYCODE_CTRL_RIGHT, Key::CTRL }, // (114) Right Control modifier key.
+ { AKEYCODE_CAPS_LOCK, Key::CAPSLOCK }, // (115) Caps Lock key.
+ { AKEYCODE_SCROLL_LOCK, Key::SCROLLLOCK }, // (116) Scroll Lock key.
+ { AKEYCODE_META_LEFT, Key::META }, // (117) Left Meta modifier key.
+ { AKEYCODE_META_RIGHT, Key::META }, // (118) Right Meta modifier key.
+ { AKEYCODE_SYSRQ, Key::PRINT }, // (120) System Request / Print Screen key.
+ { AKEYCODE_BREAK, Key::PAUSE }, // (121) Break / Pause key.
+ { AKEYCODE_INSERT, Key::INSERT }, // (124) Insert key.
+ { AKEYCODE_FORWARD, Key::FORWARD }, // (125) Forward key.
+ { AKEYCODE_MEDIA_PLAY, Key::MEDIAPLAY }, // (126) Play media key.
+ { AKEYCODE_MEDIA_RECORD, Key::MEDIARECORD }, // (130) Record media key.
+ { AKEYCODE_F1, Key::F1 }, // (131) F1 key.
+ { AKEYCODE_F2, Key::F2 }, // (132) F2 key.
+ { AKEYCODE_F3, Key::F3 }, // (133) F3 key.
+ { AKEYCODE_F4, Key::F4 }, // (134) F4 key.
+ { AKEYCODE_F5, Key::F5 }, // (135) F5 key.
+ { AKEYCODE_F6, Key::F6 }, // (136) F6 key.
+ { AKEYCODE_F7, Key::F7 }, // (137) F7 key.
+ { AKEYCODE_F8, Key::F8 }, // (138) F8 key.
+ { AKEYCODE_F9, Key::F9 }, // (139) F9 key.
+ { AKEYCODE_F10, Key::F10 }, // (140) F10 key.
+ { AKEYCODE_F11, Key::F11 }, // (141) F11 key.
+ { AKEYCODE_F12, Key::F12 }, // (142) F12 key.
+ { AKEYCODE_NUM_LOCK, Key::NUMLOCK }, // (143) Num Lock key.
+ { AKEYCODE_NUMPAD_0, Key::KP_0 }, // (144) Numeric keypad '0' key.
+ { AKEYCODE_NUMPAD_1, Key::KP_1 }, // (145) Numeric keypad '1' key.
+ { AKEYCODE_NUMPAD_2, Key::KP_2 }, // (146) Numeric keypad '2' key.
+ { AKEYCODE_NUMPAD_3, Key::KP_3 }, // (147) Numeric keypad '3' key.
+ { AKEYCODE_NUMPAD_4, Key::KP_4 }, // (148) Numeric keypad '4' key.
+ { AKEYCODE_NUMPAD_5, Key::KP_5 }, // (149) Numeric keypad '5' key.
+ { AKEYCODE_NUMPAD_6, Key::KP_6 }, // (150) Numeric keypad '6' key.
+ { AKEYCODE_NUMPAD_7, Key::KP_7 }, // (151) Numeric keypad '7' key.
+ { AKEYCODE_NUMPAD_8, Key::KP_8 }, // (152) Numeric keypad '8' key.
+ { AKEYCODE_NUMPAD_9, Key::KP_9 }, // (153) Numeric keypad '9' key.
+ { AKEYCODE_NUMPAD_DIVIDE, Key::KP_DIVIDE }, // (154) Numeric keypad '/' key (for division).
+ { AKEYCODE_NUMPAD_MULTIPLY, Key::KP_MULTIPLY }, // (155) Numeric keypad '*' key (for multiplication).
+ { AKEYCODE_NUMPAD_SUBTRACT, Key::KP_SUBTRACT }, // (156) Numeric keypad '-' key (for subtraction).
+ { AKEYCODE_NUMPAD_ADD, Key::KP_ADD }, // (157) Numeric keypad '+' key (for addition).
+ { AKEYCODE_NUMPAD_DOT, Key::KP_PERIOD }, // (158) Numeric keypad '.' key (for decimals or digit grouping).
+ { AKEYCODE_NUMPAD_ENTER, Key::KP_ENTER }, // (160) Numeric keypad Enter key.
+ { AKEYCODE_VOLUME_MUTE, Key::VOLUMEMUTE }, // (164) Volume Mute key.
+ { AKEYCODE_YEN, Key::YEN }, // (216) Japanese Yen key.
+ { AKEYCODE_HELP, Key::HELP }, // (259) Help key.
+ { AKEYCODE_REFRESH, Key::REFRESH }, // (285) Refresh key.
+ { AKEYCODE_MAX, Key::UNKNOWN }
};
-/*
-TODO: map these android key:
- AKEYCODE_SOFT_LEFT = 1,
- AKEYCODE_SOFT_RIGHT = 2,
- AKEYCODE_CALL = 5,
- AKEYCODE_ENDCALL = 6,
- AKEYCODE_STAR = 17,
- AKEYCODE_POUND = 18,
- AKEYCODE_POWER = 26,
- AKEYCODE_CAMERA = 27,
- AKEYCODE_CLEAR = 28,
- AKEYCODE_SYM = 63,
- AKEYCODE_ENVELOPE = 65,
- AKEYCODE_GRAVE = 68,
- AKEYCODE_SEMICOLON = 74,
- AKEYCODE_APOSTROPHE = 75,
- AKEYCODE_AT = 77,
- AKEYCODE_NUM = 78,
- AKEYCODE_HEADSETHOOK = 79,
- AKEYCODE_FOCUS = 80, // *Camera* focus
- AKEYCODE_NOTIFICATION = 83,
- AKEYCODE_SEARCH = 84,
- AKEYCODE_PICTSYMBOLS = 94,
- AKEYCODE_SWITCH_CHARSET = 95,
-*/
-Key android_get_keysym(unsigned int p_code);
+Key godot_code_from_android_code(unsigned int p_code);
+Key godot_code_from_unicode(unsigned int p_code);
#endif // ANDROID_KEYS_UTILS_H
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 3be220d110..b51dd18af6 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -221,12 +221,12 @@ bool DisplayServerAndroid::screen_is_touchscreen(int p_screen) const {
return true;
}
-void DisplayServerAndroid::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) {
+void DisplayServerAndroid::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) {
GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();
ERR_FAIL_NULL(godot_io_java);
if (godot_io_java->has_vk()) {
- godot_io_java->show_vk(p_existing_text, p_multiline, p_max_length, p_cursor_start, p_cursor_end);
+ godot_io_java->show_vk(p_existing_text, (int)p_type, p_max_length, p_cursor_start, p_cursor_end);
} else {
ERR_PRINT("Virtual keyboard not available");
}
@@ -276,9 +276,9 @@ void DisplayServerAndroid::_window_callback(const Callable &p_callable, const Va
Variant ret;
Callable::CallError ce;
if (p_deferred) {
- p_callable.call((const Variant **)&argp, 1, ret, ce);
+ p_callable.callp((const Variant **)&argp, 1, ret, ce);
} else {
- p_callable.call_deferred((const Variant **)&argp, 1);
+ p_callable.call_deferredp((const Variant **)&argp, 1);
}
}
}
@@ -482,7 +482,7 @@ void DisplayServerAndroid::notify_surface_changed(int p_width, int p_height) {
Variant ret;
Callable::CallError ce;
- rect_changed_callback.call(reinterpret_cast<const Variant **>(&sizep), 1, ret, ce);
+ rect_changed_callback.callp(reinterpret_cast<const Variant **>(&sizep), 1, ret, ce);
}
DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h
index 65bf2ec1a8..2f30642319 100644
--- a/platform/android/display_server_android.h
+++ b/platform/android/display_server_android.h
@@ -122,7 +122,7 @@ public:
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override;
+ virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override;
virtual void virtual_keyboard_hide() override;
virtual int virtual_keyboard_get_height() const override;
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 560f188b82..5bbe0ffab6 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -30,10 +30,10 @@
#include "export.h"
-#include "export_plugin.h"
-
#include "core/os/os.h"
#include "editor/editor_settings.h"
+#include "editor/export/editor_export.h"
+#include "export_plugin.h"
void register_android_exporter() {
EDITOR_DEF("export/android/android_sdk_path", "");
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 2cfb152804..6f1b4bde40 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -1671,7 +1671,7 @@ Vector<String> EditorExportPlatformAndroid::get_enabled_abis(const Ref<EditorExp
return enabled_abis;
}
-void EditorExportPlatformAndroid::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
+void EditorExportPlatformAndroid::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
if (driver == "opengl3") {
r_features->push_back("etc");
@@ -1705,6 +1705,8 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
}
plugins_changed.clear();
+ // Android supports multiple architectures in an app bundle, so
+ // we expose each option as a checkbox in the export dialog.
const Vector<String> abis = get_abis();
for (int i = 0; i < abis.size(); ++i) {
const String abi = abis[i];
@@ -3109,7 +3111,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
CLEANUP_AND_RETURN(OK);
}
-void EditorExportPlatformAndroid::get_platform_features(List<String> *r_features) {
+void EditorExportPlatformAndroid::get_platform_features(List<String> *r_features) const {
r_features->push_back("mobile");
r_features->push_back("android");
}
diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h
index 15ac8091be..1da3f68f9a 100644
--- a/platform/android/export/export_plugin.h
+++ b/platform/android/export/export_plugin.h
@@ -35,7 +35,7 @@
#include "core/io/zip_io.h"
#include "core/os/os.h"
-#include "editor/editor_export.h"
+#include "editor/export/editor_export_platform.h"
const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH(<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
@@ -156,7 +156,7 @@ public:
typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
public:
- virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override;
+ virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override;
virtual void get_export_options(List<ExportOption> *r_options) override;
@@ -231,7 +231,7 @@ public:
Error export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, int p_flags);
- virtual void get_platform_features(List<String> *r_features) override;
+ virtual void get_platform_features(List<String> *r_features) const override;
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, HashSet<String> &p_features) override;
diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h
index 7896392d16..232b4458c6 100644
--- a/platform/android/export/gradle_export_util.h
+++ b/platform/android/export/gradle_export_util.h
@@ -28,14 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GODOT_GRADLE_EXPORT_UTIL_H
-#define GODOT_GRADLE_EXPORT_UTIL_H
+#ifndef ANDROID_GRADLE_EXPORT_UTIL_H
+#define ANDROID_GRADLE_EXPORT_UTIL_H
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/zip_io.h"
#include "core/os/os.h"
-#include "editor/editor_export.h"
+#include "editor/export/editor_export.h"
const String godot_project_name_xml_string = R"(<?xml version="1.0" encoding="utf-8"?>
<!--WARNING: THIS FILE WILL BE OVERWRITTEN AT BUILD TIME-->
@@ -106,4 +106,4 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset);
String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_read_write_storage_permission);
-#endif // GODOT_GRADLE_EXPORT_UTIL_H
+#endif // ANDROID_GRADLE_EXPORT_UTIL_H
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index e6fd8c857b..8d7ade8ead 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -49,34 +49,34 @@ class FileAccessAndroid : public FileAccess {
public:
static AAssetManager *asset_manager;
- virtual Error _open(const String &p_path, int p_mode_flags); // open a file
- virtual bool is_open() const; // true when file is open
+ virtual Error _open(const String &p_path, int p_mode_flags) override; // open a file
+ virtual bool is_open() const override; // true when file is open
/// returns the path for the current open file
- virtual String get_path() const;
+ virtual String get_path() const override;
/// returns the absolute path for the current open file
- virtual String get_path_absolute() const;
+ virtual String get_path_absolute() const override;
- virtual void seek(uint64_t p_position); // seek to a given position
- virtual void seek_end(int64_t p_position = 0); // seek from the end of file
- virtual uint64_t get_position() const; // get position in the file
- virtual uint64_t get_length() const; // get size of the file
+ virtual void seek(uint64_t p_position) override; // seek to a given position
+ virtual void seek_end(int64_t p_position = 0) override; // seek from the end of file
+ virtual uint64_t get_position() const override; // get position in the file
+ virtual uint64_t get_length() const override; // get size of the file
- virtual bool eof_reached() const; // reading passed EOF
+ virtual bool eof_reached() const override; // reading passed EOF
- virtual uint8_t get_8() const; // get a byte
- virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
+ virtual uint8_t get_8() const override; // get a byte
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
- virtual Error get_error() const; // get last error
+ virtual Error get_error() const override; // get last error
- virtual void flush();
- virtual void store_8(uint8_t p_dest); // store a byte
+ virtual void flush() override;
+ virtual void store_8(uint8_t p_dest) override; // store a byte
- virtual bool file_exists(const String &p_path); // return true if a file exists
+ virtual bool file_exists(const String &p_path) override; // return true if a file exists
- virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
- virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
+ virtual uint64_t _get_modified_time(const String &p_file) override { return 0; }
+ virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
~FileAccessAndroid();
};
diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp
index c1a48e025e..6b21c18d59 100644
--- a/platform/android/file_access_filesystem_jandroid.cpp
+++ b/platform/android/file_access_filesystem_jandroid.cpp
@@ -29,8 +29,11 @@
/*************************************************************************/
#include "file_access_filesystem_jandroid.h"
+
#include "core/os/os.h"
+#include "core/templates/local_vector.h"
#include "thread_jandroid.h"
+
#include <unistd.h>
jobject FileAccessFilesystemJAndroid::file_access_handler = nullptr;
@@ -166,6 +169,51 @@ uint8_t FileAccessFilesystemJAndroid::get_8() const {
return byte;
}
+String FileAccessFilesystemJAndroid::get_line() const {
+ ERR_FAIL_COND_V_MSG(!is_open(), String(), "File must be opened before use.");
+
+ const size_t buffer_size_limit = 2048;
+ const uint64_t file_size = get_length();
+ const uint64_t start_position = get_position();
+
+ String result;
+ LocalVector<uint8_t> line_buffer;
+ size_t current_buffer_size = 0;
+ uint64_t line_buffer_position = 0;
+
+ while (true) {
+ size_t line_buffer_size = MIN(buffer_size_limit, file_size - get_position());
+ if (line_buffer_size <= 0) {
+ break;
+ }
+
+ current_buffer_size += line_buffer_size;
+ line_buffer.resize(current_buffer_size);
+
+ uint64_t bytes_read = get_buffer(&line_buffer[line_buffer_position], current_buffer_size - line_buffer_position);
+ if (bytes_read <= 0) {
+ break;
+ }
+
+ for (; bytes_read > 0; line_buffer_position++, bytes_read--) {
+ uint8_t elem = line_buffer[line_buffer_position];
+ if (elem == '\n' || elem == '\0') {
+ // Found the end of the line
+ const_cast<FileAccessFilesystemJAndroid *>(this)->seek(start_position + line_buffer_position + 1);
+ if (result.parse_utf8((const char *)line_buffer.ptr(), line_buffer_position, true)) {
+ return String();
+ }
+ return result;
+ }
+ }
+ }
+
+ if (result.parse_utf8((const char *)line_buffer.ptr(), line_buffer_position, true)) {
+ return String();
+ }
+ return result;
+}
+
uint64_t FileAccessFilesystemJAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
if (_file_read) {
ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h
index 18d5df1628..7deb8de37b 100644
--- a/platform/android/file_access_filesystem_jandroid.h
+++ b/platform/android/file_access_filesystem_jandroid.h
@@ -74,6 +74,7 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
virtual uint8_t get_8() const override; ///< get a byte
+ virtual String get_line() const override; ///< get a line
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; ///< get last error
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 0434efdf4c..d283de8ce8 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/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
index e2ae62d9cf..f855fc6cf6 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
@@ -151,7 +151,7 @@ public class GodotLib {
/**
* Forward regular key events from the main thread to the GL thread.
*/
- public static native void key(int p_keycode, int p_scancode, int p_unicode_char, boolean p_pressed);
+ public static native void key(int p_keycode, int p_physical_keycode, int p_unicode, boolean p_pressed);
/**
* Forward game device's key events from the main thread to the GL thread.
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 ecb2af0a7b..7925b54fc4 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 DisplayServer::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<GodotEditText> mEdit;
@@ -100,8 +112,8 @@ public class GodotEditText extends EditText {
setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_ACTION_DONE);
}
- public boolean isMultiline() {
- return mMultiline;
+ public VirtualKeyboardType getKeyboardType() {
+ return mKeyboardType;
}
private void handleMessage(final Message msg) {
@@ -122,8 +134,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);
@@ -201,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;
@@ -214,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/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
index ccfb865b1a..da15b2490c 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
@@ -96,10 +96,14 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
GodotLib.joybutton(godotJoyId, button, false);
}
} else {
- final int scanCode = event.getScanCode();
- final int chr = event.getUnicodeChar(0);
- GodotLib.key(keyCode, scanCode, chr, false);
- }
+ // getKeyCode(): The physical key that was pressed.
+ // Godot's keycodes match the ASCII codes, so for single byte unicode characters,
+ // we can use the unmodified unicode character to determine Godot's keycode.
+ final int keycode = event.getUnicodeChar(0);
+ final int physical_keycode = event.getKeyCode();
+ final int unicode = event.getUnicodeChar();
+ GodotLib.key(keycode, physical_keycode, unicode, false);
+ };
return true;
}
@@ -131,9 +135,10 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
GodotLib.joybutton(godotJoyId, button, true);
}
} else {
- final int scanCode = event.getScanCode();
- final int chr = event.getUnicodeChar(0);
- GodotLib.key(keyCode, scanCode, chr, true);
+ final int keycode = event.getUnicodeChar(0);
+ final int physical_keycode = event.getKeyCode();
+ final int unicode = event.getUnicodeChar();
+ GodotLib.key(keycode, physical_keycode, unicode, true);
}
return true;
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
index e940aafa9e..c959b5f28c 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
@@ -92,11 +92,9 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
@Override
public void beforeTextChanged(final CharSequence pCharSequence, final int start, final int count, final int after) {
- //Log.d(TAG, "beforeTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",after: " + after);
-
for (int i = 0; i < count; ++i) {
- GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, true);
- GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, false);
+ GodotLib.key(0, KeyEvent.KEYCODE_DEL, 0, true);
+ GodotLib.key(0, KeyEvent.KEYCODE_DEL, 0, false);
if (mHasSelection) {
mHasSelection = false;
@@ -107,20 +105,18 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
@Override
public void onTextChanged(final CharSequence pCharSequence, final int start, final int before, final int count) {
- //Log.d(TAG, "onTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",before: " + before);
-
final int[] newChars = new int[count];
for (int i = start; i < start + count; ++i) {
newChars[i - start] = pCharSequence.charAt(i);
}
for (int i = 0; i < count; ++i) {
int key = newChars[i];
- if ((key == '\n') && !mEdit.isMultiline()) {
+ if ((key == '\n') && !(mEdit.getKeyboardType() == GodotEditText.VirtualKeyboardType.KEYBOARD_TYPE_MULTILINE)) {
// Return keys are handled through action events
continue;
}
- GodotLib.key(0, 0, key, true);
- GodotLib.key(0, 0, key, false);
+ GodotLib.key(key, 0, key, true);
+ GodotLib.key(key, 0, key, false);
}
}
@@ -131,16 +127,16 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
for (int i = 0; i < characters.length(); i++) {
final int ch = characters.codePointAt(i);
- GodotLib.key(0, 0, ch, true);
- GodotLib.key(0, 0, ch, false);
+ GodotLib.key(ch, 0, ch, true);
+ GodotLib.key(ch, 0, ch, false);
}
}
if (pActionID == EditorInfo.IME_ACTION_DONE) {
// Enter key has been pressed
mRenderView.queueOnRenderThread(() -> {
- GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, true);
- GodotLib.key(KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_ENTER, 0, false);
+ GodotLib.key(0, KeyEvent.KEYCODE_ENTER, 0, true);
+ GodotLib.key(0, KeyEvent.KEYCODE_ENTER, 0, false);
});
mRenderView.getView().requestFocus();
return true;
diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt b/platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt
index c7bd55b620..c9282dd247 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/StorageScope.kt
@@ -54,11 +54,19 @@ internal enum class StorageScope {
*/
UNKNOWN;
- companion object {
+ class Identifier(context: Context) {
+
+ private val internalAppDir: String? = context.filesDir.canonicalPath
+ private val internalCacheDir: String? = context.cacheDir.canonicalPath
+ private val externalAppDir: String? = context.getExternalFilesDir(null)?.canonicalPath
+ private val sharedDir : String? = Environment.getExternalStorageDirectory().canonicalPath
+ private val downloadsSharedDir: String? = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).canonicalPath
+ private val documentsSharedDir: String? = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).canonicalPath
+
/**
* Determines which [StorageScope] the given path falls under.
*/
- fun getStorageScope(context: Context, path: String?): StorageScope {
+ fun identifyStorageScope(path: String?): StorageScope {
if (path == null) {
return UNKNOWN
}
@@ -70,23 +78,19 @@ internal enum class StorageScope {
val canonicalPathFile = pathFile.canonicalPath
- val internalAppDir = context.filesDir.canonicalPath ?: return UNKNOWN
- if (canonicalPathFile.startsWith(internalAppDir)) {
+ if (internalAppDir != null && canonicalPathFile.startsWith(internalAppDir)) {
return APP
}
- val internalCacheDir = context.cacheDir.canonicalPath ?: return UNKNOWN
- if (canonicalPathFile.startsWith(internalCacheDir)) {
+ if (internalCacheDir != null && canonicalPathFile.startsWith(internalCacheDir)) {
return APP
}
- val externalAppDir = context.getExternalFilesDir(null)?.canonicalPath ?: return UNKNOWN
- if (canonicalPathFile.startsWith(externalAppDir)) {
+ if (externalAppDir != null && canonicalPathFile.startsWith(externalAppDir)) {
return APP
}
- val sharedDir = Environment.getExternalStorageDirectory().canonicalPath ?: return UNKNOWN
- if (canonicalPathFile.startsWith(sharedDir)) {
+ if (sharedDir != null && canonicalPathFile.startsWith(sharedDir)) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
// Before R, apps had access to shared storage so long as they have the right
// permissions (and flag on Q).
@@ -95,13 +99,8 @@ internal enum class StorageScope {
// Post R, access is limited based on the target destination
// 'Downloads' and 'Documents' are still accessible
- val downloadsSharedDir =
- Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).canonicalPath
- ?: return SHARED
- val documentsSharedDir =
- Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).canonicalPath
- ?: return SHARED
- if (canonicalPathFile.startsWith(downloadsSharedDir) || canonicalPathFile.startsWith(documentsSharedDir)) {
+ if ((downloadsSharedDir != null && canonicalPathFile.startsWith(downloadsSharedDir))
+ || (documentsSharedDir != null && canonicalPathFile.startsWith(documentsSharedDir))) {
return APP
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/directory/FilesystemDirectoryAccess.kt b/platform/android/java/lib/src/org/godotengine/godot/io/directory/FilesystemDirectoryAccess.kt
index c3acf42568..54fc56fa3e 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/io/directory/FilesystemDirectoryAccess.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/directory/FilesystemDirectoryAccess.kt
@@ -54,6 +54,7 @@ internal class FilesystemDirectoryAccess(private val context: Context):
private data class DirData(val dirFile: File, val files: Array<File>, var current: Int = 0)
+ private val storageScopeIdentifier = StorageScope.Identifier(context)
private val storageManager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
private var lastDirId = STARTING_DIR_ID
private val dirs = SparseArray<DirData>()
@@ -62,7 +63,7 @@ internal class FilesystemDirectoryAccess(private val context: Context):
// Directory access is available for shared storage on Android 11+
// On Android 10, access is also available as long as the `requestLegacyExternalStorage`
// tag is available.
- return StorageScope.getStorageScope(context, path) != StorageScope.UNKNOWN
+ return storageScopeIdentifier.identifyStorageScope(path) != StorageScope.UNKNOWN
}
override fun hasDirId(dirId: Int) = dirs.indexOfKey(dirId) >= 0
@@ -102,7 +103,7 @@ internal class FilesystemDirectoryAccess(private val context: Context):
}
}
- override fun fileExists(path: String) = FileAccessHandler.fileExists(context, path)
+ override fun fileExists(path: String) = FileAccessHandler.fileExists(context, storageScopeIdentifier, path)
override fun dirNext(dirId: Int): String {
val dirData = dirs[dirId]
@@ -199,7 +200,7 @@ internal class FilesystemDirectoryAccess(private val context: Context):
if (fromFile.isDirectory) {
fromFile.renameTo(File(to))
} else {
- FileAccessHandler.renameFile(context, from, to)
+ FileAccessHandler.renameFile(context, storageScopeIdentifier, from, to)
}
} catch (e: SecurityException) {
false
@@ -218,7 +219,7 @@ internal class FilesystemDirectoryAccess(private val context: Context):
if (deleteFile.isDirectory) {
deleteFile.delete()
} else {
- FileAccessHandler.removeFile(context, filename)
+ FileAccessHandler.removeFile(context, storageScopeIdentifier, filename)
}
} else {
true
diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt b/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt
index aef1bed8ce..463dabfb23 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt
@@ -161,8 +161,9 @@ internal abstract class DataAccess(private val filePath: String) {
fun read(buffer: ByteBuffer): Int {
return try {
val readBytes = fileChannel.read(buffer)
+ endOfFile = readBytes == -1
+ || (fileChannel.position() >= fileChannel.size() && fileChannel.size() > 0)
if (readBytes == -1) {
- endOfFile = true
0
} else {
readBytes
diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt
index a4e0a82d6e..04b6772c45 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt
@@ -49,8 +49,8 @@ class FileAccessHandler(val context: Context) {
private const val INVALID_FILE_ID = 0
private const val STARTING_FILE_ID = 1
- fun fileExists(context: Context, path: String?): Boolean {
- val storageScope = StorageScope.getStorageScope(context, path)
+ internal fun fileExists(context: Context, storageScopeIdentifier: StorageScope.Identifier, path: String?): Boolean {
+ val storageScope = storageScopeIdentifier.identifyStorageScope(path)
if (storageScope == StorageScope.UNKNOWN) {
return false
}
@@ -62,8 +62,8 @@ class FileAccessHandler(val context: Context) {
}
}
- fun removeFile(context: Context, path: String?): Boolean {
- val storageScope = StorageScope.getStorageScope(context, path)
+ internal fun removeFile(context: Context, storageScopeIdentifier: StorageScope.Identifier, path: String?): Boolean {
+ val storageScope = storageScopeIdentifier.identifyStorageScope(path)
if (storageScope == StorageScope.UNKNOWN) {
return false
}
@@ -75,8 +75,8 @@ class FileAccessHandler(val context: Context) {
}
}
- fun renameFile(context: Context, from: String?, to: String?): Boolean {
- val storageScope = StorageScope.getStorageScope(context, from)
+ internal fun renameFile(context: Context, storageScopeIdentifier: StorageScope.Identifier, from: String?, to: String?): Boolean {
+ val storageScope = storageScopeIdentifier.identifyStorageScope(from)
if (storageScope == StorageScope.UNKNOWN) {
return false
}
@@ -89,13 +89,14 @@ class FileAccessHandler(val context: Context) {
}
}
+ private val storageScopeIdentifier = StorageScope.Identifier(context)
private val files = SparseArray<DataAccess>()
private var lastFileId = STARTING_FILE_ID
private fun hasFileId(fileId: Int) = files.indexOfKey(fileId) >= 0
fun fileOpen(path: String?, modeFlags: Int): Int {
- val storageScope = StorageScope.getStorageScope(context, path)
+ val storageScope = storageScopeIdentifier.identifyStorageScope(path)
if (storageScope == StorageScope.UNKNOWN) {
return INVALID_FILE_ID
}
@@ -162,10 +163,10 @@ class FileAccessHandler(val context: Context) {
files[fileId].flush()
}
- fun fileExists(path: String?) = Companion.fileExists(context, path)
+ fun fileExists(path: String?) = Companion.fileExists(context, storageScopeIdentifier, path)
fun fileLastModified(filepath: String?): Long {
- val storageScope = StorageScope.getStorageScope(context, filepath)
+ val storageScope = storageScopeIdentifier.identifyStorageScope(filepath)
if (storageScope == StorageScope.UNKNOWN) {
return 0L
}
diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp
index b71c6ef1e6..5877c15114 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_scaled_density = p_env->GetMethodID(cls, "getScaledDensity", "()F");
_get_screen_refresh_rate = p_env->GetMethodID(cls, "getScreenRefreshRate", "(D)D");
_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 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 aec7d1db97..dc68f4d90d 100644
--- a/platform/android/java_godot_io_wrapper.h
+++ b/platform/android/java_godot_io_wrapper.h
@@ -82,7 +82,7 @@ public:
Rect2i get_display_safe_area();
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/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index f4de4acfad..422c05e5ce 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -376,12 +376,11 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(
}
// Called on the UI thread
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jclass clazz, jint p_keycode, jint p_scancode, jint p_unicode_char, jboolean p_pressed) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jclass clazz, jint p_keycode, jint p_physical_keycode, jint p_unicode, jboolean p_pressed) {
if (step.get() <= 0) {
return;
}
-
- input_handler->process_key_event(p_keycode, p_scancode, p_unicode_char, p_pressed);
+ input_handler->process_key_event(p_keycode, p_physical_keycode, p_unicode, p_pressed);
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv *env, jclass clazz, jfloat x, jfloat y, jfloat z) {
diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h
index de16f197b8..3c48ca0459 100644
--- a/platform/android/java_godot_lib_jni.h
+++ b/platform/android/java_godot_lib_jni.h
@@ -51,7 +51,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch__IIII_3FI(JNIEn
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch__IIII_3FIFF(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray positions, jint buttons_mask, jfloat vertical_factor, jfloat horizontal_factor);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jclass clazz, jint p_type, jfloat p_x, jfloat p_y);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubleTap(JNIEnv *env, jclass clazz, jint p_button_mask, jint p_x, jint p_y);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jclass clazz, jint p_keycode, jint p_scancode, jint p_unicode_char, jboolean p_pressed);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jclass clazz, jint p_keycode, jint p_physical_keycode, jint p_unicode, jboolean p_pressed);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jclass clazz, jint p_device, jint p_button, jboolean p_pressed);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jclass clazz, jint p_device, jint p_axis, jfloat p_value);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, jclass clazz, jint p_device, jint p_hat_x, jint p_hat_y);
diff --git a/platform/android/java_godot_view_wrapper.h b/platform/android/java_godot_view_wrapper.h
index b1f258bbb5..c52f459d64 100644
--- a/platform/android/java_godot_view_wrapper.h
+++ b/platform/android/java_godot_view_wrapper.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GODOT_JAVA_GODOT_VIEW_WRAPPER_H
-#define GODOT_JAVA_GODOT_VIEW_WRAPPER_H
+#ifndef JAVA_GODOT_VIEW_WRAPPER_H
+#define JAVA_GODOT_VIEW_WRAPPER_H
#include <android/log.h>
#include <jni.h>
@@ -57,4 +57,4 @@ public:
~GodotJavaViewWrapper();
};
-#endif // GODOT_JAVA_GODOT_VIEW_WRAPPER_H
+#endif // JAVA_GODOT_VIEW_WRAPPER_H