diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a07ca931..01f191c9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -60,6 +60,7 @@ if (GLFW_BUILD_X11 OR GLFW_BUILD_WAYLAND) if (CMAKE_SYSTEM_NAME STREQUAL "Linux") target_sources(glfw PRIVATE linux_joystick.h linux_joystick.c) endif() + target_sources(glfw PRIVATE posix_poll.h posix_poll.c) endif() if (GLFW_BUILD_WAYLAND) diff --git a/src/posix_poll.c b/src/posix_poll.c new file mode 100644 index 00000000..352d9900 --- /dev/null +++ b/src/posix_poll.c @@ -0,0 +1,83 @@ +//======================================================================== +// GLFW 3.4 POSIX - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2022 Camilla Löwy +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== +// It is fine to use C99 in this file because it will not be built with VS +//======================================================================== + +#if defined(__linux__) + #define _GNU_SOURCE +#endif + +#include "internal.h" + +#include +#include +#include + +GLFWbool _glfwPollPOSIX(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; + } + } +} + diff --git a/src/posix_poll.h b/src/posix_poll.h new file mode 100644 index 00000000..1effd1cd --- /dev/null +++ b/src/posix_poll.h @@ -0,0 +1,32 @@ +//======================================================================== +// GLFW 3.4 POSIX - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2022 Camilla Löwy +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== +// It is fine to use C99 in this file because it will not be built with VS +//======================================================================== + +#include + +GLFWbool _glfwPollPOSIX(struct pollfd* fds, nfds_t count, double* timeout); + diff --git a/src/wl_platform.h b/src/wl_platform.h index 7565411b..ba405714 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -43,6 +43,7 @@ typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWa typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*); #include "xkb_unicode.h" +#include "posix_poll.h" typedef int (* PFN_wl_display_flush)(struct wl_display *display); typedef void (* PFN_wl_display_cancel_read)(struct wl_display *display); diff --git a/src/wl_window.c b/src/wl_window.c index c150b188..4dfde7af 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -735,7 +735,7 @@ static GLFWbool flushDisplay(void) return GLFW_TRUE; } -static void handleEvents(int timeout) +static void handleEvents(double* timeout) { struct pollfd fds[] = { @@ -763,7 +763,7 @@ static void handleEvents(int timeout) return; } - if (poll(fds, 3, timeout) > 0) + if (_glfwPollPOSIX(fds, 3, timeout)) { if (fds[0].revents & POLLIN) { @@ -1168,17 +1168,18 @@ GLFWbool _glfwRawMouseMotionSupportedWayland(void) void _glfwPollEventsWayland(void) { - handleEvents(0); + double timeout = 0.0; + handleEvents(&timeout); } void _glfwWaitEventsWayland(void) { - handleEvents(-1); + handleEvents(NULL); } void _glfwWaitEventsTimeoutWayland(double timeout) { - handleEvents((int) (timeout * 1e3)); + handleEvents(&timeout); } void _glfwPostEmptyEventWayland(void) @@ -1729,7 +1730,7 @@ const char* _glfwGetClipboardStringWayland(void) close(fds[1]); // XXX: this is a huge hack, this function shouldn’t be synchronous! - handleEvents(-1); + handleEvents(NULL); while (1) { diff --git a/src/x11_platform.h b/src/x11_platform.h index 8da3a2e4..956104fa 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -453,6 +453,7 @@ typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSur typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t); #include "xkb_unicode.h" +#include "posix_poll.h" #define GLFW_X11_WINDOW_STATE _GLFWwindowX11 x11; #define GLFW_X11_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11; diff --git a/src/x11_window.c b/src/x11_window.c index 52cbbcf0..6c329e63 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -27,18 +27,12 @@ // It is fine to use C99 in this file because it will not be built with VS //======================================================================== -#if defined(__linux__) - #define _GNU_SOURCE -#endif - #include "internal.h" #include #include #include -#include -#include #include #include @@ -62,53 +56,6 @@ #define _GLFW_XDND_VERSION 5 -// 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; - } - } -} - // Wait for event data to arrive on the X11 display socket // This avoids blocking other threads via the per-display Xlib lock that also // covers GLX functions @@ -119,7 +66,7 @@ static GLFWbool waitForX11Event(double* timeout) while (!XPending(_glfw.x11.display)) { - if (!waitForData(&fd, 1, timeout)) + if (!_glfwPollPOSIX(&fd, 1, timeout)) return GLFW_FALSE; } @@ -146,7 +93,7 @@ static GLFWbool waitForAnyEvent(double* timeout) while (!XPending(_glfw.x11.display)) { - if (!waitForData(fds, count, timeout)) + if (!_glfwPollPOSIX(fds, count, timeout)) return GLFW_FALSE; for (int i = 1; i < count; i++)