diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 5abcc9f503..3488cd05ac 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -170,9 +170,9 @@ typedef enum SDL_EventType SDL_EVENT_GAMEPAD_AXIS_MOTION = 0x650, /**< Gamepad axis motion */ SDL_EVENT_GAMEPAD_BUTTON_DOWN, /**< Gamepad button pressed */ SDL_EVENT_GAMEPAD_BUTTON_UP, /**< Gamepad button released */ - SDL_EVENT_GAMEPAD_ADDED, /**< A new gamepad has been inserted into the system */ - SDL_EVENT_GAMEPAD_REMOVED, /**< An opened gamepad has been removed */ - SDL_EVENT_GAMEPAD_REMAPPED, /**< The gamepad mapping was updated */ + SDL_EVENT_GAMEPAD_ADDED, /**< A new gamepad has been inserted into the system */ + SDL_EVENT_GAMEPAD_REMOVED, /**< A gamepad has been removed */ + SDL_EVENT_GAMEPAD_REMAPPED, /**< The gamepad mapping was updated */ SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN, /**< Gamepad touchpad was touched */ SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION, /**< Gamepad touchpad finger was moved */ SDL_EVENT_GAMEPAD_TOUCHPAD_UP, /**< Gamepad touchpad finger was lifted */ diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index 854afa3ac9..146fe61876 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -31,6 +31,7 @@ #include "usb_ids.h" #include "hidapi/SDL_hidapi_nintendo.h" #include "../events/SDL_events_c.h" +#include "../SDL_hashtable.h" #ifdef SDL_PLATFORM_ANDROID @@ -103,6 +104,7 @@ static GamepadMapping_t *s_pSupportedGamepads SDL_GUARDED_BY(SDL_joystick_lock) static GamepadMapping_t *s_pDefaultMapping SDL_GUARDED_BY(SDL_joystick_lock) = NULL; static GamepadMapping_t *s_pXInputMapping SDL_GUARDED_BY(SDL_joystick_lock) = NULL; static MappingChangeTracker *s_mappingChangeTracker SDL_GUARDED_BY(SDL_joystick_lock) = NULL; +static SDL_HashTable *s_gamepadInstanceIDs SDL_GUARDED_BY(SDL_joystick_lock) = NULL; #define _guarded SDL_GUARDED_BY(SDL_joystick_lock) @@ -561,8 +563,11 @@ static void PopMappingChangeTracking(void) GamepadMapping_t *old_mapping = gamepad ? gamepad->mapping : tracker->joystick_mappings[i]; if (new_mapping && !old_mapping) { + SDL_InsertIntoHashTable(s_gamepadInstanceIDs, (void *)(uintptr_t)joystick, (const void *)SDL_TRUE); SDL_PrivateGamepadAdded(joystick); } else if (old_mapping && !new_mapping) { + SDL_RemoveFromHashTable(s_gamepadInstanceIDs, (void *)(uintptr_t)joystick); + SDL_InsertIntoHashTable(s_gamepadInstanceIDs, (void *)(uintptr_t)joystick, (const void *)SDL_FALSE); SDL_PrivateGamepadRemoved(joystick); } else if (old_mapping != new_mapping || HasMappingChangeTracking(tracker, new_mapping)) { if (gamepad) { @@ -2560,10 +2565,20 @@ SDL_bool SDL_IsGamepad(SDL_JoystickID instance_id) SDL_LockJoysticks(); { - if (SDL_PrivateGetGamepadMapping(instance_id, SDL_TRUE) != NULL) { - retval = SDL_TRUE; + const void *value; + if (SDL_FindInHashTable(s_gamepadInstanceIDs, (void *)(uintptr_t)instance_id, &value)) { + retval = (SDL_bool)(uintptr_t)value; } else { - retval = SDL_FALSE; + if (SDL_PrivateGetGamepadMapping(instance_id, SDL_TRUE) != NULL) { + retval = SDL_TRUE; + } else { + retval = SDL_FALSE; + } + + if (!s_gamepadInstanceIDs) { + s_gamepadInstanceIDs = SDL_CreateHashTable(NULL, 4, SDL_HashID, SDL_KeyMatchID, NULL, SDL_FALSE); + } + SDL_InsertIntoHashTable(s_gamepadInstanceIDs, (void *)(uintptr_t)instance_id, (void *)(uintptr_t)retval); } } SDL_UnlockJoysticks(); @@ -3669,6 +3684,11 @@ void SDL_QuitGamepads(void) SDL_CloseGamepad(SDL_gamepads); } + if (s_gamepadInstanceIDs) { + SDL_DestroyHashTable(s_gamepadInstanceIDs); + s_gamepadInstanceIDs = NULL; + } + SDL_UnlockJoysticks(); } diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index c24b3e1bd6..028ff1a4f0 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -898,7 +898,7 @@ static SDL_bool ShouldAttemptSensorFusion(SDL_Joystick *joystick, SDL_bool *inve *invert_sensors = SDL_FALSE; /* The SDL controller sensor API is only available for gamepads (at the moment) */ - if (!joystick->is_gamepad) { + if (!SDL_IsGamepad(joystick->instance_id)) { return SDL_FALSE; } @@ -1150,8 +1150,6 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id) } } - joystick->is_gamepad = SDL_IsGamepad(instance_id); - /* Get the Steam Input API handle */ info = SDL_GetJoystickInstanceVirtualGamepadInfo(instance_id); if (info) { @@ -2135,10 +2133,7 @@ void SDL_PrivateJoystickRemoved(SDL_JoystickID instance_id) } } - /* FIXME: The driver no longer provides the name and GUID at this point, so we - * don't know whether this was a gamepad. For now always send the event. - */ - if (SDL_TRUE /*SDL_IsGamepad(instance_id)*/) { + if (SDL_IsGamepad(instance_id)) { SDL_PrivateGamepadRemoved(instance_id); } @@ -2363,7 +2358,7 @@ static void SendSteamHandleUpdateEvents(void) for (joystick = SDL_joysticks; joystick; joystick = joystick->next) { SDL_bool changed = SDL_FALSE; - if (!joystick->is_gamepad) { + if (!SDL_IsGamepad(joystick->instance_id)) { continue; } @@ -3449,7 +3444,7 @@ SDL_JoystickType SDL_GetJoystickType(SDL_Joystick *joystick) { CHECK_JOYSTICK_MAGIC(joystick, SDL_JOYSTICK_TYPE_UNKNOWN); - if (joystick->is_gamepad) { + if (SDL_IsGamepad(joystick->instance_id)) { type = SDL_JOYSTICK_TYPE_GAMEPAD; } } diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index 52bcd17d36..e006681f8c 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -118,7 +118,6 @@ struct SDL_Joystick Uint64 led_expiration _guarded; SDL_bool attached _guarded; - SDL_bool is_gamepad _guarded; SDL_JoystickConnectionState connection_state _guarded; SDL_PowerState battery_state _guarded; int battery_percent _guarded;