From cf79f0625717db86dd86afae2c169d87ba1eb650 Mon Sep 17 00:00:00 2001 From: Max Risuhin Date: Mon, 11 Feb 2019 19:14:03 +0200 Subject: [PATCH 1/7] Win32: Fix standard cursors not being DPI aware Closes #1431. --- src/win32_platform.h | 3 +++ src/win32_window.c | 17 +++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/win32_platform.h b/src/win32_platform.h index 712de7f1e..0c71ae490 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -61,6 +61,9 @@ // GLFW uses DirectInput8 interfaces #define DIRECTINPUT_VERSION 0x0800 +// Enable standard cursors images defines +#define OEMRESOURCE + #include #include #include diff --git a/src/win32_window.c b/src/win32_window.c index afcdc9ee2..a73aae8de 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -1999,24 +1999,25 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor, int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) { - LPCWSTR name = NULL; + int id = 0; if (shape == GLFW_ARROW_CURSOR) - name = IDC_ARROW; + id = OCR_NORMAL; else if (shape == GLFW_IBEAM_CURSOR) - name = IDC_IBEAM; + id = OCR_IBEAM; else if (shape == GLFW_CROSSHAIR_CURSOR) - name = IDC_CROSS; + id = OCR_CROSS; else if (shape == GLFW_HAND_CURSOR) - name = IDC_HAND; + id = OCR_HAND; else if (shape == GLFW_HRESIZE_CURSOR) - name = IDC_SIZEWE; + id = OCR_SIZEWE; else if (shape == GLFW_VRESIZE_CURSOR) - name = IDC_SIZENS; + id = OCR_SIZENS; else return GLFW_FALSE; - cursor->win32.handle = CopyCursor(LoadCursorW(NULL, name)); + cursor->win32.handle = + (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(id), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); if (!cursor->win32.handle) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, From e2fa82ffbbf2c14e07a24f76c17e047847c26dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 13 Feb 2019 23:21:05 +0100 Subject: [PATCH 2/7] Cleanup Related to #1431. --- README.md | 2 ++ src/win32_platform.h | 2 +- src/win32_window.c | 5 +++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5ea88f985..f847b020f 100644 --- a/README.md +++ b/README.md @@ -231,6 +231,7 @@ information on what to include when reporting a bug. (#1315,#1316) - [Win32] Bugfix: A title bar would be drawn over undecorated windows in some circumstances (#1383) +- [Win32] Bugfix: Standard cursors were not per-monitor DPI aware (#1431) - [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125) - [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading - [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X @@ -439,6 +440,7 @@ skills. - przemekmirek - Philip Rideout - Eddie Ringle + - Max Risuhin - Jorge Rodriguez - Ed Ropple - Aleksey Rybalkin diff --git a/src/win32_platform.h b/src/win32_platform.h index 0c71ae490..f08fee633 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -61,7 +61,7 @@ // GLFW uses DirectInput8 interfaces #define DIRECTINPUT_VERSION 0x0800 -// Enable standard cursors images defines +// GLFW uses OEM cursor resources #define OEMRESOURCE #include diff --git a/src/win32_window.c b/src/win32_window.c index a73aae8de..77338468f 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -2016,8 +2016,9 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) else return GLFW_FALSE; - cursor->win32.handle = - (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(id), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + cursor->win32.handle = LoadImageW(NULL, + MAKEINTRESOURCEW(id), IMAGE_CURSOR, 0, 0, + LR_DEFAULTSIZE | LR_SHARED); if (!cursor->win32.handle) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, From 2a27eb95e42ddc880fa1fdb18872d2c892bd36c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 13 Feb 2019 21:09:18 +0100 Subject: [PATCH 3/7] X11: Fix system cursor used for GLFW_HAND_CURSOR Fixes #1432. --- src/x11_window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x11_window.c b/src/x11_window.c index a83340332..8e587546e 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -2810,7 +2810,7 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) else if (shape == GLFW_CROSSHAIR_CURSOR) native = XC_crosshair; else if (shape == GLFW_HAND_CURSOR) - native = XC_hand1; + native = XC_hand2; else if (shape == GLFW_HRESIZE_CURSOR) native = XC_sb_h_double_arrow; else if (shape == GLFW_VRESIZE_CURSOR) From 2e70950c0f6093911828c7287fa7f35ac540de52 Mon Sep 17 00:00:00 2001 From: schraf Date: Sat, 29 Dec 2018 17:06:21 -0500 Subject: [PATCH 4/7] Fix quoting of CMAKE_C_COMPILER_ID I was getting an error in this cmake file when using 3.10.2 on linux. Here was the error message I was getting: [cmake] CMake Error at external/glfw/src/CMakeLists.txt:82 (if): [cmake] if given arguments: [cmake] [cmake] "STREQUAL" "GNU" "OR" "STREQUAL" "Clang" [cmake] [cmake] Unknown arguments specified Adding the quotes around the cmake variables seems to do the trick. That was also done with the STREQUAL condition earlier on line 66. Closes #1411. --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6bf4ff0d7..31f0556d9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -79,7 +79,7 @@ endif() # Make GCC and Clang warn about declarations that VS 2010 and 2012 won't accept # for all source files that VS will build -if (${CMAKE_C_COMPILER_ID} STREQUAL GNU OR ${CMAKE_C_COMPILER_ID} STREQUAL Clang) +if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") if (WIN32) set(windows_SOURCES ${glfw_SOURCES}) else() From 1d95acdf565f65894f38b8742afde8dbbb80baef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 13 Feb 2019 00:20:44 +0100 Subject: [PATCH 5/7] Cocoa: Fix detection of Clang --- src/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 31f0556d9..0913579b6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -79,7 +79,10 @@ endif() # Make GCC and Clang warn about declarations that VS 2010 and 2012 won't accept # for all source files that VS will build -if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") +if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR + "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR + "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") + if (WIN32) set(windows_SOURCES ${glfw_SOURCES}) else() @@ -115,6 +118,7 @@ target_compile_definitions(glfw PRIVATE # Enable a reasonable set of warnings (no, -Wextra is not reasonable) target_compile_options(glfw PRIVATE + "$<$:-Wall>" "$<$:-Wall>" "$<$:-Wall>") From d16134a108a2ac25ec60d0ddf5bf462984afa47e Mon Sep 17 00:00:00 2001 From: Nathan Poirier Date: Fri, 14 Dec 2018 03:08:25 +0100 Subject: [PATCH 6/7] Add GLFW_RAW_INPUT and glfwRawInputSupported This adds runtime per-window control of whether accelerated or raw mouse motion is provided when the cursor is disabled. Closes #1401. --- README.md | 2 ++ include/GLFW/glfw3.h | 48 ++++++++++++++++++++++++++++++++++++++++---- src/cocoa_window.m | 10 +++++++++ src/input.c | 11 +++++++++- src/internal.h | 3 +++ src/null_window.c | 10 +++++++++ src/win32_window.c | 37 +++++++++++++++++++++++++++++----- src/window.c | 2 +- src/wl_window.c | 10 +++++++++ src/x11_window.c | 25 ++++++++++++++++++++--- tests/cursor.c | 13 ++++++++++++ 11 files changed, 157 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index f847b020f..5f7045ab0 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,7 @@ information on what to include when reporting a bug. - Added `GLFW_OSMESA_CONTEXT_API` for creating OpenGL contexts with [OSMesa](https://www.mesa3d.org/osmesa.html) (#281) - Added `GenerateMappings.cmake` script for updating gamepad mappings +- Added `GLFW_RAW_INPUT` input mode and `glfwRawInputSupported` function (#1401) - Made `glfwCreateWindowSurface` emit an error when the window has a context (#1194,#1205) - Deprecated window parameter of clipboard string functions @@ -489,6 +490,7 @@ skills. - Santi Zupancic - Jonas Ådahl - Lasse Öörni + - Nathan Poirier - All the unmentioned and anonymous contributors in the GLFW community, for bug reports, patches, feedback, testing and encouragement diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 35a781c93..9556cede6 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1002,6 +1002,7 @@ extern "C" { #define GLFW_STICKY_KEYS 0x00033002 #define GLFW_STICKY_MOUSE_BUTTONS 0x00033003 #define GLFW_LOCK_KEY_MODS 0x00033004 +#define GLFW_RAW_INPUT 0x00033005 #define GLFW_CURSOR_NORMAL 0x00034001 #define GLFW_CURSOR_HIDDEN 0x00034002 @@ -3810,11 +3811,12 @@ GLFWAPI void glfwPostEmptyEvent(void); * * This function returns the value of an input option for the specified window. * The mode must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS, - * @ref GLFW_STICKY_MOUSE_BUTTONS or @ref GLFW_LOCK_KEY_MODS. + * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or + * @ref GLFW_RAW_INPUT. * * @param[in] window The window to query. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`, - * `GLFW_STICKY_MOUSE_BUTTONS` or `GLFW_LOCK_KEY_MODS`. + * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or `GLFW_RAW_INPUT`. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * GLFW_INVALID_ENUM. @@ -3833,7 +3835,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode); * * This function sets an input mode option for the specified window. The mode * must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS, - * @ref GLFW_STICKY_MOUSE_BUTTONS or @ref GLFW_LOCK_KEY_MODS. + * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or + * @ref GLFW_RAW_INPUT. * * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor * modes: @@ -3865,9 +3868,14 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode); * GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on, * and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on. * + * If the mode is `GLFW_RAW_INPUT`, the value must be either `GLFW_TRUE` to + * enable the use of raw input, or `GLFW_FALSE` to disable it. If enabled and + * supported by the machine, the program will retrieve high-definition mouse + * movement when cursor is grabbed. + * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`, - * `GLFW_STICKY_MOUSE_BUTTONS` or `GLFW_LOCK_KEY_MODS`. + * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or `GLFW_RAW_INPUT`. * @param[in] value The new value of the specified input mode. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref @@ -3883,6 +3891,38 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode); */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns whether the raw input is supported. + * + * This function returns whether the raw input is supported by the current + * machine. + * + * Raw input allow to retrieve high-definition movement from mouse. + * Input from a high-definition mouse is much more precise than that from a + * standard mouse. But often, they cannot be obtained through standard + * platforms API which transform mouse movement using their own improvements + * (like pointer acceleration). Platform's improvements are ideal for pointer + * control but it is not so good for moving a first-person camera. For this + * reason when the cursor of a window is grabbed by setting @ref GLFW_CURSOR + * to @ref GLFW_CURSOR_DISABLED, raw input is used. + * + * The use of raw input can be disabled using @ref glfwSetInputMode with + * @ref GLFW_RAW_INPUT mode. + * + * @return `GLFW_TRUE` if high-definition mouse movement is supported, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref glfwSetInputMode + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI int glfwRawInputSupported(void); + /*! @brief Returns the layout-specific name of the specified printable key. * * This function returns the name of the specified printable key, encoded as diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 156b97b16..e3e20de79 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1297,6 +1297,16 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) [window->ns.object setAlphaValue:opacity]; } +void _glfwPlatformSetRawInput(_GLFWwindow *window, GLFWbool enabled) +{ + window->useRawInput = enabled; +} + +GLFWbool _glfwPlatformRawInputSupported(void) +{ + return GLFW_FALSE; +} + void _glfwPlatformPollEvents(void) { for (;;) diff --git a/src/input.c b/src/input.c index 33ed06045..ef14fad53 100644 --- a/src/input.c +++ b/src/input.c @@ -484,6 +484,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode) return window->stickyMouseButtons; case GLFW_LOCK_KEY_MODS: return window->lockKeyMods; + case GLFW_RAW_INPUT: + return window->useRawInput; } _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); @@ -561,10 +563,18 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) } else if (mode == GLFW_LOCK_KEY_MODS) window->lockKeyMods = value ? GLFW_TRUE : GLFW_FALSE; + else if (mode == GLFW_RAW_INPUT) + _glfwPlatformSetRawInput(window, value ? GLFW_TRUE : GLFW_FALSE); else _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); } +GLFWAPI int glfwRawInputSupported(void) +{ + _GLFW_REQUIRE_INIT_OR_RETURN(0); + return _glfwPlatformRawInputSupported(); +} + GLFWAPI const char* glfwGetKeyName(int key, int scancode) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); @@ -1313,4 +1323,3 @@ GLFWAPI uint64_t glfwGetTimerFrequency(void) _GLFW_REQUIRE_INIT_OR_RETURN(0); return _glfwPlatformGetTimerFrequency(); } - diff --git a/src/internal.h b/src/internal.h index e8df80a07..65d77cc17 100644 --- a/src/internal.h +++ b/src/internal.h @@ -390,6 +390,7 @@ struct _GLFWwindow char keys[GLFW_KEY_LAST + 1]; // Virtual cursor position when cursor is disabled double virtualCursorPosX, virtualCursorPosY; + GLFWbool useRawInput; _GLFWcontext context; @@ -596,6 +597,8 @@ const char* _glfwPlatformGetVersionString(void); void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos); void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos); void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode); +void _glfwPlatformSetRawInput(_GLFWwindow *window, GLFWbool enabled); +GLFWbool _glfwPlatformRawInputSupported(void); int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape); diff --git a/src/null_window.c b/src/null_window.c index 6a54cfe56..cb976310e 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -196,6 +196,16 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) { } +void _glfwPlatformSetRawInput(_GLFWwindow *window, GLFWbool enabled) +{ + window->useRawInput = enabled; +} + +GLFWbool _glfwPlatformRawInputSupported(void) +{ + return GLFW_FALSE; +} + void _glfwPlatformShowWindow(_GLFWwindow* window) { } diff --git a/src/win32_window.c b/src/win32_window.c index 77338468f..ec010f7ec 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -281,7 +281,7 @@ static void disableCursor(_GLFWwindow* window) _glfwCenterCursorInContentArea(window); updateClipRect(window); - if (!RegisterRawInputDevices(&rid, 1, sizeof(rid))) + if (window->useRawInput && !RegisterRawInputDevices(&rid, 1, sizeof(rid))) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to register raw input device"); @@ -301,7 +301,7 @@ static void enableCursor(_GLFWwindow* window) _glfw.win32.restoreCursorPosY); updateCursorImage(window); - if (!RegisterRawInputDevices(&rid, 1, sizeof(rid))) + if (window->useRawInput && !RegisterRawInputDevices(&rid, 1, sizeof(rid))) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to remove raw input device"); @@ -816,9 +816,18 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, // Disabled cursor motion input is provided by WM_INPUT if (window->cursorMode == GLFW_CURSOR_DISABLED) - break; + { + if (_glfw.win32.disabledCursorWindow != window || window->useRawInput) + break; - _glfwInputCursorPos(window, x, y); + const int dx = x - window->win32.lastCursorPosX; + const int dy = y - window->win32.lastCursorPosY; + _glfwInputCursorPos(window, + window->virtualCursorPosX + dx, + window->virtualCursorPosY + dy); + } + else + _glfwInputCursorPos(window, x, y); window->win32.lastCursorPosX = x; window->win32.lastCursorPosY = y; @@ -847,7 +856,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, int dx, dy; // Only process input when disabled cursor mode is applied - if (_glfw.win32.disabledCursorWindow != window) + if (_glfw.win32.disabledCursorWindow != window || !window->useRawInput) break; GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); @@ -1845,6 +1854,24 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) } } +void _glfwPlatformSetRawInput(_GLFWwindow *window, GLFWbool enabled) +{ + if (window->useRawInput != enabled) + { + int update = (_glfw.win32.disabledCursorWindow == window); + if (update) + enableCursor(window); + window->useRawInput = enabled; + if (update) + disableCursor(window); + } +} + +GLFWbool _glfwPlatformRawInputSupported(void) +{ + return GLFW_TRUE; +} + void _glfwPlatformPollEvents(void) { MSG msg; diff --git a/src/window.c b/src/window.c index 24e60054d..f8cb030e3 100644 --- a/src/window.c +++ b/src/window.c @@ -202,6 +202,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, window->floating = wndconfig.floating; window->focusOnShow = wndconfig.focusOnShow; window->cursorMode = GLFW_CURSOR_NORMAL; + window->useRawInput = GLFW_TRUE; window->minwidth = GLFW_DONT_CARE; window->minheight = GLFW_DONT_CARE; @@ -1097,4 +1098,3 @@ GLFWAPI void glfwPostEmptyEvent(void) _GLFW_REQUIRE_INIT(); _glfwPlatformPostEmptyEvent(); } - diff --git a/src/wl_window.c b/src/wl_window.c index 98a646590..bd6ff880a 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1304,6 +1304,16 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) { } +void _glfwPlatformSetRawInput(_GLFWwindow *window, GLFWbool enabled) +{ + window->useRawInput = enabled; +} + +GLFWbool _glfwPlatformRawInputSupported(void) +{ + return GLFW_FALSE; +} + void _glfwPlatformPollEvents(void) { handleEvents(0); diff --git a/src/x11_window.c b/src/x11_window.c index 8e587546e..9e25fda32 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -526,7 +526,7 @@ static void updateCursorImage(_GLFWwindow* window) // static void disableCursor(_GLFWwindow* window) { - if (_glfw.x11.xi.available) + if (_glfw.x11.xi.available && window->useRawInput) { XIEventMask em; unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 }; @@ -557,7 +557,7 @@ static void disableCursor(_GLFWwindow* window) // static void enableCursor(_GLFWwindow* window) { - if (_glfw.x11.xi.available) + if (_glfw.x11.xi.available && window->useRawInput) { XIEventMask em; unsigned char mask[] = { 0 }; @@ -1183,6 +1183,7 @@ static void processEvent(XEvent *event) _GLFWwindow* window = _glfw.x11.disabledCursorWindow; if (window && + window->useRawInput && event->xcookie.extension == _glfw.x11.xi.majorOpcode && XGetEventData(_glfw.x11.display, &event->xcookie) && event->xcookie.evtype == XI_RawMotion) @@ -1483,7 +1484,7 @@ static void processEvent(XEvent *event) { if (_glfw.x11.disabledCursorWindow != window) return; - if (_glfw.x11.xi.available) + if (_glfw.x11.xi.available && window->useRawInput) return; const int dx = x - window->x11.lastCursorPosX; @@ -2652,6 +2653,24 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) PropModeReplace, (unsigned char*) &value, 1); } +void _glfwPlatformSetRawInput(_GLFWwindow *window, GLFWbool enabled) +{ + if (window->useRawInput != enabled) + { + int update = (_glfw.x11.disabledCursorWindow == window && _glfw.x11.xi.available); + if (update) + enableCursor(window); + window->useRawInput = enabled; + if (update) + disableCursor(window); + } +} + +GLFWbool _glfwPlatformRawInputSupported(void) +{ + return _glfw.x11.xi.available; +} + void _glfwPlatformPollEvents(void) { _GLFWwindow* window; diff --git a/tests/cursor.c b/tests/cursor.c index 4cc74ad51..a64c0bf80 100644 --- a/tests/cursor.c +++ b/tests/cursor.c @@ -163,6 +163,19 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action, printf("(( cursor is hidden ))\n"); break; + case GLFW_KEY_R: + if (glfwGetInputMode(window, GLFW_RAW_INPUT)) + { + glfwSetInputMode(window, GLFW_RAW_INPUT, GLFW_FALSE); + printf("(( raw input is disabled ))\n"); + } + else + { + glfwSetInputMode(window, GLFW_RAW_INPUT, GLFW_TRUE); + printf("(( raw input is enabled ))\n"); + } + break; + case GLFW_KEY_SPACE: swap_interval = 1 - swap_interval; printf("(( swap interval: %i ))\n", swap_interval); From f48146ebaad0c0c7181e86679b0ad8118431599d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Mon, 11 Feb 2019 19:10:20 +0100 Subject: [PATCH 7/7] Rename raw input to raw mouse motion, cleanup This renames 'raw input' to 'raw mouse motion' as there are other kinds of raw input. The update path is restructured to avoid reinitializing all of disabled cursor mode. Modification of shared state is moved out into shared code. Raw mouse motion is disabled by default for compatibility. Related to #1401. --- README.md | 5 +-- docs/input.dox | 27 +++++++++++++- docs/news.dox | 6 ++-- include/GLFW/glfw3.h | 54 ++++++++++++++-------------- src/cocoa_window.m | 5 ++- src/input.c | 31 +++++++++++++---- src/internal.h | 6 ++-- src/null_window.c | 5 ++- src/win32_window.c | 78 +++++++++++++++++++++++++---------------- src/window.c | 1 - src/wl_window.c | 5 ++- src/x11_window.c | 83 +++++++++++++++++++++++++------------------- tests/cursor.c | 9 +++-- 13 files changed, 194 insertions(+), 121 deletions(-) diff --git a/README.md b/README.md index 5f7045ab0..6422dbdec 100644 --- a/README.md +++ b/README.md @@ -182,7 +182,8 @@ information on what to include when reporting a bug. - Added `GLFW_OSMESA_CONTEXT_API` for creating OpenGL contexts with [OSMesa](https://www.mesa3d.org/osmesa.html) (#281) - Added `GenerateMappings.cmake` script for updating gamepad mappings -- Added `GLFW_RAW_INPUT` input mode and `glfwRawInputSupported` function (#1401) +- Added `GLFW_RAW_MOUSE_MOTION` input mode and `glfwRawMouseMotionSupported` + function (#1401) - Made `glfwCreateWindowSurface` emit an error when the window has a context (#1194,#1205) - Deprecated window parameter of clipboard string functions @@ -437,6 +438,7 @@ skills. - Cyril Pichard - Keith Pitt - Stanislav Podgorskiy + - Nathan Poirier - Alexandre Pretyman - przemekmirek - Philip Rideout @@ -490,7 +492,6 @@ skills. - Santi Zupancic - Jonas Ådahl - Lasse Öörni - - Nathan Poirier - All the unmentioned and anonymous contributors in the GLFW community, for bug reports, patches, feedback, testing and encouragement diff --git a/docs/input.dox b/docs/input.dox index 159fb454e..a438a18e1 100644 --- a/docs/input.dox +++ b/docs/input.dox @@ -233,7 +233,7 @@ arguments can always be passed unmodified to this function. @section input_mouse Mouse input -Mouse input comes in many forms, including cursor motion, button presses and +Mouse input comes in many forms, including mouse motion, button presses and scrolling offsets. The cursor appearance can also be changed, either to a custom image or a standard cursor shape from the system theme. @@ -308,6 +308,31 @@ glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); @endcode +@anchor GLFW_RAW_MOUSE_MOTION +@subsection raw_mouse_motion Raw mouse motion + +When the cursor is disabled, raw (unscaled and unaccelerated) mouse motion can +be enabled if available. + +Raw mouse motion is closer to the actual motion of the mouse across a surface. +It is not affected by the scaling and acceleration applied to the motion of the +desktop cursor. That processing is suitable for a cursor while raw motion is +better for controlling for example a 3D camera. Because of this, raw mouse +motion is only provided when the cursor is disabled. + +Call @ref glfwRawMouseMotionSupported to check if the current machine provides +raw motion and set the `GLFW_RAW_MOUSE_MOTION` input mode to enable it. It is +disabled by default. + +@code +if (glfwRawMouseMotionSupported()) + glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE); +@endcode + +If supported, raw mouse motion can be enabled or disabled per-window and at any +time but it will only be provided when the cursor is disabled. + + @subsection cursor_object Cursor objects GLFW supports creating both custom and system theme cursor images, encapsulated diff --git a/docs/news.dox b/docs/news.dox index 43f384eab..65812e712 100644 --- a/docs/news.dox +++ b/docs/news.dox @@ -135,8 +135,10 @@ attribute corresponds to the [cursor enter/leave](@ref cursor_enter) event. @subsection news_33_rawmotion Support for raw mouse motion -GLFW now uses raw (unscaled and unaccelerated) mouse motion in disabled cursor -mode on platforms where this is available, specifically Windows and X11. +GLFW now supports raw (unscaled and unaccelerated) mouse motion in disabled +cursor mode with the [GLFW_RAW_MOUSE_MOTION](@ref GLFW_RAW_MOUSE_MOTION) input +mode. Call @ref glfwRawMouseMotionSupported to check if the current machine +supports raw mouse motion. @subsection news_33_moltenvk Support for Vulkan on macOS via MoltenVK diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 9556cede6..a8c29f973 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1002,7 +1002,7 @@ extern "C" { #define GLFW_STICKY_KEYS 0x00033002 #define GLFW_STICKY_MOUSE_BUTTONS 0x00033003 #define GLFW_LOCK_KEY_MODS 0x00033004 -#define GLFW_RAW_INPUT 0x00033005 +#define GLFW_RAW_MOUSE_MOTION 0x00033005 #define GLFW_CURSOR_NORMAL 0x00034001 #define GLFW_CURSOR_HIDDEN 0x00034002 @@ -3812,11 +3812,12 @@ GLFWAPI void glfwPostEmptyEvent(void); * This function returns the value of an input option for the specified window. * The mode must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS, * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or - * @ref GLFW_RAW_INPUT. + * @ref GLFW_RAW_MOUSE_MOTION. * * @param[in] window The window to query. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`, - * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or `GLFW_RAW_INPUT`. + * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or + * `GLFW_RAW_MOUSE_MOTION`. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * GLFW_INVALID_ENUM. @@ -3836,7 +3837,7 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode); * This function sets an input mode option for the specified window. The mode * must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS, * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or - * @ref GLFW_RAW_INPUT. + * @ref GLFW_RAW_MOUSE_MOTION. * * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor * modes: @@ -3868,14 +3869,16 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode); * GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on, * and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on. * - * If the mode is `GLFW_RAW_INPUT`, the value must be either `GLFW_TRUE` to - * enable the use of raw input, or `GLFW_FALSE` to disable it. If enabled and - * supported by the machine, the program will retrieve high-definition mouse - * movement when cursor is grabbed. + * If the mode is `GLFW_RAW_MOUSE_MOTION`, the value must be either `GLFW_TRUE` + * to enable raw (unscaled and unaccelerated) mouse motion when the cursor is + * disabled, or `GLFW_FALSE` to disable it. If raw motion is not supported, + * attempting to set this will emit @ref GLFW_PLATFORM_ERROR. Call @ref + * glfwRawMouseMotionSupported to check for support. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`, - * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or `GLFW_RAW_INPUT`. + * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or + * `GLFW_RAW_MOUSE_MOTION`. * @param[in] value The new value of the specified input mode. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref @@ -3891,37 +3894,34 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode); */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); -/*! @brief Returns whether the raw input is supported. +/*! @brief Returns whether raw mouse motion is supported. * - * This function returns whether the raw input is supported by the current - * machine. + * This function returns whether raw mouse motion is supported on the current + * system. This status does not change after GLFW has been initialized so you + * only need to check this once. If you attempt to enable raw motion on + * a system that does not support it, @ref GLFW_PLATFORM_ERROR will be emitted. * - * Raw input allow to retrieve high-definition movement from mouse. - * Input from a high-definition mouse is much more precise than that from a - * standard mouse. But often, they cannot be obtained through standard - * platforms API which transform mouse movement using their own improvements - * (like pointer acceleration). Platform's improvements are ideal for pointer - * control but it is not so good for moving a first-person camera. For this - * reason when the cursor of a window is grabbed by setting @ref GLFW_CURSOR - * to @ref GLFW_CURSOR_DISABLED, raw input is used. + * Raw mouse motion is closer to the actual motion of the mouse across + * a surface. It is not affected by the scaling and acceleration applied to + * the motion of the desktop cursor. That processing is suitable for a cursor + * while raw motion is better for controlling for example a 3D camera. Because + * of this, raw mouse motion is only provided when the cursor is disabled. * - * The use of raw input can be disabled using @ref glfwSetInputMode with - * @ref GLFW_RAW_INPUT mode. - * - * @return `GLFW_TRUE` if high-definition mouse movement is supported, or - * `GLFW_FALSE` otherwise. + * @return `GLFW_TRUE` if raw mouse motion is supported on the current machine, + * or `GLFW_FALSE` otherwise. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @thread_safety This function may be called from any thread. + * @thread_safety This function must only be called from the main thread. * + * @sa @ref raw_mouse_motion * @sa @ref glfwSetInputMode * * @since Added in version 3.3. * * @ingroup input */ -GLFWAPI int glfwRawInputSupported(void); +GLFWAPI int glfwRawMouseMotionSupported(void); /*! @brief Returns the layout-specific name of the specified printable key. * diff --git a/src/cocoa_window.m b/src/cocoa_window.m index e3e20de79..9bea2f27f 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1297,12 +1297,11 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) [window->ns.object setAlphaValue:opacity]; } -void _glfwPlatformSetRawInput(_GLFWwindow *window, GLFWbool enabled) +void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled) { - window->useRawInput = enabled; } -GLFWbool _glfwPlatformRawInputSupported(void) +GLFWbool _glfwPlatformRawMouseMotionSupported(void) { return GLFW_FALSE; } diff --git a/src/input.c b/src/input.c index ef14fad53..b5e11542a 100644 --- a/src/input.c +++ b/src/input.c @@ -463,6 +463,7 @@ void _glfwCenterCursorInContentArea(_GLFWwindow* window) _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0); } + ////////////////////////////////////////////////////////////////////////// ////// GLFW public API ////// ////////////////////////////////////////////////////////////////////////// @@ -484,8 +485,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode) return window->stickyMouseButtons; case GLFW_LOCK_KEY_MODS: return window->lockKeyMods; - case GLFW_RAW_INPUT: - return window->useRawInput; + case GLFW_RAW_MOUSE_MOTION: + return window->rawMouseMotion; } _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); @@ -562,17 +563,33 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) window->stickyMouseButtons = value; } else if (mode == GLFW_LOCK_KEY_MODS) + { window->lockKeyMods = value ? GLFW_TRUE : GLFW_FALSE; - else if (mode == GLFW_RAW_INPUT) - _glfwPlatformSetRawInput(window, value ? GLFW_TRUE : GLFW_FALSE); + } + else if (mode == GLFW_RAW_MOUSE_MOTION) + { + if (!_glfwPlatformRawMouseMotionSupported()) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Raw mouse motion is not supported on this system"); + return; + } + + value = value ? GLFW_TRUE : GLFW_FALSE; + if (window->rawMouseMotion == value) + return; + + window->rawMouseMotion = value; + _glfwPlatformSetRawMouseMotion(window, value); + } else _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); } -GLFWAPI int glfwRawInputSupported(void) +GLFWAPI int glfwRawMouseMotionSupported(void) { - _GLFW_REQUIRE_INIT_OR_RETURN(0); - return _glfwPlatformRawInputSupported(); + _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); + return _glfwPlatformRawMouseMotionSupported(); } GLFWAPI const char* glfwGetKeyName(int key, int scancode) diff --git a/src/internal.h b/src/internal.h index 65d77cc17..abba5baf1 100644 --- a/src/internal.h +++ b/src/internal.h @@ -390,7 +390,7 @@ struct _GLFWwindow char keys[GLFW_KEY_LAST + 1]; // Virtual cursor position when cursor is disabled double virtualCursorPosX, virtualCursorPosY; - GLFWbool useRawInput; + GLFWbool rawMouseMotion; _GLFWcontext context; @@ -597,8 +597,8 @@ const char* _glfwPlatformGetVersionString(void); void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos); void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos); void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode); -void _glfwPlatformSetRawInput(_GLFWwindow *window, GLFWbool enabled); -GLFWbool _glfwPlatformRawInputSupported(void); +void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled); +GLFWbool _glfwPlatformRawMouseMotionSupported(void); int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape); diff --git a/src/null_window.c b/src/null_window.c index cb976310e..8dc92cb7d 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -196,12 +196,11 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) { } -void _glfwPlatformSetRawInput(_GLFWwindow *window, GLFWbool enabled) +void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled) { - window->useRawInput = enabled; } -GLFWbool _glfwPlatformRawInputSupported(void) +GLFWbool _glfwPlatformRawMouseMotionSupported(void) { return GLFW_FALSE; } diff --git a/src/win32_window.c b/src/win32_window.c index ec010f7ec..728b6e07a 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -267,12 +267,36 @@ static void updateClipRect(_GLFWwindow* window) ClipCursor(NULL); } +// Enables WM_INPUT messages for the mouse for the specified window +// +static void enableRawMouseMotion(_GLFWwindow* window) +{ + const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle }; + + if (!RegisterRawInputDevices(&rid, 1, sizeof(rid))) + { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to register raw input device"); + } +} + +// Disables WM_INPUT messages for the mouse +// +static void disableRawMouseMotion(_GLFWwindow* window) +{ + const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL }; + + if (!RegisterRawInputDevices(&rid, 1, sizeof(rid))) + { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to remove raw input device"); + } +} + // Apply disabled cursor mode to a focused window // static void disableCursor(_GLFWwindow* window) { - const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle }; - _glfw.win32.disabledCursorWindow = window; _glfwPlatformGetCursorPos(window, &_glfw.win32.restoreCursorPosX, @@ -281,18 +305,16 @@ static void disableCursor(_GLFWwindow* window) _glfwCenterCursorInContentArea(window); updateClipRect(window); - if (window->useRawInput && !RegisterRawInputDevices(&rid, 1, sizeof(rid))) - { - _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to register raw input device"); - } + if (window->rawMouseMotion) + enableRawMouseMotion(window); } // Exit disabled cursor mode for the specified window // static void enableCursor(_GLFWwindow* window) { - const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL }; + if (window->rawMouseMotion) + disableRawMouseMotion(window); _glfw.win32.disabledCursorWindow = NULL; updateClipRect(NULL); @@ -300,12 +322,6 @@ static void enableCursor(_GLFWwindow* window) _glfw.win32.restoreCursorPosX, _glfw.win32.restoreCursorPosY); updateCursorImage(window); - - if (window->useRawInput && !RegisterRawInputDevices(&rid, 1, sizeof(rid))) - { - _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to remove raw input device"); - } } // Returns whether the cursor is in the content area of the specified window @@ -817,11 +833,14 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, // Disabled cursor motion input is provided by WM_INPUT if (window->cursorMode == GLFW_CURSOR_DISABLED) { - if (_glfw.win32.disabledCursorWindow != window || window->useRawInput) - break; - const int dx = x - window->win32.lastCursorPosX; const int dy = y - window->win32.lastCursorPosY; + + if (_glfw.win32.disabledCursorWindow != window) + break; + if (window->rawMouseMotion) + break; + _glfwInputCursorPos(window, window->virtualCursorPosX + dx, window->virtualCursorPosY + dy); @@ -855,8 +874,9 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, RAWINPUT* data; int dx, dy; - // Only process input when disabled cursor mode is applied - if (_glfw.win32.disabledCursorWindow != window || !window->useRawInput) + if (_glfw.win32.disabledCursorWindow != window) + break; + if (!window->rawMouseMotion) break; GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); @@ -1854,20 +1874,18 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) } } -void _glfwPlatformSetRawInput(_GLFWwindow *window, GLFWbool enabled) +void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled) { - if (window->useRawInput != enabled) - { - int update = (_glfw.win32.disabledCursorWindow == window); - if (update) - enableCursor(window); - window->useRawInput = enabled; - if (update) - disableCursor(window); - } + if (_glfw.win32.disabledCursorWindow != window) + return; + + if (enabled) + enableRawMouseMotion(window); + else + disableRawMouseMotion(window); } -GLFWbool _glfwPlatformRawInputSupported(void) +GLFWbool _glfwPlatformRawMouseMotionSupported(void) { return GLFW_TRUE; } diff --git a/src/window.c b/src/window.c index f8cb030e3..91c323fbd 100644 --- a/src/window.c +++ b/src/window.c @@ -202,7 +202,6 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, window->floating = wndconfig.floating; window->focusOnShow = wndconfig.focusOnShow; window->cursorMode = GLFW_CURSOR_NORMAL; - window->useRawInput = GLFW_TRUE; window->minwidth = GLFW_DONT_CARE; window->minheight = GLFW_DONT_CARE; diff --git a/src/wl_window.c b/src/wl_window.c index bd6ff880a..a287a7570 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1304,12 +1304,11 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) { } -void _glfwPlatformSetRawInput(_GLFWwindow *window, GLFWbool enabled) +void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled) { - window->useRawInput = enabled; } -GLFWbool _glfwPlatformRawInputSupported(void) +GLFWbool _glfwPlatformRawMouseMotionSupported(void) { return GLFW_FALSE; } diff --git a/src/x11_window.c b/src/x11_window.c index 9e25fda32..92a137f48 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -522,22 +522,41 @@ static void updateCursorImage(_GLFWwindow* window) } } +// Enable XI2 raw mouse motion events +// +static void enableRawMouseMotion(_GLFWwindow* window) +{ + XIEventMask em; + unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 }; + + em.deviceid = XIAllMasterDevices; + em.mask_len = sizeof(mask); + em.mask = mask; + XISetMask(mask, XI_RawMotion); + + XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1); +} + +// Disable XI2 raw mouse motion events +// +static void disableRawMouseMotion(_GLFWwindow* window) +{ + XIEventMask em; + unsigned char mask[] = { 0 }; + + em.deviceid = XIAllMasterDevices; + em.mask_len = sizeof(mask); + em.mask = mask; + + XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1); +} + // Apply disabled cursor mode to a focused window // static void disableCursor(_GLFWwindow* window) { - if (_glfw.x11.xi.available && window->useRawInput) - { - XIEventMask em; - unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 }; - - em.deviceid = XIAllMasterDevices; - em.mask_len = sizeof(mask); - em.mask = mask; - XISetMask(mask, XI_RawMotion); - - XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1); - } + if (window->rawMouseMotion) + enableRawMouseMotion(window); _glfw.x11.disabledCursorWindow = window; _glfwPlatformGetCursorPos(window, @@ -557,17 +576,8 @@ static void disableCursor(_GLFWwindow* window) // static void enableCursor(_GLFWwindow* window) { - if (_glfw.x11.xi.available && window->useRawInput) - { - XIEventMask em; - unsigned char mask[] = { 0 }; - - em.deviceid = XIAllMasterDevices; - em.mask_len = sizeof(mask); - em.mask = mask; - - XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1); - } + if (window->rawMouseMotion) + disableRawMouseMotion(window); _glfw.x11.disabledCursorWindow = NULL; XUngrabPointer(_glfw.x11.display, CurrentTime); @@ -1183,7 +1193,7 @@ static void processEvent(XEvent *event) _GLFWwindow* window = _glfw.x11.disabledCursorWindow; if (window && - window->useRawInput && + window->rawMouseMotion && event->xcookie.extension == _glfw.x11.xi.majorOpcode && XGetEventData(_glfw.x11.display, &event->xcookie) && event->xcookie.evtype == XI_RawMotion) @@ -1484,7 +1494,7 @@ static void processEvent(XEvent *event) { if (_glfw.x11.disabledCursorWindow != window) return; - if (_glfw.x11.xi.available && window->useRawInput) + if (window->rawMouseMotion) return; const int dx = x - window->x11.lastCursorPosX; @@ -2653,20 +2663,21 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) PropModeReplace, (unsigned char*) &value, 1); } -void _glfwPlatformSetRawInput(_GLFWwindow *window, GLFWbool enabled) +void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled) { - if (window->useRawInput != enabled) - { - int update = (_glfw.x11.disabledCursorWindow == window && _glfw.x11.xi.available); - if (update) - enableCursor(window); - window->useRawInput = enabled; - if (update) - disableCursor(window); - } + if (!_glfw.x11.xi.available) + return; + + if (_glfw.x11.disabledCursorWindow != window) + return; + + if (enabled) + enableRawMouseMotion(window); + else + disableRawMouseMotion(window); } -GLFWbool _glfwPlatformRawInputSupported(void) +GLFWbool _glfwPlatformRawMouseMotionSupported(void) { return _glfw.x11.xi.available; } diff --git a/tests/cursor.c b/tests/cursor.c index a64c0bf80..68d3069f0 100644 --- a/tests/cursor.c +++ b/tests/cursor.c @@ -164,14 +164,17 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action, break; case GLFW_KEY_R: - if (glfwGetInputMode(window, GLFW_RAW_INPUT)) + if (!glfwRawMouseMotionSupported()) + break; + + if (glfwGetInputMode(window, GLFW_RAW_MOUSE_MOTION)) { - glfwSetInputMode(window, GLFW_RAW_INPUT, GLFW_FALSE); + glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_FALSE); printf("(( raw input is disabled ))\n"); } else { - glfwSetInputMode(window, GLFW_RAW_INPUT, GLFW_TRUE); + glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE); printf("(( raw input is enabled ))\n"); } break;