From 385a9081aa0f703829db04609a5b6d17c0d499bb Mon Sep 17 00:00:00 2001 From: ShirosakiMio <852468399@qq.com> Date: Sat, 14 Sep 2024 21:28:14 +0800 Subject: [PATCH] fix stuck inputs from https://github.com/PojavLauncherTeam/PojavLauncher/commit/366f1815331bd9d7e592ac9e021b387bd2ed99fa --- .../src/main/jni/pojav/environ/environ.h | 2 +- .../src/main/jni/pojav/input_bridge_v3.c | 30 +++++++++---------- .../src/main/java/org/lwjgl/glfw/GLFW.java | 15 +++++++--- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/FCLauncher/src/main/jni/pojav/environ/environ.h b/FCLauncher/src/main/jni/pojav/environ/environ.h index d63310dc..49d6f3c0 100644 --- a/FCLauncher/src/main/jni/pojav/environ/environ.h +++ b/FCLauncher/src/main/jni/pojav/environ/environ.h @@ -56,7 +56,7 @@ struct pojav_environ_s { JavaVM* dalvikJavaVMPtr; JNIEnv* dalvikJNIEnvPtr_ANDROID; long showingWindow; - bool isInputReady, isCursorEntered, isUseStackQueueCall, isPumpingEvents; + bool isInputReady, isCursorEntered, isUseStackQueueCall, shouldUpdateMouse; int savedWidth, savedHeight; #define ADD_CALLBACK_WWIN(NAME) \ GLFW_invoke_##NAME##_func* GLFW_invoke_##NAME; diff --git a/FCLauncher/src/main/jni/pojav/input_bridge_v3.c b/FCLauncher/src/main/jni/pojav/input_bridge_v3.c index a5368569..0a1a5eb4 100644 --- a/FCLauncher/src/main/jni/pojav/input_bridge_v3.c +++ b/FCLauncher/src/main/jni/pojav/input_bridge_v3.c @@ -104,14 +104,7 @@ void handleFramebufferSizeJava(long window, int w, int h) { } void pojavPumpEvents(void* window) { - if(pojav_environ->isPumpingEvents) return; - // prevent further calls until we exit the loop - // by spec, they will be called on the same thread so no synchronization here - pojav_environ->isPumpingEvents = true; - - if((pojav_environ->cLastX != pojav_environ->cursorX || pojav_environ->cLastY != pojav_environ->cursorY) && pojav_environ->GLFW_invoke_CursorPos) { - pojav_environ->cLastX = pojav_environ->cursorX; - pojav_environ->cLastY = pojav_environ->cursorY; + if (pojav_environ->shouldUpdateMouse) { pojav_environ->GLFW_invoke_CursorPos(window, floor(pojav_environ->cursorX), floor(pojav_environ->cursorY)); } @@ -151,13 +144,10 @@ void pojavPumpEvents(void* window) { if (index >= EVENT_WINDOW_SIZE) index -= EVENT_WINDOW_SIZE; } - - // The out target index is updated by the rewinder - pojav_environ->isPumpingEvents = false; } -/** Setup the amount of event that will get pumped into each window */ -void pojavComputeEventTarget() { +/** Prepare the library for sending out callbacks to all windows */ +void pojavStartPumping() { size_t counter = atomic_load_explicit(&pojav_environ->eventCounter, memory_order_acquire); size_t index = pojav_environ->outEventIndex; @@ -168,14 +158,24 @@ void pojavComputeEventTarget() { // Only accessed by one unique thread, no need for atomic store pojav_environ->inEventCount = counter; pojav_environ->outTargetIndex = targetIndex; + + //PumpEvents is called for every window, so this logic should be there in order to correctly distribute events to all windows. + if ((pojav_environ->cLastX != pojav_environ->cursorX || + pojav_environ->cLastY != pojav_environ->cursorY) && pojav_environ->GLFW_invoke_CursorPos) { + pojav_environ->cLastX = pojav_environ->cursorX; + pojav_environ->cLastY = pojav_environ->cursorY; + pojav_environ->shouldUpdateMouse = true; + } } -/** Apply index offsets after events have been pumped */ -void pojavRewindEvents() { +/** Prepare the library for the next round of new events */ +void pojavStopPumping() { pojav_environ->outEventIndex = pojav_environ->outTargetIndex; // New events may have arrived while pumping, so remove only the difference before the start and end of execution atomic_fetch_sub_explicit(&pojav_environ->eventCounter, pojav_environ->inEventCount, memory_order_acquire); + // Make sure the next frame won't send mouse updates if it's unnecessary + pojav_environ->shouldUpdateMouse = false; } JNIEXPORT void JNICALL diff --git a/LWJGL-Pojav/src/main/java/org/lwjgl/glfw/GLFW.java b/LWJGL-Pojav/src/main/java/org/lwjgl/glfw/GLFW.java index f0096244..cfe65128 100644 --- a/LWJGL-Pojav/src/main/java/org/lwjgl/glfw/GLFW.java +++ b/LWJGL-Pojav/src/main/java/org/lwjgl/glfw/GLFW.java @@ -507,6 +507,7 @@ public class GLFW private static ArrayMap mGLFWWindowMap; public static boolean mGLFWIsInputReady; + private static boolean mGLFWInputPumping; public static final ByteBuffer keyDownBuffer = ByteBuffer.allocateDirect(317); public static final ByteBuffer mouseDownBuffer = ByteBuffer.allocateDirect(8); @@ -627,8 +628,8 @@ public class GLFW SwapBuffers = apiGetFunctionAddress(GLFW, "pojavSwapBuffers"), SwapInterval = apiGetFunctionAddress(GLFW, "pojavSwapInterval"), PumpEvents = apiGetFunctionAddress(GLFW, "pojavPumpEvents"), - RewindEvents = apiGetFunctionAddress(GLFW, "pojavRewindEvents"), - SetupEvents = apiGetFunctionAddress(GLFW, "pojavComputeEventTarget"); + StopPumping = apiGetFunctionAddress(GLFW, "pojavStopPumping"), + StartPumping = apiGetFunctionAddress(GLFW, "pojavStartPumping"); } public static SharedLibrary getLibrary() { @@ -1081,9 +1082,15 @@ public class GLFW mGLFWIsInputReady = true; CallbackBridge.nativeSetInputReady(true); } - callV(Functions.SetupEvents); + // During interactions with UI elements, Minecraft likes to update the screen as events related to those inputs arrive. + // This leads to calls to glfwPollEvents within glfwPollEvents, which is not good for our queue system. + // Prevent these with this code. + if (mGLFWInputPumping) return; + mGLFWInputPumping = true; + callV(Functions.StartPumping); for (Long ptr : mGLFWWindowMap.keySet()) callJV(ptr, Functions.PumpEvents); - callV(Functions.RewindEvents); + callV(Functions.StopPumping); + mGLFWInputPumping = false; } public static void internalWindowSizeChanged(long window, int w, int h) {