Fix unplugging controller sometimes crashing game (#6692)

Could crash if the ID wasn't in the dictionary.
The old code also didn't properly close everything
(it would close either the jostick or the gamepad, but not both).
This commit is contained in:
Susko3
2026-02-08 17:53:13 +01:00
committed by GitHub
parent c9ee4da7a4
commit ec800bc9c7
2 changed files with 30 additions and 16 deletions

View File

@@ -275,8 +275,7 @@ namespace osu.Framework.Platform.SDL2
break;
case SDL_EventType.SDL_CONTROLLERDEVICEREMOVED:
SDL_GameControllerClose(controllers[evtCdevice.which].ControllerHandle);
controllers.Remove(evtCdevice.which);
removeJoystick(evtCdevice.which);
break;
case SDL_EventType.SDL_CONTROLLERDEVICEREMAPPED:
@@ -323,6 +322,20 @@ namespace osu.Framework.Platform.SDL2
controllers[instanceID] = new SDL2ControllerBindings(joystick, controller);
}
private void removeJoystick(int which)
{
int instanceID = SDL_JoystickGetDeviceInstanceID(which);
if (controllers.Remove(instanceID, out var controller))
{
if (controller.ControllerHandle != IntPtr.Zero)
SDL_GameControllerClose(controller.ControllerHandle);
if (controller.JoystickHandle != IntPtr.Zero)
SDL_JoystickClose(controller.JoystickHandle);
}
}
/// <summary>
/// Populates <see cref="controllers"/> with joysticks that are already connected.
/// </summary>
@@ -343,12 +356,7 @@ namespace osu.Framework.Platform.SDL2
break;
case SDL_EventType.SDL_JOYDEVICEREMOVED:
// if the joystick is already closed, ignore it
if (!controllers.ContainsKey(evtJdevice.which))
break;
SDL_JoystickClose(controllers[evtJdevice.which].JoystickHandle);
controllers.Remove(evtJdevice.which);
removeJoystick(evtJdevice.which);
break;
}
}

View File

@@ -324,8 +324,7 @@ namespace osu.Framework.Platform.SDL3
break;
case SDL_EventType.SDL_EVENT_GAMEPAD_REMOVED:
SDL_CloseGamepad(controllers[evtCdevice.which].GamepadHandle);
controllers.Remove(evtCdevice.which);
removeJoystick(evtCdevice.which);
break;
case SDL_EventType.SDL_EVENT_GAMEPAD_REMAPPED:
@@ -370,6 +369,18 @@ namespace osu.Framework.Platform.SDL3
controllers[instanceID] = new SDL3ControllerBindings(joystick, controller);
}
private void removeJoystick(SDL_JoystickID instanceID)
{
if (controllers.Remove(instanceID, out var controller))
{
if (controller.GamepadHandle != null)
SDL_CloseGamepad(controller.GamepadHandle);
if (controller.JoystickHandle != null)
SDL_CloseJoystick(controller.JoystickHandle);
}
}
/// <summary>
/// Populates <see cref="controllers"/> with joysticks that are already connected.
/// </summary>
@@ -395,12 +406,7 @@ namespace osu.Framework.Platform.SDL3
break;
case SDL_EventType.SDL_EVENT_JOYSTICK_REMOVED:
// if the joystick is already closed, ignore it
if (!controllers.ContainsKey(evtJdevice.which))
break;
SDL_CloseJoystick(controllers[evtJdevice.which].JoystickHandle);
controllers.Remove(evtJdevice.which);
removeJoystick(evtJdevice.which);
break;
}
}