From 994bedb024d872eba79729f39056bf1aee4bfb66 Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Thu, 11 May 2017 17:15:16 -0300 Subject: [PATCH 1/3] Get event time --- include/GLFW/glfw3.h | 22 ++++++++++++++++++++++ src/cocoa_window.m | 31 +++++++++++++++++++++++++++++++ src/internal.h | 1 + src/mir_platform.h | 1 + src/mir_window.c | 12 ++++++++++++ src/null_window.c | 5 +++++ src/win32_platform.h | 1 + src/win32_window.c | 10 ++++++++++ src/window.c | 10 ++++++++++ src/wl_init.c | 4 ++++ src/wl_platform.h | 2 ++ src/wl_window.c | 5 +++++ src/x11_platform.h | 2 ++ src/x11_window.c | 11 +++++++++++ tests/events.c | 24 ++++++++++++------------ 15 files changed, 129 insertions(+), 12 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 706fb9584..cc31a5a2b 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -3224,6 +3224,28 @@ GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window, */ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun); +/*! @brief Returns the time of the last input event. + * + * This function returns the time, in seconds, of the last event occurence. The + * only events queried are the input events button-press, button-release, + * key-press, key-release and cursor motion, and the proper place to call this + * function is in one of the input callbacks. + * + * @param[in] window The window to check for the input event. + * @return The value, in seconds, of the last input event occurence. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @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(GLFWwindow* window); + /*! @brief Processes all pending events. * * This function processes only those events that are already in the event diff --git a/src/cocoa_window.m b/src/cocoa_window.m index d2b207bb9..67789c07b 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -433,6 +433,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)mouseDown:(NSEvent *)event { + window->ns.lastEventTime = [event timestamp]; + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, @@ -441,11 +443,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)mouseDragged:(NSEvent *)event { + window->ns.lastEventTime = [event timestamp]; + [self mouseMoved:event]; } - (void)mouseUp:(NSEvent *)event { + window->ns.lastEventTime = [event timestamp]; + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE, @@ -454,6 +460,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)mouseMoved:(NSEvent *)event { + window->ns.lastEventTime = [event timestamp]; + if (window->cursorMode == GLFW_CURSOR_DISABLED) { const double dx = [event deltaX] - window->ns.cursorWarpDeltaX; @@ -477,6 +485,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)rightMouseDown:(NSEvent *)event { + window->ns.lastEventTime = [event timestamp]; + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, @@ -485,11 +495,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)rightMouseDragged:(NSEvent *)event { + window->ns.lastEventTime = [event timestamp]; + [self mouseMoved:event]; } - (void)rightMouseUp:(NSEvent *)event { + window->ns.lastEventTime = [event timestamp]; + _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE, @@ -498,6 +512,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)otherMouseDown:(NSEvent *)event { + window->ns.lastEventTime = [event timestamp]; + _glfwInputMouseClick(window, (int) [event buttonNumber], GLFW_PRESS, @@ -506,11 +522,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)otherMouseDragged:(NSEvent *)event { + window->ns.lastEventTime = [event timestamp]; + [self mouseMoved:event]; } - (void)otherMouseUp:(NSEvent *)event { + window->ns.lastEventTime = [event timestamp]; + _glfwInputMouseClick(window, (int) [event buttonNumber], GLFW_RELEASE, @@ -569,6 +589,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; const int key = translateKey([event keyCode]); const int mods = translateFlags([event modifierFlags]); + window->ns.lastEventTime = [event timestamp]; + _glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods); [self interpretKeyEvents:[NSArray arrayWithObject:event]]; @@ -600,6 +622,9 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; { const int key = translateKey([event keyCode]); const int mods = translateFlags([event modifierFlags]); + + window->ns.lastEventTime = [event timestamp]; + _glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods); } @@ -1433,6 +1458,12 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) [window->ns.object setLevel:NSNormalWindowLevel]; } +double _glfwPlatformGetEventTime(_GLFWwindow* window) +{ + /* Windows events are stored in seconds */ + return window->ns.lastEventTime; +} + void _glfwPlatformPollEvents(void) { for (;;) diff --git a/src/internal.h b/src/internal.h index c2b358133..8ada4247b 100644 --- a/src/internal.h +++ b/src/internal.h @@ -642,6 +642,7 @@ void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled); +double _glfwPlatformGetEventTime(_GLFWwindow* window); void _glfwPlatformPollEvents(void); void _glfwPlatformWaitEvents(void); void _glfwPlatformWaitEventsTimeout(double timeout); diff --git a/src/mir_platform.h b/src/mir_platform.h index d3fd10de0..aa17c8a70 100644 --- a/src/mir_platform.h +++ b/src/mir_platform.h @@ -87,6 +87,7 @@ typedef struct _GLFWwindowMir MirEGLNativeWindowType nativeWindow; _GLFWcursor* currentCursor; + int64_t lastEventTime; } _GLFWwindowMir; // Mir-specific per-monitor data diff --git a/src/mir_window.c b/src/mir_window.c index 566f571c1..09dd9226c 100644 --- a/src/mir_window.c +++ b/src/mir_window.c @@ -147,6 +147,8 @@ static void handleKeyEvent(const MirKeyboardEvent* key_event, _GLFWwindow* windo const long text = _glfwKeySym2Unicode(key_code); const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); + window->mir.lastEventTime = mir_input_event_get_event_time((MirInputEvent *) key_event); + _glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods); if (text != -1) @@ -164,6 +166,8 @@ static void handlePointerButton(_GLFWwindow* window, uint32_t newButtonStates = mir_pointer_event_buttons(pointer_event); int publicButton = GLFW_MOUSE_BUTTON_LEFT; + window->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 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 vscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll); + window->mir.lastEventTime = mir_input_event_get_event_time((MirEvent *) pointer_event); + if (window->cursorMode == GLFW_CURSOR_DISABLED) { if (_glfw.mir.disabledCursorWindow != window) @@ -632,6 +638,12 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } +double _glfwPlatformGetEventTime(_GLFWwindow* window) +{ + /* Mir events are stored in nanoseconds */ + return (double) window->mir.lastEventTime / 1000000000.0; +} + void _glfwPlatformPollEvents(void) { EventNode* node = NULL; diff --git a/src/null_window.c b/src/null_window.c index 137f80c8f..24b5a9270 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -204,6 +204,11 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window) return GLFW_FALSE; } +double _glfwPlatformGetEventTime(_GLFWwindow* window) +{ + return 0.0; +} + void _glfwPlatformPollEvents(void) { } diff --git a/src/win32_platform.h b/src/win32_platform.h index d51dee25c..6f92b45e2 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -241,6 +241,7 @@ typedef struct _GLFWwindowWin32 // The last received cursor position, regardless of source int lastCursorPosX, lastCursorPosY; + LONG lastEventTime; } _GLFWwindowWin32; // Win32-specific global data diff --git a/src/win32_window.c b/src/win32_window.c index 6d691e196..5a0eb1b06 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -552,6 +552,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_UNICHAR: { const GLFWbool plain = (uMsg != WM_SYSCHAR); + window->win32.lastEventTime = GetMessageTime(); if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR) { @@ -574,6 +575,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, const int scancode = (lParam >> 16) & 0x1ff; const int action = ((lParam >> 31) & 1) ? GLFW_RELEASE : GLFW_PRESS; const int mods = getKeyMods(); + window->win32.lastEventTime = GetMessageTime(); if (key == _GLFW_KEY_INVALID) break; @@ -608,6 +610,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_XBUTTONUP: { int i, button, action; + window->win32.lastEventTime = GetMessageTime(); if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) button = GLFW_MOUSE_BUTTON_LEFT; @@ -658,6 +661,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, { const int x = GET_X_LPARAM(lParam); const int y = GET_Y_LPARAM(lParam); + window->win32.lastEventTime = GetMessageTime(); // Disabled cursor motion input is provided by WM_INPUT if (window->cursorMode == GLFW_CURSOR_DISABLED) @@ -1451,6 +1455,12 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); } +double _glfwPlatformGetEventTime(_GLFWwindow* window) +{ + /* Windows events are stored in milliseconds */ + return (double) window->win32.lastEventTime / 1000.0; +} + void _glfwPlatformPollEvents(void) { MSG msg; diff --git a/src/window.c b/src/window.c index 546d233d8..f87da1ea1 100644 --- a/src/window.c +++ b/src/window.c @@ -961,6 +961,16 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle return cbfun; } +GLFWAPI double glfwGetEventTime(GLFWwindow* handle) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT_OR_RETURN(0.0); + + return _glfwPlatformGetEventTime(window); +} + GLFWAPI void glfwPollEvents(void) { _GLFW_REQUIRE_INIT(); diff --git a/src/wl_init.c b/src/wl_init.c index 0927a98a8..3b6a0dca7 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -83,6 +83,7 @@ static void pointerHandleMotion(void* data, if (!window) return; + window->wl.lastEventTime = time; if (window->cursorMode == GLFW_CURSOR_DISABLED) return; else @@ -109,6 +110,7 @@ static void pointerHandleButton(void* data, if (!window) return; + window->wl.lastEventTime = time; _glfw.wl.pointerSerial = serial; /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev @@ -136,6 +138,7 @@ static void pointerHandleAxis(void* data, if (!window) return; + window->wl.lastEventTime = time; /* Wayland scroll events are in pointer motion coordinate space (think * two finger scroll). The factor 10 is commonly used to convert to * "scroll step means 1.0. */ @@ -349,6 +352,7 @@ static void keyboardHandleKey(void* data, if (!window) return; + window->wl.lastEventTime = time; keyCode = toGLFWKeyCode(key); action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE; diff --git a/src/wl_platform.h b/src/wl_platform.h index bea32350b..8c609dd09 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -100,6 +100,8 @@ typedef struct _GLFWwindowWayland struct zwp_relative_pointer_v1* relativePointer; struct zwp_locked_pointer_v1* lockedPointer; } pointerLock; + + unsigned int lastEventTime; } _GLFWwindowWayland; // Wayland-specific global data diff --git a/src/wl_window.c b/src/wl_window.c index e9c817d50..f317a82f6 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -675,6 +675,11 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) "Wayland: Window attribute setting not implemented yet"); } +double _glfwPlatformGetEventTime(_GLFWwindow* window) +{ + return (double) window->wl.lastEventTime / 1000.0; +} + void _glfwPlatformPollEvents(void) { handleEvents(0); diff --git a/src/x11_platform.h b/src/x11_platform.h index a0037c88b..f9cea3a1a 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -144,6 +144,8 @@ typedef struct _GLFWwindowX11 // The time of the last KeyPress event Time lastKeyTime; + // The time of the last event + Time lastEventTime; } _GLFWwindowX11; // X11-specific global data diff --git a/src/x11_window.c b/src/x11_window.c index a683a821e..b53bc15dd 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -988,6 +988,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)); + window->x11.lastEventTime = event->xkey.time; if (window->x11.ic) { @@ -1081,6 +1082,7 @@ static void processEvent(XEvent *event) { const int key = translateKey(keycode); const int mods = translateState(event->xkey.state); + window->x11.lastEventTime = event->xkey.time; if (!_glfw.x11.xkb.detectable) { @@ -1121,6 +1123,7 @@ static void processEvent(XEvent *event) case ButtonPress: { const int mods = translateState(event->xbutton.state); + window->x11.lastEventTime = event->xbutton.time; if (event->xbutton.button == Button1) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods); @@ -1155,6 +1158,7 @@ static void processEvent(XEvent *event) case ButtonRelease: { const int mods = translateState(event->xbutton.state); + window->x11.lastEventTime = event->xbutton.time; if (event->xbutton.button == Button1) { @@ -1211,6 +1215,7 @@ static void processEvent(XEvent *event) { const int x = event->xmotion.x; const int y = event->xmotion.y; + window->x11.lastEventTime = event->xmotion.time; if (x != window->x11.warpCursorPosX || y != window->x11.warpCursorPosY) { @@ -2295,6 +2300,12 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) XFlush(_glfw.x11.display); } +double _glfwPlatformGetEventTime(_GLFWwindow* window) +{ + /* X11 events are stored in milliseconds */ + return (double) window->x11.lastEventTime / 1000.0; +} + void _glfwPlatformPollEvents(void) { _GLFWwindow* window; diff --git a/tests/events.c b/tests/events.c index 7b42e4fd3..77640aef5 100644 --- a/tests/events.c +++ b/tests/events.c @@ -269,8 +269,8 @@ static void error_callback(int error, const char* description) static void window_pos_callback(GLFWwindow* window, int x, int y) { Slot* slot = glfwGetWindowUserPointer(window); - printf("%08x to %i at %0.3f: Window position: %i %i\n", - counter++, slot->number, glfwGetTime(), x, y); + printf("%08x to %i at %0.3f (event time: %0.3f): Window position: %i %i\n", + counter++, slot->number, glfwGetTime(), glfwGetEventTime(window), x, y); } static void window_size_callback(GLFWwindow* window, int width, int height) @@ -336,8 +336,8 @@ static void window_maximize_callback(GLFWwindow* window, int maximized) static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) { Slot* slot = glfwGetWindowUserPointer(window); - printf("%08x to %i at %0.3f: Mouse button %i (%s) (with%s) was %s\n", - counter++, slot->number, glfwGetTime(), button, + printf("%08x to %i at %0.3f (event time: %0.3f): Mouse button %i (%s) (with%s) was %s\n", + counter++, slot->number, glfwGetTime(), glfwGetEventTime(window), button, get_button_name(button), get_mods_name(mods), get_action_name(action)); @@ -346,8 +346,8 @@ static void mouse_button_callback(GLFWwindow* window, int button, int action, in static void cursor_position_callback(GLFWwindow* window, double x, double y) { Slot* slot = glfwGetWindowUserPointer(window); - printf("%08x to %i at %0.3f: Cursor position: %f %f\n", - counter++, slot->number, glfwGetTime(), x, y); + printf("%08x to %i at %0.3f (event time: %0.3f): Cursor position: %f %f\n", + counter++, slot->number, glfwGetTime(), glfwGetEventTime(window), x, y); } static void cursor_enter_callback(GLFWwindow* window, int entered) @@ -372,8 +372,8 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action, if (name) { - printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (%s) (with%s) was %s\n", - counter++, slot->number, glfwGetTime(), key, scancode, + printf("%08x to %i at %0.3f (event time: %0.3f): Key 0x%04x Scancode 0x%04x (%s) (%s) (with%s) was %s\n", + counter++, slot->number, glfwGetTime(), glfwGetEventTime(window), key, scancode, get_key_name(key), name, get_mods_name(mods), @@ -381,8 +381,8 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action, } else { - printf("%08x to %i at %0.3f: Key 0x%04x Scancode 0x%04x (%s) (with%s) was %s\n", - counter++, slot->number, glfwGetTime(), key, scancode, + printf("%08x to %i at %0.3f (event time: %0.3f): Key 0x%04x Scancode 0x%04x (%s) (with%s) was %s\n", + counter++, slot->number, glfwGetTime(), glfwGetEventTime(window), key, scancode, get_key_name(key), get_mods_name(mods), get_action_name(action)); @@ -406,8 +406,8 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action, static void char_callback(GLFWwindow* window, unsigned int codepoint) { Slot* slot = glfwGetWindowUserPointer(window); - printf("%08x to %i at %0.3f: Character 0x%08x (%s) input\n", - counter++, slot->number, glfwGetTime(), codepoint, + printf("%08x to %i at %0.3f (event time: %0.3f): Character 0x%08x (%s) input\n", + counter++, slot->number, glfwGetTime(), glfwGetEventTime(window), codepoint, get_character_string(codepoint)); } From 41bca2c3cd2ca382d91165aaa102264a6c7e703c Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Thu, 11 May 2017 23:52:50 -0300 Subject: [PATCH 2/3] Fix missing event time field --- src/cocoa_platform.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 74db7fa59..3963345d0 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -96,6 +96,7 @@ typedef struct _GLFWwindowNS // This is kept to counteract Cocoa doing the same internally double cursorWarpDeltaX, cursorWarpDeltaY; + double lastEventTime; } _GLFWwindowNS; // Cocoa-specific global data From 33448e90c48e1cb72ed98354e1569d0c666098fb Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Fri, 12 May 2017 16:18:52 -0300 Subject: [PATCH 3/3] Store the event time in the global structure --- include/GLFW/glfw3.h | 3 +-- src/cocoa_platform.h | 4 +++- src/cocoa_window.m | 28 ++++++++++++++-------------- src/internal.h | 2 +- src/mir_platform.h | 4 +++- src/mir_window.c | 10 +++++----- src/null_window.c | 2 +- src/win32_platform.h | 4 +++- src/win32_window.c | 12 ++++++------ src/window.c | 7 ++----- src/wl_init.c | 8 ++++---- src/wl_platform.h | 4 +++- src/wl_window.c | 4 ++-- src/x11_platform.h | 5 +++-- src/x11_window.c | 14 +++++++------- tests/events.c | 12 ++++++------ 16 files changed, 64 insertions(+), 59 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index cc31a5a2b..0c4d5f081 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -3231,7 +3231,6 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window * key-press, key-release and cursor motion, and the proper place to call this * function is in one of the input callbacks. * - * @param[in] window The window to check for the input event. * @return The value, in seconds, of the last input event occurence. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. @@ -3244,7 +3243,7 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window * * @ingroup window */ -GLFWAPI double glfwGetEventTime(GLFWwindow* window); +GLFWAPI double glfwGetEventTime(void); /*! @brief Processes all pending events. * diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 3963345d0..75f45cac5 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -96,7 +96,6 @@ typedef struct _GLFWwindowNS // This is kept to counteract Cocoa doing the same internally double cursorWarpDeltaX, cursorWarpDeltaY; - double lastEventTime; } _GLFWwindowNS; // Cocoa-specific global data @@ -122,6 +121,9 @@ typedef struct _GLFWlibraryNS // The window whose disabled cursor mode is active _GLFWwindow* disabledCursorWindow; + // The time of the last event + double lastEventTime; + struct { CFBundleRef bundle; PFN_TISCopyCurrentKeyboardLayoutInputSource CopyCurrentKeyboardLayoutInputSource; diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 67789c07b..28c6dfbb4 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -433,7 +433,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)mouseDown:(NSEvent *)event { - window->ns.lastEventTime = [event timestamp]; + _glfw.ns.lastEventTime = [event timestamp]; _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, @@ -443,14 +443,14 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)mouseDragged:(NSEvent *)event { - window->ns.lastEventTime = [event timestamp]; + _glfw.ns.lastEventTime = [event timestamp]; [self mouseMoved:event]; } - (void)mouseUp:(NSEvent *)event { - window->ns.lastEventTime = [event timestamp]; + _glfw.ns.lastEventTime = [event timestamp]; _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, @@ -460,7 +460,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)mouseMoved:(NSEvent *)event { - window->ns.lastEventTime = [event timestamp]; + _glfw.ns.lastEventTime = [event timestamp]; if (window->cursorMode == GLFW_CURSOR_DISABLED) { @@ -485,7 +485,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)rightMouseDown:(NSEvent *)event { - window->ns.lastEventTime = [event timestamp]; + _glfw.ns.lastEventTime = [event timestamp]; _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, @@ -495,14 +495,14 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)rightMouseDragged:(NSEvent *)event { - window->ns.lastEventTime = [event timestamp]; + _glfw.ns.lastEventTime = [event timestamp]; [self mouseMoved:event]; } - (void)rightMouseUp:(NSEvent *)event { - window->ns.lastEventTime = [event timestamp]; + _glfw.ns.lastEventTime = [event timestamp]; _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, @@ -512,7 +512,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)otherMouseDown:(NSEvent *)event { - window->ns.lastEventTime = [event timestamp]; + _glfw.ns.lastEventTime = [event timestamp]; _glfwInputMouseClick(window, (int) [event buttonNumber], @@ -522,14 +522,14 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)otherMouseDragged:(NSEvent *)event { - window->ns.lastEventTime = [event timestamp]; + _glfw.ns.lastEventTime = [event timestamp]; [self mouseMoved:event]; } - (void)otherMouseUp:(NSEvent *)event { - window->ns.lastEventTime = [event timestamp]; + _glfw.ns.lastEventTime = [event timestamp]; _glfwInputMouseClick(window, (int) [event buttonNumber], @@ -589,7 +589,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; const int key = translateKey([event keyCode]); const int mods = translateFlags([event modifierFlags]); - window->ns.lastEventTime = [event timestamp]; + _glfw.ns.lastEventTime = [event timestamp]; _glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods); @@ -623,7 +623,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; const int key = translateKey([event keyCode]); const int mods = translateFlags([event modifierFlags]); - window->ns.lastEventTime = [event timestamp]; + _glfw.ns.lastEventTime = [event timestamp]; _glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods); } @@ -1458,10 +1458,10 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) [window->ns.object setLevel:NSNormalWindowLevel]; } -double _glfwPlatformGetEventTime(_GLFWwindow* window) +double _glfwPlatformGetEventTime(void) { /* Windows events are stored in seconds */ - return window->ns.lastEventTime; + return _glfw.ns.lastEventTime; } void _glfwPlatformPollEvents(void) diff --git a/src/internal.h b/src/internal.h index 8ada4247b..461b196df 100644 --- a/src/internal.h +++ b/src/internal.h @@ -642,7 +642,7 @@ void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled); -double _glfwPlatformGetEventTime(_GLFWwindow* window); +double _glfwPlatformGetEventTime(void); void _glfwPlatformPollEvents(void); void _glfwPlatformWaitEvents(void); void _glfwPlatformWaitEventsTimeout(double timeout); diff --git a/src/mir_platform.h b/src/mir_platform.h index aa17c8a70..a4b7e591f 100644 --- a/src/mir_platform.h +++ b/src/mir_platform.h @@ -87,7 +87,6 @@ typedef struct _GLFWwindowMir MirEGLNativeWindowType nativeWindow; _GLFWcursor* currentCursor; - int64_t lastEventTime; } _GLFWwindowMir; // Mir-specific per-monitor data @@ -118,6 +117,9 @@ typedef struct _GLFWlibraryMir // The window whose disabled cursor mode is active _GLFWwindow* disabledCursorWindow; + // The time of the last event + int64_t lastEventTime; + } _GLFWlibraryMir; // Mir-specific per-cursor data diff --git a/src/mir_window.c b/src/mir_window.c index 09dd9226c..395e5e271 100644 --- a/src/mir_window.c +++ b/src/mir_window.c @@ -147,7 +147,7 @@ static void handleKeyEvent(const MirKeyboardEvent* key_event, _GLFWwindow* windo const long text = _glfwKeySym2Unicode(key_code); const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); - window->mir.lastEventTime = mir_input_event_get_event_time((MirInputEvent *) key_event); + _glfw.mir.lastEventTime = mir_input_event_get_event_time((MirInputEvent *) key_event); _glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods); @@ -166,7 +166,7 @@ static void handlePointerButton(_GLFWwindow* window, uint32_t newButtonStates = mir_pointer_event_buttons(pointer_event); int publicButton = GLFW_MOUSE_BUTTON_LEFT; - window->mir.lastEventTime = mir_input_event_get_event_time((MirEvent *) pointer_event); + _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 button = newButtonStates ^ oldButtonStates; @@ -205,7 +205,7 @@ static void handlePointerMotion(_GLFWwindow* window, 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); - window->mir.lastEventTime = mir_input_event_get_event_time((MirEvent *) pointer_event); + _glfw.mir.lastEventTime = mir_input_event_get_event_time((MirEvent *) pointer_event); if (window->cursorMode == GLFW_CURSOR_DISABLED) { @@ -638,10 +638,10 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } -double _glfwPlatformGetEventTime(_GLFWwindow* window) +double _glfwPlatformGetEventTime(void) { /* Mir events are stored in nanoseconds */ - return (double) window->mir.lastEventTime / 1000000000.0; + return (double) _glfw.mir.lastEventTime / 1000000000.0; } void _glfwPlatformPollEvents(void) diff --git a/src/null_window.c b/src/null_window.c index 24b5a9270..98990d310 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -204,7 +204,7 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window) return GLFW_FALSE; } -double _glfwPlatformGetEventTime(_GLFWwindow* window) +double _glfwPlatformGetEventTime(void) { return 0.0; } diff --git a/src/win32_platform.h b/src/win32_platform.h index 6f92b45e2..a3c0c783f 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -241,7 +241,6 @@ typedef struct _GLFWwindowWin32 // The last received cursor position, regardless of source int lastCursorPosX, lastCursorPosY; - LONG lastEventTime; } _GLFWwindowWin32; // Win32-specific global data @@ -262,6 +261,9 @@ typedef struct _GLFWlibraryWin32 RAWINPUT* rawInput; int rawInputSize; + // The time of the last event + LONG lastEventTime; + struct { HINSTANCE instance; PFN_timeGetTime GetTime; diff --git a/src/win32_window.c b/src/win32_window.c index 5a0eb1b06..115342cff 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -552,7 +552,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_UNICHAR: { const GLFWbool plain = (uMsg != WM_SYSCHAR); - window->win32.lastEventTime = GetMessageTime(); + _glfw.win32.lastEventTime = GetMessageTime(); if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR) { @@ -575,7 +575,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, const int scancode = (lParam >> 16) & 0x1ff; const int action = ((lParam >> 31) & 1) ? GLFW_RELEASE : GLFW_PRESS; const int mods = getKeyMods(); - window->win32.lastEventTime = GetMessageTime(); + _glfw.win32.lastEventTime = GetMessageTime(); if (key == _GLFW_KEY_INVALID) break; @@ -610,7 +610,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_XBUTTONUP: { int i, button, action; - window->win32.lastEventTime = GetMessageTime(); + _glfw.win32.lastEventTime = GetMessageTime(); if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP) button = GLFW_MOUSE_BUTTON_LEFT; @@ -661,7 +661,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, { const int x = GET_X_LPARAM(lParam); const int y = GET_Y_LPARAM(lParam); - window->win32.lastEventTime = GetMessageTime(); + _glfw.win32.lastEventTime = GetMessageTime(); // Disabled cursor motion input is provided by WM_INPUT if (window->cursorMode == GLFW_CURSOR_DISABLED) @@ -1455,10 +1455,10 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); } -double _glfwPlatformGetEventTime(_GLFWwindow* window) +double _glfwPlatformGetEventTime(void) { /* Windows events are stored in milliseconds */ - return (double) window->win32.lastEventTime / 1000.0; + return (double) _glfw.win32.lastEventTime / 1000.0; } void _glfwPlatformPollEvents(void) diff --git a/src/window.c b/src/window.c index f87da1ea1..a7f7d5661 100644 --- a/src/window.c +++ b/src/window.c @@ -961,14 +961,11 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle return cbfun; } -GLFWAPI double glfwGetEventTime(GLFWwindow* handle) +GLFWAPI double glfwGetEventTime(void) { - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(0.0); - return _glfwPlatformGetEventTime(window); + return _glfwPlatformGetEventTime(); } GLFWAPI void glfwPollEvents(void) diff --git a/src/wl_init.c b/src/wl_init.c index 3b6a0dca7..c7324eaad 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -83,7 +83,7 @@ static void pointerHandleMotion(void* data, if (!window) return; - window->wl.lastEventTime = time; + _glfw.wl.lastEventTime = time; if (window->cursorMode == GLFW_CURSOR_DISABLED) return; else @@ -110,7 +110,7 @@ static void pointerHandleButton(void* data, if (!window) return; - window->wl.lastEventTime = time; + _glfw.wl.lastEventTime = time; _glfw.wl.pointerSerial = serial; /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev @@ -138,7 +138,7 @@ static void pointerHandleAxis(void* data, if (!window) return; - window->wl.lastEventTime = time; + _glfw.wl.lastEventTime = time; /* Wayland scroll events are in pointer motion coordinate space (think * two finger scroll). The factor 10 is commonly used to convert to * "scroll step means 1.0. */ @@ -352,7 +352,7 @@ static void keyboardHandleKey(void* data, if (!window) return; - window->wl.lastEventTime = time; + _glfw.wl.lastEventTime = time; keyCode = toGLFWKeyCode(key); action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE; diff --git a/src/wl_platform.h b/src/wl_platform.h index 8c609dd09..d73dbcceb 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -101,7 +101,6 @@ typedef struct _GLFWwindowWayland struct zwp_locked_pointer_v1* lockedPointer; } pointerLock; - unsigned int lastEventTime; } _GLFWwindowWayland; // Wayland-specific global data @@ -143,6 +142,9 @@ typedef struct _GLFWlibraryWayland _GLFWwindow* pointerFocus; _GLFWwindow* keyboardFocus; + // The time of the last event + unsigned int lastEventTime; + } _GLFWlibraryWayland; // Wayland-specific per-monitor data diff --git a/src/wl_window.c b/src/wl_window.c index f317a82f6..f2f90e652 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -675,9 +675,9 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) "Wayland: Window attribute setting not implemented yet"); } -double _glfwPlatformGetEventTime(_GLFWwindow* window) +double _glfwPlatformGetEventTime(void) { - return (double) window->wl.lastEventTime / 1000.0; + return (double) _glfw.wl.lastEventTime / 1000.0; } void _glfwPlatformPollEvents(void) diff --git a/src/x11_platform.h b/src/x11_platform.h index f9cea3a1a..1ad74fba6 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -144,8 +144,6 @@ typedef struct _GLFWwindowX11 // The time of the last KeyPress event Time lastKeyTime; - // The time of the last event - Time lastEventTime; } _GLFWwindowX11; // X11-specific global data @@ -179,6 +177,9 @@ typedef struct _GLFWlibraryX11 // The window whose disabled cursor mode is active _GLFWwindow* disabledCursorWindow; + // The time of the last event + Time lastEventTime; + // Window manager atoms Atom WM_PROTOCOLS; Atom WM_STATE; diff --git a/src/x11_window.c b/src/x11_window.c index b53bc15dd..97b7a8fdf 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -988,7 +988,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)); - window->x11.lastEventTime = event->xkey.time; + _glfw.x11.lastEventTime = event->xkey.time; if (window->x11.ic) { @@ -1082,7 +1082,7 @@ static void processEvent(XEvent *event) { const int key = translateKey(keycode); const int mods = translateState(event->xkey.state); - window->x11.lastEventTime = event->xkey.time; + _glfw.x11.lastEventTime = event->xkey.time; if (!_glfw.x11.xkb.detectable) { @@ -1123,7 +1123,7 @@ static void processEvent(XEvent *event) case ButtonPress: { const int mods = translateState(event->xbutton.state); - window->x11.lastEventTime = event->xbutton.time; + _glfw.x11.lastEventTime = event->xbutton.time; if (event->xbutton.button == Button1) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods); @@ -1158,7 +1158,7 @@ static void processEvent(XEvent *event) case ButtonRelease: { const int mods = translateState(event->xbutton.state); - window->x11.lastEventTime = event->xbutton.time; + _glfw.x11.lastEventTime = event->xbutton.time; if (event->xbutton.button == Button1) { @@ -1215,7 +1215,7 @@ static void processEvent(XEvent *event) { const int x = event->xmotion.x; const int y = event->xmotion.y; - window->x11.lastEventTime = event->xmotion.time; + _glfw.x11.lastEventTime = event->xmotion.time; if (x != window->x11.warpCursorPosX || y != window->x11.warpCursorPosY) { @@ -2300,10 +2300,10 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) XFlush(_glfw.x11.display); } -double _glfwPlatformGetEventTime(_GLFWwindow* window) +double _glfwPlatformGetEventTime(void) { /* X11 events are stored in milliseconds */ - return (double) window->x11.lastEventTime / 1000.0; + return (double) _glfw.x11.lastEventTime / 1000.0; } void _glfwPlatformPollEvents(void) diff --git a/tests/events.c b/tests/events.c index 77640aef5..7d3ce245f 100644 --- a/tests/events.c +++ b/tests/events.c @@ -270,7 +270,7 @@ static void window_pos_callback(GLFWwindow* window, int x, int y) { Slot* slot = glfwGetWindowUserPointer(window); printf("%08x to %i at %0.3f (event time: %0.3f): Window position: %i %i\n", - counter++, slot->number, glfwGetTime(), glfwGetEventTime(window), x, y); + counter++, slot->number, glfwGetTime(), glfwGetEventTime(), x, y); } static void window_size_callback(GLFWwindow* window, int width, int height) @@ -337,7 +337,7 @@ static void mouse_button_callback(GLFWwindow* window, int button, int action, in { Slot* slot = glfwGetWindowUserPointer(window); printf("%08x to %i at %0.3f (event time: %0.3f): Mouse button %i (%s) (with%s) was %s\n", - counter++, slot->number, glfwGetTime(), glfwGetEventTime(window), button, + counter++, slot->number, glfwGetTime(), glfwGetEventTime(), button, get_button_name(button), get_mods_name(mods), get_action_name(action)); @@ -347,7 +347,7 @@ static void cursor_position_callback(GLFWwindow* window, double x, double y) { Slot* slot = glfwGetWindowUserPointer(window); printf("%08x to %i at %0.3f (event time: %0.3f): Cursor position: %f %f\n", - counter++, slot->number, glfwGetTime(), glfwGetEventTime(window), x, y); + counter++, slot->number, glfwGetTime(), glfwGetEventTime(), x, y); } static void cursor_enter_callback(GLFWwindow* window, int entered) @@ -373,7 +373,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action, if (name) { printf("%08x to %i at %0.3f (event time: %0.3f): Key 0x%04x Scancode 0x%04x (%s) (%s) (with%s) was %s\n", - counter++, slot->number, glfwGetTime(), glfwGetEventTime(window), key, scancode, + counter++, slot->number, glfwGetTime(), glfwGetEventTime(), key, scancode, get_key_name(key), name, get_mods_name(mods), @@ -382,7 +382,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action, else { printf("%08x to %i at %0.3f (event time: %0.3f): Key 0x%04x Scancode 0x%04x (%s) (with%s) was %s\n", - counter++, slot->number, glfwGetTime(), glfwGetEventTime(window), key, scancode, + counter++, slot->number, glfwGetTime(), glfwGetEventTime(), key, scancode, get_key_name(key), get_mods_name(mods), get_action_name(action)); @@ -407,7 +407,7 @@ static void char_callback(GLFWwindow* window, unsigned int codepoint) { Slot* slot = glfwGetWindowUserPointer(window); printf("%08x to %i at %0.3f (event time: %0.3f): Character 0x%08x (%s) input\n", - counter++, slot->number, glfwGetTime(), glfwGetEventTime(window), codepoint, + counter++, slot->number, glfwGetTime(), glfwGetEventTime(), codepoint, get_character_string(codepoint)); }