mirror of
				https://github.com/libsdl-org/SDL.git
				synced 2025-10-26 12:27:44 +00:00 
			
		
		
		
	The names of joysticks and gamepads are valid after they've been removed
This commit is contained in:
		| @@ -74,6 +74,7 @@ | |||||||
|  |  | ||||||
| static bool SDL_gamepads_initialized; | static bool SDL_gamepads_initialized; | ||||||
| static SDL_Gamepad *SDL_gamepads SDL_GUARDED_BY(SDL_joystick_lock) = NULL; | static SDL_Gamepad *SDL_gamepads SDL_GUARDED_BY(SDL_joystick_lock) = NULL; | ||||||
|  | static SDL_HashTable *SDL_gamepad_names SDL_GUARDED_BY(SDL_joystick_lock) = NULL; | ||||||
|  |  | ||||||
| // The face button style of a gamepad | // The face button style of a gamepad | ||||||
| typedef enum | typedef enum | ||||||
| @@ -372,6 +373,45 @@ static void RecenterGamepad(SDL_Gamepad *gamepad) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static const char *SDL_UpdateGamepadNameForID(SDL_JoystickID instance_id) | ||||||
|  | { | ||||||
|  |     const char *current_name = NULL; | ||||||
|  |  | ||||||
|  |     GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id, true); | ||||||
|  |     if (mapping) { | ||||||
|  |         if (SDL_strcmp(mapping->name, "*") == 0) { | ||||||
|  |             current_name = SDL_GetJoystickNameForID(instance_id); | ||||||
|  |         } else { | ||||||
|  |             current_name = mapping->name; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!SDL_gamepad_names) { | ||||||
|  |         return SDL_GetPersistentString(current_name); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     char *name = NULL; | ||||||
|  |     bool found = SDL_FindInHashTable(SDL_gamepad_names, (const void *)(uintptr_t)instance_id, (const void **)&name); | ||||||
|  |     if (!current_name) { | ||||||
|  |         if (!found) { | ||||||
|  |             SDL_SetError("Gamepad %" SDL_PRIu32 " not found", instance_id); | ||||||
|  |             return NULL; | ||||||
|  |         } | ||||||
|  |         if (!name) { | ||||||
|  |             // SDL_strdup() failed during insert | ||||||
|  |             SDL_OutOfMemory(); | ||||||
|  |             return NULL; | ||||||
|  |         } | ||||||
|  |         return name; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!name || SDL_strcmp(name, current_name) != 0) { | ||||||
|  |         name = SDL_strdup(current_name); | ||||||
|  |         SDL_InsertIntoHashTable(SDL_gamepad_names, (const void *)(uintptr_t)instance_id, name, true); | ||||||
|  |     } | ||||||
|  |     return name; | ||||||
|  | } | ||||||
|  |  | ||||||
| void SDL_PrivateGamepadAdded(SDL_JoystickID instance_id) | void SDL_PrivateGamepadAdded(SDL_JoystickID instance_id) | ||||||
| { | { | ||||||
|     SDL_Event event; |     SDL_Event event; | ||||||
| @@ -380,6 +420,8 @@ void SDL_PrivateGamepadAdded(SDL_JoystickID instance_id) | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     SDL_UpdateGamepadNameForID(instance_id); | ||||||
|  |  | ||||||
|     event.type = SDL_EVENT_GAMEPAD_ADDED; |     event.type = SDL_EVENT_GAMEPAD_ADDED; | ||||||
|     event.common.timestamp = 0; |     event.common.timestamp = 0; | ||||||
|     event.gdevice.which = instance_id; |     event.gdevice.which = instance_id; | ||||||
| @@ -2969,6 +3011,10 @@ bool SDL_InitGamepads(void) | |||||||
|  |  | ||||||
|     SDL_gamepads_initialized = true; |     SDL_gamepads_initialized = true; | ||||||
|  |  | ||||||
|  |     SDL_LockJoysticks(); | ||||||
|  |  | ||||||
|  |     SDL_gamepad_names = SDL_CreateHashTable(0, false, SDL_HashID, SDL_KeyMatchID, SDL_DestroyHashValue, NULL); | ||||||
|  |  | ||||||
|     // Watch for joystick events and fire gamepad ones if needed |     // Watch for joystick events and fire gamepad ones if needed | ||||||
|     SDL_AddEventWatch(SDL_GamepadEventWatcher, NULL); |     SDL_AddEventWatch(SDL_GamepadEventWatcher, NULL); | ||||||
|  |  | ||||||
| @@ -2983,6 +3029,8 @@ bool SDL_InitGamepads(void) | |||||||
|         SDL_free(joysticks); |         SDL_free(joysticks); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     SDL_UnlockJoysticks(); | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -3029,19 +3077,10 @@ SDL_JoystickID *SDL_GetGamepads(int *count) | |||||||
|  |  | ||||||
| const char *SDL_GetGamepadNameForID(SDL_JoystickID instance_id) | const char *SDL_GetGamepadNameForID(SDL_JoystickID instance_id) | ||||||
| { | { | ||||||
|     const char *result = NULL; |     const char *result; | ||||||
|  |  | ||||||
|     SDL_LockJoysticks(); |     SDL_LockJoysticks(); | ||||||
|     { |     result = SDL_UpdateGamepadNameForID(instance_id); | ||||||
|         GamepadMapping_t *mapping = SDL_PrivateGetGamepadMapping(instance_id, true); |  | ||||||
|         if (mapping) { |  | ||||||
|             if (SDL_strcmp(mapping->name, "*") == 0) { |  | ||||||
|                 result = SDL_GetJoystickNameForID(instance_id); |  | ||||||
|             } else { |  | ||||||
|                 result = SDL_GetPersistentString(mapping->name); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     SDL_UnlockJoysticks(); |     SDL_UnlockJoysticks(); | ||||||
|  |  | ||||||
|     return result; |     return result; | ||||||
| @@ -4298,6 +4337,11 @@ void SDL_QuitGamepads(void) | |||||||
|         SDL_CloseGamepad(SDL_gamepads); |         SDL_CloseGamepad(SDL_gamepads); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (SDL_gamepad_names) { | ||||||
|  |         SDL_DestroyHashTable(SDL_gamepad_names); | ||||||
|  |         SDL_gamepad_names = NULL; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     SDL_UnlockJoysticks(); |     SDL_UnlockJoysticks(); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -123,6 +123,7 @@ static bool SDL_joystick_being_added; | |||||||
| static SDL_Joystick *SDL_joysticks SDL_GUARDED_BY(SDL_joystick_lock) = NULL; | static SDL_Joystick *SDL_joysticks SDL_GUARDED_BY(SDL_joystick_lock) = NULL; | ||||||
| static int SDL_joystick_player_count SDL_GUARDED_BY(SDL_joystick_lock) = 0; | static int SDL_joystick_player_count SDL_GUARDED_BY(SDL_joystick_lock) = 0; | ||||||
| static SDL_JoystickID *SDL_joystick_players SDL_GUARDED_BY(SDL_joystick_lock) = NULL; | static SDL_JoystickID *SDL_joystick_players SDL_GUARDED_BY(SDL_joystick_lock) = NULL; | ||||||
|  | static SDL_HashTable *SDL_joystick_names SDL_GUARDED_BY(SDL_joystick_lock) = NULL; | ||||||
| static bool SDL_joystick_allows_background_events = false; | static bool SDL_joystick_allows_background_events = false; | ||||||
|  |  | ||||||
| static Uint32 initial_old_xboxone_controllers[] = { | static Uint32 initial_old_xboxone_controllers[] = { | ||||||
| @@ -833,6 +834,8 @@ bool SDL_InitJoysticks(void) | |||||||
|  |  | ||||||
|     SDL_joysticks_initialized = true; |     SDL_joysticks_initialized = true; | ||||||
|  |  | ||||||
|  |     SDL_joystick_names = SDL_CreateHashTable(0, false, SDL_HashID, SDL_KeyMatchID, SDL_DestroyHashValue, NULL); | ||||||
|  |  | ||||||
|     SDL_LoadVIDPIDList(&old_xboxone_controllers); |     SDL_LoadVIDPIDList(&old_xboxone_controllers); | ||||||
|     SDL_LoadVIDPIDList(&arcadestick_devices); |     SDL_LoadVIDPIDList(&arcadestick_devices); | ||||||
|     SDL_LoadVIDPIDList(&blacklist_devices); |     SDL_LoadVIDPIDList(&blacklist_devices); | ||||||
| @@ -980,20 +983,52 @@ const SDL_SteamVirtualGamepadInfo *SDL_GetJoystickVirtualGamepadInfoForID(SDL_Jo | |||||||
| /* | /* | ||||||
|  * Get the implementation dependent name of a joystick |  * Get the implementation dependent name of a joystick | ||||||
|  */ |  */ | ||||||
| const char *SDL_GetJoystickNameForID(SDL_JoystickID instance_id) | static const char *SDL_UpdateJoystickNameForID(SDL_JoystickID instance_id) | ||||||
| { | { | ||||||
|     SDL_JoystickDriver *driver; |     SDL_JoystickDriver *driver; | ||||||
|     int device_index; |     int device_index; | ||||||
|     const char *name = NULL; |     const char *current_name = NULL; | ||||||
|     const SDL_SteamVirtualGamepadInfo *info; |     const SDL_SteamVirtualGamepadInfo *info; | ||||||
|  |  | ||||||
|     SDL_LockJoysticks(); |  | ||||||
|     info = SDL_GetJoystickVirtualGamepadInfoForID(instance_id); |     info = SDL_GetJoystickVirtualGamepadInfoForID(instance_id); | ||||||
|     if (info) { |     if (info) { | ||||||
|         name = SDL_GetPersistentString(info->name); |         current_name = info->name; | ||||||
|     } else if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) { |     } else if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) { | ||||||
|         name = SDL_GetPersistentString(driver->GetDeviceName(device_index)); |         current_name = driver->GetDeviceName(device_index); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (!SDL_joystick_names) { | ||||||
|  |         return SDL_GetPersistentString(current_name); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     char *name = NULL; | ||||||
|  |     bool found = SDL_FindInHashTable(SDL_joystick_names, (const void *)(uintptr_t)instance_id, (const void **)&name); | ||||||
|  |     if (!current_name) { | ||||||
|  |         if (!found) { | ||||||
|  |             SDL_SetError("Joystick %" SDL_PRIu32 " not found", instance_id); | ||||||
|  |             return NULL; | ||||||
|  |         } | ||||||
|  |         if (!name) { | ||||||
|  |             // SDL_strdup() failed during insert | ||||||
|  |             SDL_OutOfMemory(); | ||||||
|  |             return NULL; | ||||||
|  |         } | ||||||
|  |         return name; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!name || SDL_strcmp(name, current_name) != 0) { | ||||||
|  |         name = SDL_strdup(current_name); | ||||||
|  |         SDL_InsertIntoHashTable(SDL_joystick_names, (const void *)(uintptr_t)instance_id, name, true); | ||||||
|  |     } | ||||||
|  |     return name; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const char *SDL_GetJoystickNameForID(SDL_JoystickID instance_id) | ||||||
|  | { | ||||||
|  |     const char *name; | ||||||
|  |  | ||||||
|  |     SDL_LockJoysticks(); | ||||||
|  |     name = SDL_UpdateJoystickNameForID(instance_id); | ||||||
|     SDL_UnlockJoysticks(); |     SDL_UnlockJoysticks(); | ||||||
|  |  | ||||||
|     return name; |     return name; | ||||||
| @@ -2234,6 +2269,11 @@ void SDL_QuitJoysticks(void) | |||||||
|  |  | ||||||
|     SDL_QuitGamepadMappings(); |     SDL_QuitGamepadMappings(); | ||||||
|  |  | ||||||
|  |     if (SDL_joystick_names) { | ||||||
|  |         SDL_DestroyHashTable(SDL_joystick_names); | ||||||
|  |         SDL_joystick_names = NULL; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     SDL_joysticks_quitting = false; |     SDL_joysticks_quitting = false; | ||||||
|     SDL_joysticks_initialized = false; |     SDL_joysticks_initialized = false; | ||||||
|  |  | ||||||
| @@ -2343,6 +2383,8 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id) | |||||||
|         SDL_SetJoystickIDForPlayerIndex(player_index, instance_id); |         SDL_SetJoystickIDForPlayerIndex(player_index, instance_id); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     SDL_UpdateJoystickNameForID(instance_id); | ||||||
|  |  | ||||||
|     { |     { | ||||||
|         SDL_Event event; |         SDL_Event event; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1811,12 +1811,12 @@ void SDLTest_PrintEvent(const SDL_Event *event) | |||||||
|                 event->wheel.x, event->wheel.y, event->wheel.direction, event->wheel.windowID); |                 event->wheel.x, event->wheel.y, event->wheel.direction, event->wheel.windowID); | ||||||
|         break; |         break; | ||||||
|     case SDL_EVENT_JOYSTICK_ADDED: |     case SDL_EVENT_JOYSTICK_ADDED: | ||||||
|         SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 " attached", |         SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 " (%s) attached", | ||||||
|                 event->jdevice.which); |                 event->jdevice.which, SDL_GetJoystickNameForID(event->jdevice.which)); | ||||||
|         break; |         break; | ||||||
|     case SDL_EVENT_JOYSTICK_REMOVED: |     case SDL_EVENT_JOYSTICK_REMOVED: | ||||||
|         SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 " removed", |         SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 " (%s) removed", | ||||||
|                 event->jdevice.which); |                 event->jdevice.which, SDL_GetJoystickNameForID(event->jdevice.which)); | ||||||
|         break; |         break; | ||||||
|     case SDL_EVENT_JOYSTICK_AXIS_MOTION: |     case SDL_EVENT_JOYSTICK_AXIS_MOTION: | ||||||
|         SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 " axis %d value: %d", |         SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 " axis %d value: %d", | ||||||
| @@ -1877,12 +1877,12 @@ void SDLTest_PrintEvent(const SDL_Event *event) | |||||||
|                 event->jbattery.which, event->jbattery.percent); |                 event->jbattery.which, event->jbattery.percent); | ||||||
|         break; |         break; | ||||||
|     case SDL_EVENT_GAMEPAD_ADDED: |     case SDL_EVENT_GAMEPAD_ADDED: | ||||||
|         SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " attached", |         SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " (%s) attached", | ||||||
|                 event->gdevice.which); |                 event->gdevice.which, SDL_GetGamepadNameForID(event->gdevice.which)); | ||||||
|         break; |         break; | ||||||
|     case SDL_EVENT_GAMEPAD_REMOVED: |     case SDL_EVENT_GAMEPAD_REMOVED: | ||||||
|         SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " removed", |         SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " (%s) removed", | ||||||
|                 event->gdevice.which); |                 event->gdevice.which, SDL_GetGamepadNameForID(event->gdevice.which)); | ||||||
|         break; |         break; | ||||||
|     case SDL_EVENT_GAMEPAD_REMAPPED: |     case SDL_EVENT_GAMEPAD_REMAPPED: | ||||||
|         SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " mapping changed", |         SDL_Log("SDL EVENT: Gamepad %" SDL_PRIu32 " mapping changed", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Sam Lantinga
					Sam Lantinga