diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 43b87a051..38fed7bc9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -302,6 +302,7 @@ elseif (ANDROID) drivers/Android/Fl_Android_Application.cxx drivers/Android/Fl_Android_System_Driver.cxx drivers/Android/Fl_Android_Screen_Driver.cxx + drivers/Android/Fl_Android_Screen_Keyboard.cxx drivers/Android/Fl_Android_Window_Driver.cxx drivers/Android/Fl_Android_Image_Surface_Driver.cxx drivers/Android/Fl_Android_Graphics_Driver.cxx diff --git a/src/drivers/Android/Fl_Android_Screen_Driver.H b/src/drivers/Android/Fl_Android_Screen_Driver.H index 59cec5462..4154bf64d 100644 --- a/src/drivers/Android/Fl_Android_Screen_Driver.H +++ b/src/drivers/Android/Fl_Android_Screen_Driver.H @@ -48,10 +48,10 @@ private: public: Fl_Android_Screen_Driver() : Fl_Screen_Driver(), pScreenContentChanged(false) { } - void add_timeout(double time, Fl_Timeout_Handler cb, void *argp); - void repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp); - int has_timeout(Fl_Timeout_Handler cb, void *argp); - void remove_timeout(Fl_Timeout_Handler cb, void *argp); + virtual void add_timeout(double time, Fl_Timeout_Handler cb, void *argp) override; + virtual void repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp) override; + virtual int has_timeout(Fl_Timeout_Handler cb, void *argp) override; + virtual void remove_timeout(Fl_Timeout_Handler cb, void *argp) override; virtual int compose(int &del) override; @@ -79,8 +79,8 @@ public: virtual void beep(int type); // --- global events #endif - virtual void flush(); - virtual double wait(double time_to_wait); + virtual void flush() override; + virtual double wait(double time_to_wait) override; #if 0 virtual int ready(); virtual void grab(Fl_Window* win); diff --git a/src/drivers/Android/Fl_Android_Screen_Driver.cxx b/src/drivers/Android/Fl_Android_Screen_Driver.cxx index 4a3f8484d..43ad41148 100644 --- a/src/drivers/Android/Fl_Android_Screen_Driver.cxx +++ b/src/drivers/Android/Fl_Android_Screen_Driver.cxx @@ -38,22 +38,6 @@ void (*fl_lock_function)() = nothing; static void timer_do_callback(int timerIndex); -#if 0 - -// these are set by Fl::args() and override any system colors: from Fl_get_system_colors.cxx -extern const char *fl_fg; -extern const char *fl_bg; -extern const char *fl_bg2; -// end of extern additions workaround - - -#if !defined(HMONITOR_DECLARED) && (_WIN32_WINNT < 0x0500) -# define COMPILE_MULTIMON_STUBS -# include -#endif // !HMONITOR_DECLARED && _WIN32_WINNT < 0x0500 - -#endif - /* Creates a driver that manages all screen and display related calls. @@ -67,6 +51,7 @@ Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver() extern int fl_send_system_handlers(void *e); + int Fl_Android_Screen_Driver::handle_app_command() { // get the command @@ -84,6 +69,7 @@ int Fl_Android_Screen_Driver::handle_app_command() return 1; } + int Fl_Android_Screen_Driver::handle_input_event() { AInputQueue *queue = Fl_Android_Application::input_event_queue(); @@ -112,135 +98,6 @@ int Fl_Android_Screen_Driver::handle_input_event() } -int Fl_Android_Screen_Driver::compose(int &del) -{ - del = 0; - return 1; -} - - -int Fl_Android_Screen_Driver::handle_keyboard_event(AInputQueue *queue, AInputEvent *event) -{ -/* -int32_t AKeyEvent_getAction (const AInputEvent *key_event) - { AKEY_EVENT_ACTION_DOWN = 0, AKEY_EVENT_ACTION_UP = 1, AKEY_EVENT_ACTION_MULTIPLE = 2 } -> Reading up on ACTION_MULTIPLE also explains how to deal with -> special or sequences of characters: -> "If the key code is not KEYCODE_UNKNOWN then the getRepeatCount() -> method returns the number of times the given key code should be -> executed. Otherwise, if the key code is KEYCODE_UNKNOWN, then this -> is a sequence of characters as returned by getCharacters()." - -int32_t AKeyEvent_getFlags (const AInputEvent *key_event) - { - AKEY_EVENT_FLAG_WOKE_HERE = 0x1, AKEY_EVENT_FLAG_SOFT_KEYBOARD = 0x2, AKEY_EVENT_FLAG_KEEP_TOUCH_MODE = 0x4, AKEY_EVENT_FLAG_FROM_SYSTEM = 0x8, - AKEY_EVENT_FLAG_EDITOR_ACTION = 0x10, AKEY_EVENT_FLAG_CANCELED = 0x20, AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY = 0x40, AKEY_EVENT_FLAG_LONG_PRESS = 0x80, - AKEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100, AKEY_EVENT_FLAG_TRACKING = 0x200, AKEY_EVENT_FLAG_FALLBACK = 0x400 -} - -int32_t AKeyEvent_getKeyCode (const AInputEvent *key_event) - { - AKEYCODE_UNKNOWN = 0, AKEYCODE_SOFT_LEFT = 1, AKEYCODE_SOFT_RIGHT = 2, AKEYCODE_HOME = 3, - AKEYCODE_BACK = 4, AKEYCODE_CALL = 5, AKEYCODE_ENDCALL = 6, AKEYCODE_0 = 7, - AKEYCODE_1 = 8, AKEYCODE_2 = 9, AKEYCODE_3 = 10, AKEYCODE_4 = 11, - AKEYCODE_5 = 12, AKEYCODE_6 = 13, AKEYCODE_7 = 14, AKEYCODE_8 = 15, - AKEYCODE_9 = 16, AKEYCODE_STAR = 17, AKEYCODE_POUND = 18, AKEYCODE_DPAD_UP = 19, - AKEYCODE_DPAD_DOWN = 20, AKEYCODE_DPAD_LEFT = 21, AKEYCODE_DPAD_RIGHT = 22, AKEYCODE_DPAD_CENTER = 23, - AKEYCODE_VOLUME_UP = 24, AKEYCODE_VOLUME_DOWN = 25, AKEYCODE_POWER = 26, AKEYCODE_CAMERA = 27, - AKEYCODE_CLEAR = 28, AKEYCODE_A = 29, AKEYCODE_B = 30, AKEYCODE_C = 31, - AKEYCODE_D = 32, AKEYCODE_E = 33, AKEYCODE_F = 34, AKEYCODE_G = 35, ... - -int32_t AKeyEvent_getScanCode (const AInputEvent *key_event) - { AKEY_STATE_UNKNOWN = -1, AKEY_STATE_UP = 0, AKEY_STATE_DOWN = 1, AKEY_STATE_VIRTUAL = 2 } - -int32_t AKeyEvent_getMetaState (const AInputEvent *key_event) - { - AMETA_NONE = 0, AMETA_ALT_ON = 0x02, AMETA_ALT_LEFT_ON = 0x10, AMETA_ALT_RIGHT_ON = 0x20, - AMETA_SHIFT_ON = 0x01, AMETA_SHIFT_LEFT_ON = 0x40, AMETA_SHIFT_RIGHT_ON = 0x80, AMETA_SYM_ON = 0x04, - AMETA_FUNCTION_ON = 0x08, AMETA_CTRL_ON = 0x1000, AMETA_CTRL_LEFT_ON = 0x2000, AMETA_CTRL_RIGHT_ON = 0x4000, - AMETA_META_ON = 0x10000, AMETA_META_LEFT_ON = 0x20000, AMETA_META_RIGHT_ON = 0x40000, AMETA_CAPS_LOCK_ON = 0x100000, - AMETA_NUM_LOCK_ON = 0x200000, AMETA_SCROLL_LOCK_ON = 0x400000 -} - -int32_t AKeyEvent_getRepeatCount (const AInputEvent *key_event) -int64_t AKeyEvent_getDownTime (const AInputEvent *key_event) -int64_t AKeyEvent_getEventTime (const AInputEvent *key_event) -*/ - Fl_Android_Application::log_i("Key event: action=%d keyCode=%d metaState=0x%x scanCode=%d", - AKeyEvent_getAction(event), - AKeyEvent_getKeyCode(event), - AKeyEvent_getMetaState(event), - AKeyEvent_getScanCode(event)); - - auto keyAction = AKeyEvent_getAction(event); - if (keyAction==AKEY_EVENT_ACTION_MULTIPLE) { - if (AKeyEvent_getKeyCode(event)==AKEYCODE_UNKNOWN) { - // characters are in getCharacters() - // String class KeyEvent::getCharacters() [Java] - // is there a way to get the true Java event somehow? - // override dispatchKeyEvent(android.view.KeyEvent event) - } else { - // send keycode as many times as getRepeatCount() / AKeyEvent_getRepeatCount(event) - } - } - - JavaVM *javaVM = Fl_Android_Application::get_activity()->vm; - JNIEnv *jniEnv = Fl_Android_Application::get_activity()->env; - - JavaVMAttachArgs Args = { JNI_VERSION_1_6, "NativeThread", NULL }; - jint result = javaVM->AttachCurrentThread(&jniEnv, &Args); - if (result == JNI_ERR) return 0; - - jclass class_key_event = jniEnv->FindClass("android/view/KeyEvent"); - jmethodID eventConstructor = jniEnv->GetMethodID(class_key_event, "", - "(JJIIIIIIII)V"); - jobject eventObj = jniEnv->NewObject(class_key_event, eventConstructor, - AKeyEvent_getDownTime(event), - AKeyEvent_getEventTime(event), - AKeyEvent_getAction(event), - AKeyEvent_getKeyCode(event), - AKeyEvent_getRepeatCount(event), - AKeyEvent_getMetaState(event), - AInputEvent_getDeviceId(event), - AKeyEvent_getScanCode(event), - AKeyEvent_getFlags(event), - AInputEvent_getSource(event)); - - jmethodID method_get_unicode_char = jniEnv->GetMethodID(class_key_event, - "getUnicodeChar", - "(I)I"); - int unicodeKey = jniEnv->CallIntMethod(eventObj, method_get_unicode_char, - AKeyEvent_getMetaState(event)); - - jniEnv->DeleteLocalRef(class_key_event); - jniEnv->DeleteLocalRef(eventObj); - - javaVM->DetachCurrentThread(); - - static char buf[8]; - int len = fl_utf8encode(unicodeKey, buf); - if (len >= 0 && len < 8) - buf[len] = 0; - else - buf[0] = 0; - Fl_Android_Application::log_i("Unicode: %d Text: %s", unicodeKey, buf); - - AInputQueue_finishEvent(queue, event, 0); - - Fl_Widget *w = Fl::focus(); - if (w) { - Fl_Window *win = w->window(); - if (keyAction==AKEY_EVENT_ACTION_DOWN && unicodeKey>0) { - Fl::e_text = buf; - Fl::e_length = len; - Fl::handle(FL_KEYBOARD, win); - } - } - - return 0; -} - - int Fl_Android_Screen_Driver::handle_mouse_event(AInputQueue *queue, AInputEvent *event) { int ex = Fl::e_x_root = (int)(AMotionEvent_getX(event, 0) * 600 / @@ -304,7 +161,6 @@ int Fl_Android_Screen_Driver::handle_mouse_event(AInputQueue *queue, AInputEvent */ int Fl_Android_Screen_Driver::handle_queued_events(double time_to_wait) { - AInputQueue *queue = Fl_Android_Application::input_event_queue(); int ret = 0; // Read all pending events. int ident; @@ -414,9 +270,9 @@ void Fl_Android_Screen_Driver::flush() } } - // ---- timers ----------------------------------------------------------------- + struct TimerData { timer_t handle; @@ -561,122 +417,6 @@ void Fl_Android_Screen_Driver::remove_timeout(Fl_Timeout_Handler cb, void *data) } -// ---- keyboard --------------------------------------------------------------- - - -void Fl_Android_Screen_Driver::request_keyboard() -{ - if (pKeyboardCount==0) { - /* - ANativeActivity_showSoftInput(Fl_Android_Application::get_activity(), - ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT); - */ -// void displayKeyboard(bool pShow) -// InputMethodManager imm = ( InputMethodManager )getSystemService( Context.INPUT_METHOD_SERVICE ); -// imm.showSoftInput( this.getWindow().getDecorView(), InputMethodManager.SHOW_FORCED ); - - bool pShow = true; - { - // Attaches the current thread to the JVM. - jint lResult; - jint lFlags = 0; - - JavaVM* lJavaVM = Fl_Android_Application::get_activity()->vm; - JNIEnv* lJNIEnv = Fl_Android_Application::get_activity()->env; - - JavaVMAttachArgs lJavaVMAttachArgs; - lJavaVMAttachArgs.version = JNI_VERSION_1_6; - lJavaVMAttachArgs.name = "NativeThread"; - lJavaVMAttachArgs.group = NULL; - - lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs); - if (lResult == JNI_ERR) { - return; - } - - // Retrieves NativeActivity. - jobject lNativeActivity = Fl_Android_Application::get_activity()->clazz; - jclass ClassNativeActivity = lJNIEnv->GetObjectClass(lNativeActivity); - - // Retrieves Context.INPUT_METHOD_SERVICE. - jclass ClassContext = lJNIEnv->FindClass("android/content/Context"); - jfieldID FieldINPUT_METHOD_SERVICE = - lJNIEnv->GetStaticFieldID(ClassContext, - "INPUT_METHOD_SERVICE", "Ljava/lang/String;"); - jobject INPUT_METHOD_SERVICE = - lJNIEnv->GetStaticObjectField(ClassContext, - FieldINPUT_METHOD_SERVICE); -// jniCheck(INPUT_METHOD_SERVICE); - - // Runs getSystemService(Context.INPUT_METHOD_SERVICE). - jclass ClassInputMethodManager = lJNIEnv->FindClass( - "android/view/inputmethod/InputMethodManager"); - jmethodID MethodGetSystemService = lJNIEnv->GetMethodID( - ClassNativeActivity, "getSystemService", - "(Ljava/lang/String;)Ljava/lang/Object;"); - jobject lInputMethodManager = lJNIEnv->CallObjectMethod( - lNativeActivity, MethodGetSystemService, - INPUT_METHOD_SERVICE); - - // Runs getWindow().getDecorView(). - jmethodID MethodGetWindow = lJNIEnv->GetMethodID( - ClassNativeActivity, "getWindow", - "()Landroid/view/Window;"); - jobject lWindow = lJNIEnv->CallObjectMethod(lNativeActivity, - MethodGetWindow); - jclass ClassWindow = lJNIEnv->FindClass( - "android/view/Window"); - jmethodID MethodGetDecorView = lJNIEnv->GetMethodID( - ClassWindow, "getDecorView", "()Landroid/view/View;"); - jobject lDecorView = lJNIEnv->CallObjectMethod(lWindow, - MethodGetDecorView); - - if (pShow) { - // Runs lInputMethodManager.showSoftInput(...). - jmethodID MethodShowSoftInput = lJNIEnv->GetMethodID( - ClassInputMethodManager, "showSoftInput", - "(Landroid/view/View;I)Z"); - jboolean lResult = lJNIEnv->CallBooleanMethod( - lInputMethodManager, MethodShowSoftInput, - lDecorView, lFlags); - } else { - // Runs lWindow.getViewToken() - jclass ClassView = lJNIEnv->FindClass( - "android/view/View"); - jmethodID MethodGetWindowToken = lJNIEnv->GetMethodID( - ClassView, "getWindowToken", "()Landroid/os/IBinder;"); - jobject lBinder = lJNIEnv->CallObjectMethod(lDecorView, - MethodGetWindowToken); - - // lInputMethodManager.hideSoftInput(...). - jmethodID MethodHideSoftInput = lJNIEnv->GetMethodID( - ClassInputMethodManager, "hideSoftInputFromWindow", - "(Landroid/os/IBinder;I)Z"); - jboolean lRes = lJNIEnv->CallBooleanMethod( - lInputMethodManager, MethodHideSoftInput, - lBinder, lFlags); - } - - // Finished with the JVM. - lJavaVM->DetachCurrentThread(); - } - - } - pKeyboardCount++; -} - - -void Fl_Android_Screen_Driver::release_keyboard() -{ - pKeyboardCount--; - if (pKeyboardCount==0) { - ANativeActivity_hideSoftInput(Fl_Android_Application::get_activity(), - ANATIVEACTIVITY_HIDE_SOFT_INPUT_NOT_ALWAYS); - } -} - - - // // End of "$Id$". // diff --git a/src/drivers/Android/Fl_Android_Screen_Keyboard.cxx b/src/drivers/Android/Fl_Android_Screen_Keyboard.cxx new file mode 100644 index 000000000..341f48238 --- /dev/null +++ b/src/drivers/Android/Fl_Android_Screen_Keyboard.cxx @@ -0,0 +1,280 @@ +// +// "$Id$" +// +// Android screen interface for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2018 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + + +#include "../../config_lib.h" +#include "Fl_Android_Screen_Driver.H" +#include "Fl_Android_Application.H" +#include "Fl_Android_Graphics_Font.H" +#include +#include +#include +#include +#include +#include +#include +#include + + + + +int Fl_Android_Screen_Driver::compose(int &del) +{ + del = 0; + return 1; +} + + +int Fl_Android_Screen_Driver::handle_keyboard_event(AInputQueue *queue, AInputEvent *event) +{ +/* +int32_t AKeyEvent_getAction (const AInputEvent *key_event) + { AKEY_EVENT_ACTION_DOWN = 0, AKEY_EVENT_ACTION_UP = 1, AKEY_EVENT_ACTION_MULTIPLE = 2 } +> Reading up on ACTION_MULTIPLE also explains how to deal with +> special or sequences of characters: +> "If the key code is not KEYCODE_UNKNOWN then the getRepeatCount() +> method returns the number of times the given key code should be +> executed. Otherwise, if the key code is KEYCODE_UNKNOWN, then this +> is a sequence of characters as returned by getCharacters()." + +int32_t AKeyEvent_getFlags (const AInputEvent *key_event) + { + AKEY_EVENT_FLAG_WOKE_HERE = 0x1, AKEY_EVENT_FLAG_SOFT_KEYBOARD = 0x2, AKEY_EVENT_FLAG_KEEP_TOUCH_MODE = 0x4, AKEY_EVENT_FLAG_FROM_SYSTEM = 0x8, + AKEY_EVENT_FLAG_EDITOR_ACTION = 0x10, AKEY_EVENT_FLAG_CANCELED = 0x20, AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY = 0x40, AKEY_EVENT_FLAG_LONG_PRESS = 0x80, + AKEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100, AKEY_EVENT_FLAG_TRACKING = 0x200, AKEY_EVENT_FLAG_FALLBACK = 0x400 +} + +int32_t AKeyEvent_getKeyCode (const AInputEvent *key_event) + { + AKEYCODE_UNKNOWN = 0, AKEYCODE_SOFT_LEFT = 1, AKEYCODE_SOFT_RIGHT = 2, AKEYCODE_HOME = 3, + AKEYCODE_BACK = 4, AKEYCODE_CALL = 5, AKEYCODE_ENDCALL = 6, AKEYCODE_0 = 7, + AKEYCODE_1 = 8, AKEYCODE_2 = 9, AKEYCODE_3 = 10, AKEYCODE_4 = 11, + AKEYCODE_5 = 12, AKEYCODE_6 = 13, AKEYCODE_7 = 14, AKEYCODE_8 = 15, + AKEYCODE_9 = 16, AKEYCODE_STAR = 17, AKEYCODE_POUND = 18, AKEYCODE_DPAD_UP = 19, + AKEYCODE_DPAD_DOWN = 20, AKEYCODE_DPAD_LEFT = 21, AKEYCODE_DPAD_RIGHT = 22, AKEYCODE_DPAD_CENTER = 23, + AKEYCODE_VOLUME_UP = 24, AKEYCODE_VOLUME_DOWN = 25, AKEYCODE_POWER = 26, AKEYCODE_CAMERA = 27, + AKEYCODE_CLEAR = 28, AKEYCODE_A = 29, AKEYCODE_B = 30, AKEYCODE_C = 31, + AKEYCODE_D = 32, AKEYCODE_E = 33, AKEYCODE_F = 34, AKEYCODE_G = 35, ... + +int32_t AKeyEvent_getScanCode (const AInputEvent *key_event) + { AKEY_STATE_UNKNOWN = -1, AKEY_STATE_UP = 0, AKEY_STATE_DOWN = 1, AKEY_STATE_VIRTUAL = 2 } + +int32_t AKeyEvent_getMetaState (const AInputEvent *key_event) + { + AMETA_NONE = 0, AMETA_ALT_ON = 0x02, AMETA_ALT_LEFT_ON = 0x10, AMETA_ALT_RIGHT_ON = 0x20, + AMETA_SHIFT_ON = 0x01, AMETA_SHIFT_LEFT_ON = 0x40, AMETA_SHIFT_RIGHT_ON = 0x80, AMETA_SYM_ON = 0x04, + AMETA_FUNCTION_ON = 0x08, AMETA_CTRL_ON = 0x1000, AMETA_CTRL_LEFT_ON = 0x2000, AMETA_CTRL_RIGHT_ON = 0x4000, + AMETA_META_ON = 0x10000, AMETA_META_LEFT_ON = 0x20000, AMETA_META_RIGHT_ON = 0x40000, AMETA_CAPS_LOCK_ON = 0x100000, + AMETA_NUM_LOCK_ON = 0x200000, AMETA_SCROLL_LOCK_ON = 0x400000 +} + +int32_t AKeyEvent_getRepeatCount (const AInputEvent *key_event) +int64_t AKeyEvent_getDownTime (const AInputEvent *key_event) +int64_t AKeyEvent_getEventTime (const AInputEvent *key_event) +*/ + Fl_Android_Application::log_i("Key event: action=%d keyCode=%d metaState=0x%x scanCode=%d", + AKeyEvent_getAction(event), + AKeyEvent_getKeyCode(event), + AKeyEvent_getMetaState(event), + AKeyEvent_getScanCode(event)); + + auto keyAction = AKeyEvent_getAction(event); + if (keyAction==AKEY_EVENT_ACTION_MULTIPLE) { + if (AKeyEvent_getKeyCode(event)==AKEYCODE_UNKNOWN) { + // characters are in getCharacters() + // String class KeyEvent::getCharacters() [Java] + // is there a way to get the true Java event somehow? + // override dispatchKeyEvent(android.view.KeyEvent event) + } else { + // send keycode as many times as getRepeatCount() / AKeyEvent_getRepeatCount(event) + } + } + + JavaVM *javaVM = Fl_Android_Application::get_activity()->vm; + JNIEnv *jniEnv = Fl_Android_Application::get_activity()->env; + + JavaVMAttachArgs Args = { JNI_VERSION_1_6, "NativeThread", NULL }; + jint result = javaVM->AttachCurrentThread(&jniEnv, &Args); + if (result == JNI_ERR) return 0; + + jclass class_key_event = jniEnv->FindClass("android/view/KeyEvent"); + jmethodID eventConstructor = jniEnv->GetMethodID(class_key_event, "", + "(JJIIIIIIII)V"); + jobject eventObj = jniEnv->NewObject(class_key_event, eventConstructor, + AKeyEvent_getDownTime(event), + AKeyEvent_getEventTime(event), + AKeyEvent_getAction(event), + AKeyEvent_getKeyCode(event), + AKeyEvent_getRepeatCount(event), + AKeyEvent_getMetaState(event), + AInputEvent_getDeviceId(event), + AKeyEvent_getScanCode(event), + AKeyEvent_getFlags(event), + AInputEvent_getSource(event)); + + jmethodID method_get_unicode_char = jniEnv->GetMethodID(class_key_event, + "getUnicodeChar", + "(I)I"); + int unicodeKey = jniEnv->CallIntMethod(eventObj, method_get_unicode_char, + AKeyEvent_getMetaState(event)); + + jniEnv->DeleteLocalRef(class_key_event); + jniEnv->DeleteLocalRef(eventObj); + + javaVM->DetachCurrentThread(); + + static char buf[8]; + int len = fl_utf8encode(unicodeKey, buf); + if (len >= 0 && len < 8) + buf[len] = 0; + else + buf[0] = 0; + Fl_Android_Application::log_i("Unicode: %d Text: %s", unicodeKey, buf); + + AInputQueue_finishEvent(queue, event, 0); + + Fl_Widget *w = Fl::focus(); + if (w) { + Fl_Window *win = w->window(); + if (keyAction==AKEY_EVENT_ACTION_DOWN && unicodeKey>0) { + Fl::e_text = buf; + Fl::e_length = len; + Fl::handle(FL_KEYBOARD, win); + } + } + + return 0; +} + + +void Fl_Android_Screen_Driver::request_keyboard() +{ + if (pKeyboardCount==0) { + /* + ANativeActivity_showSoftInput(Fl_Android_Application::get_activity(), + ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT); + */ +// void displayKeyboard(bool pShow) +// InputMethodManager imm = ( InputMethodManager )getSystemService( Context.INPUT_METHOD_SERVICE ); +// imm.showSoftInput( this.getWindow().getDecorView(), InputMethodManager.SHOW_FORCED ); + + bool pShow = true; + { + // Attaches the current thread to the JVM. + jint lResult; + jint lFlags = 0; + + JavaVM* lJavaVM = Fl_Android_Application::get_activity()->vm; + JNIEnv* lJNIEnv = Fl_Android_Application::get_activity()->env; + + JavaVMAttachArgs lJavaVMAttachArgs; + lJavaVMAttachArgs.version = JNI_VERSION_1_6; + lJavaVMAttachArgs.name = "NativeThread"; + lJavaVMAttachArgs.group = NULL; + + lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs); + if (lResult == JNI_ERR) { + return; + } + + // Retrieves NativeActivity. + jobject lNativeActivity = Fl_Android_Application::get_activity()->clazz; + jclass ClassNativeActivity = lJNIEnv->GetObjectClass(lNativeActivity); + + // Retrieves Context.INPUT_METHOD_SERVICE. + jclass ClassContext = lJNIEnv->FindClass("android/content/Context"); + jfieldID FieldINPUT_METHOD_SERVICE = + lJNIEnv->GetStaticFieldID(ClassContext, + "INPUT_METHOD_SERVICE", "Ljava/lang/String;"); + jobject INPUT_METHOD_SERVICE = + lJNIEnv->GetStaticObjectField(ClassContext, + FieldINPUT_METHOD_SERVICE); +// jniCheck(INPUT_METHOD_SERVICE); + + // Runs getSystemService(Context.INPUT_METHOD_SERVICE). + jclass ClassInputMethodManager = lJNIEnv->FindClass( + "android/view/inputmethod/InputMethodManager"); + jmethodID MethodGetSystemService = lJNIEnv->GetMethodID( + ClassNativeActivity, "getSystemService", + "(Ljava/lang/String;)Ljava/lang/Object;"); + jobject lInputMethodManager = lJNIEnv->CallObjectMethod( + lNativeActivity, MethodGetSystemService, + INPUT_METHOD_SERVICE); + + // Runs getWindow().getDecorView(). + jmethodID MethodGetWindow = lJNIEnv->GetMethodID( + ClassNativeActivity, "getWindow", + "()Landroid/view/Window;"); + jobject lWindow = lJNIEnv->CallObjectMethod(lNativeActivity, + MethodGetWindow); + jclass ClassWindow = lJNIEnv->FindClass( + "android/view/Window"); + jmethodID MethodGetDecorView = lJNIEnv->GetMethodID( + ClassWindow, "getDecorView", "()Landroid/view/View;"); + jobject lDecorView = lJNIEnv->CallObjectMethod(lWindow, + MethodGetDecorView); + + if (pShow) { + // Runs lInputMethodManager.showSoftInput(...). + jmethodID MethodShowSoftInput = lJNIEnv->GetMethodID( + ClassInputMethodManager, "showSoftInput", + "(Landroid/view/View;I)Z"); + jboolean lResult = lJNIEnv->CallBooleanMethod( + lInputMethodManager, MethodShowSoftInput, + lDecorView, lFlags); + } else { + // Runs lWindow.getViewToken() + jclass ClassView = lJNIEnv->FindClass( + "android/view/View"); + jmethodID MethodGetWindowToken = lJNIEnv->GetMethodID( + ClassView, "getWindowToken", "()Landroid/os/IBinder;"); + jobject lBinder = lJNIEnv->CallObjectMethod(lDecorView, + MethodGetWindowToken); + + // lInputMethodManager.hideSoftInput(...). + jmethodID MethodHideSoftInput = lJNIEnv->GetMethodID( + ClassInputMethodManager, "hideSoftInputFromWindow", + "(Landroid/os/IBinder;I)Z"); + jboolean lRes = lJNIEnv->CallBooleanMethod( + lInputMethodManager, MethodHideSoftInput, + lBinder, lFlags); + } + + // Finished with the JVM. + lJavaVM->DetachCurrentThread(); + } + + } + pKeyboardCount++; +} + + +void Fl_Android_Screen_Driver::release_keyboard() +{ + pKeyboardCount--; + if (pKeyboardCount==0) { + ANativeActivity_hideSoftInput(Fl_Android_Application::get_activity(), + ANATIVEACTIVITY_HIDE_SOFT_INPUT_NOT_ALWAYS); + } +} + + + +// +// End of "$Id$". +//