From 71742d9a27a88d898ea13fd415fae1650dc2772e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 3 Mar 2022 22:41:36 +0100 Subject: [PATCH] Wayland: Improve event processing with timeout If the polling was interrupted by a signal or by incomplete or unrelated data on any file descriptor, handleEvents could return before the full timeout had elapsed. This retries the Wayland prepare-to-read and poll until the full timeout has elapsed or until any event was processed. Unfortunately, due to how the Wayland client API is designed, this also includes the delete_id for the frame callback created by eglSwapBuffers. This means glfwWaitEvents* are still not fully functional on Wayland. See #1911 for more details. --- src/wl_window.c | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 15cc5e5f..54257b25 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -737,6 +737,7 @@ static GLFWbool flushDisplay(void) static void handleEvents(double* timeout) { + GLFWbool event = GLFW_FALSE; struct pollfd fds[] = { { wl_display_get_fd(_glfw.wl.display), POLLIN }, @@ -744,31 +745,38 @@ static void handleEvents(double* timeout) { _glfw.wl.cursorTimerfd, POLLIN }, }; - while (wl_display_prepare_read(_glfw.wl.display) != 0) - wl_display_dispatch_pending(_glfw.wl.display); - - // If an error other than EAGAIN happens, we have likely been disconnected - // from the Wayland session; try to handle that the best we can. - if (!flushDisplay()) + while (!event) { - wl_display_cancel_read(_glfw.wl.display); + while (wl_display_prepare_read(_glfw.wl.display) != 0) + wl_display_dispatch_pending(_glfw.wl.display); - _GLFWwindow* window = _glfw.windowListHead; - while (window) + // If an error other than EAGAIN happens, we have likely been disconnected + // from the Wayland session; try to handle that the best we can. + if (!flushDisplay()) { - _glfwInputWindowCloseRequest(window); - window = window->next; + wl_display_cancel_read(_glfw.wl.display); + + _GLFWwindow* window = _glfw.windowListHead; + while (window) + { + _glfwInputWindowCloseRequest(window); + window = window->next; + } + + return; } - return; - } + if (!_glfwPollPOSIX(fds, 3, timeout)) + { + wl_display_cancel_read(_glfw.wl.display); + return; + } - if (_glfwPollPOSIX(fds, 3, timeout)) - { if (fds[0].revents & POLLIN) { wl_display_read_events(_glfw.wl.display); - wl_display_dispatch_pending(_glfw.wl.display); + if (wl_display_dispatch_pending(_glfw.wl.display) > 0) + event = GLFW_TRUE; } else wl_display_cancel_read(_glfw.wl.display); @@ -789,6 +797,8 @@ static void handleEvents(double* timeout) _glfwInputTextWayland(_glfw.wl.keyboardFocus, _glfw.wl.keyboardLastScancode); } + + event = GLFW_TRUE; } } @@ -797,11 +807,12 @@ static void handleEvents(double* timeout) uint64_t repeats; if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8) + { incrementCursorImage(_glfw.wl.pointerFocus); + event = GLFW_TRUE; + } } } - else - wl_display_cancel_read(_glfw.wl.display); } //////////////////////////////////////////////////////////////////////////