diff --git a/README.md b/README.md index 9bad25a0f..e73d30a2b 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,8 @@ information on what to include when reporting a bug. from a modal to the content area - [Wayland] Bugfix: free modules at end of terminate function to resolve potential segmentation fault (#2744) + - [Wayland] Bugfix: Events being lost due to some drivers moving events + to the default event queue during buffer swapping (#2793) - [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631) - [X11] Bugfix: Occasional crash when an idle display awakes (#2766) - [X11] Bugfix: Prevent BadWindow when creating small windows with a content scale diff --git a/src/wl_window.c b/src/wl_window.c index 4220d17e0..6fd2cae62 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1356,6 +1356,7 @@ static void handleEvents(double* timeout) #endif GLFWbool event = GLFW_FALSE; + GLFWbool wlcanread = GLFW_FALSE; enum { DISPLAY_FD, KEYREPEAT_FD, CURSOR_FD, LIBDECOR_FD }; struct pollfd fds[] = { @@ -1370,42 +1371,70 @@ static void handleEvents(double* timeout) while (!event) { - while (wl_display_prepare_read(_glfw.wl.display) != 0) + wlcanread = GLFW_FALSE; + while (!wlcanread && !event) { - if (wl_display_dispatch_pending(_glfw.wl.display) > 0) - return; + if (wl_display_prepare_read(_glfw.wl.display) == 0) + { + wlcanread = GLFW_TRUE; + } + else if (wl_display_dispatch_pending(_glfw.wl.display) > 0) + { + event = GLFW_TRUE; + if (wl_display_prepare_read(_glfw.wl.display) == 0) + { + wlcanread = GLFW_TRUE; + } + } } - // 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()) - { - wl_display_cancel_read(_glfw.wl.display); + if (wlcanread) + { + // 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()) + { + wl_display_cancel_read(_glfw.wl.display); - _GLFWwindow* window = _glfw.windowListHead; - while (window) - { - _glfwInputWindowCloseRequest(window); - window = window->next; - } + _GLFWwindow* window = _glfw.windowListHead; + while (window) + { + _glfwInputWindowCloseRequest(window); + window = window->next; + } - return; - } + return; + } - if (!_glfwPollPOSIX(fds, sizeof(fds) / sizeof(fds[0]), timeout)) - { - wl_display_cancel_read(_glfw.wl.display); - return; - } + double* ptimeout = timeout; + double notimeout = 0.0; + if (event) + ptimeout = ¬imeout; // do not wait if we already have an event + + if (!_glfwPollPOSIX(fds, sizeof(fds) / sizeof(fds[0]), ptimeout)) + { + wl_display_cancel_read(_glfw.wl.display); + return; + } - 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; - } - else - wl_display_cancel_read(_glfw.wl.display); + 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; + } + else + wl_display_cancel_read(_glfw.wl.display); + } + else + { + fds[DISPLAY_FD].fd = -1; // ignore wl events + double notimeout = 0.0; + if (!_glfwPollPOSIX(fds, sizeof(fds) / sizeof(fds[0]), ¬imeout)) + { + return; + } + } if (fds[KEYREPEAT_FD].revents & POLLIN) { @@ -1427,11 +1456,10 @@ static void handleEvents(double* timeout) event = GLFW_TRUE; } - } } - if (fds[CURSOR_FD].revents & POLLIN) + if ((fds[CURSOR_FD].fd > 0 ) && (fds[CURSOR_FD].revents & POLLIN)) { uint64_t repeats; @@ -1439,7 +1467,7 @@ static void handleEvents(double* timeout) incrementCursorImage(_glfw.wl.pointerFocus); } - if (fds[LIBDECOR_FD].revents & POLLIN) + if ((fds[LIBDECOR_FD].fd > 0 ) && (fds[LIBDECOR_FD].revents & POLLIN)) { if (libdecor_dispatch(_glfw.wl.libdecor.context, 0) > 0) event = GLFW_TRUE;