[clutter/android-enter-leave: 7/29] android: add application API to show/hide virtual keyboard
- From: Lionel Landwerlin <llandwerlin src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [clutter/android-enter-leave: 7/29] android: add application API to show/hide virtual keyboard
- Date: Wed, 11 Jul 2012 17:07:39 +0000 (UTC)
commit ad90fd69a709facd2dda07471a8715e426e1d74d
Author: Lionel Landwerlin <llandwerlin gmail com>
Date: Sun May 27 01:20:42 2012 +0100
android: add application API to show/hide virtual keyboard
clutter/Makefile.am | 2 +
clutter/android/android_jni_utils.cpp | 108 ++++++++++++++++++++++
clutter/android/android_jni_utils.h | 12 +++
clutter/android/clutter-android-application.c | 118 ++++++++++++++++++-------
clutter/android/clutter-android-application.h | 7 +-
configure.ac | 1 +
6 files changed, 213 insertions(+), 35 deletions(-)
---
diff --git a/clutter/Makefile.am b/clutter/Makefile.am
index 08aca25..e9ae411 100644
--- a/clutter/Makefile.am
+++ b/clutter/Makefile.am
@@ -510,6 +510,7 @@ android_source_c = \
$(NULL)
android_source_c_priv = \
+ $(srcdir)/android/android_jni_utils.cpp \
$(srcdir)/android/android_native_app_glue.c \
$(srcdir)/android/clutter-device-manager-android.c \
$(srcdir)/android/clutter-backend-android.c \
@@ -523,6 +524,7 @@ android_source_h = \
$(NULL)
android_source_h_priv = \
+ $(srcdir)/android/android_jni_utils.h \
$(srcdir)/android/android_native_app_glue.h \
$(srcdir)/android/clutter-device-manager-android.h \
$(srcdir)/android/clutter-backend-android.h \
diff --git a/clutter/android/android_jni_utils.cpp b/clutter/android/android_jni_utils.cpp
new file mode 100644
index 0000000..d5c61d8
--- /dev/null
+++ b/clutter/android/android_jni_utils.cpp
@@ -0,0 +1,108 @@
+#include <jni.h>
+
+#include "android_native_app_glue.h"
+
+extern "C" jint
+_android_show_keyboard (struct android_app *mApplication, jboolean show, jint flags)
+{
+ jint lResult;
+ jint lFlags = flags;
+ jboolean pShow = show;
+
+ JavaVM* lJavaVM = mApplication->activity->vm;
+ JNIEnv* lJNIEnv;
+
+ bool attached = false;
+ switch (lJavaVM->GetEnv ((void**) &lJNIEnv, JNI_VERSION_1_6))
+ {
+ case JNI_OK:
+ break;
+ case JNI_EDETACHED:
+ if (lJavaVM->AttachCurrentThread (&lJNIEnv, NULL) != 0)
+ {
+ return 1;
+ }
+ attached = true;
+ break;
+ case JNI_EVERSION:
+ return 2;
+ }
+
+ // Retrieves NativeActivity.
+ jobject lNativeActivity = mApplication->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);
+ if (INPUT_METHOD_SERVICE == NULL)
+ return 4;
+
+ // 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);
+
+ jint retval = 0;
+
+ if (pShow) {
+ // Runs lInputMethodManager.showSoftInput(...).
+ jmethodID MethodShowSoftInput =
+ lJNIEnv->GetMethodID (ClassInputMethodManager, "showSoftInput",
+ "(Landroid/view/View;I)Z");
+ jboolean lResult = lJNIEnv->CallBooleanMethod (lInputMethodManager,
+ MethodShowSoftInput,
+ lDecorView, lFlags);
+
+ retval = lResult;
+ } 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);
+
+ retval = lRes;
+ }
+
+ // Finished with the JVM.
+ lJavaVM->DetachCurrentThread();
+
+ return retval;
+}
diff --git a/clutter/android/android_jni_utils.h b/clutter/android/android_jni_utils.h
new file mode 100644
index 0000000..c3b622d
--- /dev/null
+++ b/clutter/android/android_jni_utils.h
@@ -0,0 +1,12 @@
+#ifndef __ANDROID_JNI_UTILS_H__
+#define __ANDROID_JNI_UTILS_H__
+
+#include <jni.h>
+
+#include "android_native_app_glue.h"
+
+jint _android_show_keyboard (struct android_app *mApplication,
+ jboolean show, jint flags);
+
+
+#endif /* __ANDROID_JNI_UTILS_H__ */
diff --git a/clutter/android/clutter-android-application.c b/clutter/android/clutter-android-application.c
index 30bb1bc..8a8ab53 100644
--- a/clutter/android/clutter-android-application.c
+++ b/clutter/android/clutter-android-application.c
@@ -25,7 +25,6 @@
#include <stdlib.h>
#include <config.h>
-#include <android_native_app_glue.h>
#include <android/input.h>
#include <android/window.h>
@@ -42,6 +41,9 @@
#include "clutter-android-application-private.h"
#include "clutter-stage-android.h"
+#include "android_native_app_glue.h"
+#include "android_jni_utils.h"
+
G_DEFINE_TYPE (ClutterAndroidApplication,
clutter_android_application,
G_TYPE_OBJECT)
@@ -155,10 +157,6 @@ clutter_android_handle_cmd (struct android_app *app,
//test_fini (data);
break;
- case APP_CMD_GAINED_FOCUS:
- g_message ("command: GAINED_FOCUS");
- break;
-
case APP_CMD_WINDOW_RESIZED:
g_message ("command: window resized!");
if (app->window != NULL)
@@ -200,6 +198,10 @@ clutter_android_handle_cmd (struct android_app *app,
g_message ("command: CONTENT_RECT_CHANGED");
break;
+ case APP_CMD_GAINED_FOCUS:
+ g_message ("command: GAINED_FOCUS");
+ break;
+
case APP_CMD_LOST_FOCUS:
/* When our app loses focus, we stop monitoring the accelerometer.
* This is to avoid consuming battery while not being used. */
@@ -225,9 +227,10 @@ clutter_android_handle_cmd (struct android_app *app,
}
static gboolean
-translate_motion_event (ClutterEvent *event, AInputEvent *a_event)
+translate_motion_event (AInputEvent *a_event)
{
int32_t action;
+ ClutterEvent *event;
ClutterDeviceManager *manager;
ClutterInputDevice *pointer_device;
@@ -235,14 +238,13 @@ translate_motion_event (ClutterEvent *event, AInputEvent *a_event)
pointer_device =
clutter_device_manager_get_core_device (manager,
CLUTTER_POINTER_DEVICE);
- _clutter_input_device_set_stage (pointer_device, event->any.stage);
action = AMotionEvent_getAction (a_event);
switch (action & AMOTION_EVENT_ACTION_MASK)
{
case AMOTION_EVENT_ACTION_DOWN:
- event->button.type = event->type = CLUTTER_BUTTON_PRESS;
+ event = clutter_event_new (CLUTTER_BUTTON_PRESS);
event->button.button = 1;
event->button.click_count = 1;
event->button.device = pointer_device;
@@ -252,7 +254,7 @@ translate_motion_event (ClutterEvent *event, AInputEvent *a_event)
break;
case AMOTION_EVENT_ACTION_UP:
- event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
+ event = clutter_event_new (CLUTTER_BUTTON_RELEASE);
event->button.button = 1;
event->button.click_count = 1;
event->button.device = pointer_device;
@@ -262,7 +264,7 @@ translate_motion_event (ClutterEvent *event, AInputEvent *a_event)
break;
case AMOTION_EVENT_ACTION_MOVE:
- event->motion.type = event->type = CLUTTER_MOTION;
+ event = clutter_event_new (CLUTTER_MOTION);
event->motion.device = pointer_device;
/* TODO: Following line is a massive hack for touch screen */
event->motion.modifier_state = CLUTTER_BUTTON1_MASK;
@@ -276,40 +278,64 @@ translate_motion_event (ClutterEvent *event, AInputEvent *a_event)
return FALSE;
}
+ event->any.stage =
+ clutter_stage_manager_get_default_stage (clutter_stage_manager_get_default ());
+ _clutter_input_device_set_stage (pointer_device, event->any.stage);
+
+ _clutter_event_push (event, FALSE);
+
return TRUE;
}
static gboolean
-translate_key_event (ClutterEvent *event, AInputEvent *a_event)
+translate_key_event (AInputEvent *a_event)
{
int32_t state;
+ ClutterEvent *event;
+ ClutterDeviceManager *manager;
+ ClutterInputDevice *keyboard_device;
- /* g_message ("\tbutton/motion event: (%.02lf,%0.2lf)", */
- /* AMotionEvent_getX (a_event, 0), */
- /* AMotionEvent_getY (a_event, 0)); */
+ g_message ("key event");
state = AMotionEvent_getMetaState (a_event);
- event->key.unicode_value = AKeyEvent_getKeyCode (a_event);
+ manager = clutter_device_manager_get_default ();
+ keyboard_device =
+ clutter_device_manager_get_core_device (manager,
+ CLUTTER_KEYBOARD_DEVICE);
+
+ g_message ("\tflags = %x keycode = %i",
+ AKeyEvent_getFlags (a_event),
+ AKeyEvent_getKeyCode (a_event));
switch (state)
{
case AKEY_STATE_UP:
- /* g_message ("\tkey release"); */
- event->type = event->key.type = CLUTTER_KEY_RELEASE;
+ g_message ("\tkey release");
+ event = clutter_event_new (CLUTTER_KEY_RELEASE);
break;
case AKEY_STATE_DOWN:
case AKEY_STATE_VIRTUAL: /* TODO: Should we synthetize release? */
- /* g_message ("\tkey press"); */
- event->type = event->key.type = CLUTTER_KEY_PRESS;
+ g_message ("\tkey press");
+ event = clutter_event_new (CLUTTER_KEY_PRESS);
break;
default:
- /* g_message ("\tmeh? %i", state); */
+ g_message ("\tmeh? %i", state);
return FALSE;
}
+ event->key.unicode_value = AKeyEvent_getKeyCode (a_event);
+ g_message ("\tunicode value = %i", AKeyEvent_getKeyCode (a_event));
+ event->key.device = keyboard_device;
+
+ event->any.stage =
+ clutter_stage_manager_get_default_stage (clutter_stage_manager_get_default ());
+ _clutter_input_device_set_stage (keyboard_device, event->any.stage);
+
+ _clutter_event_push (event, FALSE);
+
return TRUE;
}
@@ -320,30 +346,19 @@ static int32_t
clutter_android_handle_input (struct android_app *app,
AInputEvent *a_event)
{
- ClutterEvent *event;
gboolean process = FALSE;
g_message ("input!");
- event = clutter_event_new (CLUTTER_NOTHING);
- event->any.stage =
- clutter_stage_manager_get_default_stage (clutter_stage_manager_get_default ());
-
- g_message ("plop!");
if (AInputEvent_getType (a_event) == AINPUT_EVENT_TYPE_KEY)
{
- process = translate_key_event (event, a_event);
+ process = translate_key_event (a_event);
}
else if (AInputEvent_getType (a_event) == AINPUT_EVENT_TYPE_MOTION)
{
- process = translate_motion_event (event, a_event);
+ process = translate_motion_event (a_event);
}
- if (process)
- _clutter_event_push (event, FALSE);
- else
- clutter_event_free (event);
-
return (int32_t) process;
}
@@ -375,6 +390,43 @@ clutter_android_application_get_asset_manager (ClutterAndroidApplication *applic
return application->android_application->activity->assetManager;
}
+void
+clutter_android_application_show_keyboard (ClutterAndroidApplication *application,
+ gboolean show_keyboard,
+ gboolean implicit)
+{
+ jint ret;
+
+ g_return_if_fail (CLUTTER_IS_ANDROID_APPLICATION (application));
+
+ if (show_keyboard)
+ {
+ g_message ("showing keyboard");
+ if (implicit)
+ ret = _android_show_keyboard (application->android_application,
+ JNI_TRUE,
+ ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT);
+ else
+ ret = _android_show_keyboard (application->android_application,
+ JNI_TRUE,
+ ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT);
+ }
+ else
+ {
+ g_message ("hiding keyboard");
+ if (implicit)
+ ret = _android_show_keyboard (application->android_application,
+ JNI_FALSE,
+ ANATIVEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY);
+ else
+ ret = _android_show_keyboard (application->android_application,
+ JNI_FALSE,
+ ANATIVEACTIVITY_HIDE_SOFT_INPUT_NOT_ALWAYS);
+ }
+
+ g_message ("THE FucK %i", ret);
+}
+
/*
* This is the main entry point of a native application that is using
* android_native_app_glue. It runs in its own thread, with its own
diff --git a/clutter/android/clutter-android-application.h b/clutter/android/clutter-android-application.h
index 07c77fa..bbf58fa 100644
--- a/clutter/android/clutter-android-application.h
+++ b/clutter/android/clutter-android-application.h
@@ -70,8 +70,11 @@ void clutter_android_main (ClutterAndroidApplication *application);
GType clutter_android_application_get_type (void) G_GNUC_CONST;
-void clutter_android_application_run (ClutterAndroidApplication *application);
-AAssetManager * clutter_android_application_get_asset_manager (ClutterAndroidApplication *application);
+void clutter_android_application_show_keyboard (ClutterAndroidApplication *application,
+ gboolean show_keyboard,
+ gboolean implicit);
+void clutter_android_application_run (ClutterAndroidApplication *application);
+AAssetManager *clutter_android_application_get_asset_manager (ClutterAndroidApplication *application);
G_END_DECLS
diff --git a/configure.ac b/configure.ac
index 8e16fb6..c5811e0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -444,6 +444,7 @@ AS_IF([test "x$enable_android" = "xyes"],
CLUTTER_INPUT_BACKENDS="$CLUTTER_INPUT_BACKENDS android"
AC_DEFINE([HAVE_CLUTTER_ANDROID], [1], [Have the Android backend])
+ AC_PROG_CXX
BACKEND_PC_FILES="$BACKEND_PC_FILES glib-android-1.0"
])
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]