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 90e47670e..06b36a3fa 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..8dd91b46e 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -2171,16 +2171,27 @@ 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); + double timeStart, timeEnd, timeWait; + timeStart = glfwGetTime(); + timeWait = timeout; + do + { + MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeWait * 1e3), QS_ALLINPUT); - _glfwPollEventsWin32(); + _glfwPollEventsWin32(); + 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 3a3b66dfe..840fb206d 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.newEventsRcvd = GLFW_FALSE; _glfw.platform.waitEventsTimeout(timeout); } diff --git a/src/wl_init.c b/src/wl_init.c index d32c4adf4..dc7b64833 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); diff --git a/src/wl_window.c b/src/wl_window.c index ad39b2e0e..03f108e6f 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; } } @@ -2708,9 +2710,20 @@ void _glfwWaitEventsTimeoutWayland(double timeout) handleEvents(&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; +} + +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(); } diff --git a/src/x11_window.c b/src/x11_window.c index 045878aa5..7b353e97b 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) 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);