Skip to content

Commit

Permalink
Fix[input_bridge]: fix Forge crashing the input bridge when app is ro…
Browse files Browse the repository at this point in the history
…lled down

Also fixes incorrect behaviour of GLFW regarding shown windows by default
  • Loading branch information
artdeell committed Nov 19, 2024
1 parent ed1b879 commit 935bae1
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 10 deletions.
33 changes: 27 additions & 6 deletions app_pojavlauncher/src/main/jni/input_bridge_v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,17 +545,38 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_GLFW_nglfwSetShowingWindow(__attribut
}

JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetWindowAttrib(__attribute__((unused)) JNIEnv* env, __attribute__((unused)) jclass clazz, jint attrib, jint value) {
if (!pojav_environ->showingWindow || !pojav_environ->isUseStackQueueCall) {
// Check for stack queue no longer necessary here as the JVM crash's origin is resolved
if (!pojav_environ->showingWindow) {
// If the window is not shown, there is nothing to do yet.
// For Minecraft < 1.13, calling to JNI functions here crashes the JVM for some reason, therefore it is skipped for now.
return;
}

(*pojav_environ->runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(
pojav_environ->runtimeJNIEnvPtr_JRE,
pojav_environ->vmGlfwClass, pojav_environ->method_glftSetWindowAttrib,
(jlong) pojav_environ->showingWindow, attrib, value
// We cannot use pojav_environ->runtimeJNIEnvPtr_JRE here because that environment is attached
// on the thread that loaded pojavexec (which is the thread that first references the GLFW class)
// But this method is only called from the Android UI thread

// Technically the better solution would be to have a permanently attached env pointer stored
// in environ for the Android UI thread but this is the only place that uses it
// (very rarely, only in lifecycle callbacks) so i dont care

JavaVM* jvm = pojav_environ->runtimeJavaVMPtr;
JNIEnv *jvm_env = NULL;
jint env_result = (*jvm)->GetEnv(jvm, (void**)&jvm_env, JNI_VERSION_1_4);
if(env_result == JNI_EDETACHED) {
env_result = (*jvm)->AttachCurrentThread(jvm, &jvm_env, NULL);
}
if(env_result != JNI_OK) {
printf("input_bridge nativeSetWindowAttrib() JNI call failed: %i\n", env_result);
return;
}

(*jvm_env)->CallStaticVoidMethod(
jvm_env, pojav_environ->vmGlfwClass,
pojav_environ->method_glftSetWindowAttrib,
(jlong) pojav_environ->showingWindow, attrib, value
);

// Attaching every time is annoying, so stick the attachment to the Android GUI thread around
}
const static JNINativeMethod critical_fcns[] = {
{"nativeSetUseInputStackQueue", "(Z)V", critical_set_stackqueue},
Expand Down
22 changes: 18 additions & 4 deletions jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFW.java
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ public class GLFW
private static ArrayMap<Long, GLFWWindowProperties> mGLFWWindowMap;
public static boolean mGLFWIsInputReady;
private static boolean mGLFWInputPumping;
private static boolean mGLFWWindowVisibleOnCreation = true;
public static final ByteBuffer keyDownBuffer = ByteBuffer.allocateDirect(317);
public static final ByteBuffer mouseDownBuffer = ByteBuffer.allocateDirect(8);

Expand Down Expand Up @@ -1000,11 +1001,15 @@ public static long glfwCreateWindow(int width, int height, CharSequence title, l
win.height = mGLFWWindowHeight;
win.title = title;

win.windowAttribs.put(GLFW_HOVERED, 1);
win.windowAttribs.put(GLFW_VISIBLE, 1);

mGLFWWindowMap.put(ptr, win);
mainContext = ptr;

if(mGLFWWindowVisibleOnCreation || monitor != 0) {
// Show window by default if GLFW_VISIBLE hint is specified on creation or
// if the monitor is nonnull (fullscreen requested)
glfwShowWindow(ptr);
}

return ptr;
//Return our context
}
Expand All @@ -1021,7 +1026,9 @@ public static void glfwDestroyWindow(long window) {
nglfwSetShowingWindow(mGLFWWindowMap.size() == 0 ? 0 : mGLFWWindowMap.keyAt(mGLFWWindowMap.size() - 1));
}

public static void glfwDefaultWindowHints() {}
public static void glfwDefaultWindowHints() {
mGLFWWindowVisibleOnCreation = true;
}

public static void glfwGetWindowSize(long window, IntBuffer width, IntBuffer height) {
if (width != null) width.put(internalGetWindow(window).width);
Expand All @@ -1044,10 +1051,17 @@ public static void glfwSetWindowSize(long window, int width, int height) {
}

public static void glfwShowWindow(long window) {
GLFWWindowProperties win = internalGetWindow(window);
win.windowAttribs.put(GLFW_HOVERED, 1);
win.windowAttribs.put(GLFW_VISIBLE, 1);
nglfwSetShowingWindow(window);
}

public static void glfwWindowHint(int hint, int value) {
if (hint == GLFW_VISIBLE) {
mGLFWWindowVisibleOnCreation = value == GLFW_TRUE;
return;
}
long __functionAddress = Functions.SetWindowHint;
invokeV(hint, value, __functionAddress);
}
Expand Down

0 comments on commit 935bae1

Please sign in to comment.