Send gamepad and joystick removed events when quitting

This helps applications do proper cleanup when reinitializing gamepads, e.g. to reset controller mappings
This commit is contained in:
Sam Lantinga
2023-07-18 09:01:14 -07:00
parent 0a4e6f6d29
commit ccefce8321
2 changed files with 37 additions and 17 deletions

View File

@@ -178,6 +178,26 @@ static GamepadMapping_t *SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, co
static int SDL_SendGamepadAxis(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_GamepadAxis axis, Sint16 value); static int SDL_SendGamepadAxis(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_GamepadAxis axis, Sint16 value);
static int SDL_SendGamepadButton(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_GamepadButton button, Uint8 state); static int SDL_SendGamepadButton(Uint64 timestamp, SDL_Gamepad *gamepad, SDL_GamepadButton button, Uint8 state);
static void SDL_PrivateGamepadAdded(SDL_JoystickID instance_id)
{
SDL_Event event;
event.type = SDL_EVENT_GAMEPAD_ADDED;
event.common.timestamp = 0;
event.gdevice.which = instance_id;
SDL_PushEvent(&event);
}
static void SDL_PrivateGamepadRemoved(SDL_JoystickID instance_id)
{
SDL_Event event;
event.type = SDL_EVENT_GAMEPAD_REMOVED;
event.common.timestamp = 0;
event.gdevice.which = instance_id;
SDL_PushEvent(&event);
}
static SDL_bool HasSameOutput(SDL_GamepadBinding *a, SDL_GamepadBinding *b) static SDL_bool HasSameOutput(SDL_GamepadBinding *a, SDL_GamepadBinding *b)
{ {
if (a->outputType != b->outputType) { if (a->outputType != b->outputType) {
@@ -374,12 +394,7 @@ static int SDLCALL SDL_GamepadEventWatcher(void *userdata, SDL_Event *event)
case SDL_EVENT_JOYSTICK_ADDED: case SDL_EVENT_JOYSTICK_ADDED:
{ {
if (SDL_IsGamepad(event->jdevice.which)) { if (SDL_IsGamepad(event->jdevice.which)) {
SDL_Event deviceevent; SDL_PrivateGamepadAdded(event->jdevice.which);
deviceevent.type = SDL_EVENT_GAMEPAD_ADDED;
deviceevent.common.timestamp = 0;
deviceevent.gdevice.which = event->jdevice.which;
SDL_PushEvent(&deviceevent);
} }
} break; } break;
case SDL_EVENT_JOYSTICK_REMOVED: case SDL_EVENT_JOYSTICK_REMOVED:
@@ -393,14 +408,8 @@ static int SDLCALL SDL_GamepadEventWatcher(void *userdata, SDL_Event *event)
} }
} }
/* We don't know if this was a gamepad, so go ahead and send an event */ if (SDL_IsGamepad(event->jdevice.which)) {
{ SDL_PrivateGamepadRemoved(event->jdevice.which);
SDL_Event deviceevent;
deviceevent.type = SDL_EVENT_GAMEPAD_REMOVED;
deviceevent.common.timestamp = 0;
deviceevent.gdevice.which = event->jdevice.which;
SDL_PushEvent(&deviceevent);
} }
} break; } break;
case SDL_EVENT_JOYSTICK_UPDATE_COMPLETE: case SDL_EVENT_JOYSTICK_UPDATE_COMPLETE:
@@ -3135,10 +3144,15 @@ void SDL_CloseGamepad(SDL_Gamepad *gamepad)
void SDL_QuitGamepads(void) void SDL_QuitGamepads(void)
{ {
SDL_LockJoysticks(); SDL_LockJoysticks();
SDL_DelEventWatch(SDL_GamepadEventWatcher, NULL);
while (SDL_gamepads) { while (SDL_gamepads) {
SDL_PrivateGamepadRemoved(SDL_gamepads->joystick->instance_id);
SDL_gamepads->ref_count = 1; SDL_gamepads->ref_count = 1;
SDL_CloseGamepad(SDL_gamepads); SDL_CloseGamepad(SDL_gamepads);
} }
SDL_UnlockJoysticks(); SDL_UnlockJoysticks();
} }
@@ -3156,8 +3170,6 @@ void SDL_QuitGamepadMappings(void)
SDL_free(pGamepadMap); SDL_free(pGamepadMap);
} }
SDL_DelEventWatch(SDL_GamepadEventWatcher, NULL);
SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES, SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES,
SDL_GamepadIgnoreDevicesChanged, NULL); SDL_GamepadIgnoreDevicesChanged, NULL);
SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT, SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT,

View File

@@ -1501,12 +1501,20 @@ void SDL_CloseJoystick(SDL_Joystick *joystick)
void SDL_QuitJoysticks(void) void SDL_QuitJoysticks(void)
{ {
int i; int i;
SDL_JoystickID *joysticks;
SDL_LockJoysticks(); SDL_LockJoysticks();
SDL_joysticks_quitting = SDL_TRUE; SDL_joysticks_quitting = SDL_TRUE;
/* Stop the event polling */ joysticks = SDL_GetJoysticks(NULL);
if (joysticks) {
for (i = 0; joysticks[i]; ++i) {
SDL_PrivateJoystickRemoved(joysticks[i]);
}
SDL_free(joysticks);
}
while (SDL_joysticks) { while (SDL_joysticks) {
SDL_joysticks->ref_count = 1; SDL_joysticks->ref_count = 1;
SDL_CloseJoystick(SDL_joysticks); SDL_CloseJoystick(SDL_joysticks);