Fix[controls] 1.13+ sticky keys (#4210)

* Fix[controls] 1.13+ sticky keys

* Fix[controls]: missing setup phase

* Refactor: Use size_t instead of unsigned

* Refactor: use size_t instead of unsigned
This commit is contained in:
Boulay Mathias 2023-05-21 12:48:40 +02:00 committed by GitHub
parent baeea2916e
commit 7916166795
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 20 deletions

View File

@ -9,6 +9,9 @@
#include <stdatomic.h> #include <stdatomic.h>
#include <jni.h> #include <jni.h>
/* How many events can be handled at the same time */
#define EVENT_WINDOW_SIZE 8000
typedef struct { typedef struct {
int type; int type;
int i1; int i1;
@ -32,8 +35,12 @@ struct pojav_environ_s {
render_window_t* mainWindowBundle; render_window_t* mainWindowBundle;
int config_renderer; int config_renderer;
bool force_vsync; bool force_vsync;
atomic_size_t eventCounter; atomic_size_t eventCounter; // Count the number of events to be pumped out
GLFWInputEvent events[8000]; GLFWInputEvent events[EVENT_WINDOW_SIZE];
size_t outEventIndex; // Point to the current event that has yet to be pumped out to MC
size_t outTargetIndex; // Point to the newt index to stop by
size_t inEventIndex; // Point to the next event that has to be filled
size_t inEventCount; // Count registered right before pumping OUT events. Used as a cache.
double cursorX, cursorY, cLastX, cLastY; double cursorX, cursorY, cLastX, cLastY;
jmethodID method_accessAndroidClipboard; jmethodID method_accessAndroidClipboard;
jmethodID method_onGrabStateChanged; jmethodID method_onGrabStateChanged;

View File

@ -100,10 +100,13 @@ void pojavPumpEvents(void* window) {
// prevent further calls until we exit the loop // prevent further calls until we exit the loop
// by spec, they will be called on the same thread so no synchronization here // by spec, they will be called on the same thread so no synchronization here
pojav_environ->isPumpingEvents = true; pojav_environ->isPumpingEvents = true;
size_t counter = atomic_load_explicit(&pojav_environ->eventCounter, memory_order_acquire);
for(size_t i = 0; i < counter; i++) { size_t index = pojav_environ->outEventIndex;
GLFWInputEvent event = pojav_environ->events[i]; size_t targetIndex = pojav_environ->outTargetIndex;
switch(event.type) {
while (targetIndex != index) {
GLFWInputEvent event = pojav_environ->events[index];
switch (event.type) {
case EVENT_TYPE_CHAR: case EVENT_TYPE_CHAR:
if(pojav_environ->GLFW_invoke_Char) pojav_environ->GLFW_invoke_Char(window, event.i1); if(pojav_environ->GLFW_invoke_Char) pojav_environ->GLFW_invoke_Char(window, event.i1);
break; break;
@ -128,17 +131,41 @@ void pojavPumpEvents(void* window) {
if(pojav_environ->GLFW_invoke_WindowSize) pojav_environ->GLFW_invoke_WindowSize(window, event.i1, event.i2); if(pojav_environ->GLFW_invoke_WindowSize) pojav_environ->GLFW_invoke_WindowSize(window, event.i1, event.i2);
break; break;
} }
index++;
if (index >= EVENT_WINDOW_SIZE)
index -= EVENT_WINDOW_SIZE;
} }
if((pojav_environ->cLastX != pojav_environ->cursorX || pojav_environ->cLastY != pojav_environ->cursorY) && pojav_environ->GLFW_invoke_CursorPos) { 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->cLastX = pojav_environ->cursorX;
pojav_environ->cLastY = pojav_environ->cursorY; pojav_environ->cLastY = pojav_environ->cursorY;
pojav_environ->GLFW_invoke_CursorPos(window, pojav_environ->cursorX, pojav_environ->cursorY); pojav_environ->GLFW_invoke_CursorPos(window, pojav_environ->cursorX, pojav_environ->cursorY);
} }
atomic_store_explicit(&pojav_environ->eventCounter, counter, memory_order_release);
// The out target index is updated by the rewinder
pojav_environ->isPumpingEvents = false; pojav_environ->isPumpingEvents = false;
} }
/** Setup the amount of event that will get pumped into each window */
void pojavComputeEventTarget() {
size_t counter = atomic_load_explicit(&pojav_environ->eventCounter, memory_order_acquire);
size_t index = pojav_environ->outEventIndex;
unsigned targetIndex = index + counter;
if (targetIndex >= EVENT_WINDOW_SIZE)
targetIndex -= EVENT_WINDOW_SIZE;
// Only accessed by one unique thread, no need for atomic store
pojav_environ->inEventCount = counter;
pojav_environ->outTargetIndex = targetIndex;
}
/** Apply index offsets after events have been pumped */
void pojavRewindEvents() { void pojavRewindEvents() {
atomic_store_explicit(&pojav_environ->eventCounter, 0, memory_order_release); 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);
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
@ -175,16 +202,17 @@ Java_org_lwjgl_glfw_GLFW_glfwSetCursorPos(__attribute__((unused)) JNIEnv *env, _
void sendData(int type, int i1, int i2, int i3, int i4) { void sendData(int type, int i1, int i2, int i3, int i4) {
size_t counter = atomic_load_explicit(&pojav_environ->eventCounter, memory_order_acquire); GLFWInputEvent *event = &pojav_environ->events[pojav_environ->inEventIndex];
if (counter < 7999) { event->type = type;
GLFWInputEvent *event = &pojav_environ->events[counter++]; event->i1 = i1;
event->type = type; event->i2 = i2;
event->i1 = i1; event->i3 = i3;
event->i2 = i2; event->i4 = i4;
event->i3 = i3;
event->i4 = i4; if (++pojav_environ->inEventIndex >= EVENT_WINDOW_SIZE)
} pojav_environ->inEventIndex -= EVENT_WINDOW_SIZE;
atomic_store_explicit(&pojav_environ->eventCounter, counter, memory_order_release);
atomic_fetch_add_explicit(&pojav_environ->eventCounter, 1, memory_order_acquire);
} }
/** /**

View File

@ -617,7 +617,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"); RewindEvents = apiGetFunctionAddress(GLFW, "pojavRewindEvents"),
SetupEvents = apiGetFunctionAddress(GLFW, "pojavComputeEventTarget");
} }
public static SharedLibrary getLibrary() { public static SharedLibrary getLibrary() {
@ -1058,7 +1059,7 @@ public class GLFW
mGLFWIsInputReady = true; mGLFWIsInputReady = true;
CallbackBridge.nativeSetInputReady(true); CallbackBridge.nativeSetInputReady(true);
} }
callV(Functions.SetupEvents);
for (Long ptr : mGLFWWindowMap.keySet()) callJV(ptr, Functions.PumpEvents); for (Long ptr : mGLFWWindowMap.keySet()) callJV(ptr, Functions.PumpEvents);
callV(Functions.RewindEvents); callV(Functions.RewindEvents);
} }