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 <jni.h>
/* How many events can be handled at the same time */
#define EVENT_WINDOW_SIZE 8000
typedef struct {
int type;
int i1;
@ -32,8 +35,12 @@ struct pojav_environ_s {
render_window_t* mainWindowBundle;
int config_renderer;
bool force_vsync;
atomic_size_t eventCounter;
GLFWInputEvent events[8000];
atomic_size_t eventCounter; // Count the number of events to be pumped out
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;
jmethodID method_accessAndroidClipboard;
jmethodID method_onGrabStateChanged;

View File

@ -100,10 +100,13 @@ void pojavPumpEvents(void* window) {
// 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;
size_t counter = atomic_load_explicit(&pojav_environ->eventCounter, memory_order_acquire);
for(size_t i = 0; i < counter; i++) {
GLFWInputEvent event = pojav_environ->events[i];
switch(event.type) {
size_t index = pojav_environ->outEventIndex;
size_t targetIndex = pojav_environ->outTargetIndex;
while (targetIndex != index) {
GLFWInputEvent event = pojav_environ->events[index];
switch (event.type) {
case EVENT_TYPE_CHAR:
if(pojav_environ->GLFW_invoke_Char) pojav_environ->GLFW_invoke_Char(window, event.i1);
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);
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) {
pojav_environ->cLastX = pojav_environ->cursorX;
pojav_environ->cLastY = 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;
}
/** 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() {
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
@ -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) {
size_t counter = atomic_load_explicit(&pojav_environ->eventCounter, memory_order_acquire);
if (counter < 7999) {
GLFWInputEvent *event = &pojav_environ->events[counter++];
event->type = type;
event->i1 = i1;
event->i2 = i2;
event->i3 = i3;
event->i4 = i4;
}
atomic_store_explicit(&pojav_environ->eventCounter, counter, memory_order_release);
GLFWInputEvent *event = &pojav_environ->events[pojav_environ->inEventIndex];
event->type = type;
event->i1 = i1;
event->i2 = i2;
event->i3 = i3;
event->i4 = i4;
if (++pojav_environ->inEventIndex >= EVENT_WINDOW_SIZE)
pojav_environ->inEventIndex -= EVENT_WINDOW_SIZE;
atomic_fetch_add_explicit(&pojav_environ->eventCounter, 1, memory_order_acquire);
}
/**

View File

@ -617,7 +617,8 @@ public class GLFW
SwapBuffers = apiGetFunctionAddress(GLFW, "pojavSwapBuffers"),
SwapInterval = apiGetFunctionAddress(GLFW, "pojavSwapInterval"),
PumpEvents = apiGetFunctionAddress(GLFW, "pojavPumpEvents"),
RewindEvents = apiGetFunctionAddress(GLFW, "pojavRewindEvents");
RewindEvents = apiGetFunctionAddress(GLFW, "pojavRewindEvents"),
SetupEvents = apiGetFunctionAddress(GLFW, "pojavComputeEventTarget");
}
public static SharedLibrary getLibrary() {
@ -1058,7 +1059,7 @@ public class GLFW
mGLFWIsInputReady = true;
CallbackBridge.nativeSetInputReady(true);
}
callV(Functions.SetupEvents);
for (Long ptr : mGLFWWindowMap.keySet()) callJV(ptr, Functions.PumpEvents);
callV(Functions.RewindEvents);
}