|
|
@@ -9,8 +9,18 @@ namespace Ryujinx.Input.SDL2
|
|
|
{
|
|
|
private readonly Dictionary<int, string> _gamepadsInstanceIdsMapping;
|
|
|
private readonly List<string> _gamepadsIds;
|
|
|
+ private readonly object _lock = new object();
|
|
|
|
|
|
- public ReadOnlySpan<string> GamepadsIds => _gamepadsIds.ToArray();
|
|
|
+ public ReadOnlySpan<string> GamepadsIds
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ lock (_lock)
|
|
|
+ {
|
|
|
+ return _gamepadsIds.ToArray();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
public string DriverName => "SDL2";
|
|
|
|
|
|
@@ -35,28 +45,39 @@ namespace Ryujinx.Input.SDL2
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private static string GenerateGamepadId(int joystickIndex)
|
|
|
+ private string GenerateGamepadId(int joystickIndex)
|
|
|
{
|
|
|
Guid guid = SDL_JoystickGetDeviceGUID(joystickIndex);
|
|
|
|
|
|
+ // Add a unique identifier to the start of the GUID in case of duplicates.
|
|
|
+
|
|
|
if (guid == Guid.Empty)
|
|
|
{
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- return joystickIndex + "-" + guid;
|
|
|
+ string id;
|
|
|
+
|
|
|
+ lock (_lock)
|
|
|
+ {
|
|
|
+ int guidIndex = 0;
|
|
|
+ id = guidIndex + "-" + guid;
|
|
|
+
|
|
|
+ while (_gamepadsIds.Contains(id))
|
|
|
+ {
|
|
|
+ id = (++guidIndex) + "-" + guid;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return id;
|
|
|
}
|
|
|
|
|
|
- private static int GetJoystickIndexByGamepadId(string id)
|
|
|
+ private int GetJoystickIndexByGamepadId(string id)
|
|
|
{
|
|
|
- string[] data = id.Split("-");
|
|
|
-
|
|
|
- if (data.Length != 6 || !int.TryParse(data[0], out int joystickIndex))
|
|
|
+ lock (_lock)
|
|
|
{
|
|
|
- return -1;
|
|
|
+ return _gamepadsIds.IndexOf(id);
|
|
|
}
|
|
|
-
|
|
|
- return joystickIndex;
|
|
|
}
|
|
|
|
|
|
private void HandleJoyStickDisconnected(int joystickInstanceId)
|
|
|
@@ -64,7 +85,11 @@ namespace Ryujinx.Input.SDL2
|
|
|
if (_gamepadsInstanceIdsMapping.TryGetValue(joystickInstanceId, out string id))
|
|
|
{
|
|
|
_gamepadsInstanceIdsMapping.Remove(joystickInstanceId);
|
|
|
- _gamepadsIds.Remove(id);
|
|
|
+
|
|
|
+ lock (_lock)
|
|
|
+ {
|
|
|
+ _gamepadsIds.Remove(id);
|
|
|
+ }
|
|
|
|
|
|
OnGamepadDisconnected?.Invoke(id);
|
|
|
}
|
|
|
@@ -74,23 +99,26 @@ namespace Ryujinx.Input.SDL2
|
|
|
{
|
|
|
if (SDL_IsGameController(joystickDeviceId) == SDL_bool.SDL_TRUE)
|
|
|
{
|
|
|
- string id = GenerateGamepadId(joystickDeviceId);
|
|
|
-
|
|
|
- if (id == null)
|
|
|
+ if (_gamepadsInstanceIdsMapping.ContainsKey(joystickInstanceId))
|
|
|
{
|
|
|
+ // Sometimes a JoyStick connected event fires after the app starts even though it was connected before
|
|
|
+ // so it is rejected to avoid doubling the entries.
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // Sometimes a JoyStick connected event fires after the app starts even though it was connected before
|
|
|
- // so it is rejected to avoid doubling the entries.
|
|
|
- if (_gamepadsIds.Contains(id))
|
|
|
+ string id = GenerateGamepadId(joystickDeviceId);
|
|
|
+
|
|
|
+ if (id == null)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (_gamepadsInstanceIdsMapping.TryAdd(joystickInstanceId, id))
|
|
|
{
|
|
|
- _gamepadsIds.Add(id);
|
|
|
+ lock (_lock)
|
|
|
+ {
|
|
|
+ _gamepadsIds.Add(id);
|
|
|
+ }
|
|
|
|
|
|
OnGamepadConnected?.Invoke(id);
|
|
|
}
|
|
|
@@ -110,7 +138,10 @@ namespace Ryujinx.Input.SDL2
|
|
|
OnGamepadDisconnected?.Invoke(id);
|
|
|
}
|
|
|
|
|
|
- _gamepadsIds.Clear();
|
|
|
+ lock (_lock)
|
|
|
+ {
|
|
|
+ _gamepadsIds.Clear();
|
|
|
+ }
|
|
|
|
|
|
SDL2Driver.Instance.Dispose();
|
|
|
}
|
|
|
@@ -131,11 +162,6 @@ namespace Ryujinx.Input.SDL2
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- if (id != GenerateGamepadId(joystickIndex))
|
|
|
- {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
IntPtr gamepadHandle = SDL_GameControllerOpen(joystickIndex);
|
|
|
|
|
|
if (gamepadHandle == IntPtr.Zero)
|