Jelajahi Sumber

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
Grzesiek11 1 tahun lalu
induk
melakukan
bf945f1213
8 mengubah file dengan 81 tambahan dan 21 penghapusan
  1. 3 0
      README.md
  2. 22 3
      docs/input.md
  3. 11 0
      docs/news.md
  4. 26 12
      include/GLFW/glfw3.h
  5. 16 6
      src/input.c
  6. 1 0
      src/internal.h
  7. 1 0
      tests/events.c
  8. 1 0
      tests/window.c

+ 3 - 0
README.md

@@ -121,6 +121,9 @@ information on what to include when reporting a bug.
 
 
 ## Changelog since 3.4
 ## 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
 ## Contact
 
 

+ 22 - 3
docs/input.md

@@ -492,6 +492,20 @@ a mouse button callback.
 glfwSetMouseButtonCallback(window, 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
 The callback function receives the [mouse button](@ref buttons), button action
 and [modifier bits](@ref mods).
 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 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
 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
 ```c
 int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
 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`.
 otherwise it will remain `GLFW_PRESS`.
 
 
 The `GLFW_MOUSE_BUTTON_LAST` constant holds the highest value of any
 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}
 ### Scroll input {#scrolling}

+ 11 - 0
docs/news.md

@@ -5,6 +5,15 @@
 
 
 ## New features {#features}
 ## 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}
 ## Caveats {#caveats}
 
 
 ## Deprecations {#deprecations}
 ## Deprecations {#deprecations}
@@ -19,6 +28,8 @@
 
 
 ### New constants {#new_constants}
 ### New constants {#new_constants}
 
 
+- @ref GLFW_UNLIMITED_MOUSE_BUTTONS
+
 ## Release notes for earlier versions {#news_archive}
 ## Release notes for earlier versions {#news_archive}
 
 
 - [Release notes for 3.4](https://www.glfw.org/docs/3.4/news.html)
 - [Release notes for 3.4](https://www.glfw.org/docs/3.4/news.html)

+ 26 - 12
include/GLFW/glfw3.h

@@ -1149,11 +1149,12 @@ extern "C" {
 #define GLFW_OPENGL_CORE_PROFILE    0x00032001
 #define GLFW_OPENGL_CORE_PROFILE    0x00032001
 #define GLFW_OPENGL_COMPAT_PROFILE  0x00032002
 #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_NORMAL          0x00034001
 #define GLFW_CURSOR_HIDDEN          0x00034002
 #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
  *  This function sets an input mode option for the specified window.  The mode
  *  must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
  *  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
  *  If the mode is `GLFW_CURSOR`, the value must be one of the following cursor
  *  modes:
  *  modes:
@@ -4717,6 +4718,11 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
  *  attempting to set this will emit @ref GLFW_FEATURE_UNAVAILABLE.  Call @ref
  *  attempting to set this will emit @ref GLFW_FEATURE_UNAVAILABLE.  Call @ref
  *  glfwRawMouseMotionSupported to check for support.
  *  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] window The window whose input mode to set.
  *  @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
  *  @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
  *  `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or
  *  `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
  *  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.
  *  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] 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`.
  *  @return One of `GLFW_PRESS` or `GLFW_RELEASE`.
  *
  *
  *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
  *  @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.
  *  is called when a mouse button is pressed or released.
  *
  *
  *  When a window loses input focus, it will generate synthetic mouse button
  *  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] window The window whose callback to set.
  *  @param[in] callback The new callback, or `NULL` to remove the currently set
  *  @param[in] callback The new callback, or `NULL` to remove the currently set

+ 16 - 6
src/input.c

@@ -348,20 +348,22 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
 {
 {
     assert(window != NULL);
     assert(window != NULL);
     assert(button >= 0);
     assert(button >= 0);
-    assert(button <= GLFW_MOUSE_BUTTON_LAST);
     assert(action == GLFW_PRESS || action == GLFW_RELEASE);
     assert(action == GLFW_PRESS || action == GLFW_RELEASE);
     assert(mods == (mods & GLFW_MOD_MASK));
     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;
         return;
 
 
     if (!window->lockKeyMods)
     if (!window->lockKeyMods)
         mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
         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)
     if (window->callbacks.mouseButton)
         window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
         window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
@@ -576,6 +578,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
             return window->lockKeyMods;
             return window->lockKeyMods;
         case GLFW_RAW_MOUSE_MOTION:
         case GLFW_RAW_MOUSE_MOTION:
             return window->rawMouseMotion;
             return window->rawMouseMotion;
+        case GLFW_UNLIMITED_MOUSE_BUTTONS:
+            return window->disableMouseButtonLimit;
     }
     }
 
 
     _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
     _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);
             _glfw.platform.setRawMouseMotion(window, value);
             return;
             return;
         }
         }
+
+        case GLFW_UNLIMITED_MOUSE_BUTTONS:
+        {
+            window->disableMouseButtonLimit = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        }
     }
     }
 
 
     _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
     _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);

+ 1 - 0
src/internal.h

@@ -544,6 +544,7 @@ struct _GLFWwindow
     GLFWbool            stickyKeys;
     GLFWbool            stickyKeys;
     GLFWbool            stickyMouseButtons;
     GLFWbool            stickyMouseButtons;
     GLFWbool            lockKeyMods;
     GLFWbool            lockKeyMods;
+    GLFWbool            disableMouseButtonLimit;
     int                 cursorMode;
     int                 cursorMode;
     char                mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
     char                mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
     char                keys[GLFW_KEY_LAST + 1];
     char                keys[GLFW_KEY_LAST + 1];

+ 1 - 0
tests/events.c

@@ -630,6 +630,7 @@ int main(int argc, char** argv)
             glfwTerminate();
             glfwTerminate();
             exit(EXIT_FAILURE);
             exit(EXIT_FAILURE);
         }
         }
+        glfwSetInputMode(slots[i].window, GLFW_UNLIMITED_MOUSE_BUTTONS, GLFW_TRUE);
 
 
         glfwSetWindowUserPointer(slots[i].window, slots + i);
         glfwSetWindowUserPointer(slots[i].window, slots + i);
 
 

+ 1 - 0
tests/window.c

@@ -78,6 +78,7 @@ int main(int argc, char** argv)
         glfwTerminate();
         glfwTerminate();
         exit(EXIT_FAILURE);
         exit(EXIT_FAILURE);
     }
     }
+    glfwSetInputMode(window, GLFW_UNLIMITED_MOUSE_BUTTONS, GLFW_TRUE);
 
 
     glfwMakeContextCurrent(window);
     glfwMakeContextCurrent(window);
     gladLoadGL(glfwGetProcAddress);
     gladLoadGL(glfwGetProcAddress);