From 07fd42ee3cafd1548b11e43fb8c860c00005ba70 Mon Sep 17 00:00:00 2001 From: Deve Date: Mon, 20 Aug 2018 23:31:31 +0200 Subject: [PATCH] Add support for unicode characters for hardware keyboard on android --- .../source/Irrlicht/CIrrDeviceAndroid.cpp | 94 ++++++++++++++++--- .../source/Irrlicht/CIrrDeviceAndroid.h | 5 +- src/guiengine/widgets/CGUIEditBox.cpp | 28 +++++- 3 files changed, 111 insertions(+), 16 deletions(-) diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp index 096cdbc63..a10076b1b 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.cpp @@ -50,6 +50,7 @@ CIrrDeviceAndroid::CIrrDeviceAndroid(const SIrrlichtCreationParameters& param) Gyroscope(0), AccelerometerActive(false), GyroscopeActive(false), + TextInputEnabled(false), IsMousePressed(false), GamepadAxisX(0), GamepadAxisY(0), @@ -701,7 +702,15 @@ s32 CIrrDeviceAndroid::handleKeyboard(AInputEvent* androidEvent) if (event.KeyInput.Key > 0) { - getKeyChar(event); + if (TextInputEnabled == true) + { + event.KeyInput.Char = getUnicodeChar(androidEvent); + } + + if (event.KeyInput.Char == 0) + { + event.KeyInput.Char = getKeyChar(event); + } } // If button doesn't return key code, then at least use device-specific @@ -1110,59 +1119,118 @@ void CIrrDeviceAndroid::createKeyMap() KeyMap[AKEYCODE_MEDIA_AUDIO_TRACK] = IRR_KEY_UNKNOWN; } -void CIrrDeviceAndroid::getKeyChar(SEvent& event) +wchar_t CIrrDeviceAndroid::getKeyChar(SEvent& event) { // Handle ASCII chars - event.KeyInput.Char = 0; + wchar_t key_char = 0; // A-Z if (event.KeyInput.SystemKeyCode > 28 && event.KeyInput.SystemKeyCode < 55) { if (event.KeyInput.Shift) { - event.KeyInput.Char = event.KeyInput.SystemKeyCode + 36; + key_char = event.KeyInput.SystemKeyCode + 36; } else { - event.KeyInput.Char = event.KeyInput.SystemKeyCode + 68; + key_char = event.KeyInput.SystemKeyCode + 68; } } // 0-9 else if (event.KeyInput.SystemKeyCode > 6 && event.KeyInput.SystemKeyCode < 17) { - event.KeyInput.Char = event.KeyInput.SystemKeyCode + 41; + key_char = event.KeyInput.SystemKeyCode + 41; } else if (event.KeyInput.SystemKeyCode == AKEYCODE_BACK) { - event.KeyInput.Char = 8; + key_char = 8; } else if (event.KeyInput.SystemKeyCode == AKEYCODE_DEL) { - event.KeyInput.Char = 8; + key_char = 8; } else if (event.KeyInput.SystemKeyCode == AKEYCODE_TAB) { - event.KeyInput.Char = 9; + key_char = 9; } else if (event.KeyInput.SystemKeyCode == AKEYCODE_ENTER) { - event.KeyInput.Char = 13; + key_char = 13; } else if (event.KeyInput.SystemKeyCode == AKEYCODE_SPACE) { - event.KeyInput.Char = 32; + key_char = 32; } else if (event.KeyInput.SystemKeyCode == AKEYCODE_COMMA) { - event.KeyInput.Char = 44; + key_char = 44; } else if (event.KeyInput.SystemKeyCode == AKEYCODE_PERIOD) { - event.KeyInput.Char = 46; + key_char = 46; } + + return key_char; +} + +wchar_t CIrrDeviceAndroid::getUnicodeChar(AInputEvent* event) +{ + bool was_detached = false; + JNIEnv* env = NULL; + + jint status = Android->activity->vm->GetEnv((void**)&env, JNI_VERSION_1_6); + + if (status == JNI_EDETACHED) + { + JavaVMAttachArgs args; + args.version = JNI_VERSION_1_6; + args.name = "NativeThread"; + args.group = NULL; + + status = Android->activity->vm->AttachCurrentThread(&env, &args); + was_detached = true; + } + + if (status != JNI_OK) + { + os::Printer::log("Cannot get unicode character.", ELL_DEBUG); + return 0; + } + + jlong down_time = AKeyEvent_getDownTime(event); + jlong event_time = AKeyEvent_getEventTime(event); + jint action = AKeyEvent_getAction(event); + jint code = AKeyEvent_getKeyCode(event); + jint repeat = AKeyEvent_getRepeatCount(event); + jint meta_state = AKeyEvent_getMetaState(event); + jint device_id = AInputEvent_getDeviceId(event); + jint scan_code = AKeyEvent_getScanCode(event); + jint flags = AKeyEvent_getFlags(event); + jint source = AInputEvent_getSource(event); + + jclass key_event = env->FindClass("android/view/KeyEvent"); + jmethodID key_event_constructor = env->GetMethodID(key_event, "", + "(JJIIIIIIII)V"); + + jobject key_event_obj = env->NewObject(key_event, key_event_constructor, + down_time, event_time, action, code, + repeat, meta_state, device_id, + scan_code, flags, source); + + jmethodID get_unicode = env->GetMethodID(key_event, "getUnicodeChar", "(I)I"); + + wchar_t unicode_char = env->CallIntMethod(key_event_obj, get_unicode, + meta_state); + + if (was_detached) + { + Android->activity->vm->DetachCurrentThread(); + } + + return unicode_char; } void CIrrDeviceAndroid::hideNavBar(ANativeActivity* activity) diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h b/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h index 3c56b934e..64c3f8b4a 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceAndroid.h @@ -64,6 +64,7 @@ namespace irr virtual bool deactivateGyroscope(); virtual bool isGyroscopeActive(); virtual bool isGyroscopeAvailable(); + virtual void setTextInputEnabled(bool enabled) {TextInputEnabled = enabled;} class CCursorControl : public gui::ICursorControl { @@ -113,6 +114,7 @@ namespace irr const ASensor* Gyroscope; bool AccelerometerActive; bool GyroscopeActive; + bool TextInputEnabled; static bool IsPaused; static bool IsFocused; @@ -141,7 +143,8 @@ namespace irr void createDriver(); void createKeyMap(); void createVideoModeList(); - void getKeyChar(SEvent& event); + wchar_t getKeyChar(SEvent& event); + wchar_t getUnicodeChar(AInputEvent* event); static void hideNavBar(ANativeActivity* activity); int getRotation(); DeviceOrientation getDefaultOrientation(); diff --git a/src/guiengine/widgets/CGUIEditBox.cpp b/src/guiengine/widgets/CGUIEditBox.cpp index f39d3ff77..c76712c09 100644 --- a/src/guiengine/widgets/CGUIEditBox.cpp +++ b/src/guiengine/widgets/CGUIEditBox.cpp @@ -120,6 +120,14 @@ CGUIEditBox::~CGUIEditBox() dl->setIMEEnable(false); } #endif +#ifdef ANDROID + if (irr_driver->getDevice()->getType() == irr::EIDT_ANDROID) + { + CIrrDeviceAndroid* dl = dynamic_cast( + irr_driver->getDevice()); + dl->setTextInputEnabled(false); + } +#endif #endif } @@ -268,11 +276,19 @@ bool CGUIEditBox::OnEvent(const SEvent& event) irr_driver->getDevice()); dl->setIMEEnable(false); } +#endif +#ifdef ANDROID + if (irr_driver->getDevice()->getType() == irr::EIDT_ANDROID) + { + CIrrDeviceAndroid* dl = dynamic_cast( + irr_driver->getDevice()); + dl->setTextInputEnabled(false); + } #endif } -#ifdef _IRR_COMPILE_WITH_X11_DEVICE_ else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED) { +#ifdef _IRR_COMPILE_WITH_X11_DEVICE_ if (irr_driver->getDevice()->getType() == irr::EIDT_X11) { CIrrDeviceLinux* dl = dynamic_cast( @@ -280,8 +296,16 @@ bool CGUIEditBox::OnEvent(const SEvent& event) dl->setIMEEnable(true); dl->setIMELocation(calculateICPos()); } - } #endif +#ifdef ANDROID + if (irr_driver->getDevice()->getType() == irr::EIDT_ANDROID) + { + CIrrDeviceAndroid* dl = dynamic_cast( + irr_driver->getDevice()); + dl->setTextInputEnabled(true); + } +#endif + } break; #if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_) case EET_IMPUT_METHOD_EVENT: