fix stuck inputs

from 366f181533
This commit is contained in:
ShirosakiMio 2024-09-14 21:28:14 +08:00
parent 2b039c04f5
commit 385a9081aa
3 changed files with 27 additions and 20 deletions

View File

@ -56,7 +56,7 @@ struct pojav_environ_s {
JavaVM* dalvikJavaVMPtr; JavaVM* dalvikJavaVMPtr;
JNIEnv* dalvikJNIEnvPtr_ANDROID; JNIEnv* dalvikJNIEnvPtr_ANDROID;
long showingWindow; long showingWindow;
bool isInputReady, isCursorEntered, isUseStackQueueCall, isPumpingEvents; bool isInputReady, isCursorEntered, isUseStackQueueCall, shouldUpdateMouse;
int savedWidth, savedHeight; int savedWidth, savedHeight;
#define ADD_CALLBACK_WWIN(NAME) \ #define ADD_CALLBACK_WWIN(NAME) \
GLFW_invoke_##NAME##_func* GLFW_invoke_##NAME; GLFW_invoke_##NAME##_func* GLFW_invoke_##NAME;

View File

@ -104,14 +104,7 @@ void handleFramebufferSizeJava(long window, int w, int h) {
} }
void pojavPumpEvents(void* window) { void pojavPumpEvents(void* window) {
if(pojav_environ->isPumpingEvents) return; if (pojav_environ->shouldUpdateMouse) {
// 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;
pojav_environ->GLFW_invoke_CursorPos(window, floor(pojav_environ->cursorX), pojav_environ->GLFW_invoke_CursorPos(window, floor(pojav_environ->cursorX),
floor(pojav_environ->cursorY)); floor(pojav_environ->cursorY));
} }
@ -151,13 +144,10 @@ void pojavPumpEvents(void* window) {
if (index >= EVENT_WINDOW_SIZE) if (index >= EVENT_WINDOW_SIZE)
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 */ /** Prepare the library for sending out callbacks to all windows */
void pojavComputeEventTarget() { void pojavStartPumping() {
size_t counter = atomic_load_explicit(&pojav_environ->eventCounter, memory_order_acquire); size_t counter = atomic_load_explicit(&pojav_environ->eventCounter, memory_order_acquire);
size_t index = pojav_environ->outEventIndex; size_t index = pojav_environ->outEventIndex;
@ -168,14 +158,24 @@ void pojavComputeEventTarget() {
// Only accessed by one unique thread, no need for atomic store // Only accessed by one unique thread, no need for atomic store
pojav_environ->inEventCount = counter; pojav_environ->inEventCount = counter;
pojav_environ->outTargetIndex = targetIndex; 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 */ /** Prepare the library for the next round of new events */
void pojavRewindEvents() { void pojavStopPumping() {
pojav_environ->outEventIndex = pojav_environ->outTargetIndex; 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 // 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); 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 JNIEXPORT void JNICALL

View File

@ -507,6 +507,7 @@ public class GLFW
private static ArrayMap<Long, GLFWWindowProperties> mGLFWWindowMap; private static ArrayMap<Long, GLFWWindowProperties> mGLFWWindowMap;
public static boolean mGLFWIsInputReady; public static boolean mGLFWIsInputReady;
private static boolean mGLFWInputPumping;
public static final ByteBuffer keyDownBuffer = ByteBuffer.allocateDirect(317); public static final ByteBuffer keyDownBuffer = ByteBuffer.allocateDirect(317);
public static final ByteBuffer mouseDownBuffer = ByteBuffer.allocateDirect(8); public static final ByteBuffer mouseDownBuffer = ByteBuffer.allocateDirect(8);
@ -627,8 +628,8 @@ public class GLFW
SwapBuffers = apiGetFunctionAddress(GLFW, "pojavSwapBuffers"), SwapBuffers = apiGetFunctionAddress(GLFW, "pojavSwapBuffers"),
SwapInterval = apiGetFunctionAddress(GLFW, "pojavSwapInterval"), SwapInterval = apiGetFunctionAddress(GLFW, "pojavSwapInterval"),
PumpEvents = apiGetFunctionAddress(GLFW, "pojavPumpEvents"), PumpEvents = apiGetFunctionAddress(GLFW, "pojavPumpEvents"),
RewindEvents = apiGetFunctionAddress(GLFW, "pojavRewindEvents"), StopPumping = apiGetFunctionAddress(GLFW, "pojavStopPumping"),
SetupEvents = apiGetFunctionAddress(GLFW, "pojavComputeEventTarget"); StartPumping = apiGetFunctionAddress(GLFW, "pojavStartPumping");
} }
public static SharedLibrary getLibrary() { public static SharedLibrary getLibrary() {
@ -1081,9 +1082,15 @@ public class GLFW
mGLFWIsInputReady = true; mGLFWIsInputReady = true;
CallbackBridge.nativeSetInputReady(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); 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) { public static void internalWindowSizeChanged(long window, int w, int h) {