- Rewrite to input bridge v3

- Language switcher: fix crash on select the final item.
This commit is contained in:
khanhduytran0 2020-11-02 19:48:41 +07:00
parent dc4ca549d9
commit 0123ae62d6
5 changed files with 183 additions and 162 deletions

View File

@ -234,12 +234,13 @@ public class PojavLoginActivity extends AppCompatActivity
if (position == 0) {
locale = Locale.getDefault();
} else {
locale = Locale.getAvailableLocales()[position + 1];
locale = Locale.getAvailableLocales()[position - 1];
}
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
config.setLocale(locale);
// TODO replace deprecated
getResources().updateConfiguration(config, getResources().getDisplayMetrics());
}
@Override

View File

@ -9,7 +9,7 @@ LOCAL_MODULE := pojavexec
# LOCAL_CFLAGS += -DGLES_TEST
LOCAL_SRC_FILES := \
egl_bridge.c \
input_bridge.c \
input_bridge_v3.c \
jre_launcher.c \
utils.c
include $(BUILD_SHARED_LIBRARY)

View File

@ -0,0 +1,107 @@
#include <jni.h>
#include <assert.h>
#include "utils.h"
jclass inputBridgeClass_ANDROID;
jmethodID inputBridgeMethod_ANDROID;
jclass inputBridgeClass_JRE;
jmethodID inputBridgeMethod_JRE;
jboolean isGrabbing;
JavaVM* firstJavaVM;
JNIEnv* firstJNIEnv;
JavaVM* secondJavaVM;
JNIEnv* secondJNIEnv;
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
if (dalvikJavaVMPtr == NULL) {
//Save dalvik global JavaVM pointer
dalvikJavaVMPtr = vm;
(*vm)->GetEnv(vm, (void**) &dalvikJNIEnvPtr_ANDROID, JNI_VERSION_1_4);
} else if (dalvikJavaVMPtr != vm) {
runtimeJavaVMPtr = vm;
(*vm)->GetEnv(vm, (void**) &runtimeJNIEnvPtr_JRE, JNI_VERSION_1_4);
}
isGrabbing = JNI_FALSE;
return JNI_VERSION_1_4;
}
// Should be?
/*
void JNI_OnUnload(JavaVM* vm, void* reserved) {
if (dalvikJavaVMPtr == vm) {
} else {
}
DetachCurrentThread(vm);
return JNI_VERSION_1_4;
}
*/
void attachThreadIfNeed(bool* isAttached, JNIEnv** secondJNIEnvPtr) {
if (!*isAttached && secondJavaVM) {
(*secondJavaVM)->AttachCurrentThread(secondJavaVM, secondJNIEnvPtr, NULL);
*isAttached = true;
}
secondJNIEnv = *secondJNIEnvPtr;
}
void getJavaInputBridge(jclass* clazz, jmethodID* method) {
if (*method == NULL && secondJNIEnv != NULL) {
*clazz = (*secondJNIEnv)->FindClass(secondJNIEnv, "org/lwjgl/glfw/CallbackBridge");
assert(*clazz != NULL);
*method = (*secondJNIEnv)->GetStaticMethodID(secondJNIEnv, *clazz, "receiveCallback", "(ILjava/lang/String;)V");
assert(*method != NULL);
}
}
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendData(JNIEnv* env, jclass clazz, jboolean isAndroid, jint type, jstring data) {
if (isAndroid == JNI_TRUE) {
firstJavaVM = dalvikJavaVMPtr;
firstJNIEnv = dalvikJNIEnvPtr_ANDROID;
secondJavaVM = runtimeJavaVMPtr;
attachThreadIfNeed(&isAndroidThreadAttached, &runtimeJNIEnvPtr_ANDROID);
getJavaInputBridge(&inputBridgeClass_ANDROID, &inputBridgeMethod_ANDROID);
} else {
firstJavaVM = runtimeJavaVMPtr;
firstJNIEnv = runtimeJNIEnvPtr_JRE;
secondJavaVM = dalvikJavaVMPtr;
attachThreadIfNeed(&isRuntimeThreadAttached, &dalvikJNIEnvPtr_JRE);
getJavaInputBridge(&inputBridgeClass_JRE, &inputBridgeMethod_JRE);
}
// printf("isAndroid=%p, isSecondJVMNull=%p\n", isAndroid, secondJavaVM == NULL);
if (secondJavaVM != NULL) {
char *data_c = (char*)(*env)->GetStringUTFChars(env, data, 0);
// printf("data=%s\n", data_c);
jstring data_jre = (*secondJNIEnv)->NewStringUTF(secondJNIEnv, data_c);
(*env)->ReleaseStringUTFChars(env, data, data_c);
(*secondJNIEnv)->CallStaticVoidMethod(
secondJNIEnv,
isAndroid == JNI_TRUE ? inputBridgeClass_ANDROID : inputBridgeClass_JRE,
isAndroid == JNI_TRUE ? inputBridgeMethod_ANDROID : inputBridgeMethod_JRE,
type,
data_jre
);
}
// else: too early!
}
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetGrabbing(JNIEnv* env, jclass clazz, jboolean grabbing) {
isGrabbing = grabbing;
}
JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeIsGrabbing(JNIEnv* env, jclass clazz) {
return isGrabbing;
}

View File

@ -4,6 +4,26 @@
#include "log.h"
#include "utils.h"
#define EVENT_TYPE_CHAR 1000
#define EVENT_TYPE_CHAR_MODS 1001
#define EVENT_TYPE_CURSOR_ENTER 1002
#define EVENT_TYPE_CURSOR_POS 1003
#define EVENT_TYPE_FRAMEBUFFER_SIZE 1004
#define EVENT_TYPE_KEY 1005
#define EVENT_TYPE_MOUSE_BUTTON 1006
#define EVENT_TYPE_SCROLL 1007
#define EVENT_TYPE_WINDOW_SIZE 1008
typedef void GLFW_invoke_Char_func(void* window, unsigned int codepoint);
typedef void GLFW_invoke_CharMods_func(void* window, unsigned int codepoint, int mods);
typedef void GLFW_invoke_CursorEnter_func(void* window, int entered);
typedef void GLFW_invoke_CursorPos_func(void* window, double xpos, double ypos);
typedef void GLFW_invoke_FramebufferSize_func(void* window, int width, int height);
typedef void GLFW_invoke_Key_func(void* window, int key, int scancode, int action, int mods);
typedef void GLFW_invoke_MouseButton_func(void* window, int button, int action, int mods);
typedef void GLFW_invoke_Scroll_func(void* window, double xoffset, double yoffset);
typedef void GLFW_invoke_WindowSize_func(void* window, int width, int height);
int grabCursorX, grabCursorY, lastCursorX, lastCursorY;
JavaVM* firstJavaVM;
@ -77,41 +97,22 @@ void getJavaInputBridge(jclass* clazz, jmethodID* method) {
if (*method == NULL && secondJNIEnv != NULL) {
*clazz = (*secondJNIEnv)->FindClass(secondJNIEnv, "org/lwjgl/glfw/CallbackBridge");
assert(*clazz != NULL);
*method = (*secondJNIEnv)->GetStaticMethodID(secondJNIEnv, *clazz, "receiveCallback", "(ILjava/lang/String;)V");
*method = (*secondJNIEnv)->GetStaticMethodID(secondJNIEnv, *clazz, "receiveCallback", "(IIIII)V");
assert(*method != NULL);
}
}
void invokeCursorPos(int x, int y) {
if (isGrabbing) {
if (!isPrepareGrabPos) {
grabCursorX += x - lastCursorX;
grabCursorY += y - lastCursorY;
} else {
isPrepareGrabPos = false;
lastCursorX = x;
lastCursorY = y;
return;
}
}
if (!isUseStackQueueCall && GLFW_invoke_CursorPos) {
GLFW_invoke_CursorPos(showingWindow, (double) (isGrabbing ? grabCursorX : x), (double) (isGrabbing ? grabCursorY : y));
}
lastCursorX = x;
lastCursorY = y;
}
void addInputToQueue(GLFWInputEvent event) {
if (glfwInputEventIndex++ >= 100) {
// player type too fast? or fps lower than player tps?
glfwInputEventIndex = 0;
}
glfwInputEventArr[glfwInputEventIndex] = &event;
void sendData(int type, int i1, int i2, int i3, int i4) {
(*secondJNIEnv)->CallStaticVoidMethod(
secondJNIEnv,
inputBridgeClass_ANDROID,
inputBridgeMethod_ANDROID,
type,
i1, i2, i3, i4
);
}
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeAttachThreadToOther(JNIEnv* env, jclass clazz, jboolean isAndroid, jboolean isUseStackQueue) {
glfwInputEventIndex = -1;
// isUseStackQueueCall = 1;
isUseStackQueueCall = (int) isUseStackQueue;
if (isUseStackQueue) {
isPrepareGrabPos = true;
@ -124,14 +125,14 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeAttachThreadToOt
getJavaInputBridge(&inputBridgeClass_ANDROID, &inputBridgeMethod_ANDROID);
isPrepareGrabPos = true;
} else {
} /* else {
firstJavaVM = runtimeJavaVMPtr;
firstJNIEnv = runtimeJNIEnvPtr_JRE;
secondJavaVM = dalvikJavaVMPtr;
attachThreadIfNeed(&isRuntimeThreadAttached, &dalvikJNIEnvPtr_JRE);
getJavaInputBridge(&inputBridgeClass_JRE, &inputBridgeMethod_JRE);
}
} */
}
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetGrabbing(JNIEnv* env, jclass clazz, jboolean grabbing) {
@ -142,93 +143,10 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeIsGrabbing(J
return isGrabbing;
}
int diffX, diffY, diffGrabX, diffGrabY, debugTimes;
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_GLFW_nglfwPollEvents(JNIEnv* env, jclass clazz) {
if (!isInputReady) isInputReady = true;
/*
if (debugTimes < 1000) {
debugTimes++;
LOGI("INPUT: IsUseStackQueue=%d, CurrentInputLength=%d, CursorX=%d, CursorY=%d", isUseStackQueueCall, glfwInputEventIndex, lastCursorX, lastCursorY);
}
*/
if (isUseStackQueueCall) {
if (diffX != lastCursorX || diffY != lastCursorY) {
diffX = lastCursorX;
diffY = lastCursorY;
if (GLFW_invoke_CursorPos) {
GLFW_invoke_CursorPos(showingWindow,
isGrabbing ? grabCursorX : lastCursorX,
isGrabbing ? grabCursorY : lastCursorY);
}
}
for (int i = 0; i <= glfwInputEventIndex; i++) {
GLFWInputEvent curr = *glfwInputEventArr[i];
((GLFW_invoke_callback*) curr.trigger)(curr);
// if (debugTimes < 1000) {
// LOGI("INPUT: Got input event %d", curr.type);
// }
/*
switch (curr.type) {
case EVENT_TYPE_CHAR:
if (GLFW_invoke_Char) {
GLFW_invoke_Char(showingWindow, curr.ui1);
}
break;
case EVENT_TYPE_CHAR_MODS:
if (GLFW_invoke_CharMods) {
GLFW_invoke_CharMods(showingWindow, curr.ui1, curr.i2);
}
break;
case EVENT_TYPE_CURSOR_ENTER:
if (GLFW_invoke_CursorEnter) {
GLFW_invoke_CursorEnter(showingWindow, curr.i1);
}
break;
case EVENT_TYPE_FRAMEBUFFER_SIZE:
if (GLFW_invoke_FramebufferSize) {
GLFW_invoke_FramebufferSize(showingWindow, curr.i1, curr.i2);
}
break;
case EVENT_TYPE_KEY:
if (GLFW_invoke_Key) {
GLFW_invoke_Key(showingWindow, curr.i1, curr.i2, curr.i3, curr.i4);
}
break;
case EVENT_TYPE_MOUSE_BUTTON:
if (GLFW_invoke_MouseButton) {
GLFW_invoke_MouseButton(showingWindow, curr.i1, curr.i2, curr.i3);
}
break;
case EVENT_TYPE_SCROLL:
if (GLFW_invoke_Scroll) {
GLFW_invoke_Scroll(showingWindow, curr.d1, curr.d2);
}
break;
case EVENT_TYPE_WINDOW_SIZE:
if (GLFW_invoke_WindowSize) {
GLFW_invoke_WindowSize(showingWindow, curr.i1, curr.i2);
}
break;
default:
LOGW("Unknown GLFW input event: %d", curr.type);
break;
}
*/
}
glfwInputEventIndex = -1;
}
}
JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendChar(JNIEnv* env, jclass clazz, jint codepoint) {
if (GLFW_invoke_Char && isInputReady) {
if (isUseStackQueueCall) {
GLFWInputEvent curr;
curr.trigger = triggerChar;
curr.ui1 = (unsigned int) codepoint;
addInputToQueue(curr);
sendData(EVENT_TYPE_CHAR, codepoint, 0, 0, 0);
} else
GLFW_invoke_Char(showingWindow, codepoint);
return JNI_TRUE;
@ -239,11 +157,7 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendChar(JNI
JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendCharMods(JNIEnv* env, jclass clazz, jint codepoint, jint mods) {
if (GLFW_invoke_CharMods && isInputReady) {
if (isUseStackQueueCall) {
GLFWInputEvent curr;
curr.trigger = triggerCharMods;
curr.ui1 = (unsigned int) codepoint;
curr.i2 = mods;
addInputToQueue(curr);
sendData(EVENT_TYPE_CHAR_MODS, codepoint, mods, 0, 0);
} else
GLFW_invoke_CharMods(showingWindow, codepoint, mods);
return JNI_TRUE;
@ -263,12 +177,10 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendCursorPos(JN
if (GLFW_invoke_CursorEnter) {
isCursorEntered = true;
if (isUseStackQueueCall) {
GLFWInputEvent curr;
curr.trigger = triggerCursorEnter;
curr.i1 = 1;
addInputToQueue(curr);
} else
sendData(EVENT_TYPE_CURSOR_ENTER, 1, 0, 0, 0);
} else {
GLFW_invoke_CursorEnter(showingWindow, 1);
}
} else if (isGrabbing) {
// Some Minecraft versions does not use GLFWCursorEnterCallback
// This is a smart check, as Minecraft will not in grab mode if already not.
@ -276,36 +188,47 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendCursorPos(JN
}
}
invokeCursorPos(x, y);
if (isGrabbing) {
if (!isPrepareGrabPos) {
grabCursorX += x - lastCursorX;
grabCursorY += y - lastCursorY;
} else {
isPrepareGrabPos = false;
lastCursorX = x;
lastCursorY = y;
return;
}
}
if (!isUseStackQueueCall) {
GLFW_invoke_CursorPos(showingWindow, (double) (isGrabbing ? grabCursorX : x), (double) (isGrabbing ? grabCursorY : y));
} else {
sendData(EVENT_TYPE_CURSOR_POS, (isGrabbing ? grabCursorX : x), (isGrabbing ? grabCursorY : y), 0, 0);
}
lastCursorX = x;
lastCursorY = y;
}
}
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendFramebufferSize(JNIEnv* env, jclass clazz, jint width, jint height) {
if (GLFW_invoke_FramebufferSize && isInputReady) {
if (isUseStackQueueCall) {
GLFWInputEvent curr;
curr.trigger = triggerFramebufferSize;
curr.i1 = width;
curr.i2 = height;
addInputToQueue(curr);
} else
sendData(EVENT_TYPE_FRAMEBUFFER_SIZE, width, height, 0, 0);
} else {
GLFW_invoke_FramebufferSize(showingWindow, width, height);
}
}
}
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(JNIEnv* env, jclass clazz, jint key, jint scancode, jint action, jint mods) {
if (GLFW_invoke_Key && isInputReady) {
if (isUseStackQueueCall) {
GLFWInputEvent curr;
curr.trigger = triggerKey;
curr.i1 = key;
curr.i2 = scancode;
curr.i3 = action;
curr.i4 = mods;
addInputToQueue(curr);
} else
sendData(EVENT_TYPE_KEY, key, scancode, action, mods);
} else {
GLFW_invoke_Key(showingWindow, key, scancode, action, mods);
}
}
}
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendMouseButton(JNIEnv* env, jclass clazz, jint button, jint action, jint mods) {
@ -315,42 +238,32 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendMouseButton(
isPrepareGrabPos = true;
} else if (GLFW_invoke_MouseButton) {
if (isUseStackQueueCall) {
GLFWInputEvent curr;
curr.trigger = triggerMouseButton;
curr.i1 = button;
curr.i2 = action;
curr.i3 = mods;
addInputToQueue(curr);
} else
sendData(EVENT_TYPE_MOUSE_BUTTON, button, action, mods, 0);
} else {
GLFW_invoke_MouseButton(showingWindow, button, action, mods);
}
}
}
}
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendScroll(JNIEnv* env, jclass clazz, jdouble xoffset, jdouble yoffset) {
if (GLFW_invoke_Scroll && isInputReady) {
if (isUseStackQueueCall) {
GLFWInputEvent curr;
curr.trigger = triggerScroll;
curr.d1 = (double) xoffset;
curr.d2 = (double) yoffset;
addInputToQueue(curr);
} else
sendData(EVENT_TYPE_SCROLL, xoffset, yoffset, 0, 0);
} else {
GLFW_invoke_Scroll(showingWindow, (double) xoffset, (double) yoffset);
}
}
}
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendWindowSize(JNIEnv* env, jclass clazz, jint width, jint height) {
if (GLFW_invoke_WindowSize && isInputReady) {
if (isUseStackQueueCall) {
GLFWInputEvent curr;
curr.trigger = triggerWindowSize;
curr.i1 = width;
curr.i2 = height;
addInputToQueue(curr);
} else
sendData(EVENT_TYPE_WINDOW_SIZE, width, height, 0, 0);
} else {
GLFW_invoke_WindowSize(showingWindow, width, height);
}
}
}
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_GLFW_nglfwSetShowingWindow(JNIEnv* env, jclass clazz, jlong window) {