Skip to content

Commit

Permalink
Fix[input]: fix stuck inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
artdeell committed Sep 8, 2024
1 parent 8c90b54 commit a44ec89
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 21 deletions.
2 changes: 1 addition & 1 deletion app_pojavlauncher/src/main/jni/environ/environ.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
27 changes: 14 additions & 13 deletions app_pojavlauncher/src/main/jni/input_bridge_v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,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));
}
Expand Down Expand Up @@ -148,11 +141,10 @@ void pojavPumpEvents(void* window) {
}

// 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;

Expand All @@ -163,14 +155,23 @@ 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
Expand Down
18 changes: 11 additions & 7 deletions jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFW.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import android.util.*;

import java.lang.annotation.Native;
import java.lang.reflect.*;
import java.nio.*;

Expand All @@ -23,8 +22,6 @@
import static org.lwjgl.system.MemoryUtil.*;
import java.util.*;

import sun.misc.Unsafe;

public class GLFW
{
static FloatBuffer joystickData = (FloatBuffer)FloatBuffer.allocate(8).flip();
Expand Down Expand Up @@ -507,6 +504,7 @@ public class GLFW

private static ArrayMap<Long, GLFWWindowProperties> 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);

Expand Down Expand Up @@ -627,8 +625,8 @@ private Functions() {}
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() {
Expand Down Expand Up @@ -1080,9 +1078,15 @@ public static void glfwPollEvents() {
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) {
Expand Down

0 comments on commit a44ec89

Please sign in to comment.