From 556cc61848e5e9bd302b4aed4b780a4f8b032ea6 Mon Sep 17 00:00:00 2001 From: Beoran Date: Wed, 30 Oct 2019 23:56:53 +0100 Subject: [PATCH 1/5] Added WIP types for the joystick callbacks. --- include/GLFW/glfw3.h | 99 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 2aade0f0..4460d94c 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1613,6 +1613,105 @@ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); */ typedef void (* GLFWjoystickfun)(int,int); +/*! @brief The function pointer type for joystick button callbacks. + * + * This is the function pointer type for joystick button callbacks. A joystick + * button callback function has the following signature: + * @code + * void function_name(int jid, int button, int action) + * @endcode + * + * @param[in] jid The joystick that had a button pressed or released. + * @param[in] button The [joystick button](@ref buttons) that was pressed or released. + * @param[in] action `GLFW_PRESS` or `GLFW_RELEASE`. Future + * releases may add more actions. + * + * @sa @ref input_joystick_button + * @sa @ref glfwSetJoystickButonCallback + * + * @since Added in version 3.4. + * @ingroup input + */ +typedef void (* GLFWjoystickbuttonfun)(int,int,int); + +/*! @brief The function pointer type for joystick axis movement callbacks. + * + * This is the function pointer type for joystick axis movement callbacks. A joystick + * axis movement callback function has the following signature: + * @code + * void function_name(int jid, int axis, float position) + * @endcode + * + * @param[in] jid The joystick that had an axis moved. + * @param[in] axis The [joystick axis](@ref gamepad axes) that was moved. + * @param[in] position A value between -1.0 and 1.0 that indicates the position of the axis. + * + * @sa @ref input_gamepad_axis + * @sa @ref glfwSetJoystickAxisCallback + * + * @since Added in version 3.4. + * @ingroup input + */ +typedef void (* GLFWjoystickaxisfun)(int,int,float); + +/*! @brief The function pointer type for joystick hat movement callbacks. + * + * This is the function pointer type for joystick hat movement callbacks. A joystick + * hat movement callback function has the following signature: + * @code + * void function_name(int jid, int hat, int position) + * @endcode + * + * @param[in] jid The joystick that had an axis moved. + * @param[in] hat The [joystick hat](@ref joystick hats) that was moved. + * @param[in] position A value that indicates the position of the hat. + * The position parameter is one of the following values: + * + * Name | Value + * ---- | ----- + * `GLFW_HAT_CENTERED` | 0 + * `GLFW_HAT_UP` | 1 + * `GLFW_HAT_RIGHT` | 2 + * `GLFW_HAT_DOWN` | 4 + * `GLFW_HAT_LEFT` | 8 + * `GLFW_HAT_RIGHT_UP` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP` + * `GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN` + * `GLFW_HAT_LEFT_UP` | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP` + * `GLFW_HAT_LEFT_DOWN` | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN` + * + * The diagonal directions are bitwise combinations of the primary (up, right, + * down and left) directions and you can test for these individually by ANDing + * it with the corresponding direction. + * + * @sa @ref input_joystick_hat + * @sa @ref glfwSetJoystickHatCallback + * + * @since Added in version 3.4. + * @ingroup input + */ +typedef void (* GLFWjoystickhatfun)(int,int,int); + +/*! @brief The function pointer type for Unicode character callbacks. + * + * This is the function pointer type for Unicode character callbacks. + * A Unicode character callback function has the following signature: + * @code + * void function_name(GLFWwindow* window, unsigned int codepoint) + * @endcode + * + * @param[in] window The window that received the event. + * @param[in] codepoint The Unicode code point of the character. + * + * @sa @ref input_char + * @sa @ref glfwSetCharCallback + * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * + * @ingroup input + */ +typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); + /*! @brief Video mode type. * * This describes a single video mode. From f5536ccae0a751994a0cfdf6541a841a2198482f Mon Sep 17 00:00:00 2001 From: Beoran Date: Thu, 31 Oct 2019 20:49:39 +0100 Subject: [PATCH 2/5] Implement joystick and game pad callbacks. This allows using GLFW joysticks in an event based manner. For the joysticks, this was done by adding the callbacks and then calling them in the shared code in input.c. For the gamepads, a new shared function is called whenever the joystick's state changes. However the gamepad state callback is only called if the joystick is mapped to a gamepad. --- include/GLFW/glfw3.h | 166 +++++++++++++++++++++++++++++++++++++++++++ src/input.c | 59 +++++++++++++++ src/internal.h | 8 ++- 3 files changed, 231 insertions(+), 2 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 4460d94c..34713091 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1168,6 +1168,17 @@ typedef struct GLFWwindow GLFWwindow; */ typedef struct GLFWcursor GLFWcursor; +/*! @brief Gamepad state object. + * + * Gamepad state object, predeclared here. + * + * @since Added in version 3.4. + * + * @ingroup input + */ +typedef struct GLFWgamepadstate GLFWgamepadstate; + + /*! @brief The function pointer type for error callbacks. * * This is the function pointer type for error callbacks. An error callback @@ -1691,6 +1702,26 @@ typedef void (* GLFWjoystickaxisfun)(int,int,float); */ typedef void (* GLFWjoystickhatfun)(int,int,int); +/*! @brief The function pointer type for game pad state changes. + * + * This is the function pointer type for game pad state change callbacks. + * A game pad state change callback function has the following signature: + * @code + * void function_name(int jid, GLFWgamepadstate* state) + * @endcode + * + * @param[in] jid The ID of the game pad that changed state. + * @param[in] state The updated state of the game pad. + * + * @sa @ref input_gamepad + * @sa @ref glfwSetGamepadStateCallback + * + * @since Added in version 3.4. + * @ingroup input + */ +typedef void (* GLFWgamepadstatefun)(int,GLFWgamepadstate*); + + /*! @brief The function pointer type for Unicode character callbacks. * * This is the function pointer type for Unicode character callbacks. @@ -1807,6 +1838,7 @@ typedef struct GLFWimage * * @sa @ref gamepad * @sa @ref glfwGetGamepadState + * @sa @ref glfwSetGamepadStateCallback * * @since Added in version 3.3. * @@ -5237,6 +5269,140 @@ GLFWAPI int glfwJoystickIsGamepad(int jid); */ GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun callback); +/*! @brief Sets the joystick button callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick button is pressed + * or released. + * + * For joystick button events to be delivered on all platforms, + * you need to call one of the [event processing](@ref events) + * functions. + * + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(int jid, int button, int state) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWjoystickbuttonfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickbuttonfun glfwSetJoystickButtonCallback(GLFWjoystickbuttonfun callback); + +/*! @brief Sets the joystick axis callback. + * + * This function sets the joystick axis callback, or removes the + * currently set callback. This is called when a joystick axis moved. + * + * For joystick axis events to be delivered on all platforms, + * you need to call one of the [event processing](@ref events) + * functions. + * + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(int jid, int axis, float state) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWjoystickaxisfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickaxisfun glfwSetJoystickAxisCallback(GLFWjoystickaxisfun callback); + +/*! @brief Sets the joystick hat callback. + * + * This function sets the joystick hat callback, or removes the + * currently set callback. This is called when a joystick hat moved. + * + * For joystick hat events to be delivered on all platforms, + * you need to call one of the [event processing](@ref events) + * functions. + * + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(int jid, int hat, int state) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWjoystickhatfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickhatfun glfwSetJoystickHatCallback(GLFWjoystickhatfun callback); + +/*! @brief Sets the game pad state callback. + * + * This function sets the game pad state callback, or removes the + * currently set callback. This is called when a game pad state changes. + * + * For game pad events to be delivered on all platforms, + * you need to call one of the [event processing](@ref events) + * functions. + * + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(int jid, GLFWgamepadstate* state) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWgamepadstatefun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWgamepadstatefun glfwSetGamepadStateCallback(GLFWgamepadstatefun callback); + + /*! @brief Adds the specified SDL_GameControllerDB gamepad mappings. * * This function parses the specified ASCII encoded string and updates the diff --git a/src/input.c b/src/input.c index 28291750..6d07ce73 100644 --- a/src/input.c +++ b/src/input.c @@ -365,6 +365,19 @@ void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths) window->callbacks.drop((GLFWwindow*) window, count, paths); } +// Notifies shared code of a change in the gamepad state. +// Automatically recalculates the state if the gamepad callback is installed. +void _glfwInputGamepad(_GLFWjoystick* js) +{ + const int jid = (int) (js - _glfw.joysticks); + if (glfwJoystickIsGamepad(jid) && (_glfw.callbacks.gamepad_state)) { + GLFWgamepadstate state; + if (0 == glfwGetGamepadState(jid, &state)) { + _glfw.callbacks.gamepad_state(jid, &state); + } + } +} + // Notifies shared code of a joystick connection or disconnection // void _glfwInputJoystick(_GLFWjoystick* js, int event) @@ -379,20 +392,33 @@ void _glfwInputJoystick(_GLFWjoystick* js, int event) // void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value) { + const int jid = (int) (js - _glfw.joysticks); + js->axes[axis] = value; + + if (_glfw.callbacks.joystick_axis) + _glfw.callbacks.joystick_axis(jid, axis, value); + _glfwInputGamepad(js); } // Notifies shared code of the new value of a joystick button // void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value) { + const int jid = (int) (js - _glfw.joysticks); + js->buttons[button] = value; + + if (_glfw.callbacks.joystick_button) + _glfw.callbacks.joystick_button(jid, button, value); + _glfwInputGamepad(js); } // Notifies shared code of the new value of a joystick hat // void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value) { + const int jid = (int) (js - _glfw.joysticks); const int base = js->buttonCount + hat * 4; js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE; @@ -401,6 +427,10 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value) js->buttons[base + 3] = (value & 0x08) ? GLFW_PRESS : GLFW_RELEASE; js->hats[hat] = value; + + if (_glfw.callbacks.joystick_hat) + _glfw.callbacks.joystick_hat(jid, hat, value); + _glfwInputGamepad(js); } @@ -1112,6 +1142,35 @@ GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun) return cbfun; } +GLFWAPI GLFWgamepadstatefun glfwSetGamepadStateCallback(GLFWgamepadstatefun cbfun) +{ + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP_POINTERS(_glfw.callbacks.gamepad_state, cbfun); + return cbfun; +} + +GLFWAPI GLFWjoystickbuttonfun glfwSetJoystickButtonCallback(GLFWjoystickbuttonfun cbfun) +{ + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP_POINTERS(_glfw.callbacks.joystick_button, cbfun); + return cbfun; +} + +GLFWAPI GLFWjoystickaxisfun glfwSetJoystickAxisCallback(GLFWjoystickaxisfun cbfun) +{ + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP_POINTERS(_glfw.callbacks.joystick_axis, cbfun); + return cbfun; +} + +GLFWAPI GLFWjoystickhatfun glfwSetJoystickHatCallback(GLFWjoystickhatfun cbfun) +{ + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP_POINTERS(_glfw.callbacks.joystick_hat, cbfun); + return cbfun; +} + + GLFWAPI int glfwUpdateGamepadMappings(const char* string) { int jid; diff --git a/src/internal.h b/src/internal.h index acdae22d..c135083f 100644 --- a/src/internal.h +++ b/src/internal.h @@ -565,8 +565,12 @@ struct _GLFWlibrary } vk; struct { - GLFWmonitorfun monitor; - GLFWjoystickfun joystick; + GLFWmonitorfun monitor; + GLFWjoystickfun joystick; + GLFWjoystickaxisfun joystick_axis; + GLFWjoystickbuttonfun joystick_button; + GLFWjoystickhatfun joystick_hat; + GLFWgamepadstatefun gamepad_state; } callbacks; // This is defined in the window API's platform.h From ee4132b5cfb278b9660eedff55f283f0aaab4645 Mon Sep 17 00:00:00 2001 From: Beoran Date: Thu, 7 Nov 2019 01:01:31 +0100 Subject: [PATCH 3/5] Test and fix joystick and game pad callbacks on Linux. --- include/GLFW/glfw3.h | 22 ++++++---------- src/input.c | 27 ++++++++++++++++---- src/internal.h | 1 + src/window.c | 2 ++ src/x11_window.c | 60 +++++++++++++++++++++++++++++++------------- tests/events.c | 50 ++++++++++++++++++++++++++++++++++++ 6 files changed, 125 insertions(+), 37 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 34713091..21ae6ce3 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1168,17 +1168,6 @@ typedef struct GLFWwindow GLFWwindow; */ typedef struct GLFWcursor GLFWcursor; -/*! @brief Gamepad state object. - * - * Gamepad state object, predeclared here. - * - * @since Added in version 3.4. - * - * @ingroup input - */ -typedef struct GLFWgamepadstate GLFWgamepadstate; - - /*! @brief The function pointer type for error callbacks. * * This is the function pointer type for error callbacks. An error callback @@ -1711,7 +1700,11 @@ typedef void (* GLFWjoystickhatfun)(int,int,int); * @endcode * * @param[in] jid The ID of the game pad that changed state. - * @param[in] state The updated state of the game pad. + * @param[in] buttons The states of each + * [gamepad button](@ref gamepad_buttons), + * `GLFW_PRESS` or `GLFW_RELEASE`. + * @param[in] axes The states of each [gamepad axis](@ref gamepad_axes), + * in the range -1.0 to 1.0 inclusive. * * @sa @ref input_gamepad * @sa @ref glfwSetGamepadStateCallback @@ -1719,7 +1712,8 @@ typedef void (* GLFWjoystickhatfun)(int,int,int); * @since Added in version 3.4. * @ingroup input */ -typedef void (* GLFWgamepadstatefun)(int,GLFWgamepadstate*); +typedef void (* GLFWgamepadstatefun)(int, unsigned char buttons[15], + float axes[6]); /*! @brief The function pointer type for Unicode character callbacks. @@ -5385,7 +5379,7 @@ GLFWAPI GLFWjoystickhatfun glfwSetJoystickHatCallback(GLFWjoystickhatfun callbac * * @callback_signature * @code - * void function_name(int jid, GLFWgamepadstate* state) + * void function_name(int jid, unsigned char buttons[15], float axes[6]) * @endcode * For more information about the callback parameters, see the * [function pointer type](@ref GLFWgamepadstatefun). diff --git a/src/input.c b/src/input.c index 6d07ce73..3664379b 100644 --- a/src/input.c +++ b/src/input.c @@ -370,10 +370,15 @@ void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths) void _glfwInputGamepad(_GLFWjoystick* js) { const int jid = (int) (js - _glfw.joysticks); - if (glfwJoystickIsGamepad(jid) && (_glfw.callbacks.gamepad_state)) { + + if (!_glfw.initialized) { + return; + } + + if ((js->mapping != NULL) && (_glfw.callbacks.gamepad_state)) { GLFWgamepadstate state; - if (0 == glfwGetGamepadState(jid, &state)) { - _glfw.callbacks.gamepad_state(jid, &state); + if (glfwGetGamepadState(jid, &state)) { + _glfw.callbacks.gamepad_state(jid, state.buttons, state.axes); } } } @@ -394,10 +399,11 @@ void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value) { const int jid = (int) (js - _glfw.joysticks); + if ((_glfw.callbacks.joystick_axis) && (js->axes[axis] != value)) + _glfw.callbacks.joystick_axis(jid, axis, value); + js->axes[axis] = value; - if (_glfw.callbacks.joystick_axis) - _glfw.callbacks.joystick_axis(jid, axis, value); _glfwInputGamepad(js); } @@ -495,6 +501,17 @@ void _glfwCenterCursorInContentArea(_GLFWwindow* window) _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0); } +void _glfwPollAllJoysticks() { + int jid; + + for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) + { + if (_glfw.joysticks[jid].present == GLFW_TRUE) { + _glfwPlatformPollJoystick(_glfw.joysticks + jid, _GLFW_POLL_ALL); + } + } +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW public API ////// diff --git a/src/internal.h b/src/internal.h index c135083f..4fdd4780 100644 --- a/src/internal.h +++ b/src/internal.h @@ -769,6 +769,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name, int hatCount); void _glfwFreeJoystick(_GLFWjoystick* js); void _glfwCenterCursorInContentArea(_GLFWwindow* window); +void _glfwPollAllJoysticks(); GLFWbool _glfwInitVulkan(int mode); void _glfwTerminateVulkan(void); diff --git a/src/window.c b/src/window.c index fa604d01..a8a00c3e 100644 --- a/src/window.c +++ b/src/window.c @@ -1069,12 +1069,14 @@ GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* GLFWAPI void glfwPollEvents(void) { _GLFW_REQUIRE_INIT(); + _glfwPollAllJoysticks(); _glfwPlatformPollEvents(); } GLFWAPI void glfwWaitEvents(void) { _GLFW_REQUIRE_INIT(); + _glfwPollAllJoysticks(); _glfwPlatformWaitEvents(); } diff --git a/src/x11_window.c b/src/x11_window.c index 56379a3c..b1182735 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -65,21 +65,32 @@ static GLFWbool waitForEvent(double* timeout) { fd_set fds; const int fd = ConnectionNumber(_glfw.x11.display); - int count = fd + 1; - -#if defined(__linux__) - if (_glfw.linjs.inotify > fd) - count = _glfw.linjs.inotify + 1; -#endif for (;;) { + int count = fd + 1; FD_ZERO(&fds); FD_SET(fd, &fds); + #if defined(__linux__) if (_glfw.linjs.inotify > 0) - FD_SET(_glfw.linjs.inotify, &fds); -#endif + { + if (_glfw.linjs.inotify >= count ) + count = _glfw.linjs.inotify + 1; + FD_SET(_glfw.linjs.inotify, &fds); + } + + for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) + { + if (_glfw.joysticks[jid].present) { + if (_glfw.joysticks[jid].linjs.fd >= count) + count = _glfw.joysticks[jid].linjs.fd + 1; + + FD_SET(_glfw.joysticks[jid].linjs.fd, &fds); + } + } + +#endif if (timeout) { const long seconds = (long) *timeout; @@ -2681,6 +2692,7 @@ void _glfwPlatformPollEvents(void) #if defined(__linux__) _glfwDetectJoystickConnectionLinux(); + _glfwPollAllJoysticks(); #endif XPending(_glfw.x11.display); @@ -2709,23 +2721,35 @@ void _glfwPlatformPollEvents(void) XFlush(_glfw.x11.display); } -void _glfwPlatformWaitEvents(void) +static GLFWbool waitForAndPollEvents(double * timeout) { - while (!XPending(_glfw.x11.display)) - waitForEvent(NULL); + GLFWbool result = GLFW_FALSE; + for (;;) + { + int xpending = XPending(_glfw.x11.display); + GLFWbool event = waitForEvent(timeout); + // We cannot use the boolean shortcut here, since + // waiting for events might have a side effect. + if (event || xpending ) + { + result = GLFW_TRUE; + break; + } + } _glfwPlatformPollEvents(); + return result; +} + + +void _glfwPlatformWaitEvents(void) +{ + waitForAndPollEvents(NULL); } void _glfwPlatformWaitEventsTimeout(double timeout) { - while (!XPending(_glfw.x11.display)) - { - if (!waitForEvent(&timeout)) - break; - } - - _glfwPlatformPollEvents(); + waitForAndPollEvents(&timeout); } void _glfwPlatformPostEmptyEvent(void) diff --git a/tests/events.c b/tests/events.c index 251e15d9..043436f4 100644 --- a/tests/events.c +++ b/tests/events.c @@ -494,6 +494,52 @@ static void joystick_callback(int jid, int event) } } +static void joystick_button_callback(int jid, int button, int state) { + printf("%08x at %0.3f: Joystick %i (%s) button %d state %d\n", + counter++, glfwGetTime(), + jid, + glfwGetJoystickName(jid), + button, + state); +} + +static void joystick_axis_callback(int jid, int axis, float value) { + printf("%08x at %0.3f: Joystick %i (%s) axis %d value %0.4f\n", + counter++, glfwGetTime(), jid, + glfwGetJoystickName(jid), + axis, + value); +} + +static void joystick_hat_callback(int jid, int hat, int value) { + printf("%08x at %0.3f: Joystick %i (%s) hat %d value %d\n", + counter++, glfwGetTime(), + jid, + glfwGetJoystickName(jid), + hat, + value); +} + +static void gamepad_state_callback(int jid, unsigned char buttons[15], float axes[6]) { + int i = 0; + printf("%08x at %0.3f: Gamepad %i (%s) state:", + counter++, glfwGetTime(), + jid, + glfwGetJoystickName(jid)); + + printf("Buttons: "); + for (i= 0 ; i < 15; i++) { + printf(" %d:%d", i, buttons[i]); + } + printf("Axes: "); + for (i= 0 ; i < 6; i++) { + printf(" %d:%0.4f", i, axes[i]); + } + printf("\n"); + +} + + int main(int argc, char** argv) { Slot* slots; @@ -511,6 +557,10 @@ int main(int argc, char** argv) glfwSetMonitorCallback(monitor_callback); glfwSetJoystickCallback(joystick_callback); + glfwSetJoystickAxisCallback(joystick_axis_callback); + glfwSetJoystickButtonCallback(joystick_button_callback); + glfwSetJoystickHatCallback(joystick_hat_callback); + glfwSetGamepadStateCallback(gamepad_state_callback); while ((ch = getopt(argc, argv, "hfn:")) != -1) { From 1ed4c6955031150fb814c322bd1b682c673faf82 Mon Sep 17 00:00:00 2001 From: Beoran Date: Thu, 7 Nov 2019 01:19:01 +0100 Subject: [PATCH 4/5] Remove accidentally duplicated function type definition. --- include/GLFW/glfw3.h | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 21ae6ce3..2f2ddd23 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1714,29 +1714,6 @@ typedef void (* GLFWjoystickhatfun)(int,int,int); */ typedef void (* GLFWgamepadstatefun)(int, unsigned char buttons[15], float axes[6]); - - -/*! @brief The function pointer type for Unicode character callbacks. - * - * This is the function pointer type for Unicode character callbacks. - * A Unicode character callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, unsigned int codepoint) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] codepoint The Unicode code point of the character. - * - * @sa @ref input_char - * @sa @ref glfwSetCharCallback - * - * @since Added in version 2.4. - * @glfw3 Added window handle parameter. - * - * @ingroup input - */ -typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); - /*! @brief Video mode type. * * This describes a single video mode. From ef269c0ae95627efad6dacf02eba55e589aaf64a Mon Sep 17 00:00:00 2001 From: Beoran Date: Sun, 15 Mar 2020 20:53:20 +0100 Subject: [PATCH 5/5] Only call the joystick event callback if the state actually changed. Only calculate the joystick ID when the event callback is actually called. --- src/input.c | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/input.c b/src/input.c index 3664379b..02675513 100644 --- a/src/input.c +++ b/src/input.c @@ -387,44 +387,45 @@ void _glfwInputGamepad(_GLFWjoystick* js) // void _glfwInputJoystick(_GLFWjoystick* js, int event) { - const int jid = (int) (js - _glfw.joysticks); - - if (_glfw.callbacks.joystick) + if (_glfw.callbacks.joystick) { + const int jid = (int) (js - _glfw.joysticks); _glfw.callbacks.joystick(jid, event); + } } + // Notifies shared code of the new value of a joystick axis // void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value) { - const int jid = (int) (js - _glfw.joysticks); + if (js->axes[axis] != value) { + const int jid = (int) (js - _glfw.joysticks); - if ((_glfw.callbacks.joystick_axis) && (js->axes[axis] != value)) - _glfw.callbacks.joystick_axis(jid, axis, value); - - js->axes[axis] = value; - - _glfwInputGamepad(js); + js->axes[axis] = value; + if (_glfw.callbacks.joystick_axis) + _glfw.callbacks.joystick_axis(jid, axis, value); + _glfwInputGamepad(js); + } } // Notifies shared code of the new value of a joystick button // void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value) { - const int jid = (int) (js - _glfw.joysticks); + if (js->buttons[button] != value) { + const int jid = (int) (js - _glfw.joysticks); - js->buttons[button] = value; - - if (_glfw.callbacks.joystick_button) - _glfw.callbacks.joystick_button(jid, button, value); - _glfwInputGamepad(js); + js->buttons[button] = value; + if(_glfw.callbacks.joystick_button) + _glfw.callbacks.joystick_button(jid, button, value); + _glfwInputGamepad(js); + } } // Notifies shared code of the new value of a joystick hat // void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value) { - const int jid = (int) (js - _glfw.joysticks); const int base = js->buttonCount + hat * 4; js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE; @@ -432,11 +433,14 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value) js->buttons[base + 2] = (value & 0x04) ? GLFW_PRESS : GLFW_RELEASE; js->buttons[base + 3] = (value & 0x08) ? GLFW_PRESS : GLFW_RELEASE; - js->hats[hat] = value; + if (js->hats[hat] != value) { + const int jid = (int) (js - _glfw.joysticks); - if (_glfw.callbacks.joystick_hat) - _glfw.callbacks.joystick_hat(jid, hat, value); - _glfwInputGamepad(js); + js->hats[hat] = value; + if(_glfw.callbacks.joystick_hat) + _glfw.callbacks.joystick_hat(jid, hat, value); + _glfwInputGamepad(js); + } }