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
|
// This avoids blocking other threads via the per-display Xlib lock that also
|
||||||
// covers GLX functions
|
// covers GLX functions
|
||||||
//
|
//
|
||||||
void selectDisplayConnection(struct timeval* timeout)
|
static GLFWbool waitForEvent(double* timeout)
|
||||||
{
|
{
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
int result, count;
|
|
||||||
const int fd = ConnectionNumber(_glfw.x11.display);
|
const int fd = ConnectionNumber(_glfw.x11.display);
|
||||||
|
int count = fd + 1;
|
||||||
count = fd + 1;
|
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(fd, &fds);
|
FD_SET(fd, &fds);
|
||||||
@ -69,15 +67,29 @@ void selectDisplayConnection(struct timeval* timeout)
|
|||||||
if (fd < _glfw.linux_js.inotify)
|
if (fd < _glfw.linux_js.inotify)
|
||||||
count = _glfw.linux_js.inotify + 1;
|
count = _glfw.linux_js.inotify + 1;
|
||||||
#endif
|
#endif
|
||||||
|
for (;;)
|
||||||
// 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
|
|
||||||
{
|
{
|
||||||
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
|
// 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) &&
|
if (!_glfwPlatformWindowVisible(window) &&
|
||||||
_glfw.x11.NET_REQUEST_FRAME_EXTENTS)
|
_glfw.x11.NET_REQUEST_FRAME_EXTENTS)
|
||||||
{
|
{
|
||||||
uint64_t base;
|
|
||||||
XEvent event;
|
XEvent event;
|
||||||
|
double timeout = 0.5;
|
||||||
|
|
||||||
// Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to
|
// Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to
|
||||||
// function before the window is mapped
|
// function before the window is mapped
|
||||||
sendEventToWM(window, _glfw.x11.NET_REQUEST_FRAME_EXTENTS,
|
sendEventToWM(window, _glfw.x11.NET_REQUEST_FRAME_EXTENTS,
|
||||||
0, 0, 0, 0, 0);
|
0, 0, 0, 0, 0);
|
||||||
|
|
||||||
base = _glfwPlatformGetTimerValue();
|
|
||||||
|
|
||||||
// HACK: Use a timeout because earlier versions of some window managers
|
// HACK: Use a timeout because earlier versions of some window managers
|
||||||
// (at least Unity, Fluxbox and Xfwm) failed to send the reply
|
// (at least Unity, Fluxbox and Xfwm) failed to send the reply
|
||||||
// They have been fixed but broken versions are still in the wild
|
// They have been fixed but broken versions are still in the wild
|
||||||
@ -1813,21 +1823,12 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
|||||||
isFrameExtentsEvent,
|
isFrameExtentsEvent,
|
||||||
(XPointer) window))
|
(XPointer) window))
|
||||||
{
|
{
|
||||||
double remaining;
|
if (!waitForEvent(&timeout))
|
||||||
struct timeval timeout;
|
|
||||||
|
|
||||||
remaining = 0.5 - (_glfwPlatformGetTimerValue() - base) /
|
|
||||||
(double) _glfwPlatformGetTimerFrequency();
|
|
||||||
if (remaining <= 0.0)
|
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");
|
"X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout.tv_sec = 0;
|
|
||||||
timeout.tv_usec = (long) (remaining * 1e6);
|
|
||||||
selectDisplayConnection(&timeout);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2048,28 +2049,17 @@ void _glfwPlatformPollEvents(void)
|
|||||||
void _glfwPlatformWaitEvents(void)
|
void _glfwPlatformWaitEvents(void)
|
||||||
{
|
{
|
||||||
while (!XPending(_glfw.x11.display))
|
while (!XPending(_glfw.x11.display))
|
||||||
selectDisplayConnection(NULL);
|
waitForEvent(NULL);
|
||||||
|
|
||||||
_glfwPlatformPollEvents();
|
_glfwPlatformPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||||
{
|
{
|
||||||
const double deadline = timeout + _glfwPlatformGetTimerValue() /
|
|
||||||
(double) _glfwPlatformGetTimerFrequency();
|
|
||||||
|
|
||||||
while (!XPending(_glfw.x11.display))
|
while (!XPending(_glfw.x11.display))
|
||||||
{
|
{
|
||||||
const double remaining = deadline - _glfwPlatformGetTimerValue() /
|
if (!waitForEvent(&timeout))
|
||||||
(double) _glfwPlatformGetTimerFrequency();
|
break;
|
||||||
if (remaining <= 0.0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const long seconds = (long) remaining;
|
|
||||||
const long microseconds = (long) ((remaining - seconds) * 1e6);
|
|
||||||
struct timeval tv = { seconds, microseconds };
|
|
||||||
|
|
||||||
selectDisplayConnection(&tv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwPlatformPollEvents();
|
_glfwPlatformPollEvents();
|
||||||
@ -2261,7 +2251,7 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
|||||||
window->x11.handle, CurrentTime);
|
window->x11.handle, CurrentTime);
|
||||||
|
|
||||||
while (!XCheckTypedEvent(_glfw.x11.display, SelectionNotify, &event))
|
while (!XCheckTypedEvent(_glfw.x11.display, SelectionNotify, &event))
|
||||||
selectDisplayConnection(NULL);
|
waitForEvent(NULL);
|
||||||
|
|
||||||
if (event.xselection.property == None)
|
if (event.xselection.property == None)
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
Reference in New Issue
Block a user