From b0af476799adc34805768e25581fffdcd3ad9235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Sun, 13 Mar 2022 16:25:19 +0100 Subject: [PATCH] Wayland: Adopt the poll wrapper from X11 This is adapted to 3.3-stable from bb9d699ae66b2bdc8718995ba13c57c9c8e59602. --- src/wl_window.c | 63 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 56f74c4d..2f6d17f2 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -39,7 +39,8 @@ #include #include #include - +#include +#include static void shellSurfaceHandlePing(void* data, struct wl_shell_surface* shellSurface, @@ -248,6 +249,53 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image) return buffer; } +// Wait for data to arrive on any of the specified file descriptors +// +static GLFWbool waitForData(struct pollfd* fds, nfds_t count, double* timeout) +{ + for (;;) + { + if (timeout) + { + const uint64_t base = _glfwPlatformGetTimerValue(); + +#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) + const time_t seconds = (time_t) *timeout; + const long nanoseconds = (long) ((*timeout - seconds) * 1e9); + const struct timespec ts = { seconds, nanoseconds }; + const int result = ppoll(fds, count, &ts, NULL); +#elif defined(__NetBSD__) + const time_t seconds = (time_t) *timeout; + const long nanoseconds = (long) ((*timeout - seconds) * 1e9); + const struct timespec ts = { seconds, nanoseconds }; + const int result = pollts(fds, count, &ts, NULL); +#else + const int milliseconds = (int) (*timeout * 1e3); + const int result = poll(fds, count, milliseconds); +#endif + const int error = errno; // clock_gettime may overwrite our error + + *timeout -= (_glfwPlatformGetTimerValue() - base) / + (double) _glfwPlatformGetTimerFrequency(); + + if (result > 0) + return GLFW_TRUE; + else if (result == -1 && error != EINTR && error != EAGAIN) + return GLFW_FALSE; + else if (*timeout <= 0.0) + return GLFW_FALSE; + } + else + { + const int result = poll(fds, count, -1); + if (result > 0) + return GLFW_TRUE; + else if (result == -1 && errno != EINTR && errno != EAGAIN) + return GLFW_FALSE; + } + } +} + static void createDecoration(_GLFWdecorationWayland* decoration, struct wl_surface* parent, struct wl_buffer* buffer, GLFWbool opaque, @@ -850,7 +898,7 @@ static GLFWbool flushDisplay(void) return GLFW_TRUE; } -static void handleEvents(int timeout) +static void handleEvents(double* timeout) { struct pollfd fds[] = { @@ -878,7 +926,7 @@ static void handleEvents(int timeout) return; } - if (poll(fds, 3, timeout) > 0) + if (waitForData(fds, 3, timeout) > 0) { if (fds[0].revents & POLLIN) { @@ -1328,17 +1376,18 @@ GLFWbool _glfwPlatformRawMouseMotionSupported(void) void _glfwPlatformPollEvents(void) { - handleEvents(0); + double timeout = 0.0; + handleEvents(&timeout); } void _glfwPlatformWaitEvents(void) { - handleEvents(-1); + handleEvents(NULL); } void _glfwPlatformWaitEventsTimeout(double timeout) { - handleEvents((int) (timeout * 1e3)); + handleEvents(&timeout); } void _glfwPlatformPostEmptyEvent(void) @@ -1815,7 +1864,7 @@ const char* _glfwPlatformGetClipboardString(void) close(fds[1]); // XXX: this is a huge hack, this function shouldn’t be synchronous! - handleEvents(-1); + handleEvents(NULL); while (1) {