From bf945f1213728a98f7647380616f9cff9f6b3611 Mon Sep 17 00:00:00 2001 From: Grzesiek11 Date: Thu, 29 Feb 2024 15:50:50 +0000 Subject: [PATCH] Unlimited mouse button input mode This adds the GLFW_UNLIMITED_MOUSE_BUTTONS input mode which permits mouse buttons over GLFW_MOUSE_BUTTON_LAST to be reported to the mouse button callback. Closes #2423 --- README.md | 3 +++ docs/input.md | 25 ++++++++++++++++++++++--- docs/news.md | 11 +++++++++++ include/GLFW/glfw3.h | 38 ++++++++++++++++++++++++++------------ src/input.c | 22 ++++++++++++++++------ src/internal.h | 1 + tests/events.c | 1 + tests/window.c | 1 + 8 files changed, 81 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 050ada3c..d2615b17 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,9 @@ information on what to include when reporting a bug. ## Changelog since 3.4 + - Added `GLFW_UNLIMITED_MOUSE_BUTTONS` input mode that allows mouse buttons beyond + the limit of the mouse button tokens to be reported (#2423) + ## Contact diff --git a/docs/input.md b/docs/input.md index 56983b08..3ef1aebe 100644 --- a/docs/input.md +++ b/docs/input.md @@ -492,6 +492,20 @@ a mouse button callback. glfwSetMouseButtonCallback(window, mouse_button_callback); ``` +@anchor GLFW_UNLIMITED_MOUSE_BUTTONS +To handle all mouse buttons in the callback, instead of only ones with associated +[button tokens](@ref buttons), set the @ref GLFW_UNLIMITED_MOUSE_BUTTONS +input mode. + +```c +glfwSetInputMode(window, GLFW_UNLIMITED_MOUSE_BUTTONS, GLFW_TRUE); +``` + +When this input mode is enabled, GLFW doesn't limit the reported mouse buttons +to only those that have an associated button token, for compatibility with +earlier versions of GLFW, which never reported any buttons over +@ref GLFW_MOUSE_BUTTON_LAST, on which users could have relied on. + The callback function receives the [mouse button](@ref buttons), button action and [modifier bits](@ref mods). @@ -503,11 +517,16 @@ void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) } ``` +The mouse button is an integer that can be one of the +[mouse button tokens](@ref buttons) or, if the +@ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode is set, any other positive value. + The action is one of `GLFW_PRESS` or `GLFW_RELEASE`. -The last reported state for every [supported mouse button](@ref buttons) is also +The last reported state for every [mouse button token](@ref buttons) is also saved in per-window state arrays that can be polled with @ref -glfwGetMouseButton. +glfwGetMouseButton. This is not effected by the @ref GLFW_UNLIMITED_MOUSE_BUTTONS +input mode. ```c int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT); @@ -540,7 +559,7 @@ had been processed in the meantime, the state will reset to `GLFW_RELEASE`, otherwise it will remain `GLFW_PRESS`. The `GLFW_MOUSE_BUTTON_LAST` constant holds the highest value of any -[supported mouse button](@ref buttons). +[mouse button token](@ref buttons). ### Scroll input {#scrolling} diff --git a/docs/news.md b/docs/news.md index fd93a712..148d0871 100644 --- a/docs/news.md +++ b/docs/news.md @@ -5,6 +5,15 @@ ## New features {#features} +### Unlimited mouse buttons {#unlimited_mouse_buttons} + +GLFW now has an input mode which allows an unlimited number of mouse buttons to +be reported by the mouse buttton callback, rather than just the associated +[mouse button tokens](@ref buttons). This allows using mouse buttons with +values over 8. For compatibility with older versions, the +@ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode needs to be set to make use of +this. + ## Caveats {#caveats} ## Deprecations {#deprecations} @@ -19,6 +28,8 @@ ### New constants {#new_constants} +- @ref GLFW_UNLIMITED_MOUSE_BUTTONS + ## Release notes for earlier versions {#news_archive} - [Release notes for 3.4](https://www.glfw.org/docs/3.4/news.html) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 9a6ad6fd..bed739dc 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1149,11 +1149,12 @@ extern "C" { #define GLFW_OPENGL_CORE_PROFILE 0x00032001 #define GLFW_OPENGL_COMPAT_PROFILE 0x00032002 -#define GLFW_CURSOR 0x00033001 -#define GLFW_STICKY_KEYS 0x00033002 -#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003 -#define GLFW_LOCK_KEY_MODS 0x00033004 -#define GLFW_RAW_MOUSE_MOTION 0x00033005 +#define GLFW_CURSOR 0x00033001 +#define GLFW_STICKY_KEYS 0x00033002 +#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003 +#define GLFW_LOCK_KEY_MODS 0x00033004 +#define GLFW_RAW_MOUSE_MOTION 0x00033005 +#define GLFW_UNLIMITED_MOUSE_BUTTONS 0x00033006 #define GLFW_CURSOR_NORMAL 0x00034001 #define GLFW_CURSOR_HIDDEN 0x00034002 @@ -4676,8 +4677,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, @ref GLFW_LOCK_KEY_MODS or - * @ref GLFW_RAW_MOUSE_MOTION. + * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS + * @ref GLFW_RAW_MOUSE_MOTION, or @ref GLFW_UNLIMITED_MOUSE_BUTTONS. * * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor * modes: @@ -4717,6 +4718,11 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode); * attempting to set this will emit @ref GLFW_FEATURE_UNAVAILABLE. Call @ref * glfwRawMouseMotionSupported to check for support. * + * If the mode is `GLFW_UNLIMITED_MOUSE_BUTTONS`, the value must be either + * `GLFW_TRUE` to disable the mouse button limit when calling the mouse button + * callback, or `GLFW_FALSE` to limit the mouse buttons sent to the callback + * to the mouse button token values up to `GLFW_MOUSE_BUTTON_LAST`. + * * @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 @@ -4911,8 +4917,11 @@ GLFWAPI int glfwGetKey(GLFWwindow* window, int key); * returns `GLFW_PRESS` the first time you call it for a mouse button that was * pressed, even if that mouse button has already been released. * + * The @ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode does not effect the + * limit on buttons which can be polled with this function. + * * @param[in] window The desired window. - * @param[in] button The desired [mouse button](@ref buttons). + * @param[in] button The desired [mouse button token](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref @@ -5288,10 +5297,15 @@ GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmods * is called when a mouse button is pressed or released. * * When a window loses input focus, it will generate synthetic mouse button - * release events for all pressed mouse buttons. You can tell these events - * from user-generated events by the fact that the synthetic ones are generated - * after the focus loss event has been processed, i.e. after the - * [window focus callback](@ref glfwSetWindowFocusCallback) has been called. + * release events for all pressed mouse buttons with associated button tokens. + * You can tell these events from user-generated events by the fact that the + * synthetic ones are generated after the focus loss event has been processed, + * i.e. after the [window focus callback](@ref glfwSetWindowFocusCallback) has + * been called. + * + * The reported `button` value can be higher than `GLFW_MOUSE_BUTTON_LAST` if + * the button does not have an associated [button token](@ref buttons) and the + * @ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode is set. * * @param[in] window The window whose callback to set. * @param[in] callback The new callback, or `NULL` to remove the currently set diff --git a/src/input.c b/src/input.c index 3f8ddb30..8148a57d 100644 --- a/src/input.c +++ b/src/input.c @@ -348,20 +348,22 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) { assert(window != NULL); assert(button >= 0); - assert(button <= GLFW_MOUSE_BUTTON_LAST); assert(action == GLFW_PRESS || action == GLFW_RELEASE); assert(mods == (mods & GLFW_MOD_MASK)); - if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST) + if (button < 0 || (!window->disableMouseButtonLimit && button > GLFW_MOUSE_BUTTON_LAST)) return; if (!window->lockKeyMods) mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK); - if (action == GLFW_RELEASE && window->stickyMouseButtons) - window->mouseButtons[button] = _GLFW_STICK; - else - window->mouseButtons[button] = (char) action; + if (button <= GLFW_MOUSE_BUTTON_LAST) + { + if (action == GLFW_RELEASE && window->stickyMouseButtons) + window->mouseButtons[button] = _GLFW_STICK; + else + window->mouseButtons[button] = (char) action; + } if (window->callbacks.mouseButton) window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods); @@ -576,6 +578,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode) return window->lockKeyMods; case GLFW_RAW_MOUSE_MOTION: return window->rawMouseMotion; + case GLFW_UNLIMITED_MOUSE_BUTTONS: + return window->disableMouseButtonLimit; } _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); @@ -683,6 +687,12 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) _glfw.platform.setRawMouseMotion(window, value); return; } + + case GLFW_UNLIMITED_MOUSE_BUTTONS: + { + window->disableMouseButtonLimit = value ? GLFW_TRUE : GLFW_FALSE; + return; + } } _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); diff --git a/src/internal.h b/src/internal.h index 76f3ede2..eae87c73 100644 --- a/src/internal.h +++ b/src/internal.h @@ -544,6 +544,7 @@ struct _GLFWwindow GLFWbool stickyKeys; GLFWbool stickyMouseButtons; GLFWbool lockKeyMods; + GLFWbool disableMouseButtonLimit; int cursorMode; char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1]; char keys[GLFW_KEY_LAST + 1]; diff --git a/tests/events.c b/tests/events.c index fdc3c199..ab3b99a7 100644 --- a/tests/events.c +++ b/tests/events.c @@ -630,6 +630,7 @@ int main(int argc, char** argv) glfwTerminate(); exit(EXIT_FAILURE); } + glfwSetInputMode(slots[i].window, GLFW_UNLIMITED_MOUSE_BUTTONS, GLFW_TRUE); glfwSetWindowUserPointer(slots[i].window, slots + i); diff --git a/tests/window.c b/tests/window.c index c81bf024..ffea5dbf 100644 --- a/tests/window.c +++ b/tests/window.c @@ -78,6 +78,7 @@ int main(int argc, char** argv) glfwTerminate(); exit(EXIT_FAILURE); } + glfwSetInputMode(window, GLFW_UNLIMITED_MOUSE_BUTTONS, GLFW_TRUE); glfwMakeContextCurrent(window); gladLoadGL(glfwGetProcAddress);