Compare commits

...

5 Commits

Author SHA1 Message Date
Camilla Löwy
8429402f9e Documentation work 2017-09-15 18:38:05 +02:00
Camilla Löwy
c4b73750b7 Cleanup
Related to #1012.
2017-09-15 18:38:05 +02:00
Camilla Löwy
750ac64245 X11: Fix event time wrapping
Related to #1012.
2017-09-15 18:37:53 +02:00
Camilla Löwy
138b10eb28 Win32: Fix event time wrapping
Related to #1012.
2017-09-15 18:35:24 +02:00
Felipe Ferreira da Silva
c577ae4b0e Add glfwGetEventTime for querying input event time
Fixes #1012.
2017-09-15 18:34:34 +02:00
17 changed files with 166 additions and 12 deletions

View File

@ -138,6 +138,8 @@ information on what to include when reporting a bug.
for retrieving gamepad input state (#900) for retrieving gamepad input state (#900)
- Added `glfwRequestWindowAttention` function for requesting attention from the - Added `glfwRequestWindowAttention` function for requesting attention from the
user (#732,#988) user (#732,#988)
- Added `glfwGetEventTime` function for querying the time of the last input
event (#1012)
- Added `glfwGetKeyScancode` function that allows retrieving platform dependent - Added `glfwGetKeyScancode` function that allows retrieving platform dependent
scancodes for keys (#830) scancodes for keys (#830)
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for - Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for

View File

@ -3366,6 +3366,31 @@ GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window,
*/ */
GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun); GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun);
/*! @brief Returns the time of the last input event.
*
* This function returns the time, in seconds, that the last input event
* occurred. The time is collected for key, mouse button, scrolling and cursor
* position events including enter and leave. The function is intended to be
* called from the relevant event callback.
*
* @return The time of the input event, in seconds, or zero if an
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @remarks The event timestamps provided by most platforms have much lower
* resolution than the GLFW timer.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref events
*
* @since Added in version 3.3.
*
* @ingroup window
*/
GLFWAPI double glfwGetEventTime(void);
/*! @brief Processes all pending events. /*! @brief Processes all pending events.
* *
* This function processes only those events that are already in the event * This function processes only those events that are already in the event

View File

@ -118,6 +118,9 @@ typedef struct _GLFWlibraryNS
// The window whose disabled cursor mode is active // The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow; _GLFWwindow* disabledCursorWindow;
// The time of the last event
double lastEventTime;
struct { struct {
CFBundleRef bundle; CFBundleRef bundle;
PFN_TISCopyCurrentKeyboardLayoutInputSource CopyCurrentKeyboardLayoutInputSource; PFN_TISCopyCurrentKeyboardLayoutInputSource CopyCurrentKeyboardLayoutInputSource;

View File

@ -446,6 +446,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)mouseDown:(NSEvent *)event - (void)mouseDown:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_LEFT,
GLFW_PRESS, GLFW_PRESS,
@ -454,11 +456,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)mouseDragged:(NSEvent *)event - (void)mouseDragged:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
[self mouseMoved:event]; [self mouseMoved:event];
} }
- (void)mouseUp:(NSEvent *)event - (void)mouseUp:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
GLFW_MOUSE_BUTTON_LEFT, GLFW_MOUSE_BUTTON_LEFT,
GLFW_RELEASE, GLFW_RELEASE,
@ -467,6 +473,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)mouseMoved:(NSEvent *)event - (void)mouseMoved:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
{ {
const double dx = [event deltaX] - window->ns.cursorWarpDeltaX; const double dx = [event deltaX] - window->ns.cursorWarpDeltaX;
@ -490,6 +498,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)rightMouseDown:(NSEvent *)event - (void)rightMouseDown:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
GLFW_MOUSE_BUTTON_RIGHT, GLFW_MOUSE_BUTTON_RIGHT,
GLFW_PRESS, GLFW_PRESS,
@ -498,11 +508,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)rightMouseDragged:(NSEvent *)event - (void)rightMouseDragged:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
[self mouseMoved:event]; [self mouseMoved:event];
} }
- (void)rightMouseUp:(NSEvent *)event - (void)rightMouseUp:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
GLFW_MOUSE_BUTTON_RIGHT, GLFW_MOUSE_BUTTON_RIGHT,
GLFW_RELEASE, GLFW_RELEASE,
@ -511,6 +525,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)otherMouseDown:(NSEvent *)event - (void)otherMouseDown:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
(int) [event buttonNumber], (int) [event buttonNumber],
GLFW_PRESS, GLFW_PRESS,
@ -519,11 +535,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)otherMouseDragged:(NSEvent *)event - (void)otherMouseDragged:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
[self mouseMoved:event]; [self mouseMoved:event];
} }
- (void)otherMouseUp:(NSEvent *)event - (void)otherMouseUp:(NSEvent *)event
{ {
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputMouseClick(window, _glfwInputMouseClick(window,
(int) [event buttonNumber], (int) [event buttonNumber],
GLFW_RELEASE, GLFW_RELEASE,
@ -588,6 +608,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
const int key = translateKey([event keyCode]); const int key = translateKey([event keyCode]);
const int mods = translateFlags([event modifierFlags]); const int mods = translateFlags([event modifierFlags]);
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods); _glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
[self interpretKeyEvents:[NSArray arrayWithObject:event]]; [self interpretKeyEvents:[NSArray arrayWithObject:event]];
@ -619,6 +641,9 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
{ {
const int key = translateKey([event keyCode]); const int key = translateKey([event keyCode]);
const int mods = translateFlags([event modifierFlags]); const int mods = translateFlags([event modifierFlags]);
_glfw.ns.lastEventTime = [event timestamp];
_glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods); _glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods);
} }
@ -1462,6 +1487,12 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
[window->ns.object setLevel:NSNormalWindowLevel]; [window->ns.object setLevel:NSNormalWindowLevel];
} }
double _glfwPlatformGetEventTime(void)
{
/* Windows events are stored in seconds */
return _glfw.ns.lastEventTime;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
for (;;) for (;;)

View File

@ -685,6 +685,7 @@ void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
double _glfwPlatformGetEventTime(void);
void _glfwPlatformPollEvents(void); void _glfwPlatformPollEvents(void);
void _glfwPlatformWaitEvents(void); void _glfwPlatformWaitEvents(void);
void _glfwPlatformWaitEventsTimeout(double timeout); void _glfwPlatformWaitEventsTimeout(double timeout);

View File

@ -114,6 +114,9 @@ typedef struct _GLFWlibraryMir
// The window whose disabled cursor mode is active // The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow; _GLFWwindow* disabledCursorWindow;
// The time of the last event
int64_t lastEventTime;
} _GLFWlibraryMir; } _GLFWlibraryMir;
// Mir-specific per-cursor data // Mir-specific per-cursor data

View File

@ -147,6 +147,8 @@ static void handleKeyEvent(const MirKeyboardEvent* key_event, _GLFWwindow* windo
const long text = _glfwKeySym2Unicode(key_code); const long text = _glfwKeySym2Unicode(key_code);
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
_glfw.mir.lastEventTime = mir_input_event_get_event_time((MirInputEvent *) key_event);
_glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods); _glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods);
if (text != -1) if (text != -1)
@ -164,6 +166,8 @@ static void handlePointerButton(_GLFWwindow* window,
uint32_t newButtonStates = mir_pointer_event_buttons(pointer_event); uint32_t newButtonStates = mir_pointer_event_buttons(pointer_event);
int publicButton = GLFW_MOUSE_BUTTON_LEFT; int publicButton = GLFW_MOUSE_BUTTON_LEFT;
_glfw.mir.lastEventTime = mir_input_event_get_event_time((MirEvent *) pointer_event);
// XOR our old button states our new states to figure out what was added or removed // XOR our old button states our new states to figure out what was added or removed
button = newButtonStates ^ oldButtonStates; button = newButtonStates ^ oldButtonStates;
@ -201,6 +205,8 @@ static void handlePointerMotion(_GLFWwindow* window,
const int hscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll); const int hscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
const int vscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll); const int vscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
_glfw.mir.lastEventTime = mir_input_event_get_event_time((MirEvent *) pointer_event);
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
{ {
if (_glfw.mir.disabledCursorWindow != window) if (_glfw.mir.disabledCursorWindow != window)
@ -632,6 +638,12 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
"Mir: Unsupported function %s", __PRETTY_FUNCTION__); "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
} }
double _glfwPlatformGetEventTime(void)
{
/* Mir events are stored in nanoseconds */
return (double) _glfw.mir.lastEventTime / 1000000000.0;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
EventNode* node = NULL; EventNode* node = NULL;

View File

@ -204,6 +204,11 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window)
return GLFW_FALSE; return GLFW_FALSE;
} }
double _glfwPlatformGetEventTime(void)
{
return 0.0;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
} }

View File

@ -259,6 +259,10 @@ typedef struct _GLFWlibraryWin32
RAWINPUT* rawInput; RAWINPUT* rawInput;
int rawInputSize; int rawInputSize;
// State for accumulating a non-wrapping event time
uint32_t lastTimestamp;
uint64_t eventTime;
struct { struct {
HINSTANCE instance; HINSTANCE instance;
PFN_timeGetTime GetTime; PFN_timeGetTime GetTime;

View File

@ -347,6 +347,14 @@ static int getKeyMods(void)
return mods; return mods;
} }
// Updates the event time with the specified timestamp
//
static void updateEventTime(LONG timestamp)
{
_glfw.win32.eventTime += (uint32_t) timestamp - _glfw.win32.lastTimestamp;
_glfw.win32.lastTimestamp = timestamp;
}
// Retrieves and translates modifier keys // Retrieves and translates modifier keys
// //
static int getAsyncKeyMods(void) static int getAsyncKeyMods(void)
@ -595,6 +603,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_UNICHAR: case WM_UNICHAR:
{ {
const GLFWbool plain = (uMsg != WM_SYSCHAR); const GLFWbool plain = (uMsg != WM_SYSCHAR);
updateEventTime(GetMessageTime());
if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR) if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR)
{ {
@ -617,6 +626,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
const int scancode = (lParam >> 16) & 0x1ff; const int scancode = (lParam >> 16) & 0x1ff;
const int action = ((lParam >> 31) & 1) ? GLFW_RELEASE : GLFW_PRESS; const int action = ((lParam >> 31) & 1) ? GLFW_RELEASE : GLFW_PRESS;
const int mods = getKeyMods(); const int mods = getKeyMods();
updateEventTime(GetMessageTime());
if (key == _GLFW_KEY_INVALID) if (key == _GLFW_KEY_INVALID)
break; break;
@ -651,6 +661,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_XBUTTONUP: case WM_XBUTTONUP:
{ {
int i, button, action; int i, button, action;
updateEventTime(GetMessageTime());
if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
button = GLFW_MOUSE_BUTTON_LEFT; button = GLFW_MOUSE_BUTTON_LEFT;
@ -701,6 +712,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
{ {
const int x = GET_X_LPARAM(lParam); const int x = GET_X_LPARAM(lParam);
const int y = GET_Y_LPARAM(lParam); const int y = GET_Y_LPARAM(lParam);
updateEventTime(GetMessageTime());
// Disabled cursor motion input is provided by WM_INPUT // Disabled cursor motion input is provided by WM_INPUT
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
@ -779,6 +791,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_MOUSELEAVE: case WM_MOUSELEAVE:
{ {
updateEventTime(GetMessageTime());
window->win32.cursorTracked = GLFW_FALSE; window->win32.cursorTracked = GLFW_FALSE;
_glfwInputCursorEnter(window, GLFW_FALSE); _glfwInputCursorEnter(window, GLFW_FALSE);
return 0; return 0;
@ -786,6 +799,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
{ {
updateEventTime(GetMessageTime());
_glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA); _glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA);
return 0; return 0;
} }
@ -793,6 +807,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_MOUSEHWHEEL: case WM_MOUSEHWHEEL:
{ {
// This message is only sent on Windows Vista and later // This message is only sent on Windows Vista and later
updateEventTime(GetMessageTime());
// NOTE: The X-axis is inverted for consistency with macOS and X11 // NOTE: The X-axis is inverted for consistency with macOS and X11
_glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0); _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
return 0; return 0;
@ -1498,6 +1513,11 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
} }
double _glfwPlatformGetEventTime(void)
{
return (double) _glfw.win32.eventTime / 1000.0;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
MSG msg; MSG msg;

View File

@ -956,6 +956,12 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle
return cbfun; return cbfun;
} }
GLFWAPI double glfwGetEventTime(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(0.0);
return _glfwPlatformGetEventTime();
}
GLFWAPI void glfwPollEvents(void) GLFWAPI void glfwPollEvents(void)
{ {
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();

View File

@ -83,6 +83,7 @@ static void pointerHandleMotion(void* data,
if (!window) if (!window)
return; return;
_glfw.wl.lastEventTime = time;
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
return; return;
else else
@ -109,6 +110,7 @@ static void pointerHandleButton(void* data,
if (!window) if (!window)
return; return;
_glfw.wl.lastEventTime = time;
_glfw.wl.pointerSerial = serial; _glfw.wl.pointerSerial = serial;
/* Makes left, right and middle 0, 1 and 2. Overall order follows evdev /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
@ -136,6 +138,7 @@ static void pointerHandleAxis(void* data,
if (!window) if (!window)
return; return;
_glfw.wl.lastEventTime = time;
/* Wayland scroll events are in pointer motion coordinate space (think /* Wayland scroll events are in pointer motion coordinate space (think
* two finger scroll). The factor 10 is commonly used to convert to * two finger scroll). The factor 10 is commonly used to convert to
* "scroll step means 1.0. */ * "scroll step means 1.0. */
@ -349,6 +352,7 @@ static void keyboardHandleKey(void* data,
if (!window) if (!window)
return; return;
_glfw.wl.lastEventTime = time;
keyCode = toGLFWKeyCode(key); keyCode = toGLFWKeyCode(key);
action = state == WL_KEYBOARD_KEY_STATE_PRESSED action = state == WL_KEYBOARD_KEY_STATE_PRESSED
? GLFW_PRESS : GLFW_RELEASE; ? GLFW_PRESS : GLFW_RELEASE;

View File

@ -97,6 +97,7 @@ typedef struct _GLFWwindowWayland
struct zwp_relative_pointer_v1* relativePointer; struct zwp_relative_pointer_v1* relativePointer;
struct zwp_locked_pointer_v1* lockedPointer; struct zwp_locked_pointer_v1* lockedPointer;
} pointerLock; } pointerLock;
} _GLFWwindowWayland; } _GLFWwindowWayland;
// Wayland-specific global data // Wayland-specific global data
@ -138,6 +139,9 @@ typedef struct _GLFWlibraryWayland
_GLFWwindow* pointerFocus; _GLFWwindow* pointerFocus;
_GLFWwindow* keyboardFocus; _GLFWwindow* keyboardFocus;
// The time of the last event
unsigned int lastEventTime;
} _GLFWlibraryWayland; } _GLFWlibraryWayland;
// Wayland-specific per-monitor data // Wayland-specific per-monitor data

View File

@ -675,6 +675,11 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
"Wayland: Window attribute setting not implemented yet"); "Wayland: Window attribute setting not implemented yet");
} }
double _glfwPlatformGetEventTime(void)
{
return (double) _glfw.wl.lastEventTime / 1000.0;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
handleEvents(0); handleEvents(0);

View File

@ -225,6 +225,9 @@ typedef struct _GLFWlibraryX11
double restoreCursorPosX, restoreCursorPosY; double restoreCursorPosX, restoreCursorPosY;
// The window whose disabled cursor mode is active // The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow; _GLFWwindow* disabledCursorWindow;
// State for accumulating a non-wrapping event time
Time lastTimestamp;
uint64_t eventTime;
// Window manager atoms // Window manager atoms
Atom WM_PROTOCOLS; Atom WM_PROTOCOLS;

View File

@ -1034,6 +1034,14 @@ static unsigned int decodeUTF8(const char** s)
} }
#endif /*X_HAVE_UTF8_STRING*/ #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 // Process the specified X event
// //
static void processEvent(XEvent *event) static void processEvent(XEvent *event)
@ -1076,6 +1084,7 @@ static void processEvent(XEvent *event)
const double* values = re->raw_values; const double* values = re->raw_values;
double xpos = window->virtualCursorPosX; double xpos = window->virtualCursorPosX;
double ypos = window->virtualCursorPosY; double ypos = window->virtualCursorPosY;
updateEventTime(re->time);
if (XIMaskIsSet(re->valuators.mask, 0)) if (XIMaskIsSet(re->valuators.mask, 0))
{ {
@ -1121,6 +1130,7 @@ static void processEvent(XEvent *event)
const int key = translateKey(keycode); const int key = translateKey(keycode);
const int mods = translateState(event->xkey.state); const int mods = translateState(event->xkey.state);
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
updateEventTime(event->xkey.time);
if (window->x11.ic) if (window->x11.ic)
{ {
@ -1214,6 +1224,7 @@ static void processEvent(XEvent *event)
{ {
const int key = translateKey(keycode); const int key = translateKey(keycode);
const int mods = translateState(event->xkey.state); const int mods = translateState(event->xkey.state);
updateEventTime(event->xkey.time);
if (!_glfw.x11.xkb.detectable) if (!_glfw.x11.xkb.detectable)
{ {
@ -1254,6 +1265,7 @@ static void processEvent(XEvent *event)
case ButtonPress: case ButtonPress:
{ {
const int mods = translateState(event->xbutton.state); const int mods = translateState(event->xbutton.state);
updateEventTime(event->xbutton.time);
if (event->xbutton.button == Button1) if (event->xbutton.button == Button1)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods); _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods);
@ -1288,6 +1300,7 @@ static void processEvent(XEvent *event)
case ButtonRelease: case ButtonRelease:
{ {
const int mods = translateState(event->xbutton.state); const int mods = translateState(event->xbutton.state);
updateEventTime(event->xbutton.time);
if (event->xbutton.button == Button1) if (event->xbutton.button == Button1)
{ {
@ -1325,6 +1338,8 @@ static void processEvent(XEvent *event)
case EnterNotify: case EnterNotify:
{ {
updateEventTime(event->xcrossing.time);
// HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise // HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise
// ignore the defined cursor for hidden cursor mode // ignore the defined cursor for hidden cursor mode
if (window->cursorMode == GLFW_CURSOR_HIDDEN) if (window->cursorMode == GLFW_CURSOR_HIDDEN)
@ -1336,6 +1351,7 @@ static void processEvent(XEvent *event)
case LeaveNotify: case LeaveNotify:
{ {
updateEventTime(event->xcrossing.time);
_glfwInputCursorEnter(window, GLFW_FALSE); _glfwInputCursorEnter(window, GLFW_FALSE);
return; return;
} }
@ -1344,6 +1360,7 @@ static void processEvent(XEvent *event)
{ {
const int x = event->xmotion.x; const int x = event->xmotion.x;
const int y = event->xmotion.y; const int y = event->xmotion.y;
updateEventTime(event->xmotion.time);
if (x != window->x11.warpCursorPosX || y != window->x11.warpCursorPosY) if (x != window->x11.warpCursorPosX || y != window->x11.warpCursorPosY)
{ {
@ -2428,6 +2445,11 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
XFlush(_glfw.x11.display); XFlush(_glfw.x11.display);
} }
double _glfwPlatformGetEventTime(void)
{
return (double) _glfw.x11.eventTime / 1000.0;
}
void _glfwPlatformPollEvents(void) void _glfwPlatformPollEvents(void)
{ {
_GLFWwindow* window; _GLFWwindow* window;

View File

@ -336,33 +336,35 @@ static void window_maximize_callback(GLFWwindow* window, int maximized)
static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{ {
Slot* slot = glfwGetWindowUserPointer(window); Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Mouse button %i (%s) (with%s) was %s\n", printf("%08x to %i at %0.3f: Mouse button %i (%s) (with%s) was %s at %0.3f\n",
counter++, slot->number, glfwGetTime(), button, counter++, slot->number, glfwGetTime(), button,
get_button_name(button), get_button_name(button),
get_mods_name(mods), get_mods_name(mods),
get_action_name(action)); get_action_name(action),
glfwGetEventTime());
} }
static void cursor_position_callback(GLFWwindow* window, double x, double y) static void cursor_position_callback(GLFWwindow* window, double x, double y)
{ {
Slot* slot = glfwGetWindowUserPointer(window); Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Cursor position: %f %f\n", printf("%08x to %i at %0.3f: Cursor position: %f %f at %0.3f\n",
counter++, slot->number, glfwGetTime(), x, y); counter++, slot->number, glfwGetTime(), x, y, glfwGetEventTime());
} }
static void cursor_enter_callback(GLFWwindow* window, int entered) static void cursor_enter_callback(GLFWwindow* window, int entered)
{ {
Slot* slot = glfwGetWindowUserPointer(window); Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Cursor %s window\n", printf("%08x to %i at %0.3f: Cursor %s window at %0.3f\n",
counter++, slot->number, glfwGetTime(), counter++, slot->number, glfwGetTime(),
entered ? "entered" : "left"); entered ? "entered" : "left",
glfwGetEventTime());
} }
static void scroll_callback(GLFWwindow* window, double x, double y) static void scroll_callback(GLFWwindow* window, double x, double y)
{ {
Slot* slot = glfwGetWindowUserPointer(window); Slot* slot = glfwGetWindowUserPointer(window);
printf("%08x to %i at %0.3f: Scroll: %0.3f %0.3f\n", printf("%08x to %i at %0.3f: Scroll: %0.3f %0.3f at %0.3f\n",
counter++, slot->number, glfwGetTime(), x, y); counter++, slot->number, glfwGetTime(), x, y, glfwGetEventTime());
} }
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
@ -372,20 +374,22 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
if (name) if (name)
{ {
printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (%s) (with%s) was %s\n", printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (%s) (with%s) was %s at %0.3f\n",
counter++, slot->number, glfwGetTime(), key, scancode, counter++, slot->number, glfwGetTime(), key, scancode,
get_key_name(key), get_key_name(key),
name, name,
get_mods_name(mods), get_mods_name(mods),
get_action_name(action)); get_action_name(action),
glfwGetEventTime());
} }
else else
{ {
printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (with%s) was %s\n", printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (with%s) was %s at %0.3f\n",
counter++, slot->number, glfwGetTime(), key, scancode, counter++, slot->number, glfwGetTime(), key, scancode,
get_key_name(key), get_key_name(key),
get_mods_name(mods), get_mods_name(mods),
get_action_name(action)); get_action_name(action),
glfwGetEventTime());
} }
if (action != GLFW_PRESS) if (action != GLFW_PRESS)