mirror of
https://github.com/glfw/glfw.git
synced 2024-11-25 22:14:34 +00:00
X11: Clean up event wait timeout logic
Simplify interface and implement timeout updating.
This commit is contained in:
parent
f88a609000
commit
ad9233e620
@ -53,13 +53,11 @@
|
||||
// This avoids blocking other threads via the per-display Xlib lock that also
|
||||
// covers GLX functions
|
||||
//
|
||||
void selectDisplayConnection(struct timeval* timeout)
|
||||
static GLFWbool waitForEvent(double* timeout)
|
||||
{
|
||||
fd_set fds;
|
||||
int result, count;
|
||||
const int fd = ConnectionNumber(_glfw.x11.display);
|
||||
|
||||
count = fd + 1;
|
||||
int count = fd + 1;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
@ -69,15 +67,29 @@ void selectDisplayConnection(struct timeval* timeout)
|
||||
if (fd < _glfw.linux_js.inotify)
|
||||
count = _glfw.linux_js.inotify + 1;
|
||||
#endif
|
||||
|
||||
// NOTE: Only retry on EINTR if there is no timeout, as select is not
|
||||
// required to update it for the time elapsed
|
||||
// TODO: Update timeout value manually
|
||||
do
|
||||
for (;;)
|
||||
{
|
||||
result = select(count, &fds, NULL, NULL, timeout);
|
||||
if (timeout)
|
||||
{
|
||||
const long seconds = (long) *timeout;
|
||||
const long microseconds = (long) ((*timeout - seconds) * 1e6);
|
||||
struct timeval tv = { seconds, microseconds };
|
||||
const uint64_t base = _glfwPlatformGetTimerValue();
|
||||
|
||||
const int result = select(count, &fds, NULL, NULL, &tv);
|
||||
const int error = errno;
|
||||
|
||||
*timeout -= (_glfwPlatformGetTimerValue() - base) /
|
||||
(double) _glfwPlatformGetTimerFrequency();
|
||||
|
||||
if (result > 0)
|
||||
return GLFW_TRUE;
|
||||
if ((result == -1 && error == EINTR) || *timeout <= 0.0)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
else if (select(count, &fds, NULL, NULL, NULL) != -1 || errno != EINTR)
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
while (result == -1 && errno == EINTR && timeout == NULL);
|
||||
}
|
||||
|
||||
// Returns whether the window is iconified
|
||||
@ -818,7 +830,7 @@ static void pushSelectionToManager(_GLFWwindow* window)
|
||||
}
|
||||
}
|
||||
|
||||
selectDisplayConnection(NULL);
|
||||
waitForEvent(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1793,16 +1805,14 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||
if (!_glfwPlatformWindowVisible(window) &&
|
||||
_glfw.x11.NET_REQUEST_FRAME_EXTENTS)
|
||||
{
|
||||
uint64_t base;
|
||||
XEvent event;
|
||||
double timeout = 0.5;
|
||||
|
||||
// Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to
|
||||
// function before the window is mapped
|
||||
sendEventToWM(window, _glfw.x11.NET_REQUEST_FRAME_EXTENTS,
|
||||
0, 0, 0, 0, 0);
|
||||
|
||||
base = _glfwPlatformGetTimerValue();
|
||||
|
||||
// HACK: Use a timeout because earlier versions of some window managers
|
||||
// (at least Unity, Fluxbox and Xfwm) failed to send the reply
|
||||
// They have been fixed but broken versions are still in the wild
|
||||
@ -1813,21 +1823,12 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||
isFrameExtentsEvent,
|
||||
(XPointer) window))
|
||||
{
|
||||
double remaining;
|
||||
struct timeval timeout;
|
||||
|
||||
remaining = 0.5 - (_glfwPlatformGetTimerValue() - base) /
|
||||
(double) _glfwPlatformGetTimerFrequency();
|
||||
if (remaining <= 0.0)
|
||||
if (!waitForEvent(&timeout))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");
|
||||
return;
|
||||
}
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = (long) (remaining * 1e6);
|
||||
selectDisplayConnection(&timeout);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2048,28 +2049,17 @@ void _glfwPlatformPollEvents(void)
|
||||
void _glfwPlatformWaitEvents(void)
|
||||
{
|
||||
while (!XPending(_glfw.x11.display))
|
||||
selectDisplayConnection(NULL);
|
||||
waitForEvent(NULL);
|
||||
|
||||
_glfwPlatformPollEvents();
|
||||
}
|
||||
|
||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||
{
|
||||
const double deadline = timeout + _glfwPlatformGetTimerValue() /
|
||||
(double) _glfwPlatformGetTimerFrequency();
|
||||
|
||||
while (!XPending(_glfw.x11.display))
|
||||
{
|
||||
const double remaining = deadline - _glfwPlatformGetTimerValue() /
|
||||
(double) _glfwPlatformGetTimerFrequency();
|
||||
if (remaining <= 0.0)
|
||||
return;
|
||||
|
||||
const long seconds = (long) remaining;
|
||||
const long microseconds = (long) ((remaining - seconds) * 1e6);
|
||||
struct timeval tv = { seconds, microseconds };
|
||||
|
||||
selectDisplayConnection(&tv);
|
||||
if (!waitForEvent(&timeout))
|
||||
break;
|
||||
}
|
||||
|
||||
_glfwPlatformPollEvents();
|
||||
@ -2261,7 +2251,7 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
window->x11.handle, CurrentTime);
|
||||
|
||||
while (!XCheckTypedEvent(_glfw.x11.display, SelectionNotify, &event))
|
||||
selectDisplayConnection(NULL);
|
||||
waitForEvent(NULL);
|
||||
|
||||
if (event.xselection.property == None)
|
||||
continue;
|
||||
|
Loading…
Reference in New Issue
Block a user