From 750ac642457b1c1ee5cde4880322096850aad90a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 14 Sep 2017 15:03:06 +0200 Subject: [PATCH] X11: Fix event time wrapping Related to #1012. --- src/x11_platform.h | 6 +++--- src/x11_window.c | 25 ++++++++++++++++++------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/x11_platform.h b/src/x11_platform.h index cb710cf3..dcaa27ad 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -225,9 +225,9 @@ typedef struct _GLFWlibraryX11 double restoreCursorPosX, restoreCursorPosY; // The window whose disabled cursor mode is active _GLFWwindow* disabledCursorWindow; - - // The time of the last event - Time lastEventTime; + // State for accumulating a non-wrapping event time + Time lastTimestamp; + uint64_t eventTime; // Window manager atoms Atom WM_PROTOCOLS; diff --git a/src/x11_window.c b/src/x11_window.c index d6a96247..f352a49a 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1034,6 +1034,14 @@ static unsigned int decodeUTF8(const char** s) } #endif /*X_HAVE_UTF8_STRING*/ +// Updates the event time with the specified timestamp +// +static void updateEventTime(Time timestamp) +{ + _glfw.x11.eventTime += timestamp - _glfw.x11.lastTimestamp; + _glfw.x11.lastTimestamp = timestamp; +} + // Process the specified X event // static void processEvent(XEvent *event) @@ -1076,6 +1084,7 @@ static void processEvent(XEvent *event) const double* values = re->raw_values; double xpos = window->virtualCursorPosX; double ypos = window->virtualCursorPosY; + updateEventTime(re->time); if (XIMaskIsSet(re->valuators.mask, 0)) { @@ -1121,7 +1130,7 @@ static void processEvent(XEvent *event) const int key = translateKey(keycode); const int mods = translateState(event->xkey.state); const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); - _glfw.x11.lastEventTime = event->xkey.time; + updateEventTime(event->xkey.time); if (window->x11.ic) { @@ -1215,7 +1224,7 @@ static void processEvent(XEvent *event) { const int key = translateKey(keycode); const int mods = translateState(event->xkey.state); - _glfw.x11.lastEventTime = event->xkey.time; + updateEventTime(event->xkey.time); if (!_glfw.x11.xkb.detectable) { @@ -1256,7 +1265,7 @@ static void processEvent(XEvent *event) case ButtonPress: { const int mods = translateState(event->xbutton.state); - _glfw.x11.lastEventTime = event->xbutton.time; + updateEventTime(event->xbutton.time); if (event->xbutton.button == Button1) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods); @@ -1291,7 +1300,7 @@ static void processEvent(XEvent *event) case ButtonRelease: { const int mods = translateState(event->xbutton.state); - _glfw.x11.lastEventTime = event->xbutton.time; + updateEventTime(event->xbutton.time); if (event->xbutton.button == Button1) { @@ -1329,6 +1338,8 @@ static void processEvent(XEvent *event) case EnterNotify: { + updateEventTime(event->xcrossing.time); + // HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise // ignore the defined cursor for hidden cursor mode if (window->cursorMode == GLFW_CURSOR_HIDDEN) @@ -1340,6 +1351,7 @@ static void processEvent(XEvent *event) case LeaveNotify: { + updateEventTime(event->xcrossing.time); _glfwInputCursorEnter(window, GLFW_FALSE); return; } @@ -1348,7 +1360,7 @@ static void processEvent(XEvent *event) { const int x = event->xmotion.x; const int y = event->xmotion.y; - _glfw.x11.lastEventTime = event->xmotion.time; + updateEventTime(event->xmotion.time); if (x != window->x11.warpCursorPosX || y != window->x11.warpCursorPosY) { @@ -2435,8 +2447,7 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) double _glfwPlatformGetEventTime(void) { - /* X11 events are stored in milliseconds */ - return (double) _glfw.x11.lastEventTime / 1000.0; + return (double) _glfw.x11.eventTime / 1000.0; } void _glfwPlatformPollEvents(void)