mirror of
https://github.com/glfw/glfw.git
synced 2024-11-25 22:14:34 +00:00
Share X11 fd polling logic with Wayland
This moves the X11 polling implementation to a separate file where it can be used by either the X11 or Wayland backend or both. This code should be POSIX compatible where necessary but will use the lower latency but non-standard polling functions ppoll or pollts where those are available. This commit is based on work by OlivierSohn and kovidgoyal. Fixes #1281 Closes #1285
This commit is contained in:
parent
203a7c59d2
commit
bb9d699ae6
@ -60,6 +60,7 @@ if (GLFW_BUILD_X11 OR GLFW_BUILD_WAYLAND)
|
|||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
target_sources(glfw PRIVATE linux_joystick.h linux_joystick.c)
|
target_sources(glfw PRIVATE linux_joystick.h linux_joystick.c)
|
||||||
endif()
|
endif()
|
||||||
|
target_sources(glfw PRIVATE posix_poll.h posix_poll.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (GLFW_BUILD_WAYLAND)
|
if (GLFW_BUILD_WAYLAND)
|
||||||
|
83
src/posix_poll.c
Normal file
83
src/posix_poll.c
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.4 POSIX - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2022 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// 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 <signal.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
32
src/posix_poll.h
Normal file
32
src/posix_poll.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.4 POSIX - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2022 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
//
|
||||||
|
// 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 <poll.h>
|
||||||
|
|
||||||
|
GLFWbool _glfwPollPOSIX(struct pollfd* fds, nfds_t count, double* timeout);
|
||||||
|
|
@ -43,6 +43,7 @@ typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWa
|
|||||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
|
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
|
||||||
|
|
||||||
#include "xkb_unicode.h"
|
#include "xkb_unicode.h"
|
||||||
|
#include "posix_poll.h"
|
||||||
|
|
||||||
typedef int (* PFN_wl_display_flush)(struct wl_display *display);
|
typedef int (* PFN_wl_display_flush)(struct wl_display *display);
|
||||||
typedef void (* PFN_wl_display_cancel_read)(struct wl_display *display);
|
typedef void (* PFN_wl_display_cancel_read)(struct wl_display *display);
|
||||||
|
@ -735,7 +735,7 @@ static GLFWbool flushDisplay(void)
|
|||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleEvents(int timeout)
|
static void handleEvents(double* timeout)
|
||||||
{
|
{
|
||||||
struct pollfd fds[] =
|
struct pollfd fds[] =
|
||||||
{
|
{
|
||||||
@ -763,7 +763,7 @@ static void handleEvents(int timeout)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (poll(fds, 3, timeout) > 0)
|
if (_glfwPollPOSIX(fds, 3, timeout))
|
||||||
{
|
{
|
||||||
if (fds[0].revents & POLLIN)
|
if (fds[0].revents & POLLIN)
|
||||||
{
|
{
|
||||||
@ -1168,17 +1168,18 @@ GLFWbool _glfwRawMouseMotionSupportedWayland(void)
|
|||||||
|
|
||||||
void _glfwPollEventsWayland(void)
|
void _glfwPollEventsWayland(void)
|
||||||
{
|
{
|
||||||
handleEvents(0);
|
double timeout = 0.0;
|
||||||
|
handleEvents(&timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwWaitEventsWayland(void)
|
void _glfwWaitEventsWayland(void)
|
||||||
{
|
{
|
||||||
handleEvents(-1);
|
handleEvents(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwWaitEventsTimeoutWayland(double timeout)
|
void _glfwWaitEventsTimeoutWayland(double timeout)
|
||||||
{
|
{
|
||||||
handleEvents((int) (timeout * 1e3));
|
handleEvents(&timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPostEmptyEventWayland(void)
|
void _glfwPostEmptyEventWayland(void)
|
||||||
@ -1729,7 +1730,7 @@ const char* _glfwGetClipboardStringWayland(void)
|
|||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
|
|
||||||
// XXX: this is a huge hack, this function shouldn’t be synchronous!
|
// XXX: this is a huge hack, this function shouldn’t be synchronous!
|
||||||
handleEvents(-1);
|
handleEvents(NULL);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
|
||||||
|
|
||||||
#include "xkb_unicode.h"
|
#include "xkb_unicode.h"
|
||||||
|
#include "posix_poll.h"
|
||||||
|
|
||||||
#define GLFW_X11_WINDOW_STATE _GLFWwindowX11 x11;
|
#define GLFW_X11_WINDOW_STATE _GLFWwindowX11 x11;
|
||||||
#define GLFW_X11_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11;
|
#define GLFW_X11_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11;
|
||||||
|
@ -27,18 +27,12 @@
|
|||||||
// It is fine to use C99 in this file because it will not be built with VS
|
// 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 "internal.h"
|
||||||
|
|
||||||
#include <X11/cursorfont.h>
|
#include <X11/cursorfont.h>
|
||||||
#include <X11/Xmd.h>
|
#include <X11/Xmd.h>
|
||||||
|
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -62,53 +56,6 @@
|
|||||||
|
|
||||||
#define _GLFW_XDND_VERSION 5
|
#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
|
// Wait for event data to arrive on the X11 display socket
|
||||||
// This avoids blocking other threads via the per-display Xlib lock that also
|
// This avoids blocking other threads via the per-display Xlib lock that also
|
||||||
// covers GLX functions
|
// covers GLX functions
|
||||||
@ -119,7 +66,7 @@ static GLFWbool waitForX11Event(double* timeout)
|
|||||||
|
|
||||||
while (!XPending(_glfw.x11.display))
|
while (!XPending(_glfw.x11.display))
|
||||||
{
|
{
|
||||||
if (!waitForData(&fd, 1, timeout))
|
if (!_glfwPollPOSIX(&fd, 1, timeout))
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +93,7 @@ static GLFWbool waitForAnyEvent(double* timeout)
|
|||||||
|
|
||||||
while (!XPending(_glfw.x11.display))
|
while (!XPending(_glfw.x11.display))
|
||||||
{
|
{
|
||||||
if (!waitForData(fds, count, timeout))
|
if (!_glfwPollPOSIX(fds, count, timeout))
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
for (int i = 1; i < count; i++)
|
for (int i = 1; i < count; i++)
|
||||||
|
Loading…
Reference in New Issue
Block a user