Android: Updated the JNI/event handling code
* Local Java references are now freed after use. * SFML is now able to consider (Android) events as unhandled and pass them. * Hovering a pen over the screen no longer triggers movement events (untested).
This commit is contained in:
parent
cadc4d801c
commit
11357b354f
@ -78,6 +78,7 @@ void InputImpl::setVirtualKeyboardVisible(bool visible)
|
||||
"INPUT_METHOD_SERVICE", "Ljava/lang/String;");
|
||||
jobject INPUT_METHOD_SERVICE = lJNIEnv->GetStaticObjectField(ClassContext,
|
||||
FieldINPUT_METHOD_SERVICE);
|
||||
lJNIEnv->DeleteLocalRef(ClassContext);
|
||||
|
||||
// Runs getSystemService(Context.INPUT_METHOD_SERVICE)
|
||||
jclass ClassInputMethodManager =
|
||||
@ -86,6 +87,7 @@ void InputImpl::setVirtualKeyboardVisible(bool visible)
|
||||
"getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
|
||||
jobject lInputMethodManager = lJNIEnv->CallObjectMethod(lNativeActivity,
|
||||
MethodGetSystemService, INPUT_METHOD_SERVICE);
|
||||
lJNIEnv->DeleteLocalRef(INPUT_METHOD_SERVICE);
|
||||
|
||||
// Runs getWindow().getDecorView()
|
||||
jmethodID MethodGetWindow = lJNIEnv->GetMethodID(ClassNativeActivity,
|
||||
@ -95,6 +97,8 @@ void InputImpl::setVirtualKeyboardVisible(bool visible)
|
||||
jmethodID MethodGetDecorView = lJNIEnv->GetMethodID(ClassWindow,
|
||||
"getDecorView", "()Landroid/view/View;");
|
||||
jobject lDecorView = lJNIEnv->CallObjectMethod(lWindow, MethodGetDecorView);
|
||||
lJNIEnv->DeleteLocalRef(lWindow);
|
||||
lJNIEnv->DeleteLocalRef(ClassWindow);
|
||||
|
||||
if (visible)
|
||||
{
|
||||
@ -112,13 +116,19 @@ void InputImpl::setVirtualKeyboardVisible(bool visible)
|
||||
"getWindowToken", "()Landroid/os/IBinder;");
|
||||
jobject lBinder = lJNIEnv->CallObjectMethod(lDecorView,
|
||||
MethodGetWindowToken);
|
||||
lJNIEnv->DeleteLocalRef(ClassView);
|
||||
|
||||
// lInputMethodManager.hideSoftInput(...)
|
||||
jmethodID MethodHideSoftInput = lJNIEnv->GetMethodID(ClassInputMethodManager,
|
||||
"hideSoftInputFromWindow", "(Landroid/os/IBinder;I)Z");
|
||||
jboolean lRes = lJNIEnv->CallBooleanMethod(lInputMethodManager,
|
||||
MethodHideSoftInput, lBinder, lFlags);
|
||||
lJNIEnv->DeleteLocalRef(lBinder);
|
||||
}
|
||||
lJNIEnv->DeleteLocalRef(lNativeActivity);
|
||||
lJNIEnv->DeleteLocalRef(ClassNativeActivity);
|
||||
lJNIEnv->DeleteLocalRef(ClassInputMethodManager);
|
||||
lJNIEnv->DeleteLocalRef(lDecorView);
|
||||
|
||||
// Finished with the JVM
|
||||
lJavaVM->DetachCurrentThread();
|
||||
|
@ -33,9 +33,11 @@
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <android/looper.h>
|
||||
|
||||
// Define missing constants
|
||||
#define AMOTION_EVENT_ACTION_HOVER_MOVE 0x00000007
|
||||
#define AMOTION_EVENT_ACTION_SCROLL 0x00000008
|
||||
// Define missing constants for older API levels
|
||||
#if __ANDROID_API__ < 13
|
||||
#define AMOTION_EVENT_ACTION_HOVER_MOVE 0x00000007
|
||||
#define AMOTION_EVENT_ACTION_SCROLL 0x00000008
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Private data
|
||||
@ -232,7 +234,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
||||
if (AInputQueue_preDispatchEvent(states->inputQueue, _event))
|
||||
return 1;
|
||||
|
||||
int32_t handled = 0;
|
||||
int handled = 0;
|
||||
|
||||
int32_t type = AInputEvent_getType(_event);
|
||||
|
||||
@ -244,8 +246,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
||||
if ((action == AKEY_EVENT_ACTION_DOWN || action == AKEY_EVENT_ACTION_UP || action == AKEY_EVENT_ACTION_MULTIPLE) &&
|
||||
key != AKEYCODE_VOLUME_UP && key != AKEYCODE_VOLUME_DOWN)
|
||||
{
|
||||
processKeyEvent(_event, states);
|
||||
handled = 1;
|
||||
handled = processKeyEvent(_event, states);
|
||||
}
|
||||
}
|
||||
else if (type == AINPUT_EVENT_TYPE_MOTION)
|
||||
@ -256,16 +257,15 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
||||
{
|
||||
case AMOTION_EVENT_ACTION_SCROLL:
|
||||
{
|
||||
processScrollEvent(_event, states);
|
||||
handled = 1;
|
||||
handled = processScrollEvent(_event, states);
|
||||
break;
|
||||
}
|
||||
|
||||
case AMOTION_EVENT_ACTION_HOVER_MOVE:
|
||||
// todo: should hover_move indeed trigger the event?
|
||||
// case AMOTION_EVENT_ACTION_HOVER_MOVE:
|
||||
case AMOTION_EVENT_ACTION_MOVE:
|
||||
{
|
||||
processMotionEvent(_event, states);
|
||||
handled = 1;
|
||||
handled = processMotionEvent(_event, states);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -273,8 +273,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
||||
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
||||
case AMOTION_EVENT_ACTION_DOWN:
|
||||
{
|
||||
processPointerEvent(true, _event, states);
|
||||
handled = 1;
|
||||
handled = processPointerEvent(true, _event, states);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -282,8 +281,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
||||
case AMOTION_EVENT_ACTION_UP:
|
||||
case AMOTION_EVENT_ACTION_CANCEL:
|
||||
{
|
||||
processPointerEvent(false, _event, states);
|
||||
handled = 1;
|
||||
handled = processPointerEvent(false, _event, states);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -298,7 +296,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates* states)
|
||||
int WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates* states)
|
||||
{
|
||||
// Prepare the Java virtual machine
|
||||
jint lResult;
|
||||
@ -314,8 +312,10 @@ void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates*
|
||||
|
||||
lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs);
|
||||
|
||||
if (lResult == JNI_ERR)
|
||||
if (lResult == JNI_ERR) {
|
||||
err() << "Failed to initialize JNI, couldn't get the Unicode value" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Retrieve everything we need to create this MotionEvent in Java
|
||||
jlong downTime = AMotionEvent_getDownTime(_event);
|
||||
@ -340,6 +340,9 @@ void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates*
|
||||
jmethodID MethodGetAxisValue = lJNIEnv->GetMethodID(ClassMotionEvent, "getAxisValue", "(I)F");
|
||||
jfloat delta = lJNIEnv->CallFloatMethod(ObjectMotionEvent, MethodGetAxisValue, 0x00000001);
|
||||
|
||||
lJNIEnv->DeleteLocalRef(ClassMotionEvent);
|
||||
lJNIEnv->DeleteLocalRef(ObjectMotionEvent);
|
||||
|
||||
// Create and send our mouse wheel event
|
||||
Event event;
|
||||
event.type = Event::MouseWheelMoved;
|
||||
@ -351,11 +354,13 @@ void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates*
|
||||
|
||||
// Detach this thread from the JVM
|
||||
lJavaVM->DetachCurrentThread();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* states)
|
||||
int WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* states)
|
||||
{
|
||||
int32_t device = AInputEvent_getSource(_event);
|
||||
int32_t action = AKeyEvent_getAction(_event);
|
||||
@ -374,7 +379,7 @@ void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* sta
|
||||
case AKEY_EVENT_ACTION_DOWN:
|
||||
event.type = Event::KeyPressed;
|
||||
forwardEvent(event);
|
||||
break;
|
||||
return 1;
|
||||
case AKEY_EVENT_ACTION_UP:
|
||||
event.type = Event::KeyReleased;
|
||||
forwardEvent(event);
|
||||
@ -385,7 +390,7 @@ void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* sta
|
||||
event.text.unicode = unicode;
|
||||
forwardEvent(event);
|
||||
}
|
||||
break;
|
||||
return 1;
|
||||
case AKEY_EVENT_ACTION_MULTIPLE:
|
||||
// Since complex inputs don't get separate key down/up events
|
||||
// both have to be faked at once
|
||||
@ -400,11 +405,9 @@ void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* sta
|
||||
{
|
||||
// This is a unique sequence, which is not yet exposed in the NDK
|
||||
// http://code.google.com/p/android/issues/detail?id=33998
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a repeated sequence
|
||||
if (int unicode = getUnicode(_event))
|
||||
else if (int unicode = getUnicode(_event)) // This is a repeated sequence
|
||||
{
|
||||
event.type = Event::TextEntered;
|
||||
event.text.unicode = unicode;
|
||||
@ -412,15 +415,16 @@ void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* sta
|
||||
int32_t repeats = AKeyEvent_getRepeatCount(_event);
|
||||
for (int32_t i = 0; i < repeats; ++i)
|
||||
forwardEvent(event);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* states)
|
||||
int WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* states)
|
||||
{
|
||||
int32_t device = AInputEvent_getSource(_event);
|
||||
int32_t action = AMotionEvent_getAction(_event);
|
||||
@ -462,11 +466,12 @@ void WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates*
|
||||
|
||||
forwardEvent(event);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, ActivityStates* states)
|
||||
int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, ActivityStates* states)
|
||||
{
|
||||
int32_t device = AInputEvent_getSource(_event);
|
||||
int32_t action = AMotionEvent_getAction(_event);
|
||||
@ -525,6 +530,7 @@ void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Ac
|
||||
}
|
||||
|
||||
forwardEvent(event);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -693,6 +699,9 @@ int WindowImplAndroid::getUnicode(AInputEvent* event)
|
||||
jmethodID MethodGetUnicode = lJNIEnv->GetMethodID(ClassKeyEvent, "getUnicodeChar", "(I)I");
|
||||
int unicode = lJNIEnv->CallIntMethod(ObjectKeyEvent, MethodGetUnicode, metaState);
|
||||
|
||||
lJNIEnv->DeleteLocalRef(ClassKeyEvent);
|
||||
lJNIEnv->DeleteLocalRef(ObjectKeyEvent);
|
||||
|
||||
// Detach this thread from the JVM
|
||||
lJavaVM->DetachCurrentThread();
|
||||
|
||||
|
@ -194,10 +194,10 @@ private:
|
||||
////////////////////////////////////////////////////////////
|
||||
static int processEvent(int fd, int events, void* data);
|
||||
|
||||
static void processScrollEvent(AInputEvent* _event, ActivityStates* states);
|
||||
static void processKeyEvent(AInputEvent* _event, ActivityStates* states);
|
||||
static void processMotionEvent(AInputEvent* _event, ActivityStates* states);
|
||||
static void processPointerEvent(bool isDown, AInputEvent* event, ActivityStates* states);
|
||||
static int processScrollEvent(AInputEvent* _event, ActivityStates* states);
|
||||
static int processKeyEvent(AInputEvent* _event, ActivityStates* states);
|
||||
static int processMotionEvent(AInputEvent* _event, ActivityStates* states);
|
||||
static int processPointerEvent(bool isDown, AInputEvent* event, ActivityStates* states);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Convert a Android key to SFML key code
|
||||
|
Loading…
Reference in New Issue
Block a user