From 5cdd0b4cdf0be2f0e63d30b8a159a17cf8bcfb68 Mon Sep 17 00:00:00 2001 From: Doug Binks Date: Fri, 21 Nov 2025 16:29:04 +0000 Subject: [PATCH 1/9] tests/events.c added glfwWaitEvents return info --- tests/events.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/events.c b/tests/events.c index ab3b99a7b..dc18fa341 100644 --- a/tests/events.c +++ b/tests/events.c @@ -670,6 +670,8 @@ int main(int argc, char** argv) break; glfwWaitEvents(); + printf("%08x at %0.3f: glfwWaitEvents() returned\n", + counter++, glfwGetTime()); // Workaround for an issue with msvcrt and mintty fflush(stdout); From 38011e1e07ba686ba40a6fba323b5f7b3c3be5cf Mon Sep 17 00:00:00 2001 From: Doug Binks Date: Fri, 21 Nov 2025 16:29:27 +0000 Subject: [PATCH 2/9] wait-events win32 implementation --- src/init.c | 2 ++ src/input.c | 20 ++++++++++++++++++++ src/internal.h | 2 ++ src/monitor.c | 4 ++++ src/win32_init.c | 3 +++ src/win32_window.c | 15 +++++++++++---- src/window.c | 22 ++++++++++++++++++++++ 7 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/init.c b/src/init.c index dbd5a900c..d7b6c82c4 100644 --- a/src/init.c +++ b/src/init.c @@ -376,6 +376,8 @@ void _glfwInputError(int code, const char* format, ...) if (_glfwErrorCallback) _glfwErrorCallback(code, description); + + _glfw.newEventsRcvd = GLFW_TRUE; } diff --git a/src/input.c b/src/input.c index c619eefce..d72480b8b 100644 --- a/src/input.c +++ b/src/input.c @@ -301,6 +301,8 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m if (window->callbacks.key) window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code of a Unicode codepoint input event @@ -326,6 +328,8 @@ void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool if (window->callbacks.character) window->callbacks.character((GLFWwindow*) window, codepoint); } + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code of a scroll event @@ -340,6 +344,8 @@ void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset) if (window->callbacks.scroll) window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code of a mouse button click event @@ -367,6 +373,8 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) if (window->callbacks.mouseButton) window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code of a cursor motion event @@ -388,6 +396,8 @@ void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos) if (window->callbacks.cursorPos) window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code of a cursor enter/leave event @@ -399,6 +409,8 @@ void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered) if (window->callbacks.cursorEnter) window->callbacks.cursorEnter((GLFWwindow*) window, entered); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code of files or directories dropped on a window @@ -411,6 +423,8 @@ void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths) if (window->callbacks.drop) window->callbacks.drop((GLFWwindow*) window, count, paths); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code of a joystick connection or disconnection @@ -427,6 +441,8 @@ void _glfwInputJoystick(_GLFWjoystick* js, int event) if (_glfw.callbacks.joystick) _glfw.callbacks.joystick((int) (js - _glfw.joysticks), event); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code of the new value of a joystick axis @@ -450,6 +466,8 @@ void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value) assert(value == GLFW_PRESS || value == GLFW_RELEASE); js->buttons[button] = value; + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code of the new value of a joystick hat @@ -476,6 +494,8 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value) js->buttons[base + 3] = (value & 0x08) ? GLFW_PRESS : GLFW_RELEASE; js->hats[hat] = value; + + _glfw.newEventsRcvd = GLFW_TRUE; } diff --git a/src/internal.h b/src/internal.h index de703740f..e90257935 100644 --- a/src/internal.h +++ b/src/internal.h @@ -793,6 +793,8 @@ struct _GLFWlibrary _GLFWtls contextSlot; _GLFWmutex errorLock; + GLFWbool newEventsRcvd; + struct { uint64_t offset; // This is defined in platform.h diff --git a/src/monitor.c b/src/monitor.c index cc95efb64..395410fb1 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -150,6 +150,8 @@ void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement) if (action == GLFW_DISCONNECTED) _glfwFreeMonitor(monitor); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code that a full screen window has acquired or released @@ -159,6 +161,8 @@ void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window) { assert(monitor != NULL); monitor->window = window; + + _glfw.newEventsRcvd = GLFW_TRUE; } diff --git a/src/win32_init.c b/src/win32_init.c index 6b6e9d08e..9c44f8b74 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -357,6 +357,9 @@ static LRESULT CALLBACK helperWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP break; } + case WM_NULL: + _glfw.newEventsRcvd = GLFW_TRUE; + return 0; } return DefWindowProcW(hWnd, uMsg, wParam, lParam); diff --git a/src/win32_window.c b/src/win32_window.c index 6427a673e..37d8830e5 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -2171,16 +2171,23 @@ void _glfwPollEventsWin32(void) void _glfwWaitEventsWin32(void) { - WaitMessage(); + while (_glfw.newEventsRcvd == GLFW_FALSE) + { + WaitMessage(); - _glfwPollEventsWin32(); + _glfwPollEventsWin32(); + } } void _glfwWaitEventsTimeoutWin32(double timeout) { - MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLINPUT); + DWORD ret; + do + { + ret = MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLINPUT); - _glfwPollEventsWin32(); + _glfwPollEventsWin32(); + } while (_glfw.newEventsRcvd == GLFW_FALSE || ret == WAIT_TIMEOUT); } void _glfwPostEmptyEventWin32(void) diff --git a/src/window.c b/src/window.c index 3a3b66dfe..cef6699a8 100644 --- a/src/window.c +++ b/src/window.c @@ -67,6 +67,8 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) _glfwInputMouseClick(window, button, GLFW_RELEASE, 0); } } + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code that a window has moved @@ -78,6 +80,8 @@ void _glfwInputWindowPos(_GLFWwindow* window, int x, int y) if (window->callbacks.pos) window->callbacks.pos((GLFWwindow*) window, x, y); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code that a window has been resized @@ -91,6 +95,8 @@ void _glfwInputWindowSize(_GLFWwindow* window, int width, int height) if (window->callbacks.size) window->callbacks.size((GLFWwindow*) window, width, height); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code that a window has been iconified or restored @@ -102,6 +108,8 @@ void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified) if (window->callbacks.iconify) window->callbacks.iconify((GLFWwindow*) window, iconified); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code that a window has been maximized or restored @@ -113,6 +121,8 @@ void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized) if (window->callbacks.maximize) window->callbacks.maximize((GLFWwindow*) window, maximized); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code that a window framebuffer has been resized @@ -126,6 +136,8 @@ void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height) if (window->callbacks.fbsize) window->callbacks.fbsize((GLFWwindow*) window, width, height); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code that a window content scale has changed @@ -141,6 +153,8 @@ void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscal if (window->callbacks.scale) window->callbacks.scale((GLFWwindow*) window, xscale, yscale); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code that the window contents needs updating @@ -151,6 +165,8 @@ void _glfwInputWindowDamage(_GLFWwindow* window) if (window->callbacks.refresh) window->callbacks.refresh((GLFWwindow*) window); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code that the user wishes to close a window @@ -163,6 +179,8 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window) if (window->callbacks.close) window->callbacks.close((GLFWwindow*) window); + + _glfw.newEventsRcvd = GLFW_TRUE; } // Notifies shared code that a window has changed its desired monitor @@ -171,6 +189,8 @@ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor) { assert(window != NULL); window->monitor = monitor; + + _glfw.newEventsRcvd = GLFW_TRUE; } ////////////////////////////////////////////////////////////////////////// @@ -1172,6 +1192,7 @@ GLFWAPI void glfwPollEvents(void) GLFWAPI void glfwWaitEvents(void) { _GLFW_REQUIRE_INIT(); + _glfw.newEventsRcvd = GLFW_FALSE; _glfw.platform.waitEvents(); } @@ -1188,6 +1209,7 @@ GLFWAPI void glfwWaitEventsTimeout(double timeout) return; } + _glfw.platform.waitEvents(); _glfw.platform.waitEventsTimeout(timeout); } From 22427b1215aa7a401c2ba8d34df295c5e6abe72e Mon Sep 17 00:00:00 2001 From: Doug Binks Date: Fri, 21 Nov 2025 17:17:47 +0000 Subject: [PATCH 3/9] wait-events Wayland implementation --- src/wl_window.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 4220d17e0..71ad51fc3 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1397,12 +1397,14 @@ static void handleEvents(double* timeout) wl_display_cancel_read(_glfw.wl.display); return; } + + if (timeout && *timeout <= 0.0) + event = GLFW_TRUE; if (fds[DISPLAY_FD].revents & POLLIN) { wl_display_read_events(_glfw.wl.display); - if (wl_display_dispatch_pending(_glfw.wl.display) > 0) - event = GLFW_TRUE; + wl_display_dispatch_pending(_glfw.wl.display); } else wl_display_cancel_read(_glfw.wl.display); @@ -1424,8 +1426,6 @@ static void handleEvents(double* timeout) _glfw.wl.xkb.modifiers); inputText(_glfw.wl.keyboardFocus, _glfw.wl.keyRepeatScancode); } - - event = GLFW_TRUE; } } @@ -1441,9 +1441,11 @@ static void handleEvents(double* timeout) if (fds[LIBDECOR_FD].revents & POLLIN) { - if (libdecor_dispatch(_glfw.wl.libdecor.context, 0) > 0) - event = GLFW_TRUE; + libdecor_dispatch(_glfw.wl.libdecor.context, 0); } + + if (_glfw.newEventsRcvd) + event = GLFW_TRUE; } } @@ -2705,9 +2707,19 @@ void _glfwWaitEventsTimeoutWayland(double timeout) handleEvents(&timeout); } +static void wlSyncDoneHandler(void *data, struct wl_callback *callback, uint32_t callback_data) +{ + _glfw.newEventsRcvd = GLFW_TRUE; +} + +static const struct wl_callback_listener wlSyncDoneListener = { + wlSyncDoneHandler +}; + void _glfwPostEmptyEventWayland(void) { - wl_display_sync(_glfw.wl.display); + struct wl_callback *callback = wl_display_sync(_glfw.wl.display); + wl_callback_add_listener(callback,&wlSyncDoneListener,NULL); flushDisplay(); } From 9f2dc1fce20960e53ac41d0017b9e339fc4b7f16 Mon Sep 17 00:00:00 2001 From: Doug Binks Date: Fri, 21 Nov 2025 17:37:11 +0000 Subject: [PATCH 4/9] wait-events added comment --- src/wl_window.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wl_window.c b/src/wl_window.c index 71ad51fc3..fe2dcb265 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -2709,6 +2709,7 @@ void _glfwWaitEventsTimeoutWayland(double timeout) static void wlSyncDoneHandler(void *data, struct wl_callback *callback, uint32_t callback_data) { + // this will be called on the same thread as handleEvents _glfw.newEventsRcvd = GLFW_TRUE; } From 4c2c30e9514e0b1f694aadb246668cfd66a6d289 Mon Sep 17 00:00:00 2001 From: Doug Binks Date: Fri, 21 Nov 2025 18:00:27 +0000 Subject: [PATCH 5/9] wait-events glfwWaitEventsTimeout bugfixes --- src/win32_window.c | 2 +- src/window.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/win32_window.c b/src/win32_window.c index 37d8830e5..efaab42db 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -2187,7 +2187,7 @@ void _glfwWaitEventsTimeoutWin32(double timeout) ret = MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLINPUT); _glfwPollEventsWin32(); - } while (_glfw.newEventsRcvd == GLFW_FALSE || ret == WAIT_TIMEOUT); + } while (_glfw.newEventsRcvd == GLFW_FALSE && ret != WAIT_TIMEOUT); } void _glfwPostEmptyEventWin32(void) diff --git a/src/window.c b/src/window.c index cef6699a8..fa827fc41 100644 --- a/src/window.c +++ b/src/window.c @@ -1209,6 +1209,7 @@ GLFWAPI void glfwWaitEventsTimeout(double timeout) return; } + _glfw.newEventsRcvd = GLFW_FALSE; _glfw.platform.waitEvents(); _glfw.platform.waitEventsTimeout(timeout); } From d1d118de3ef788b53e377151ea817d282c23bdc2 Mon Sep 17 00:00:00 2001 From: Doug Binks Date: Fri, 21 Nov 2025 18:20:01 +0000 Subject: [PATCH 6/9] wait-events glfwWaitEventsTimeout further bugfixes --- src/win32_window.c | 9 +++++++-- src/window.c | 1 - 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/win32_window.c b/src/win32_window.c index efaab42db..c120b3a17 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -2182,12 +2182,17 @@ void _glfwWaitEventsWin32(void) void _glfwWaitEventsTimeoutWin32(double timeout) { DWORD ret; + double timeStart, timeEnd, timeWait; + timeStart = glfwGetTime(); + timeWait = timeout; do { - ret = MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLINPUT); + ret = MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeWait * 1e3), QS_ALLINPUT); _glfwPollEventsWin32(); - } while (_glfw.newEventsRcvd == GLFW_FALSE && ret != WAIT_TIMEOUT); + timeEnd = glfwGetTime(); + timeWait = timeout - (timeEnd - timeStart); + } while (_glfw.newEventsRcvd == GLFW_FALSE && timeWait > 0.0 ); } void _glfwPostEmptyEventWin32(void) diff --git a/src/window.c b/src/window.c index fa827fc41..840fb206d 100644 --- a/src/window.c +++ b/src/window.c @@ -1210,7 +1210,6 @@ GLFWAPI void glfwWaitEventsTimeout(double timeout) } _glfw.newEventsRcvd = GLFW_FALSE; - _glfw.platform.waitEvents(); _glfw.platform.waitEventsTimeout(timeout); } From e12aacb41adff21914d75e76d35c774762bad2e9 Mon Sep 17 00:00:00 2001 From: Doug Binks Date: Fri, 21 Nov 2025 18:21:58 +0000 Subject: [PATCH 7/9] wait-events X11 implementation --- src/x11_window.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/x11_window.c b/src/x11_window.c index 02c4ab58d..3eeee589c 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -128,6 +128,8 @@ static void drainEmptyEvents(void) { char dummy[64]; const ssize_t result = read(_glfw.x11.emptyEventPipe[0], dummy, sizeof(dummy)); + if (result > 0) + _glfw.newEventsRcvd = GLFW_TRUE; if (result == -1 && errno != EINTR) break; } @@ -2824,14 +2826,20 @@ void _glfwPollEventsX11(void) void _glfwWaitEventsX11(void) { - waitForAnyEvent(NULL); - _glfwPollEventsX11(); + while (_glfw.newEventsRcvd == GLFW_FALSE) + { + waitForAnyEvent(NULL); + _glfwPollEventsX11(); + } } void _glfwWaitEventsTimeoutX11(double timeout) { - waitForAnyEvent(&timeout); - _glfwPollEventsX11(); + do + { + waitForAnyEvent(&timeout); + _glfwPollEventsX11(); + } while (_glfw.newEventsRcvd == GLFW_FALSE && timeout > 0.0 ); } void _glfwPostEmptyEventX11(void) From 97fd1cd2a1c98562d71b57e1bb483e4a8a4ec334 Mon Sep 17 00:00:00 2001 From: Doug Binks Date: Sat, 22 Nov 2025 13:46:03 +0000 Subject: [PATCH 8/9] Fix warning --- src/win32_window.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/win32_window.c b/src/win32_window.c index c120b3a17..8dd91b46e 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -2181,13 +2181,12 @@ void _glfwWaitEventsWin32(void) void _glfwWaitEventsTimeoutWin32(double timeout) { - DWORD ret; double timeStart, timeEnd, timeWait; timeStart = glfwGetTime(); timeWait = timeout; do { - ret = MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeWait * 1e3), QS_ALLINPUT); + MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeWait * 1e3), QS_ALLINPUT); _glfwPollEventsWin32(); timeEnd = glfwGetTime(); From bfd13bc0959b27ae655e07f08bdd7f2beb95a281 Mon Sep 17 00:00:00 2001 From: Doug Binks Date: Thu, 27 Nov 2025 13:19:55 +0000 Subject: [PATCH 9/9] wait-events: ensure libdecorReadyCallback exits WaitEvents --- src/wl_init.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wl_init.c b/src/wl_init.c index 704906381..aee609595 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -251,6 +251,9 @@ static void libdecorReadyCallback(void* userData, uint32_t time) { _glfw.wl.libdecor.ready = GLFW_TRUE; + + // Ensure wait events returns so the ready flag can be received + _glfw.newEventsRcvd = GLFW_TRUE; assert(_glfw.wl.libdecor.callback == callback); wl_callback_destroy(_glfw.wl.libdecor.callback);