Added Steam Input API support for game controllers

Added support for getting the real controller info, as well as the function SDL_GameControllerGetSteamHandle() to get the Steam Input API handle, from the virtual gamepads provided by Steam.

Also added an event SDL_CONTROLLERSTEAMHANDLEUPDATED which is triggered when a controller's API handle changes, e.g. the controllers were reassigned slots in the Steam UI.

(cherry picked from commit c981a597dc7c69e7532796b3a206071807479d35)
This commit is contained in:
Sam Lantinga 2023-12-09 23:05:34 -08:00
parent 9720672374
commit 7bb0e839a6
41 changed files with 827 additions and 49 deletions

View file

@ -412,6 +412,7 @@
<ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapi_rumble.h" /> <ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapi_rumble.h" />
<ClInclude Include="..\..\src\joystick\SDL_gamecontrollerdb.h" /> <ClInclude Include="..\..\src\joystick\SDL_gamecontrollerdb.h" />
<ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" /> <ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" />
<ClInclude Include="..\..\src\joystick\SDL_steam_virtual_gamepad.h" />
<ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" /> <ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
<ClInclude Include="..\..\src\joystick\usb_ids.h" /> <ClInclude Include="..\..\src\joystick\usb_ids.h" />
<ClInclude Include="..\..\src\joystick\virtual\SDL_virtualjoystick_c.h" /> <ClInclude Include="..\..\src\joystick\virtual\SDL_virtualjoystick_c.h" />
@ -609,6 +610,7 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c" /> <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c" />
<ClCompile Include="..\..\src\joystick\SDL_gamecontroller.c" /> <ClCompile Include="..\..\src\joystick\SDL_gamecontroller.c" />
<ClCompile Include="..\..\src\joystick\SDL_joystick.c" /> <ClCompile Include="..\..\src\joystick\SDL_joystick.c" />
<ClCompile Include="..\..\src\joystick\SDL_steam_virtual_gamepad.c" />
<ClCompile Include="..\..\src\joystick\virtual\SDL_virtualjoystick.c" /> <ClCompile Include="..\..\src\joystick\virtual\SDL_virtualjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c" /> <ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_rawinputjoystick.c" /> <ClCompile Include="..\..\src\joystick\windows\SDL_rawinputjoystick.c" />

View file

@ -501,6 +501,9 @@
<ClInclude Include="..\..\src\joystick\SDL_joystick_c.h"> <ClInclude Include="..\..\src\joystick\SDL_joystick_c.h">
<Filter>joystick</Filter> <Filter>joystick</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\joystick\SDL_steam_virtual_gamepad.h">
<Filter>joystick</Filter>
</ClInclude>
<ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h"> <ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h">
<Filter>joystick</Filter> <Filter>joystick</Filter>
</ClInclude> </ClInclude>
@ -943,6 +946,9 @@
<ClCompile Include="..\..\src\joystick\SDL_joystick.c"> <ClCompile Include="..\..\src\joystick\SDL_joystick.c">
<Filter>joystick</Filter> <Filter>joystick</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\joystick\SDL_steam_virtual_gamepad.c">
<Filter>joystick</Filter>
</ClCompile>
<ClCompile Include="..\..\src\libm\e_atan2.c"> <ClCompile Include="..\..\src\libm\e_atan2.c">
<Filter>libm</Filter> <Filter>libm</Filter>
</ClCompile> </ClCompile>

View file

@ -125,6 +125,7 @@
<ClInclude Include="..\src\joystick\controller_type.h" /> <ClInclude Include="..\src\joystick\controller_type.h" />
<ClInclude Include="..\src\joystick\SDL_gamecontrollerdb.h" /> <ClInclude Include="..\src\joystick\SDL_gamecontrollerdb.h" />
<ClInclude Include="..\src\joystick\SDL_joystick_c.h" /> <ClInclude Include="..\src\joystick\SDL_joystick_c.h" />
<ClInclude Include="..\src\joystick\SDL_steam_virtual_gamepad.h" />
<ClInclude Include="..\src\joystick\SDL_sysjoystick.h" /> <ClInclude Include="..\src\joystick\SDL_sysjoystick.h" />
<ClInclude Include="..\src\joystick\virtual\SDL_virtualjoystick_c.h" /> <ClInclude Include="..\src\joystick\virtual\SDL_virtualjoystick_c.h" />
<ClInclude Include="..\src\joystick\windows\SDL_dinputjoystick_c.h" /> <ClInclude Include="..\src\joystick\windows\SDL_dinputjoystick_c.h" />
@ -237,6 +238,7 @@
<ClCompile Include="..\src\joystick\controller_type.c" /> <ClCompile Include="..\src\joystick\controller_type.c" />
<ClCompile Include="..\src\joystick\SDL_gamecontroller.c" /> <ClCompile Include="..\src\joystick\SDL_gamecontroller.c" />
<ClCompile Include="..\src\joystick\SDL_joystick.c" /> <ClCompile Include="..\src\joystick\SDL_joystick.c" />
<ClCompile Include="..\src\joystick\SDL_steam_virtual_gamepad.c" />
<ClCompile Include="..\src\joystick\virtual\SDL_virtualjoystick.c" /> <ClCompile Include="..\src\joystick\virtual\SDL_virtualjoystick.c" />
<ClCompile Include="..\src\joystick\windows\SDL_dinputjoystick.c" /> <ClCompile Include="..\src\joystick\windows\SDL_dinputjoystick.c" />
<ClCompile Include="..\src\joystick\windows\SDL_windowsjoystick.c" /> <ClCompile Include="..\src\joystick\windows\SDL_windowsjoystick.c" />

View file

@ -255,6 +255,9 @@
<ClInclude Include="..\src\joystick\SDL_joystick_c.h"> <ClInclude Include="..\src\joystick\SDL_joystick_c.h">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\src\joystick\SDL_steam_virtual_gamepad.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="..\src\joystick\SDL_sysjoystick.h"> <ClInclude Include="..\src\joystick\SDL_sysjoystick.h">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClInclude> </ClInclude>
@ -558,6 +561,9 @@
<ClCompile Include="..\src\joystick\SDL_joystick.c"> <ClCompile Include="..\src\joystick\SDL_joystick.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\joystick\SDL_steam_virtual_gamepad.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\joystick\virtual\SDL_virtualjoystick.c"> <ClCompile Include="..\src\joystick\virtual\SDL_virtualjoystick.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>

View file

@ -336,6 +336,7 @@
<ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapi_rumble.h" /> <ClInclude Include="..\..\src\joystick\hidapi\SDL_hidapi_rumble.h" />
<ClInclude Include="..\..\src\joystick\SDL_gamecontrollerdb.h" /> <ClInclude Include="..\..\src\joystick\SDL_gamecontrollerdb.h" />
<ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" /> <ClInclude Include="..\..\src\joystick\SDL_joystick_c.h" />
<ClInclude Include="..\..\src\joystick\SDL_steam_virtual_gamepad.h" />
<ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" /> <ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h" />
<ClInclude Include="..\..\src\joystick\usb_ids.h" /> <ClInclude Include="..\..\src\joystick\usb_ids.h" />
<ClInclude Include="..\..\src\joystick\virtual\SDL_virtualjoystick_c.h" /> <ClInclude Include="..\..\src\joystick\virtual\SDL_virtualjoystick_c.h" />
@ -501,6 +502,7 @@
<ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c" /> <ClCompile Include="..\..\src\joystick\hidapi\SDL_hidapi_xboxone.c" />
<ClCompile Include="..\..\src\joystick\SDL_gamecontroller.c" /> <ClCompile Include="..\..\src\joystick\SDL_gamecontroller.c" />
<ClCompile Include="..\..\src\joystick\SDL_joystick.c" /> <ClCompile Include="..\..\src\joystick\SDL_joystick.c" />
<ClCompile Include="..\..\src\joystick\SDL_steam_virtual_gamepad.c" />
<ClCompile Include="..\..\src\joystick\virtual\SDL_virtualjoystick.c" /> <ClCompile Include="..\..\src\joystick\virtual\SDL_virtualjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c" /> <ClCompile Include="..\..\src\joystick\windows\SDL_dinputjoystick.c" />
<ClCompile Include="..\..\src\joystick\windows\SDL_rawinputjoystick.c" /> <ClCompile Include="..\..\src\joystick\windows\SDL_rawinputjoystick.c" />

View file

@ -501,6 +501,9 @@
<ClInclude Include="..\..\src\joystick\SDL_joystick_c.h"> <ClInclude Include="..\..\src\joystick\SDL_joystick_c.h">
<Filter>joystick</Filter> <Filter>joystick</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\joystick\SDL_steam_virtual_gamepad.h">
<Filter>joystick</Filter>
</ClInclude>
<ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h"> <ClInclude Include="..\..\src\joystick\SDL_sysjoystick.h">
<Filter>joystick</Filter> <Filter>joystick</Filter>
</ClInclude> </ClInclude>
@ -934,6 +937,9 @@
<ClCompile Include="..\..\src\joystick\SDL_joystick.c"> <ClCompile Include="..\..\src\joystick\SDL_joystick.c">
<Filter>joystick</Filter> <Filter>joystick</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\joystick\SDL_steam_virtual_gamepad.c">
<Filter>joystick</Filter>
</ClCompile>
<ClCompile Include="..\..\src\libm\e_atan2.c"> <ClCompile Include="..\..\src\libm\e_atan2.c">
<Filter>libm</Filter> <Filter>libm</Filter>
</ClCompile> </ClCompile>

View file

@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 52; objectVersion = 54;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
@ -3396,6 +3396,33 @@
F34B9895291DEFF500AAC96E /* SDL_hidapi_steam.c in Sources */ = {isa = PBXBuildFile; fileRef = A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */; }; F34B9895291DEFF500AAC96E /* SDL_hidapi_steam.c in Sources */ = {isa = PBXBuildFile; fileRef = A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */; };
F34B9896291DEFF700AAC96E /* SDL_hidapi_steam.c in Sources */ = {isa = PBXBuildFile; fileRef = A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */; }; F34B9896291DEFF700AAC96E /* SDL_hidapi_steam.c in Sources */ = {isa = PBXBuildFile; fileRef = A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */; };
F34B9897291DEFFA00AAC96E /* SDL_hidapi_steam.c in Sources */ = {isa = PBXBuildFile; fileRef = A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */; }; F34B9897291DEFFA00AAC96E /* SDL_hidapi_steam.c in Sources */ = {isa = PBXBuildFile; fileRef = A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */; };
F362B9202B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9212B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9222B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9232B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9242B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9252B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9262B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9272B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9282B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */; };
F362B9292B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B92A2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B92B2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B92C2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B92D2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B92E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B92F2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B9302B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B9312B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */; };
F362B9322B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B9332B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B9342B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B9352B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B9362B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B9372B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B9382B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B9392B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F362B93A2B33916600D30B94 /* controller_list.h in Headers */ = {isa = PBXBuildFile; fileRef = F362B91F2B33916600D30B94 /* controller_list.h */; };
F3631C6424884ACF004F28EA /* SDL_locale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26792462701100718109 /* SDL_locale.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3631C6424884ACF004F28EA /* SDL_locale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26792462701100718109 /* SDL_locale.h */; settings = {ATTRIBUTES = (Public, ); }; };
F3631C652488534E004F28EA /* SDL_locale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26792462701100718109 /* SDL_locale.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3631C652488534E004F28EA /* SDL_locale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26792462701100718109 /* SDL_locale.h */; settings = {ATTRIBUTES = (Public, ); }; };
F376F6192559B29300CFC0BC /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F376F6182559B29300CFC0BC /* OpenGLES.framework */; platformFilter = ios; }; F376F6192559B29300CFC0BC /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F376F6182559B29300CFC0BC /* OpenGLES.framework */; platformFilter = ios; };
@ -4107,6 +4134,9 @@
F31A92C628D4CB39003BFD6A /* SDL_offscreenopengles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_offscreenopengles.h; sourceTree = "<group>"; }; F31A92C628D4CB39003BFD6A /* SDL_offscreenopengles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_offscreenopengles.h; sourceTree = "<group>"; };
F31A92C728D4CB39003BFD6A /* SDL_offscreenopengles.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_offscreenopengles.c; sourceTree = "<group>"; }; F31A92C728D4CB39003BFD6A /* SDL_offscreenopengles.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_offscreenopengles.c; sourceTree = "<group>"; };
F32305FE28939F6400E66D30 /* SDL_hidapi_combined.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_combined.c; sourceTree = "<group>"; }; F32305FE28939F6400E66D30 /* SDL_hidapi_combined.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_combined.c; sourceTree = "<group>"; };
F362B91D2B33916600D30B94 /* SDL_steam_virtual_gamepad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_steam_virtual_gamepad.c; sourceTree = "<group>"; };
F362B91E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_steam_virtual_gamepad.h; sourceTree = "<group>"; };
F362B91F2B33916600D30B94 /* controller_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = controller_list.h; sourceTree = "<group>"; };
F376F6182559B29300CFC0BC /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.1.sdk/System/Library/Frameworks/OpenGLES.framework; sourceTree = DEVELOPER_DIR; }; F376F6182559B29300CFC0BC /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.1.sdk/System/Library/Frameworks/OpenGLES.framework; sourceTree = DEVELOPER_DIR; };
F376F61A2559B2AF00CFC0BC /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/iOSSupport/System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; F376F61A2559B2AF00CFC0BC /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/iOSSupport/System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
F376F6312559B31D00CFC0BC /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/iOSSupport/System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; }; F376F6312559B31D00CFC0BC /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/iOSSupport/System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
@ -4950,12 +4980,15 @@
A7D8A7AA23E2513E00DCD162 /* iphoneos */, A7D8A7AA23E2513E00DCD162 /* iphoneos */,
A7D8A7A123E2513E00DCD162 /* steam */, A7D8A7A123E2513E00DCD162 /* steam */,
75E09157241EA924004729E1 /* virtual */, 75E09157241EA924004729E1 /* virtual */,
A7D8A7AD23E2513E00DCD162 /* SDL_gamecontroller.c */, F362B91F2B33916600D30B94 /* controller_list.h */,
A7D8A7A923E2513E00DCD162 /* SDL_joystick.c */,
F3820712284F3609004DD584 /* controller_type.c */, F3820712284F3609004DD584 /* controller_type.c */,
A7D8A7D923E2513E00DCD162 /* controller_type.h */, A7D8A7D923E2513E00DCD162 /* controller_type.h */,
A7D8A7AD23E2513E00DCD162 /* SDL_gamecontroller.c */,
A7D8A79E23E2513E00DCD162 /* SDL_gamecontrollerdb.h */, A7D8A79E23E2513E00DCD162 /* SDL_gamecontrollerdb.h */,
A7D8A7D023E2513E00DCD162 /* SDL_joystick_c.h */, A7D8A7D023E2513E00DCD162 /* SDL_joystick_c.h */,
A7D8A7A923E2513E00DCD162 /* SDL_joystick.c */,
F362B9182B3349E200D30B94 /* SDL_steam_virtual_gamepad.c */,
F362B9172B3349E200D30B94 /* SDL_steam_virtual_gamepad.h */,
A7D8A7CF23E2513E00DCD162 /* SDL_sysjoystick.h */, A7D8A7CF23E2513E00DCD162 /* SDL_sysjoystick.h */,
A7D8A7CB23E2513E00DCD162 /* usb_ids.h */, A7D8A7CB23E2513E00DCD162 /* usb_ids.h */,
); );
@ -5456,6 +5489,7 @@
A75FCD4323E25AB700529352 /* SDL_keyboard.h in Headers */, A75FCD4323E25AB700529352 /* SDL_keyboard.h in Headers */,
A75FCD4423E25AB700529352 /* SDL_uikitevents.h in Headers */, A75FCD4423E25AB700529352 /* SDL_uikitevents.h in Headers */,
A75FCD4523E25AB700529352 /* SDL_gesture_c.h in Headers */, A75FCD4523E25AB700529352 /* SDL_gesture_c.h in Headers */,
F362B9392B33916600D30B94 /* controller_list.h in Headers */,
A75FCD4623E25AB700529352 /* SDL_shaders_gl.h in Headers */, A75FCD4623E25AB700529352 /* SDL_shaders_gl.h in Headers */,
A75FCD4723E25AB700529352 /* SDL_systhread_c.h in Headers */, A75FCD4723E25AB700529352 /* SDL_systhread_c.h in Headers */,
A1BB8B7327F6CF330057CFA8 /* SDL_list.h in Headers */, A1BB8B7327F6CF330057CFA8 /* SDL_list.h in Headers */,
@ -5540,6 +5574,7 @@
A75FCD9E23E25AB700529352 /* controller_type.h in Headers */, A75FCD9E23E25AB700529352 /* controller_type.h in Headers */,
A75FCDA023E25AB700529352 /* SDL_uikitclipboard.h in Headers */, A75FCDA023E25AB700529352 /* SDL_uikitclipboard.h in Headers */,
A75FCDA123E25AB700529352 /* vulkan_xlib.h in Headers */, A75FCDA123E25AB700529352 /* vulkan_xlib.h in Headers */,
F362B9302B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A75FCDA223E25AB700529352 /* SDL_uikitwindow.h in Headers */, A75FCDA223E25AB700529352 /* SDL_uikitwindow.h in Headers */,
A75FCDA323E25AB700529352 /* vulkan_vi.h in Headers */, A75FCDA323E25AB700529352 /* vulkan_vi.h in Headers */,
A75FCDA423E25AB700529352 /* vulkan_mir.h in Headers */, A75FCDA423E25AB700529352 /* vulkan_mir.h in Headers */,
@ -5685,6 +5720,7 @@
A75FCEFC23E25AC700529352 /* SDL_keyboard.h in Headers */, A75FCEFC23E25AC700529352 /* SDL_keyboard.h in Headers */,
A75FCEFD23E25AC700529352 /* SDL_uikitevents.h in Headers */, A75FCEFD23E25AC700529352 /* SDL_uikitevents.h in Headers */,
A75FCEFE23E25AC700529352 /* SDL_gesture_c.h in Headers */, A75FCEFE23E25AC700529352 /* SDL_gesture_c.h in Headers */,
F362B93A2B33916600D30B94 /* controller_list.h in Headers */,
A75FCEFF23E25AC700529352 /* SDL_shaders_gl.h in Headers */, A75FCEFF23E25AC700529352 /* SDL_shaders_gl.h in Headers */,
A75FCF0023E25AC700529352 /* SDL_systhread_c.h in Headers */, A75FCF0023E25AC700529352 /* SDL_systhread_c.h in Headers */,
A1BB8B7427F6CF330057CFA8 /* SDL_list.h in Headers */, A1BB8B7427F6CF330057CFA8 /* SDL_list.h in Headers */,
@ -5769,6 +5805,7 @@
A75FCF5723E25AC700529352 /* controller_type.h in Headers */, A75FCF5723E25AC700529352 /* controller_type.h in Headers */,
A75FCF5923E25AC700529352 /* SDL_uikitclipboard.h in Headers */, A75FCF5923E25AC700529352 /* SDL_uikitclipboard.h in Headers */,
A75FCF5A23E25AC700529352 /* vulkan_xlib.h in Headers */, A75FCF5A23E25AC700529352 /* vulkan_xlib.h in Headers */,
F362B9312B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A75FCF5B23E25AC700529352 /* SDL_uikitwindow.h in Headers */, A75FCF5B23E25AC700529352 /* SDL_uikitwindow.h in Headers */,
A75FCF5C23E25AC700529352 /* vulkan_vi.h in Headers */, A75FCF5C23E25AC700529352 /* vulkan_vi.h in Headers */,
A75FCF5D23E25AC700529352 /* vulkan_mir.h in Headers */, A75FCF5D23E25AC700529352 /* vulkan_mir.h in Headers */,
@ -5933,6 +5970,7 @@
A769B10223E259AE00872273 /* math_private.h in Headers */, A769B10223E259AE00872273 /* math_private.h in Headers */,
A769B10323E259AE00872273 /* vulkan_wayland.h in Headers */, A769B10323E259AE00872273 /* vulkan_wayland.h in Headers */,
A769B10523E259AE00872273 /* SDL_cocoashape.h in Headers */, A769B10523E259AE00872273 /* SDL_cocoashape.h in Headers */,
F362B92E2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A769B10723E259AE00872273 /* SDL_shaders_gles2.h in Headers */, A769B10723E259AE00872273 /* SDL_shaders_gles2.h in Headers */,
A769B10923E259AE00872273 /* SDL_glesfuncs.h in Headers */, A769B10923E259AE00872273 /* SDL_glesfuncs.h in Headers */,
A769B10A23E259AE00872273 /* SDL_blendpoint.h in Headers */, A769B10A23E259AE00872273 /* SDL_blendpoint.h in Headers */,
@ -5997,6 +6035,7 @@
A769B15623E259AE00872273 /* SDL_syshaptic.h in Headers */, A769B15623E259AE00872273 /* SDL_syshaptic.h in Headers */,
A769B15723E259AE00872273 /* SDL_vulkan_internal.h in Headers */, A769B15723E259AE00872273 /* SDL_vulkan_internal.h in Headers */,
A769B15923E259AE00872273 /* SDL_cocoaevents.h in Headers */, A769B15923E259AE00872273 /* SDL_cocoaevents.h in Headers */,
F362B9372B33916600D30B94 /* controller_list.h in Headers */,
A769B15A23E259AE00872273 /* vk_icd.h in Headers */, A769B15A23E259AE00872273 /* vk_icd.h in Headers */,
A769B15B23E259AE00872273 /* SDL_nullframebuffer_c.h in Headers */, A769B15B23E259AE00872273 /* SDL_nullframebuffer_c.h in Headers */,
A769B15D23E259AE00872273 /* SDL_dynapi_procs.h in Headers */, A769B15D23E259AE00872273 /* SDL_dynapi_procs.h in Headers */,
@ -6218,6 +6257,7 @@
A7D8BB2223E2514500DCD162 /* scancodes_windows.h in Headers */, A7D8BB2223E2514500DCD162 /* scancodes_windows.h in Headers */,
A7D8BBA023E2514500DCD162 /* scancodes_xfree86.h in Headers */, A7D8BBA023E2514500DCD162 /* scancodes_xfree86.h in Headers */,
A7D8B57023E2514300DCD162 /* usb_ids.h in Headers */, A7D8B57023E2514300DCD162 /* usb_ids.h in Headers */,
F362B92A2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A1626A532617008D003F1973 /* SDL_triangle.h in Headers */, A1626A532617008D003F1973 /* SDL_triangle.h in Headers */,
A7D8B25523E2514200DCD162 /* vk_icd.h in Headers */, A7D8B25523E2514200DCD162 /* vk_icd.h in Headers */,
A7D8B24F23E2514200DCD162 /* vk_layer.h in Headers */, A7D8B24F23E2514200DCD162 /* vk_layer.h in Headers */,
@ -6234,6 +6274,7 @@
A7D8B25B23E2514200DCD162 /* vulkan_vi.h in Headers */, A7D8B25B23E2514200DCD162 /* vulkan_vi.h in Headers */,
A7D8B27923E2514200DCD162 /* vulkan_wayland.h in Headers */, A7D8B27923E2514200DCD162 /* vulkan_wayland.h in Headers */,
A7D8B27F23E2514200DCD162 /* vulkan_win32.h in Headers */, A7D8B27F23E2514200DCD162 /* vulkan_win32.h in Headers */,
F362B9332B33916600D30B94 /* controller_list.h in Headers */,
A7D8B29123E2514200DCD162 /* vulkan_xcb.h in Headers */, A7D8B29123E2514200DCD162 /* vulkan_xcb.h in Headers */,
A7D8B29D23E2514200DCD162 /* vulkan_xlib.h in Headers */, A7D8B29D23E2514200DCD162 /* vulkan_xlib.h in Headers */,
A7D8B28B23E2514200DCD162 /* vulkan_xlib_xrandr.h in Headers */, A7D8B28B23E2514200DCD162 /* vulkan_xlib_xrandr.h in Headers */,
@ -6452,6 +6493,7 @@
A7D8BB2323E2514500DCD162 /* scancodes_windows.h in Headers */, A7D8BB2323E2514500DCD162 /* scancodes_windows.h in Headers */,
A7D8BBA123E2514500DCD162 /* scancodes_xfree86.h in Headers */, A7D8BBA123E2514500DCD162 /* scancodes_xfree86.h in Headers */,
A7D8B57123E2514300DCD162 /* usb_ids.h in Headers */, A7D8B57123E2514300DCD162 /* usb_ids.h in Headers */,
F362B92B2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A1626A542617008D003F1973 /* SDL_triangle.h in Headers */, A1626A542617008D003F1973 /* SDL_triangle.h in Headers */,
A7D8B25623E2514200DCD162 /* vk_icd.h in Headers */, A7D8B25623E2514200DCD162 /* vk_icd.h in Headers */,
A7D8B25023E2514200DCD162 /* vk_layer.h in Headers */, A7D8B25023E2514200DCD162 /* vk_layer.h in Headers */,
@ -6468,6 +6510,7 @@
A7D8B25C23E2514200DCD162 /* vulkan_vi.h in Headers */, A7D8B25C23E2514200DCD162 /* vulkan_vi.h in Headers */,
A7D8B27A23E2514200DCD162 /* vulkan_wayland.h in Headers */, A7D8B27A23E2514200DCD162 /* vulkan_wayland.h in Headers */,
A7D8B28023E2514200DCD162 /* vulkan_win32.h in Headers */, A7D8B28023E2514200DCD162 /* vulkan_win32.h in Headers */,
F362B9342B33916600D30B94 /* controller_list.h in Headers */,
A7D8B29223E2514200DCD162 /* vulkan_xcb.h in Headers */, A7D8B29223E2514200DCD162 /* vulkan_xcb.h in Headers */,
A7D8B29E23E2514200DCD162 /* vulkan_xlib.h in Headers */, A7D8B29E23E2514200DCD162 /* vulkan_xlib.h in Headers */,
A7D8B28C23E2514200DCD162 /* vulkan_xlib_xrandr.h in Headers */, A7D8B28C23E2514200DCD162 /* vulkan_xlib_xrandr.h in Headers */,
@ -6570,6 +6613,7 @@
A7D8BAC523E2514500DCD162 /* math_private.h in Headers */, A7D8BAC523E2514500DCD162 /* math_private.h in Headers */,
A7D8B27C23E2514200DCD162 /* vulkan_wayland.h in Headers */, A7D8B27C23E2514200DCD162 /* vulkan_wayland.h in Headers */,
A7D8AE8623E2514100DCD162 /* SDL_cocoashape.h in Headers */, A7D8AE8623E2514100DCD162 /* SDL_cocoashape.h in Headers */,
F362B92D2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A7D8BA5323E2514400DCD162 /* SDL_shaders_gles2.h in Headers */, A7D8BA5323E2514400DCD162 /* SDL_shaders_gles2.h in Headers */,
A7D8BA4723E2514400DCD162 /* SDL_glesfuncs.h in Headers */, A7D8BA4723E2514400DCD162 /* SDL_glesfuncs.h in Headers */,
A7D8BA1123E2514400DCD162 /* SDL_blendpoint.h in Headers */, A7D8BA1123E2514400DCD162 /* SDL_blendpoint.h in Headers */,
@ -6634,6 +6678,7 @@
A7D8AAD823E2514100DCD162 /* SDL_syshaptic.h in Headers */, A7D8AAD823E2514100DCD162 /* SDL_syshaptic.h in Headers */,
A7D8AD2123E2514100DCD162 /* SDL_vulkan_internal.h in Headers */, A7D8AD2123E2514100DCD162 /* SDL_vulkan_internal.h in Headers */,
A7D8AF1623E2514100DCD162 /* SDL_cocoaevents.h in Headers */, A7D8AF1623E2514100DCD162 /* SDL_cocoaevents.h in Headers */,
F362B9362B33916600D30B94 /* controller_list.h in Headers */,
A7D8B25823E2514200DCD162 /* vk_icd.h in Headers */, A7D8B25823E2514200DCD162 /* vk_icd.h in Headers */,
A7D8ABE923E2514100DCD162 /* SDL_nullframebuffer_c.h in Headers */, A7D8ABE923E2514100DCD162 /* SDL_nullframebuffer_c.h in Headers */,
A7D8AB2023E2514100DCD162 /* SDL_dynapi_procs.h in Headers */, A7D8AB2023E2514100DCD162 /* SDL_dynapi_procs.h in Headers */,
@ -6855,6 +6900,7 @@
A7D8BB2123E2514500DCD162 /* scancodes_windows.h in Headers */, A7D8BB2123E2514500DCD162 /* scancodes_windows.h in Headers */,
A7D8BB9F23E2514500DCD162 /* scancodes_xfree86.h in Headers */, A7D8BB9F23E2514500DCD162 /* scancodes_xfree86.h in Headers */,
A7D8B56F23E2514300DCD162 /* usb_ids.h in Headers */, A7D8B56F23E2514300DCD162 /* usb_ids.h in Headers */,
F362B9292B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A1626A522617008D003F1973 /* SDL_triangle.h in Headers */, A1626A522617008D003F1973 /* SDL_triangle.h in Headers */,
A7D8B25423E2514200DCD162 /* vk_icd.h in Headers */, A7D8B25423E2514200DCD162 /* vk_icd.h in Headers */,
A7D8B24E23E2514200DCD162 /* vk_layer.h in Headers */, A7D8B24E23E2514200DCD162 /* vk_layer.h in Headers */,
@ -6871,6 +6917,7 @@
A7D8B25A23E2514200DCD162 /* vulkan_vi.h in Headers */, A7D8B25A23E2514200DCD162 /* vulkan_vi.h in Headers */,
A7D8B27823E2514200DCD162 /* vulkan_wayland.h in Headers */, A7D8B27823E2514200DCD162 /* vulkan_wayland.h in Headers */,
A7D8B27E23E2514200DCD162 /* vulkan_win32.h in Headers */, A7D8B27E23E2514200DCD162 /* vulkan_win32.h in Headers */,
F362B9322B33916600D30B94 /* controller_list.h in Headers */,
A7D8B29023E2514200DCD162 /* vulkan_xcb.h in Headers */, A7D8B29023E2514200DCD162 /* vulkan_xcb.h in Headers */,
A7D8B29C23E2514200DCD162 /* vulkan_xlib.h in Headers */, A7D8B29C23E2514200DCD162 /* vulkan_xlib.h in Headers */,
A7D8B28A23E2514200DCD162 /* vulkan_xlib_xrandr.h in Headers */, A7D8B28A23E2514200DCD162 /* vulkan_xlib_xrandr.h in Headers */,
@ -6888,6 +6935,7 @@
A7D8AC0C23E2514100DCD162 /* SDL_shape_internals.h in Headers */, A7D8AC0C23E2514100DCD162 /* SDL_shape_internals.h in Headers */,
A7D8BA7C23E2514400DCD162 /* SDL_glfuncs.h in Headers */, A7D8BA7C23E2514400DCD162 /* SDL_glfuncs.h in Headers */,
A7D8AC0623E2514100DCD162 /* SDL_rect_c.h in Headers */, A7D8AC0623E2514100DCD162 /* SDL_rect_c.h in Headers */,
F362B9352B33916600D30B94 /* controller_list.h in Headers */,
75E09166241EA924004729E1 /* SDL_virtualjoystick_c.h in Headers */, 75E09166241EA924004729E1 /* SDL_virtualjoystick_c.h in Headers */,
A7D8B99E23E2514400DCD162 /* SDL_shaders_metal_osx.h in Headers */, A7D8B99E23E2514400DCD162 /* SDL_shaders_metal_osx.h in Headers */,
A7D8B98F23E2514400DCD162 /* SDL_shaders_metal_ios.h in Headers */, A7D8B98F23E2514400DCD162 /* SDL_shaders_metal_ios.h in Headers */,
@ -6963,6 +7011,7 @@
A7D8BBFF23E2574800DCD162 /* SDL_uikitview.h in Headers */, A7D8BBFF23E2574800DCD162 /* SDL_uikitview.h in Headers */,
A7D8BBA823E2514500DCD162 /* SDL_events_c.h in Headers */, A7D8BBA823E2514500DCD162 /* SDL_events_c.h in Headers */,
A7D8BAC423E2514500DCD162 /* math_private.h in Headers */, A7D8BAC423E2514500DCD162 /* math_private.h in Headers */,
F362B92C2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A7D8B27B23E2514200DCD162 /* vulkan_wayland.h in Headers */, A7D8B27B23E2514200DCD162 /* vulkan_wayland.h in Headers */,
A7D8BBF523E2574800DCD162 /* SDL_uikitmetalview.h in Headers */, A7D8BBF523E2574800DCD162 /* SDL_uikitmetalview.h in Headers */,
A7D8AE8523E2514100DCD162 /* SDL_cocoashape.h in Headers */, A7D8AE8523E2514100DCD162 /* SDL_cocoashape.h in Headers */,
@ -7122,6 +7171,7 @@
DB313FDA17554B71006C0E22 /* SDL_keyboard.h in Headers */, DB313FDA17554B71006C0E22 /* SDL_keyboard.h in Headers */,
A7D8ACC223E2514100DCD162 /* SDL_uikitevents.h in Headers */, A7D8ACC223E2514100DCD162 /* SDL_uikitevents.h in Headers */,
A7D8BB3E23E2514500DCD162 /* SDL_gesture_c.h in Headers */, A7D8BB3E23E2514500DCD162 /* SDL_gesture_c.h in Headers */,
F362B9382B33916600D30B94 /* controller_list.h in Headers */,
A7D8BA7823E2514400DCD162 /* SDL_shaders_gl.h in Headers */, A7D8BA7823E2514400DCD162 /* SDL_shaders_gl.h in Headers */,
A7D8B42D23E2514300DCD162 /* SDL_systhread_c.h in Headers */, A7D8B42D23E2514300DCD162 /* SDL_systhread_c.h in Headers */,
A1BB8B7227F6CF330057CFA8 /* SDL_list.h in Headers */, A1BB8B7227F6CF330057CFA8 /* SDL_list.h in Headers */,
@ -7206,6 +7256,7 @@
A7D8AC7A23E2514100DCD162 /* SDL_uikitclipboard.h in Headers */, A7D8AC7A23E2514100DCD162 /* SDL_uikitclipboard.h in Headers */,
A7D8B2A123E2514200DCD162 /* vulkan_xlib.h in Headers */, A7D8B2A123E2514200DCD162 /* vulkan_xlib.h in Headers */,
A7D8AC9E23E2514100DCD162 /* SDL_uikitwindow.h in Headers */, A7D8AC9E23E2514100DCD162 /* SDL_uikitwindow.h in Headers */,
F362B92F2B33916600D30B94 /* SDL_steam_virtual_gamepad.h in Headers */,
A7D8B25F23E2514200DCD162 /* vulkan_vi.h in Headers */, A7D8B25F23E2514200DCD162 /* vulkan_vi.h in Headers */,
A7D8B29B23E2514200DCD162 /* vulkan_mir.h in Headers */, A7D8B29B23E2514200DCD162 /* vulkan_mir.h in Headers */,
DB313FE817554B71006C0E22 /* SDL_quit.h in Headers */, DB313FE817554B71006C0E22 /* SDL_quit.h in Headers */,
@ -7797,6 +7848,7 @@
A75FCE2823E25AB700529352 /* SDL_dropevents.c in Sources */, A75FCE2823E25AB700529352 /* SDL_dropevents.c in Sources */,
A75FCE2923E25AB700529352 /* e_atan2.c in Sources */, A75FCE2923E25AB700529352 /* e_atan2.c in Sources */,
A75FCE2A23E25AB700529352 /* s_sin.c in Sources */, A75FCE2A23E25AB700529352 /* s_sin.c in Sources */,
F362B9272B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A75FCE2B23E25AB700529352 /* SDL_power.c in Sources */, A75FCE2B23E25AB700529352 /* SDL_power.c in Sources */,
A75FCE2C23E25AB700529352 /* SDL_cocoakeyboard.m in Sources */, A75FCE2C23E25AB700529352 /* SDL_cocoakeyboard.m in Sources */,
A75FCE2D23E25AB700529352 /* SDL_dynapi.c in Sources */, A75FCE2D23E25AB700529352 /* SDL_dynapi.c in Sources */,
@ -7993,6 +8045,7 @@
A75FCFE123E25AC700529352 /* SDL_dropevents.c in Sources */, A75FCFE123E25AC700529352 /* SDL_dropevents.c in Sources */,
A75FCFE223E25AC700529352 /* e_atan2.c in Sources */, A75FCFE223E25AC700529352 /* e_atan2.c in Sources */,
A75FCFE323E25AC700529352 /* s_sin.c in Sources */, A75FCFE323E25AC700529352 /* s_sin.c in Sources */,
F362B9282B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A75FCFE423E25AC700529352 /* SDL_power.c in Sources */, A75FCFE423E25AC700529352 /* SDL_power.c in Sources */,
A75FCFE523E25AC700529352 /* SDL_cocoakeyboard.m in Sources */, A75FCFE523E25AC700529352 /* SDL_cocoakeyboard.m in Sources */,
A75FCFE623E25AC700529352 /* SDL_dynapi.c in Sources */, A75FCFE623E25AC700529352 /* SDL_dynapi.c in Sources */,
@ -8303,6 +8356,7 @@
A769B22723E259AE00872273 /* e_sqrt.c in Sources */, A769B22723E259AE00872273 /* e_sqrt.c in Sources */,
A769B22823E259AE00872273 /* SDL_cocoavideo.m in Sources */, A769B22823E259AE00872273 /* SDL_cocoavideo.m in Sources */,
A769B22923E259AE00872273 /* SDL.c in Sources */, A769B22923E259AE00872273 /* SDL.c in Sources */,
F362B9252B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A769B22B23E259AE00872273 /* SDL_cocoavulkan.m in Sources */, A769B22B23E259AE00872273 /* SDL_cocoavulkan.m in Sources */,
A769B22C23E259AE00872273 /* SDL_uikitappdelegate.m in Sources */, A769B22C23E259AE00872273 /* SDL_uikitappdelegate.m in Sources */,
A1626A432617006A003F1973 /* SDL_triangle.c in Sources */, A1626A432617006A003F1973 /* SDL_triangle.c in Sources */,
@ -8386,6 +8440,7 @@
A7D8B5E823E2514300DCD162 /* SDL_power.c in Sources */, A7D8B5E823E2514300DCD162 /* SDL_power.c in Sources */,
A7D8AED723E2514100DCD162 /* SDL_cocoakeyboard.m in Sources */, A7D8AED723E2514100DCD162 /* SDL_cocoakeyboard.m in Sources */,
A7D8AB1723E2514100DCD162 /* SDL_dynapi.c in Sources */, A7D8AB1723E2514100DCD162 /* SDL_dynapi.c in Sources */,
F362B9212B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A7D8BA8623E2514400DCD162 /* SDL_shaders_gl.c in Sources */, A7D8BA8623E2514400DCD162 /* SDL_shaders_gl.c in Sources */,
A7D8BAF223E2514500DCD162 /* e_log.c in Sources */, A7D8BAF223E2514500DCD162 /* e_log.c in Sources */,
A7D8AED123E2514100DCD162 /* SDL_cocoamessagebox.m in Sources */, A7D8AED123E2514100DCD162 /* SDL_cocoamessagebox.m in Sources */,
@ -8582,6 +8637,7 @@
A7D8B5E923E2514300DCD162 /* SDL_power.c in Sources */, A7D8B5E923E2514300DCD162 /* SDL_power.c in Sources */,
A7D8AED823E2514100DCD162 /* SDL_cocoakeyboard.m in Sources */, A7D8AED823E2514100DCD162 /* SDL_cocoakeyboard.m in Sources */,
A7D8AB1823E2514100DCD162 /* SDL_dynapi.c in Sources */, A7D8AB1823E2514100DCD162 /* SDL_dynapi.c in Sources */,
F362B9222B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A7D8BA8723E2514400DCD162 /* SDL_shaders_gl.c in Sources */, A7D8BA8723E2514400DCD162 /* SDL_shaders_gl.c in Sources */,
A7D8BAF323E2514500DCD162 /* e_log.c in Sources */, A7D8BAF323E2514500DCD162 /* e_log.c in Sources */,
A7D8AED223E2514100DCD162 /* SDL_cocoamessagebox.m in Sources */, A7D8AED223E2514100DCD162 /* SDL_cocoamessagebox.m in Sources */,
@ -8892,6 +8948,7 @@
A7D8BAFB23E2514500DCD162 /* e_sqrt.c in Sources */, A7D8BAFB23E2514500DCD162 /* e_sqrt.c in Sources */,
A7D8AEB023E2514100DCD162 /* SDL_cocoavideo.m in Sources */, A7D8AEB023E2514100DCD162 /* SDL_cocoavideo.m in Sources */,
A7D8A94F23E2514000DCD162 /* SDL.c in Sources */, A7D8A94F23E2514000DCD162 /* SDL.c in Sources */,
F362B9242B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A7D8AEA423E2514100DCD162 /* SDL_cocoavulkan.m in Sources */, A7D8AEA423E2514100DCD162 /* SDL_cocoavulkan.m in Sources */,
A7D8AC6723E2514100DCD162 /* SDL_uikitappdelegate.m in Sources */, A7D8AC6723E2514100DCD162 /* SDL_uikitappdelegate.m in Sources */,
A1626A422617006A003F1973 /* SDL_triangle.c in Sources */, A1626A422617006A003F1973 /* SDL_triangle.c in Sources */,
@ -8955,6 +9012,7 @@
A7D8BA1F23E2514400DCD162 /* SDL_blendline.c in Sources */, A7D8BA1F23E2514400DCD162 /* SDL_blendline.c in Sources */,
A7D8BBE723E2574800DCD162 /* SDL_uikitviewcontroller.m in Sources */, A7D8BBE723E2574800DCD162 /* SDL_uikitviewcontroller.m in Sources */,
A7D8ADF223E2514100DCD162 /* SDL_blit_A.c in Sources */, A7D8ADF223E2514100DCD162 /* SDL_blit_A.c in Sources */,
F362B9202B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A7D8BBDD23E2574800DCD162 /* SDL_uikitmodes.m in Sources */, A7D8BBDD23E2574800DCD162 /* SDL_uikitmodes.m in Sources */,
A7D8BA3723E2514400DCD162 /* SDL_d3dmath.c in Sources */, A7D8BA3723E2514400DCD162 /* SDL_d3dmath.c in Sources */,
75E0915A241EA924004729E1 /* SDL_virtualjoystick.c in Sources */, 75E0915A241EA924004729E1 /* SDL_virtualjoystick.c in Sources */,
@ -8999,6 +9057,7 @@
A7D8BAD323E2514500DCD162 /* s_tan.c in Sources */, A7D8BAD323E2514500DCD162 /* s_tan.c in Sources */,
A7D8AA6523E2514000DCD162 /* SDL_hints.c in Sources */, A7D8AA6523E2514000DCD162 /* SDL_hints.c in Sources */,
A7D8B53F23E2514300DCD162 /* SDL_hidapi_ps4.c in Sources */, A7D8B53F23E2514300DCD162 /* SDL_hidapi_ps4.c in Sources */,
F362B91C2B3349E200D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A7D8AD6E23E2514100DCD162 /* SDL_pixels.c in Sources */, A7D8AD6E23E2514100DCD162 /* SDL_pixels.c in Sources */,
A7D8B75E23E2514300DCD162 /* SDL_sysloadso.c in Sources */, A7D8B75E23E2514300DCD162 /* SDL_sysloadso.c in Sources */,
A7D8BBD723E2574800DCD162 /* SDL_uikitevents.m in Sources */, A7D8BBD723E2574800DCD162 /* SDL_uikitevents.m in Sources */,
@ -9150,6 +9209,7 @@
A7D8B53C23E2514300DCD162 /* SDL_hidapi_xbox360.c in Sources */, A7D8B53C23E2514300DCD162 /* SDL_hidapi_xbox360.c in Sources */,
A7D8B8D523E2514400DCD162 /* SDL_coreaudio.m in Sources */, A7D8B8D523E2514400DCD162 /* SDL_coreaudio.m in Sources */,
A7D8BA2223E2514400DCD162 /* SDL_blendline.c in Sources */, A7D8BA2223E2514400DCD162 /* SDL_blendline.c in Sources */,
F362B9232B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A7D8BC0623E2574800DCD162 /* SDL_uikitwindow.m in Sources */, A7D8BC0623E2574800DCD162 /* SDL_uikitwindow.m in Sources */,
A7D8ADF523E2514100DCD162 /* SDL_blit_A.c in Sources */, A7D8ADF523E2514100DCD162 /* SDL_blit_A.c in Sources */,
A7D8BA3A23E2514400DCD162 /* SDL_d3dmath.c in Sources */, A7D8BA3A23E2514400DCD162 /* SDL_d3dmath.c in Sources */,
@ -9345,6 +9405,7 @@
A7D8B8D723E2514400DCD162 /* SDL_coreaudio.m in Sources */, A7D8B8D723E2514400DCD162 /* SDL_coreaudio.m in Sources */,
A7D8BA2423E2514400DCD162 /* SDL_blendline.c in Sources */, A7D8BA2423E2514400DCD162 /* SDL_blendline.c in Sources */,
A7D8ADF723E2514100DCD162 /* SDL_blit_A.c in Sources */, A7D8ADF723E2514100DCD162 /* SDL_blit_A.c in Sources */,
F362B9262B33916600D30B94 /* SDL_steam_virtual_gamepad.c in Sources */,
A7D8BA3C23E2514400DCD162 /* SDL_d3dmath.c in Sources */, A7D8BA3C23E2514400DCD162 /* SDL_d3dmath.c in Sources */,
A7D8ABF023E2514100DCD162 /* SDL_nullvideo.c in Sources */, A7D8ABF023E2514100DCD162 /* SDL_nullvideo.c in Sources */,
A7D8AB6C23E2514100DCD162 /* SDL_offscreenevents.c in Sources */, A7D8AB6C23E2514100DCD162 /* SDL_offscreenevents.c in Sources */,

View file

@ -131,6 +131,8 @@ typedef enum
SDL_CONTROLLERTOUCHPADMOTION, /**< Game controller touchpad finger was moved */ SDL_CONTROLLERTOUCHPADMOTION, /**< Game controller touchpad finger was moved */
SDL_CONTROLLERTOUCHPADUP, /**< Game controller touchpad finger was lifted */ SDL_CONTROLLERTOUCHPADUP, /**< Game controller touchpad finger was lifted */
SDL_CONTROLLERSENSORUPDATE, /**< Game controller sensor was updated */ SDL_CONTROLLERSENSORUPDATE, /**< Game controller sensor was updated */
SDL_CONTROLLERUPDATECOMPLETE_RESERVED_FOR_SDL3,
SDL_CONTROLLERSTEAMHANDLEUPDATED, /**< Game controller Steam handle has changed */
/* Touch events */ /* Touch events */
SDL_FINGERDOWN = 0x700, SDL_FINGERDOWN = 0x700,
@ -446,7 +448,7 @@ typedef struct SDL_ControllerButtonEvent
*/ */
typedef struct SDL_ControllerDeviceEvent typedef struct SDL_ControllerDeviceEvent
{ {
Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */ Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, ::SDL_CONTROLLERDEVICEREMAPPED, or ::SDL_CONTROLLERSTEAMHANDLEUPDATED */
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */ Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */
} SDL_ControllerDeviceEvent; } SDL_ControllerDeviceEvent;

View file

@ -524,6 +524,20 @@ extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetFirmwareVersion(SDL_GameCont
*/ */
extern DECLSPEC const char * SDLCALL SDL_GameControllerGetSerial(SDL_GameController *gamecontroller); extern DECLSPEC const char * SDLCALL SDL_GameControllerGetSerial(SDL_GameController *gamecontroller);
/**
* Get the Steam Input handle of an opened controller, if available.
*
* Returns an InputHandle_t for the controller that can be used with Steam Input API:
* https://partner.steamgames.com/doc/api/ISteamInput
*
* \param gamecontroller the game controller object to query.
* \returns the gamepad handle, or 0 if unavailable.
*
* \since This function is available since SDL 2.30.0.
*/
extern DECLSPEC Uint64 SDLCALL SDL_GameControllerGetSteamHandle(SDL_GameController *gamecontroller);
/** /**
* Check if a controller has been opened and is currently connected. * Check if a controller has been opened and is currently connected.
* *

View file

@ -871,3 +871,4 @@
++'_SDL_HasWindowSurface'.'SDL2.dll'.'SDL_HasWindowSurface' ++'_SDL_HasWindowSurface'.'SDL2.dll'.'SDL_HasWindowSurface'
++'_SDL_DestroyWindowSurface'.'SDL2.dll'.'SDL_DestroyWindowSurface' ++'_SDL_DestroyWindowSurface'.'SDL2.dll'.'SDL_DestroyWindowSurface'
# ++'_SDL_GDKGetDefaultUser'.'SDL2.dll'.'SDL_GDKGetDefaultUser' # ++'_SDL_GDKGetDefaultUser'.'SDL2.dll'.'SDL_GDKGetDefaultUser'
++'_SDL_GameControllerGetSteamHandle'.'SDL2.dll'.'SDL_GameControllerGetSteamHandle'

View file

@ -897,3 +897,4 @@
#define SDL_HasWindowSurface SDL_HasWindowSurface_REAL #define SDL_HasWindowSurface SDL_HasWindowSurface_REAL
#define SDL_DestroyWindowSurface SDL_DestroyWindowSurface_REAL #define SDL_DestroyWindowSurface SDL_DestroyWindowSurface_REAL
#define SDL_GDKGetDefaultUser SDL_GDKGetDefaultUser_REAL #define SDL_GDKGetDefaultUser SDL_GDKGetDefaultUser_REAL
#define SDL_GameControllerGetSteamHandle SDL_GameControllerGetSteamHandle_REAL

View file

@ -984,3 +984,4 @@ SDL_DYNAPI_PROC(int,SDL_DestroyWindowSurface,(SDL_Window *a),(a),return)
#if defined(__GDK__) #if defined(__GDK__)
SDL_DYNAPI_PROC(int,SDL_GDKGetDefaultUser,(XUserHandle *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GDKGetDefaultUser,(XUserHandle *a),(a),return)
#endif #endif
SDL_DYNAPI_PROC(Uint64,SDL_GameControllerGetSteamHandle,(SDL_GameController *a),(a),return)

View file

@ -425,6 +425,9 @@ static void SDL_LogEvent(const SDL_Event *event)
SDL_EVENT_CASE(SDL_CONTROLLERDEVICEREMAPPED) SDL_EVENT_CASE(SDL_CONTROLLERDEVICEREMAPPED)
PRINT_CONTROLLERDEV_EVENT(event); PRINT_CONTROLLERDEV_EVENT(event);
break; break;
SDL_EVENT_CASE(SDL_CONTROLLERSTEAMHANDLEUPDATED)
PRINT_CONTROLLERDEV_EVENT(event);
break;
#undef PRINT_CONTROLLERDEV_EVENT #undef PRINT_CONTROLLERDEV_EVENT
#define PRINT_CTOUCHPAD_EVENT(event) \ #define PRINT_CTOUCHPAD_EVENT(event) \

View file

@ -27,6 +27,7 @@
#include "SDL_timer.h" #include "SDL_timer.h"
#include "SDL_sysjoystick.h" #include "SDL_sysjoystick.h"
#include "SDL_joystick_c.h" #include "SDL_joystick_c.h"
#include "SDL_steam_virtual_gamepad.h"
#include "SDL_gamecontrollerdb.h" #include "SDL_gamecontrollerdb.h"
#include "controller_type.h" #include "controller_type.h"
#include "usb_ids.h" #include "usb_ids.h"
@ -822,7 +823,7 @@ SDL_COMPILE_TIME_ASSERT(map_StringForGameControllerType, SDL_arraysize(map_Strin
/* /*
* convert a string to its enum equivalent * convert a string to its enum equivalent
*/ */
static SDL_GameControllerType SDL_GetGameControllerTypeFromString(const char *str) SDL_GameControllerType SDL_GetGameControllerTypeFromString(const char *str)
{ {
int i; int i;
@ -2675,7 +2676,8 @@ const char *SDL_GameControllerName(SDL_GameController *gamecontroller)
{ {
CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL); CHECK_GAMECONTROLLER_MAGIC(gamecontroller, NULL);
if (SDL_strcmp(gamecontroller->name, "*") == 0) { if (SDL_strcmp(gamecontroller->name, "*") == 0 ||
gamecontroller->joystick->steam_handle != 0) {
retval = SDL_JoystickName(gamecontroller->joystick); retval = SDL_JoystickName(gamecontroller->joystick);
} else { } else {
retval = gamecontroller->name; retval = gamecontroller->name;
@ -2698,15 +2700,27 @@ const char *SDL_GameControllerPath(SDL_GameController *gamecontroller)
SDL_GameControllerType SDL_GameControllerGetType(SDL_GameController *gamecontroller) SDL_GameControllerType SDL_GameControllerGetType(SDL_GameController *gamecontroller)
{ {
SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); SDL_GameControllerType type = SDL_CONTROLLER_TYPE_UNKNOWN;
SDL_Joystick *joystick;
const SDL_SteamVirtualGamepadInfo *info;
if (!joystick) { SDL_LockJoysticks();
return SDL_CONTROLLER_TYPE_UNKNOWN; {
CHECK_GAMECONTROLLER_MAGIC(gamecontroller, SDL_CONTROLLER_TYPE_UNKNOWN);
joystick = gamecontroller->joystick;
info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id);
if (info) {
type = info->type;
} else if (gamecontroller->type != SDL_CONTROLLER_TYPE_UNKNOWN) {
type = gamecontroller->type;
} else {
type = SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGetGUID(joystick), SDL_JoystickName(joystick));
}
} }
if (gamecontroller->type != SDL_CONTROLLER_TYPE_UNKNOWN) { SDL_UnlockJoysticks();
return gamecontroller->type;
} return type;
return SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGetGUID(joystick), SDL_JoystickName(joystick));
} }
int SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller) int SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller)
@ -2782,6 +2796,21 @@ const char * SDL_GameControllerGetSerial(SDL_GameController *gamecontroller)
return SDL_JoystickGetSerial(joystick); return SDL_JoystickGetSerial(joystick);
} }
Uint64 SDL_GameControllerGetSteamHandle(SDL_GameController *gamecontroller)
{
Uint64 handle = 0;
SDL_LockJoysticks();
{
CHECK_GAMECONTROLLER_MAGIC(gamecontroller, 0);
handle = gamecontroller->joystick->steam_handle;
}
SDL_UnlockJoysticks();
return handle;
}
/* /*
* Return if the controller in question is currently attached to the system, * Return if the controller in question is currently attached to the system,
* \return 0 if not plugged in, 1 if still present. * \return 0 if not plugged in, 1 if still present.

View file

@ -28,6 +28,7 @@
#include "SDL_sysjoystick.h" #include "SDL_sysjoystick.h"
#include "SDL_hints.h" #include "SDL_hints.h"
#include "../SDL_hints_c.h" #include "../SDL_hints_c.h"
#include "SDL_steam_virtual_gamepad.h"
#ifndef SDL_EVENTS_DISABLED #ifndef SDL_EVENTS_DISABLED
#include "../events/SDL_events_c.h" #include "../events/SDL_events_c.h"
@ -622,6 +623,8 @@ int SDL_JoystickInit(void)
SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
SDL_JoystickAllowBackgroundEventsChanged, NULL); SDL_JoystickAllowBackgroundEventsChanged, NULL);
SDL_InitSteamVirtualGamepadInfo();
status = -1; status = -1;
for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) { for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
if (SDL_joystick_drivers[i]->Init() >= 0) { if (SDL_joystick_drivers[i]->Init() >= 0) {
@ -660,6 +663,19 @@ SDL_JoystickID SDL_GetNextJoystickInstanceID()
return SDL_AtomicIncRef(&SDL_next_joystick_instance_id); return SDL_AtomicIncRef(&SDL_next_joystick_instance_id);
} }
const SDL_SteamVirtualGamepadInfo *SDL_GetJoystickInstanceVirtualGamepadInfo(SDL_JoystickID instance_id)
{
SDL_JoystickDriver *driver;
int device_index;
const SDL_SteamVirtualGamepadInfo *info = NULL;
if (SDL_SteamVirtualGamepadEnabled() &&
SDL_GetDriverAndJoystickIndex(SDL_JoystickGetDeviceIndexFromInstanceID(instance_id), &driver, &device_index)) {
info = SDL_GetSteamVirtualGamepadInfo(driver->GetDeviceSteamVirtualGamepadSlot(device_index));
}
return info;
}
/* /*
* Get the implementation dependent name of a joystick * Get the implementation dependent name of a joystick
*/ */
@ -667,9 +683,13 @@ const char *SDL_JoystickNameForIndex(int device_index)
{ {
SDL_JoystickDriver *driver; SDL_JoystickDriver *driver;
const char *name = NULL; const char *name = NULL;
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks(); SDL_LockJoysticks();
if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) { info = SDL_GetJoystickInstanceVirtualGamepadInfo(SDL_JoystickGetDeviceInstanceID(device_index));
if (info) {
name = info->name;
} else if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
name = driver->GetDeviceName(device_index); name = driver->GetDeviceName(device_index);
} }
SDL_UnlockJoysticks(); SDL_UnlockJoysticks();
@ -750,6 +770,7 @@ SDL_Joystick *SDL_JoystickOpen(int device_index)
const char *joystickname = NULL; const char *joystickname = NULL;
const char *joystickpath = NULL; const char *joystickpath = NULL;
SDL_JoystickPowerLevel initial_power_level; SDL_JoystickPowerLevel initial_power_level;
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks(); SDL_LockJoysticks();
@ -839,6 +860,12 @@ SDL_Joystick *SDL_JoystickOpen(int device_index)
joystick->is_game_controller = SDL_IsGameController(device_index); joystick->is_game_controller = SDL_IsGameController(device_index);
/* Get the Steam Input API handle */
info = SDL_GetJoystickInstanceVirtualGamepadInfo(instance_id);
if (info) {
joystick->steam_handle = info->handle;
}
/* Add joystick to list */ /* Add joystick to list */
++joystick->ref_count; ++joystick->ref_count;
/* Link the joystick in the list */ /* Link the joystick in the list */
@ -1282,15 +1309,20 @@ SDL_Joystick *SDL_JoystickFromPlayerIndex(int player_index)
const char *SDL_JoystickName(SDL_Joystick *joystick) const char *SDL_JoystickName(SDL_Joystick *joystick)
{ {
const char *retval; const char *retval;
const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks(); SDL_LockJoysticks();
{ info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id);
if (info) {
retval = info->name;
} else {
CHECK_JOYSTICK_MAGIC(joystick, NULL); CHECK_JOYSTICK_MAGIC(joystick, NULL);
retval = joystick->name; retval = joystick->name;
} }
SDL_UnlockJoysticks(); SDL_UnlockJoysticks();
/* FIXME: Really we should reference count this name so it doesn't go away after unlock */
return retval; return retval;
} }
@ -1609,6 +1641,8 @@ void SDL_JoystickQuit(void)
SDL_QuitSubSystem(SDL_INIT_EVENTS); SDL_QuitSubSystem(SDL_INIT_EVENTS);
#endif #endif
SDL_QuitSteamVirtualGamepadInfo();
SDL_DelHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, SDL_DelHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
SDL_JoystickAllowBackgroundEventsChanged, NULL); SDL_JoystickAllowBackgroundEventsChanged, NULL);
@ -1709,7 +1743,10 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
} }
if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) { if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) {
player_index = driver->GetDevicePlayerIndex(driver_device_index); player_index = driver->GetDeviceSteamVirtualGamepadSlot(driver_device_index);
if (player_index < 0) {
player_index = driver->GetDevicePlayerIndex(driver_device_index);
}
} }
if (player_index < 0 && SDL_IsGameController(device_index)) { if (player_index < 0 && SDL_IsGameController(device_index)) {
player_index = SDL_FindFreePlayerIndex(); player_index = SDL_FindFreePlayerIndex();
@ -2064,6 +2101,43 @@ int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
return posted; return posted;
} }
static void SendSteamHandleUpdateEvents(void)
{
SDL_Joystick *joystick;
const SDL_SteamVirtualGamepadInfo *info;
/* Check to see if any Steam handles changed */
for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
SDL_bool changed = SDL_FALSE;
if (!joystick->is_game_controller) {
continue;
}
info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id);
if (info) {
if (joystick->steam_handle != info->handle) {
joystick->steam_handle = info->handle;
changed = SDL_TRUE;
}
} else {
if (joystick->steam_handle != 0) {
joystick->steam_handle = 0;
changed = SDL_TRUE;
}
}
if (changed) {
SDL_Event event;
SDL_zero(event);
event.type = SDL_CONTROLLERSTEAMHANDLEUPDATED;
event.common.timestamp = 0;
event.cdevice.which = joystick->instance_id;
SDL_PushEvent(&event);
}
}
}
void SDL_JoystickUpdate(void) void SDL_JoystickUpdate(void)
{ {
int i; int i;
@ -2076,6 +2150,10 @@ void SDL_JoystickUpdate(void)
SDL_LockJoysticks(); SDL_LockJoysticks();
if (SDL_UpdateSteamVirtualGamepadInfo()) {
SendSteamHandleUpdateEvents();
}
#ifdef SDL_JOYSTICK_HIDAPI #ifdef SDL_JOYSTICK_HIDAPI
/* Special function for HIDAPI devices, as a single device can provide multiple SDL_Joysticks */ /* Special function for HIDAPI devices, as a single device can provide multiple SDL_Joysticks */
HIDAPI_UpdateDevices(); HIDAPI_UpdateDevices();
@ -2906,18 +2984,38 @@ SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
Uint16 SDL_JoystickGetDeviceVendor(int device_index) Uint16 SDL_JoystickGetDeviceVendor(int device_index)
{ {
Uint16 vendor; Uint16 vendor;
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index); const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
info = SDL_GetJoystickInstanceVirtualGamepadInfo(SDL_JoystickGetDeviceInstanceID(device_index));
if (info) {
vendor = info->vendor_id;
} else {
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL);
}
SDL_UnlockJoysticks();
SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL);
return vendor; return vendor;
} }
Uint16 SDL_JoystickGetDeviceProduct(int device_index) Uint16 SDL_JoystickGetDeviceProduct(int device_index)
{ {
Uint16 product; Uint16 product;
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index); const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
info = SDL_GetJoystickInstanceVirtualGamepadInfo(SDL_JoystickGetDeviceInstanceID(device_index));
if (info) {
product = info->product_id;
} else {
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(device_index);
SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL);
}
SDL_UnlockJoysticks();
SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL);
return product; return product;
} }
@ -2995,18 +3093,38 @@ SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick *joystick)
Uint16 SDL_JoystickGetVendor(SDL_Joystick *joystick) Uint16 SDL_JoystickGetVendor(SDL_Joystick *joystick)
{ {
Uint16 vendor; Uint16 vendor;
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id);
if (info) {
vendor = info->vendor_id;
} else {
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL);
}
SDL_UnlockJoysticks();
SDL_GetJoystickGUIDInfo(guid, &vendor, NULL, NULL, NULL);
return vendor; return vendor;
} }
Uint16 SDL_JoystickGetProduct(SDL_Joystick *joystick) Uint16 SDL_JoystickGetProduct(SDL_Joystick *joystick)
{ {
Uint16 product; Uint16 product;
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); const SDL_SteamVirtualGamepadInfo *info;
SDL_LockJoysticks();
info = SDL_GetJoystickInstanceVirtualGamepadInfo(joystick->instance_id);
if (info) {
product = info->product_id;
} else {
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL);
}
SDL_UnlockJoysticks();
SDL_GetJoystickGUIDInfo(guid, NULL, &product, NULL, NULL);
return product; return product;
} }

View file

@ -34,6 +34,7 @@ extern "C" {
#endif #endif
struct _SDL_JoystickDriver; struct _SDL_JoystickDriver;
struct SDL_SteamVirtualGamepadInfo;
extern char SDL_joystick_magic; extern char SDL_joystick_magic;
/* Initialization and shutdown functions */ /* Initialization and shutdown functions */
@ -179,6 +180,9 @@ extern int SDL_PrivateJoystickSensor(SDL_Joystick *joystick,
extern void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick, extern void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick,
SDL_JoystickPowerLevel ePowerLevel); SDL_JoystickPowerLevel ePowerLevel);
/* Function to get the Steam virtual gamepad info for a joystick */
extern const struct SDL_SteamVirtualGamepadInfo *SDL_GetJoystickInstanceVirtualGamepadInfo(SDL_JoystickID instance_id);
/* Internal sanity checking functions */ /* Internal sanity checking functions */
extern SDL_bool SDL_PrivateJoystickValid(SDL_Joystick *joystick); extern SDL_bool SDL_PrivateJoystickValid(SDL_Joystick *joystick);

View file

@ -0,0 +1,252 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../SDL_internal.h"
#include "SDL_hints.h"
#include "SDL_timer.h"
#include "SDL_joystick_c.h"
#include "SDL_steam_virtual_gamepad.h"
#ifdef __WIN32__
#include "../core/windows/SDL_windows.h"
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif
#define SDL_HINT_STEAM_VIRTUAL_GAMEPAD_INFO_FILE "SteamVirtualGamepadInfo"
extern SDL_GameControllerType SDL_GetGameControllerTypeFromString(const char *str);
static char *SDL_steam_virtual_gamepad_info_file SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
static Uint64 SDL_steam_virtual_gamepad_info_file_mtime SDL_GUARDED_BY(SDL_joystick_lock) = 0;
static Uint32 SDL_steam_virtual_gamepad_info_check_time SDL_GUARDED_BY(SDL_joystick_lock) = 0;
static SDL_SteamVirtualGamepadInfo **SDL_steam_virtual_gamepad_info SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
static int SDL_steam_virtual_gamepad_info_count SDL_GUARDED_BY(SDL_joystick_lock) = 0;
static Uint64 GetFileModificationTime(const char *file)
{
Uint64 modification_time = 0;
#ifdef __WIN32__
WCHAR *wFile = WIN_UTF8ToStringW(file);
if (wFile) {
HANDLE hFile = CreateFileW(wFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
FILETIME last_write_time;
if (GetFileTime(hFile, NULL, NULL, &last_write_time)) {
modification_time = last_write_time.dwHighDateTime;
modification_time <<= 32;
modification_time |= last_write_time.dwLowDateTime;
}
CloseHandle(hFile);
}
SDL_free(wFile);
}
#else
struct stat sb;
if (stat(file, &sb) == 0) {
modification_time = (Uint64)sb.st_mtime;
}
#endif
return modification_time;
}
static void SDL_FreeSteamVirtualGamepadInfo(void)
{
int i;
SDL_AssertJoysticksLocked();
for (i = 0; i < SDL_steam_virtual_gamepad_info_count; ++i) {
SDL_SteamVirtualGamepadInfo *entry = SDL_steam_virtual_gamepad_info[i];
if (entry) {
SDL_free(entry->name);
SDL_free(entry);
}
}
SDL_free(SDL_steam_virtual_gamepad_info);
SDL_steam_virtual_gamepad_info = NULL;
SDL_steam_virtual_gamepad_info_count = 0;
}
static void AddVirtualGamepadInfo(int slot, SDL_SteamVirtualGamepadInfo *info)
{
SDL_SteamVirtualGamepadInfo *new_info;
SDL_AssertJoysticksLocked();
if (slot < 0) {
return;
}
if (slot >= SDL_steam_virtual_gamepad_info_count) {
SDL_SteamVirtualGamepadInfo **slots = (SDL_SteamVirtualGamepadInfo **)SDL_realloc(SDL_steam_virtual_gamepad_info, (slot + 1)*sizeof(*SDL_steam_virtual_gamepad_info));
if (!slots) {
return;
}
while (SDL_steam_virtual_gamepad_info_count <= slot) {
slots[SDL_steam_virtual_gamepad_info_count++] = NULL;
}
SDL_steam_virtual_gamepad_info = slots;
}
if (SDL_steam_virtual_gamepad_info[slot]) {
/* We already have this slot info */
return;
}
new_info = (SDL_SteamVirtualGamepadInfo *)SDL_malloc(sizeof(*new_info));
if (!new_info) {
return;
}
SDL_copyp(new_info, info);
SDL_steam_virtual_gamepad_info[slot] = new_info;
SDL_zerop(info);
}
void SDL_InitSteamVirtualGamepadInfo(void)
{
const char *file;
SDL_AssertJoysticksLocked();
file = SDL_GetHint(SDL_HINT_STEAM_VIRTUAL_GAMEPAD_INFO_FILE);
if (file && *file) {
SDL_steam_virtual_gamepad_info_file = SDL_strdup(file);
}
SDL_UpdateSteamVirtualGamepadInfo();
}
SDL_bool SDL_SteamVirtualGamepadEnabled(void)
{
SDL_AssertJoysticksLocked();
return (SDL_steam_virtual_gamepad_info != NULL);
}
SDL_bool SDL_UpdateSteamVirtualGamepadInfo(void)
{
const int UPDATE_CHECK_INTERVAL_MS = 3000;
Uint32 now;
Uint64 mtime;
char *data, *end, *next, *line, *value;
size_t size;
int slot, new_slot;
SDL_SteamVirtualGamepadInfo info;
SDL_AssertJoysticksLocked();
if (!SDL_steam_virtual_gamepad_info_file) {
return SDL_FALSE;
}
now = SDL_GetTicks();
if (SDL_steam_virtual_gamepad_info_check_time &&
!SDL_TICKS_PASSED(now, (SDL_steam_virtual_gamepad_info_check_time + UPDATE_CHECK_INTERVAL_MS))) {
return SDL_FALSE;
}
SDL_steam_virtual_gamepad_info_check_time = now;
mtime = GetFileModificationTime(SDL_steam_virtual_gamepad_info_file);
if (mtime == 0 || mtime == SDL_steam_virtual_gamepad_info_file_mtime) {
return SDL_FALSE;
}
data = (char *)SDL_LoadFile(SDL_steam_virtual_gamepad_info_file, &size);
if (!data) {
return SDL_FALSE;
}
SDL_FreeSteamVirtualGamepadInfo();
slot = -1;
SDL_zero(info);
for (next = data, end = data + size; next < end; ) {
while (next < end && (*next == '\0' || *next == '\r' || *next == '\n')) {
++next;
}
line = next;
while (next < end && (*next != '\r' && *next != '\n')) {
++next;
}
*next = '\0';
if (SDL_sscanf(line, "[slot %d]", &new_slot) == 1) {
if (slot >= 0) {
AddVirtualGamepadInfo(slot, &info);
}
slot = new_slot;
} else {
value = SDL_strchr(line, '=');
if (value) {
*value++ = '\0';
if (SDL_strcmp(line, "name") == 0) {
SDL_free(info.name);
info.name = SDL_strdup(value);
} else if (SDL_strcmp(line, "VID") == 0) {
info.vendor_id = (Uint16)SDL_strtoul(value, NULL, 0);
} else if (SDL_strcmp(line, "PID") == 0) {
info.product_id = (Uint16)SDL_strtoul(value, NULL, 0);
} else if (SDL_strcmp(line, "type") == 0) {
info.type = SDL_GetGameControllerTypeFromString(value);
} else if (SDL_strcmp(line, "handle") == 0) {
info.handle = SDL_strtoull(value, NULL, 0);
}
}
}
}
if (slot >= 0) {
AddVirtualGamepadInfo(slot, &info);
}
SDL_free(data);
SDL_steam_virtual_gamepad_info_file_mtime = mtime;
return SDL_TRUE;
}
const SDL_SteamVirtualGamepadInfo *SDL_GetSteamVirtualGamepadInfo(int slot)
{
SDL_AssertJoysticksLocked();
if (slot < 0 || slot >= SDL_steam_virtual_gamepad_info_count) {
return NULL;
}
return SDL_steam_virtual_gamepad_info[slot];
}
void SDL_QuitSteamVirtualGamepadInfo(void)
{
SDL_AssertJoysticksLocked();
if (SDL_steam_virtual_gamepad_info_file) {
SDL_FreeSteamVirtualGamepadInfo();
SDL_free(SDL_steam_virtual_gamepad_info_file);
SDL_steam_virtual_gamepad_info_file = NULL;
}
}

View file

@ -0,0 +1,36 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../SDL_internal.h"
typedef struct SDL_SteamVirtualGamepadInfo
{
Uint64 handle;
char *name;
Uint16 vendor_id;
Uint16 product_id;
SDL_GameControllerType type;
} SDL_SteamVirtualGamepadInfo;
void SDL_InitSteamVirtualGamepadInfo(void);
SDL_bool SDL_SteamVirtualGamepadEnabled(void);
SDL_bool SDL_UpdateSteamVirtualGamepadInfo(void);
const SDL_SteamVirtualGamepadInfo *SDL_GetSteamVirtualGamepadInfo(int slot);
void SDL_QuitSteamVirtualGamepadInfo(void);

View file

@ -79,6 +79,7 @@ struct _SDL_Joystick
char *serial _guarded; /* Joystick serial */ char *serial _guarded; /* Joystick serial */
SDL_JoystickGUID guid _guarded; /* Joystick guid */ SDL_JoystickGUID guid _guarded; /* Joystick guid */
Uint16 firmware_version _guarded; /* Firmware version, if available */ Uint16 firmware_version _guarded; /* Firmware version, if available */
Uint64 steam_handle _guarded; /* Steam controller API handle */
int naxes _guarded; /* Number of axis controls on the joystick */ int naxes _guarded; /* Number of axis controls on the joystick */
SDL_JoystickAxisInfo *axes _guarded; SDL_JoystickAxisInfo *axes _guarded;
@ -167,6 +168,9 @@ typedef struct _SDL_JoystickDriver
/* Function to get the device-dependent path of a joystick */ /* Function to get the device-dependent path of a joystick */
const char *(*GetDevicePath)(int device_index); const char *(*GetDevicePath)(int device_index);
/* Function to get the Steam virtual gamepad slot of a joystick */
int (*GetDeviceSteamVirtualGamepadSlot)(int device_index);
/* Function to get the player index of a joystick */ /* Function to get the player index of a joystick */
int (*GetDevicePlayerIndex)(int device_index); int (*GetDevicePlayerIndex)(int device_index);

View file

@ -542,6 +542,11 @@ static const char *ANDROID_JoystickGetDevicePath(int device_index)
return NULL; return NULL;
} }
static int ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int ANDROID_JoystickGetDevicePlayerIndex(int device_index) static int ANDROID_JoystickGetDevicePlayerIndex(int device_index)
{ {
return -1; return -1;
@ -682,6 +687,7 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver = {
ANDROID_JoystickDetect, ANDROID_JoystickDetect,
ANDROID_JoystickGetDeviceName, ANDROID_JoystickGetDeviceName,
ANDROID_JoystickGetDevicePath, ANDROID_JoystickGetDevicePath,
ANDROID_JoystickGetDeviceSteamVirtualGamepadSlot,
ANDROID_JoystickGetDevicePlayerIndex, ANDROID_JoystickGetDevicePlayerIndex,
ANDROID_JoystickSetDevicePlayerIndex, ANDROID_JoystickSetDevicePlayerIndex,
ANDROID_JoystickGetDeviceGUID, ANDROID_JoystickGetDeviceGUID,

View file

@ -574,6 +574,11 @@ static const char *BSD_JoystickGetDevicePath(int device_index)
return JoystickByDevIndex(device_index)->path; return JoystickByDevIndex(device_index)->path;
} }
static int BSD_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int BSD_JoystickGetDevicePlayerIndex(int device_index) static int BSD_JoystickGetDevicePlayerIndex(int device_index)
{ {
return -1; return -1;
@ -870,6 +875,7 @@ SDL_JoystickDriver SDL_BSD_JoystickDriver = {
BSD_JoystickDetect, BSD_JoystickDetect,
BSD_JoystickGetDeviceName, BSD_JoystickGetDeviceName,
BSD_JoystickGetDevicePath, BSD_JoystickGetDevicePath,
BSD_JoystickGetDeviceSteamVirtualGamepadSlot,
BSD_JoystickGetDevicePlayerIndex, BSD_JoystickGetDevicePlayerIndex,
BSD_JoystickSetDevicePlayerIndex, BSD_JoystickSetDevicePlayerIndex,
BSD_JoystickGetDeviceGUID, BSD_JoystickGetDeviceGUID,

View file

@ -407,6 +407,19 @@ static void AddHIDElement(const void *value, void *parameter)
} }
} }
static int GetSteamVirtualGamepadSlot(Uint16 vendor_id, Uint16 product_id, const char *product_string)
{
int slot = -1;
if (vendor_id == USB_VENDOR_MICROSOFT && product_id == USB_PRODUCT_XBOX360_WIRED_CONTROLLER) {
/* Gamepad name is "GamePad-N", where N is slot + 1 */
if (SDL_sscanf(product_string, "GamePad-%d", &slot) == 1) {
slot -= 1;
}
}
return slot;
}
static SDL_bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice) static SDL_bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
{ {
Sint32 vendor = 0; Sint32 vendor = 0;
@ -487,6 +500,7 @@ static SDL_bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
#endif #endif
pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, pDevice->product, 0, 0); pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, pDevice->product, 0, 0);
pDevice->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot((Uint16)vendor, (Uint16)product, product_string);
array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone); array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone);
if (array) { if (array) {
@ -714,6 +728,12 @@ const char *DARWIN_JoystickGetDevicePath(int device_index)
return NULL; return NULL;
} }
static int DARWIN_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
recDevice *device = GetDeviceForIndex(device_index);
return device ? device->steam_virtual_gamepad_slot : -1;
}
static int DARWIN_JoystickGetDevicePlayerIndex(int device_index) static int DARWIN_JoystickGetDevicePlayerIndex(int device_index)
{ {
return -1; return -1;
@ -1059,6 +1079,7 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver = {
DARWIN_JoystickDetect, DARWIN_JoystickDetect,
DARWIN_JoystickGetDeviceName, DARWIN_JoystickGetDeviceName,
DARWIN_JoystickGetDevicePath, DARWIN_JoystickGetDevicePath,
DARWIN_JoystickGetDeviceSteamVirtualGamepadSlot,
DARWIN_JoystickGetDevicePlayerIndex, DARWIN_JoystickGetDevicePlayerIndex,
DARWIN_JoystickSetDevicePlayerIndex, DARWIN_JoystickSetDevicePlayerIndex,
DARWIN_JoystickGetDeviceGUID, DARWIN_JoystickGetDeviceGUID,

View file

@ -71,6 +71,7 @@ struct joystick_hwdata
int instance_id; int instance_id;
SDL_JoystickGUID guid; SDL_JoystickGUID guid;
int steam_virtual_gamepad_slot;
struct joystick_hwdata *pNext; /* next device */ struct joystick_hwdata *pNext; /* next device */
}; };

View file

@ -52,6 +52,11 @@ static const char *DUMMY_JoystickGetDevicePath(int device_index)
return NULL; return NULL;
} }
static int DUMMY_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int DUMMY_JoystickGetDevicePlayerIndex(int device_index) static int DUMMY_JoystickGetDevicePlayerIndex(int device_index)
{ {
return -1; return -1;
@ -131,6 +136,7 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver = {
DUMMY_JoystickDetect, DUMMY_JoystickDetect,
DUMMY_JoystickGetDeviceName, DUMMY_JoystickGetDeviceName,
DUMMY_JoystickGetDevicePath, DUMMY_JoystickGetDevicePath,
DUMMY_JoystickGetDeviceSteamVirtualGamepadSlot,
DUMMY_JoystickGetDevicePlayerIndex, DUMMY_JoystickGetDevicePlayerIndex,
DUMMY_JoystickSetDevicePlayerIndex, DUMMY_JoystickSetDevicePlayerIndex,
DUMMY_JoystickGetDeviceGUID, DUMMY_JoystickGetDeviceGUID,

View file

@ -274,6 +274,11 @@ static const char *EMSCRIPTEN_JoystickGetDevicePath(int device_index)
return NULL; return NULL;
} }
static int EMSCRIPTEN_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int EMSCRIPTEN_JoystickGetDevicePlayerIndex(int device_index) static int EMSCRIPTEN_JoystickGetDevicePlayerIndex(int device_index)
{ {
return -1; return -1;
@ -421,6 +426,7 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver = {
EMSCRIPTEN_JoystickDetect, EMSCRIPTEN_JoystickDetect,
EMSCRIPTEN_JoystickGetDeviceName, EMSCRIPTEN_JoystickGetDeviceName,
EMSCRIPTEN_JoystickGetDevicePath, EMSCRIPTEN_JoystickGetDevicePath,
EMSCRIPTEN_JoystickGetDeviceSteamVirtualGamepadSlot,
EMSCRIPTEN_JoystickGetDevicePlayerIndex, EMSCRIPTEN_JoystickGetDevicePlayerIndex,
EMSCRIPTEN_JoystickSetDevicePlayerIndex, EMSCRIPTEN_JoystickSetDevicePlayerIndex,
EMSCRIPTEN_JoystickGetDeviceGUID, EMSCRIPTEN_JoystickGetDeviceGUID,

View file

@ -102,6 +102,11 @@ extern "C"
return SDL_joyport[device_index]; return SDL_joyport[device_index];
} }
static int HAIKU_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int HAIKU_JoystickGetDevicePlayerIndex(int device_index) static int HAIKU_JoystickGetDevicePlayerIndex(int device_index)
{ {
return -1; return -1;
@ -299,6 +304,7 @@ extern "C"
HAIKU_JoystickDetect, HAIKU_JoystickDetect,
HAIKU_JoystickGetDeviceName, HAIKU_JoystickGetDeviceName,
HAIKU_JoystickGetDevicePath, HAIKU_JoystickGetDevicePath,
HAIKU_JoystickGetDeviceSteamVirtualGamepadSlot,
HAIKU_JoystickGetDevicePlayerIndex, HAIKU_JoystickGetDevicePlayerIndex,
HAIKU_JoystickSetDevicePlayerIndex, HAIKU_JoystickSetDevicePlayerIndex,
HAIKU_JoystickGetDeviceGUID, HAIKU_JoystickGetDeviceGUID,

View file

@ -1373,6 +1373,11 @@ static const char *HIDAPI_JoystickGetDevicePath(int device_index)
return path; return path;
} }
static int HIDAPI_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int HIDAPI_JoystickGetDevicePlayerIndex(int device_index) static int HIDAPI_JoystickGetDevicePlayerIndex(int device_index)
{ {
SDL_HIDAPI_Device *device; SDL_HIDAPI_Device *device;
@ -1651,6 +1656,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver = {
HIDAPI_JoystickDetect, HIDAPI_JoystickDetect,
HIDAPI_JoystickGetDeviceName, HIDAPI_JoystickGetDeviceName,
HIDAPI_JoystickGetDevicePath, HIDAPI_JoystickGetDevicePath,
HIDAPI_JoystickGetDeviceSteamVirtualGamepadSlot,
HIDAPI_JoystickGetDevicePlayerIndex, HIDAPI_JoystickGetDevicePlayerIndex,
HIDAPI_JoystickSetDevicePlayerIndex, HIDAPI_JoystickSetDevicePlayerIndex,
HIDAPI_JoystickGetDeviceGUID, HIDAPI_JoystickGetDeviceGUID,

View file

@ -668,6 +668,10 @@ static BOOL IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle
} }
device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, name, 'm', subtype); device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, name, 'm', subtype);
if (SDL_ShouldIgnoreJoystick(name, device->guid)) {
return SDL_FALSE;
}
/* This will be set when the first button press of the controller is /* This will be set when the first button press of the controller is
* detected. */ * detected. */
controller.playerIndex = -1; controller.playerIndex = -1;
@ -712,6 +716,7 @@ static void IOS_AddJoystickDevice(GCController *controller, SDL_bool acceleromet
} else if (controller) { } else if (controller) {
#ifdef SDL_JOYSTICK_MFI #ifdef SDL_JOYSTICK_MFI
if (!IOS_AddMFIJoystickDevice(device, controller)) { if (!IOS_AddMFIJoystickDevice(device, controller)) {
SDL_free(device->name);
SDL_free(device); SDL_free(device);
return; return;
} }
@ -905,6 +910,11 @@ static const char *IOS_JoystickGetDevicePath(int device_index)
return NULL; return NULL;
} }
static int IOS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int IOS_JoystickGetDevicePlayerIndex(int device_index) static int IOS_JoystickGetDevicePlayerIndex(int device_index)
{ {
#ifdef SDL_JOYSTICK_MFI #ifdef SDL_JOYSTICK_MFI
@ -2163,6 +2173,7 @@ SDL_JoystickDriver SDL_IOS_JoystickDriver = {
IOS_JoystickDetect, IOS_JoystickDetect,
IOS_JoystickGetDeviceName, IOS_JoystickGetDeviceName,
IOS_JoystickGetDevicePath, IOS_JoystickGetDevicePath,
IOS_JoystickGetDeviceSteamVirtualGamepadSlot,
IOS_JoystickGetDevicePlayerIndex, IOS_JoystickGetDevicePlayerIndex,
IOS_JoystickSetDevicePlayerIndex, IOS_JoystickSetDevicePlayerIndex,
IOS_JoystickGetDeviceGUID, IOS_JoystickGetDeviceGUID,

View file

@ -221,14 +221,18 @@ static SDL_bool IsVirtualJoystick(Uint16 vendor, Uint16 product, Uint16 version,
} }
#endif /* SDL_JOYSTICK_HIDAPI */ #endif /* SDL_JOYSTICK_HIDAPI */
static SDL_bool GetVirtualGamepadSlot(const char *name, int *slot) static SDL_bool GetSteamVirtualGamepadSlot(int fd, int *slot)
{ {
const char *digits = SDL_strstr(name, "pad "); char name[128];
if (digits) {
digits += 4; if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0) {
if (SDL_isdigit(*digits)) { const char *digits = SDL_strstr(name, "pad ");
*slot = SDL_atoi(digits); if (digits) {
return SDL_TRUE; digits += 4;
if (SDL_isdigit(*digits)) {
*slot = SDL_atoi(digits);
return SDL_TRUE;
}
} }
} }
return SDL_FALSE; return SDL_FALSE;
@ -441,7 +445,6 @@ static void MaybeAddDevice(const char *path)
#ifdef DEBUG_INPUT_EVENTS #ifdef DEBUG_INPUT_EVENTS
SDL_Log("found joystick: %s\n", path); SDL_Log("found joystick: %s\n", path);
#endif #endif
close(fd);
item = (SDL_joylist_item *)SDL_calloc(1, sizeof(SDL_joylist_item)); item = (SDL_joylist_item *)SDL_calloc(1, sizeof(SDL_joylist_item));
if (!item) { if (!item) {
SDL_free(name); SDL_free(name);
@ -456,7 +459,7 @@ static void MaybeAddDevice(const char *path)
if (vendor == USB_VENDOR_VALVE && if (vendor == USB_VENDOR_VALVE &&
product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) { product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
GetVirtualGamepadSlot(item->name, &item->steam_virtual_gamepad_slot); GetSteamVirtualGamepadSlot(fd, &item->steam_virtual_gamepad_slot);
} }
if ((!item->path) || (!item->name)) { if ((!item->path) || (!item->name)) {
@ -483,7 +486,6 @@ static void MaybeAddDevice(const char *path)
#ifdef DEBUG_INPUT_EVENTS #ifdef DEBUG_INPUT_EVENTS
SDL_Log("found sensor: %s\n", path); SDL_Log("found sensor: %s\n", path);
#endif #endif
close(fd);
item_sensor = (SDL_sensorlist_item *)SDL_calloc(1, sizeof(SDL_sensorlist_item)); item_sensor = (SDL_sensorlist_item *)SDL_calloc(1, sizeof(SDL_sensorlist_item));
if (!item_sensor) { if (!item_sensor) {
goto done; goto done;
@ -501,8 +503,10 @@ static void MaybeAddDevice(const char *path)
goto done; goto done;
} }
close(fd);
done: done:
if (fd >= 0) {
close(fd);
}
SDL_UnlockJoysticks(); SDL_UnlockJoysticks();
} }
@ -870,7 +874,6 @@ static void LINUX_ScanSteamVirtualGamepads(void)
int fd; int fd;
struct dirent **entries = NULL; struct dirent **entries = NULL;
char path[PATH_MAX]; char path[PATH_MAX];
char name[128];
struct input_id inpid; struct input_id inpid;
int num_virtual_gamepads = 0; int num_virtual_gamepads = 0;
int virtual_gamepad_slot; int virtual_gamepad_slot;
@ -885,8 +888,7 @@ static void LINUX_ScanSteamVirtualGamepads(void)
if (ioctl(fd, EVIOCGID, &inpid) == 0 && if (ioctl(fd, EVIOCGID, &inpid) == 0 &&
inpid.vendor == USB_VENDOR_VALVE && inpid.vendor == USB_VENDOR_VALVE &&
inpid.product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD && inpid.product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD &&
ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0 && GetSteamVirtualGamepadSlot(fd, &virtual_gamepad_slot)) {
GetVirtualGamepadSlot(name, &virtual_gamepad_slot)) {
VirtualGamepadEntry *new_virtual_gamepads = (VirtualGamepadEntry *)SDL_realloc(virtual_gamepads, (num_virtual_gamepads + 1) * sizeof(*virtual_gamepads)); VirtualGamepadEntry *new_virtual_gamepads = (VirtualGamepadEntry *)SDL_realloc(virtual_gamepads, (num_virtual_gamepads + 1) * sizeof(*virtual_gamepads));
if (new_virtual_gamepads) { if (new_virtual_gamepads) {
VirtualGamepadEntry *entry = &new_virtual_gamepads[num_virtual_gamepads]; VirtualGamepadEntry *entry = &new_virtual_gamepads[num_virtual_gamepads];
@ -1112,11 +1114,16 @@ static const char *LINUX_JoystickGetDevicePath(int device_index)
return JoystickByDevIndex(device_index)->path; return JoystickByDevIndex(device_index)->path;
} }
static int LINUX_JoystickGetDevicePlayerIndex(int device_index) static int LINUX_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{ {
return JoystickByDevIndex(device_index)->steam_virtual_gamepad_slot; return JoystickByDevIndex(device_index)->steam_virtual_gamepad_slot;
} }
static int LINUX_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
}
static void LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index) static void LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index)
{ {
} }
@ -2736,6 +2743,7 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver = {
LINUX_JoystickDetect, LINUX_JoystickDetect,
LINUX_JoystickGetDeviceName, LINUX_JoystickGetDeviceName,
LINUX_JoystickGetDevicePath, LINUX_JoystickGetDevicePath,
LINUX_JoystickGetDeviceSteamVirtualGamepadSlot,
LINUX_JoystickGetDevicePlayerIndex, LINUX_JoystickGetDevicePlayerIndex,
LINUX_JoystickSetDevicePlayerIndex, LINUX_JoystickSetDevicePlayerIndex,
LINUX_JoystickGetDeviceGUID, LINUX_JoystickGetDeviceGUID,

View file

@ -234,6 +234,11 @@ static const char *N3DS_JoystickGetDevicePath(int device_index)
return NULL; return NULL;
} }
static int N3DS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int N3DS_JoystickGetDevicePlayerIndex(int device_index) static int N3DS_JoystickGetDevicePlayerIndex(int device_index)
{ {
return -1; return -1;
@ -274,6 +279,7 @@ SDL_JoystickDriver SDL_N3DS_JoystickDriver = {
.Detect = N3DS_JoystickDetect, .Detect = N3DS_JoystickDetect,
.GetDeviceName = N3DS_JoystickGetDeviceName, .GetDeviceName = N3DS_JoystickGetDeviceName,
.GetDevicePath = N3DS_JoystickGetDevicePath, .GetDevicePath = N3DS_JoystickGetDevicePath,
.GetDeviceSteamVirtualGamepadSlot = N3DS_JoystickGetDeviceSteamVirtualGamepadSlot,
.GetDevicePlayerIndex = N3DS_JoystickGetDevicePlayerIndex, .GetDevicePlayerIndex = N3DS_JoystickGetDevicePlayerIndex,
.SetDevicePlayerIndex = N3DS_JoystickSetDevicePlayerIndex, .SetDevicePlayerIndex = N3DS_JoystickSetDevicePlayerIndex,
.GetDeviceGUID = N3DS_JoystickGetDeviceGUID, .GetDeviceGUID = N3DS_JoystickGetDeviceGUID,

View file

@ -160,6 +160,12 @@ static const char *PS2_JoystickGetDevicePath(int index)
return NULL; return NULL;
} }
/* Function to get the Steam virtual gamepad slot of a joystick */
static int PS2_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
/* Function to get the player index of a joystick */ /* Function to get the player index of a joystick */
static int PS2_JoystickGetDevicePlayerIndex(int device_index) static int PS2_JoystickGetDevicePlayerIndex(int device_index)
{ {
@ -343,6 +349,7 @@ SDL_JoystickDriver SDL_PS2_JoystickDriver = {
PS2_JoystickDetect, PS2_JoystickDetect,
PS2_JoystickGetDeviceName, PS2_JoystickGetDeviceName,
PS2_JoystickGetDevicePath, PS2_JoystickGetDevicePath,
PS2_JoystickGetDeviceSteamVirtualGamepadSlot,
PS2_JoystickGetDevicePlayerIndex, PS2_JoystickGetDevicePlayerIndex,
PS2_JoystickSetDevicePlayerIndex, PS2_JoystickSetDevicePlayerIndex,
PS2_JoystickGetDeviceGUID, PS2_JoystickGetDeviceGUID,

View file

@ -124,6 +124,11 @@ static const char *PSP_JoystickGetDevicePath(int index)
return NULL; return NULL;
} }
static int PSP_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int PSP_JoystickGetDevicePlayerIndex(int device_index) static int PSP_JoystickGetDevicePlayerIndex(int device_index)
{ {
return -1; return -1;
@ -255,6 +260,7 @@ SDL_JoystickDriver SDL_PSP_JoystickDriver = {
PSP_JoystickDetect, PSP_JoystickDetect,
PSP_JoystickGetDeviceName, PSP_JoystickGetDeviceName,
PSP_JoystickGetDevicePath, PSP_JoystickGetDevicePath,
PSP_JoystickGetDeviceSteamVirtualGamepadSlot,
PSP_JoystickGetDevicePlayerIndex, PSP_JoystickGetDevicePlayerIndex,
PSP_JoystickSetDevicePlayerIndex, PSP_JoystickSetDevicePlayerIndex,
PSP_JoystickGetDeviceGUID, PSP_JoystickGetDeviceGUID,

View file

@ -362,6 +362,11 @@ static const char *VIRTUAL_JoystickGetDevicePath(int device_index)
return NULL; return NULL;
} }
static int VIRTUAL_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int VIRTUAL_JoystickGetDevicePlayerIndex(int device_index) static int VIRTUAL_JoystickGetDevicePlayerIndex(int device_index)
{ {
return -1; return -1;
@ -722,6 +727,7 @@ SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver = {
VIRTUAL_JoystickDetect, VIRTUAL_JoystickDetect,
VIRTUAL_JoystickGetDeviceName, VIRTUAL_JoystickGetDeviceName,
VIRTUAL_JoystickGetDevicePath, VIRTUAL_JoystickGetDevicePath,
VIRTUAL_JoystickGetDeviceSteamVirtualGamepadSlot,
VIRTUAL_JoystickGetDevicePlayerIndex, VIRTUAL_JoystickGetDevicePlayerIndex,
VIRTUAL_JoystickSetDevicePlayerIndex, VIRTUAL_JoystickSetDevicePlayerIndex,
VIRTUAL_JoystickGetDeviceGUID, VIRTUAL_JoystickGetDeviceGUID,

View file

@ -187,6 +187,11 @@ const char *VITA_JoystickGetDevicePath(int index)
return NULL; return NULL;
} }
static int VITA_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return -1;
}
static int VITA_JoystickGetDevicePlayerIndex(int device_index) static int VITA_JoystickGetDevicePlayerIndex(int device_index)
{ {
return -1; return -1;
@ -377,6 +382,7 @@ SDL_JoystickDriver SDL_VITA_JoystickDriver = {
VITA_JoystickDetect, VITA_JoystickDetect,
VITA_JoystickGetDeviceName, VITA_JoystickGetDeviceName,
VITA_JoystickGetDevicePath, VITA_JoystickGetDevicePath,
VITA_JoystickGetDeviceSteamVirtualGamepadSlot,
VITA_JoystickGetDevicePlayerIndex, VITA_JoystickGetDevicePlayerIndex,
VITA_JoystickSetDevicePlayerIndex, VITA_JoystickSetDevicePlayerIndex,
VITA_JoystickGetDeviceGUID, VITA_JoystickGetDeviceGUID,

View file

@ -437,6 +437,17 @@ int SDL_DINPUT_JoystickInit(void)
return 0; return 0;
} }
static int GetSteamVirtualGamepadSlot(Uint16 vendor_id, Uint16 product_id, const char *device_path)
{
int slot = -1;
if (vendor_id == USB_VENDOR_VALVE &&
product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
(void)SDL_sscanf(device_path, "\\\\?\\HID#VID_28DE&PID_11FF&IG_0%d", &slot);
}
return slot;
}
/* helper function for direct input, gets called for each connected joystick */ /* helper function for direct input, gets called for each connected joystick */
static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext) static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext)
{ {
@ -489,10 +500,10 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta
pNewJoystick = pNewJoystick->pNext; pNewJoystick = pNewJoystick->pNext;
} }
pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData)); pNewJoystick = (JoyStick_DeviceData *)SDL_calloc(1, sizeof(JoyStick_DeviceData));
CHECK(pNewJoystick); CHECK(pNewJoystick);
SDL_zerop(pNewJoystick); pNewJoystick->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(vendor, product, hidPath);
SDL_strlcpy(pNewJoystick->path, hidPath, SDL_arraysize(pNewJoystick->path)); SDL_strlcpy(pNewJoystick->path, hidPath, SDL_arraysize(pNewJoystick->path));
SDL_memcpy(&pNewJoystick->dxdevice, pDeviceInstance, sizeof(DIDEVICEINSTANCE)); SDL_memcpy(&pNewJoystick->dxdevice, pDeviceInstance, sizeof(DIDEVICEINSTANCE));

View file

@ -119,6 +119,7 @@ typedef struct _SDL_RAWINPUT_Device
SDL_JoystickGUID guid; SDL_JoystickGUID guid;
SDL_bool is_xinput; SDL_bool is_xinput;
SDL_bool is_xboxone; SDL_bool is_xboxone;
int steam_virtual_gamepad_slot;
PHIDP_PREPARSED_DATA preparsed_data; PHIDP_PREPARSED_DATA preparsed_data;
HANDLE hDevice; HANDLE hDevice;
@ -836,6 +837,19 @@ static SDL_RAWINPUT_Device *RAWINPUT_DeviceFromHandle(HANDLE hDevice)
return NULL; return NULL;
} }
static int GetSteamVirtualGamepadSlot(Uint16 vendor_id, Uint16 product_id, const char *device_path)
{
int slot = -1;
// The format for the raw input device path is documented here:
// https://partner.steamgames.com/doc/features/steam_controller/steam_input_gamepad_emulation_bestpractices
if (vendor_id == USB_VENDOR_VALVE &&
product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
(void)SDL_sscanf(device_path, "\\\\.\\pipe\\HID#VID_045E&PID_028E&IG_00#%*X&%*X&%*X#%d#%*u", &slot);
}
return slot;
}
static void RAWINPUT_AddDevice(HANDLE hDevice) static void RAWINPUT_AddDevice(HANDLE hDevice)
{ {
#define CHECK(expression) \ #define CHECK(expression) \
@ -877,6 +891,7 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
device->version = (Uint16)rdi.hid.dwVersionNumber; device->version = (Uint16)rdi.hid.dwVersionNumber;
device->is_xinput = SDL_TRUE; device->is_xinput = SDL_TRUE;
device->is_xboxone = SDL_IsJoystickXboxOne(device->vendor_id, device->product_id); device->is_xboxone = SDL_IsJoystickXboxOne(device->vendor_id, device->product_id);
device->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(device->vendor_id, device->product_id, dev_name);
/* Get HID Top-Level Collection Preparsed Data */ /* Get HID Top-Level Collection Preparsed Data */
size = 0; size = 0;
@ -1183,6 +1198,11 @@ static const char *RAWINPUT_JoystickGetDevicePath(int device_index)
return RAWINPUT_GetDeviceByIndex(device_index)->path; return RAWINPUT_GetDeviceByIndex(device_index)->path;
} }
static int RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return RAWINPUT_GetDeviceByIndex(device_index)->steam_virtual_gamepad_slot;
}
static int RAWINPUT_JoystickGetDevicePlayerIndex(int device_index) static int RAWINPUT_JoystickGetDevicePlayerIndex(int device_index)
{ {
return -1; return -1;
@ -2175,6 +2195,7 @@ SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver = {
RAWINPUT_JoystickDetect, RAWINPUT_JoystickDetect,
RAWINPUT_JoystickGetDeviceName, RAWINPUT_JoystickGetDeviceName,
RAWINPUT_JoystickGetDevicePath, RAWINPUT_JoystickGetDevicePath,
RAWINPUT_JoystickGetDeviceSteamVirtualGamepadSlot,
RAWINPUT_JoystickGetDevicePlayerIndex, RAWINPUT_JoystickGetDevicePlayerIndex,
RAWINPUT_JoystickSetDevicePlayerIndex, RAWINPUT_JoystickSetDevicePlayerIndex,
RAWINPUT_JoystickGetDeviceGUID, RAWINPUT_JoystickGetDeviceGUID,

View file

@ -64,6 +64,7 @@ typedef struct WindowsGamingInputControllerState
int naxes; int naxes;
int nhats; int nhats;
int nbuttons; int nbuttons;
int steam_virtual_gamepad_slot;
} WindowsGamingInputControllerState; } WindowsGamingInputControllerState;
static struct static struct
@ -385,6 +386,50 @@ static ULONG STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_Release(__FI
return rc; return rc;
} }
static int GetSteamVirtualGamepadSlot(__x_ABI_CWindows_CGaming_CInput_CIRawGameController *controller, Uint16 vendor_id, Uint16 product_id)
{
int slot = -1;
if (vendor_id == USB_VENDOR_VALVE &&
product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
__x_ABI_CWindows_CGaming_CInput_CIRawGameController2 *controller2 = NULL;
HRESULT hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IRawGameController2, (void **)&controller2);
if (SUCCEEDED(hr)) {
HSTRING hString;
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController2_get_NonRoamableId(controller2, &hString);
if (SUCCEEDED(hr)) {
typedef PCWSTR(WINAPI * WindowsGetStringRawBuffer_t)(HSTRING string, UINT32 * length);
typedef HRESULT(WINAPI * WindowsDeleteString_t)(HSTRING string);
WindowsGetStringRawBuffer_t WindowsGetStringRawBufferFunc = NULL;
WindowsDeleteString_t WindowsDeleteStringFunc = NULL;
#ifdef __WINRT__
WindowsGetStringRawBufferFunc = WindowsGetStringRawBuffer;
WindowsDeleteStringFunc = WindowsDeleteString;
#else
{
WindowsGetStringRawBufferFunc = (WindowsGetStringRawBuffer_t)WIN_LoadComBaseFunction("WindowsGetStringRawBuffer");
WindowsDeleteStringFunc = (WindowsDeleteString_t)WIN_LoadComBaseFunction("WindowsDeleteString");
}
#endif /* __WINRT__ */
if (WindowsGetStringRawBufferFunc && WindowsDeleteStringFunc) {
PCWSTR string = WindowsGetStringRawBufferFunc(hString, NULL);
if (string) {
char *id = WIN_StringToUTF8W(string);
if (id) {
(void)SDL_sscanf(id, "{wgi/nrid/:steam-%*X&%*X&%*X#%d#%*u}", &slot);
SDL_free(id);
}
}
WindowsDeleteStringFunc(hString);
}
}
__x_ABI_CWindows_CGaming_CInput_CIRawGameController2_Release(controller2);
}
}
return slot;
}
static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdded(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController *This, IInspectable *sender, __x_ABI_CWindows_CGaming_CInput_CIRawGameController *e) static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdded(__FIEventHandler_1_Windows__CGaming__CInput__CRawGameController *This, IInspectable *sender, __x_ABI_CWindows_CGaming_CInput_CIRawGameController *e)
{ {
HRESULT hr; HRESULT hr;
@ -502,6 +547,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
state->name = name; state->name = name;
state->guid = guid; state->guid = guid;
state->type = type; state->type = type;
state->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(controller, vendor, product);
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_ButtonCount(controller, &state->nbuttons); __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_ButtonCount(controller, &state->nbuttons);
__x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_AxisCount(controller, &state->naxes); __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_AxisCount(controller, &state->naxes);
@ -688,6 +734,11 @@ static const char *WGI_JoystickGetDevicePath(int device_index)
return NULL; return NULL;
} }
static int WGI_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
return wgi.controllers[device_index].steam_virtual_gamepad_slot;
}
static int WGI_JoystickGetDevicePlayerIndex(int device_index) static int WGI_JoystickGetDevicePlayerIndex(int device_index)
{ {
return -1; return -1;
@ -1004,6 +1055,7 @@ SDL_JoystickDriver SDL_WGI_JoystickDriver = {
WGI_JoystickDetect, WGI_JoystickDetect,
WGI_JoystickGetDeviceName, WGI_JoystickGetDeviceName,
WGI_JoystickGetDevicePath, WGI_JoystickGetDevicePath,
WGI_JoystickGetDeviceSteamVirtualGamepadSlot,
WGI_JoystickGetDevicePlayerIndex, WGI_JoystickGetDevicePlayerIndex,
WGI_JoystickSetDevicePlayerIndex, WGI_JoystickSetDevicePlayerIndex,
WGI_JoystickGetDeviceGUID, WGI_JoystickGetDeviceGUID,

View file

@ -618,6 +618,23 @@ static const char *WINDOWS_JoystickGetDevicePath(int device_index)
return device->path; return device->path;
} }
static int WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
{
JoyStick_DeviceData *device = SYS_Joystick;
int index;
for (index = device_index; index > 0; index--) {
device = device->pNext;
}
if (device->bXInputDevice) {
/* The slot for XInput devices can change as controllers are seated */
return SDL_XINPUT_GetSteamVirtualGamepadSlot(device->XInputUserId);
} else {
return device->steam_virtual_gamepad_slot;
}
}
static int WINDOWS_JoystickGetDevicePlayerIndex(int device_index) static int WINDOWS_JoystickGetDevicePlayerIndex(int device_index)
{ {
JoyStick_DeviceData *device = SYS_Joystick; JoyStick_DeviceData *device = SYS_Joystick;
@ -676,12 +693,10 @@ static int WINDOWS_JoystickOpen(SDL_Joystick *joystick, int device_index)
/* allocate memory for system specific hardware data */ /* allocate memory for system specific hardware data */
joystick->instance_id = device->nInstanceID; joystick->instance_id = device->nInstanceID;
joystick->hwdata = joystick->hwdata = (struct joystick_hwdata *)SDL_calloc(1, sizeof(struct joystick_hwdata));
(struct joystick_hwdata *)SDL_malloc(sizeof(struct joystick_hwdata));
if (!joystick->hwdata) { if (!joystick->hwdata) {
return SDL_OutOfMemory(); return SDL_OutOfMemory();
} }
SDL_zerop(joystick->hwdata);
joystick->hwdata->guid = device->guid; joystick->hwdata->guid = device->guid;
if (device->bXInputDevice) { if (device->bXInputDevice) {
@ -800,6 +815,7 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver = {
WINDOWS_JoystickDetect, WINDOWS_JoystickDetect,
WINDOWS_JoystickGetDeviceName, WINDOWS_JoystickGetDeviceName,
WINDOWS_JoystickGetDevicePath, WINDOWS_JoystickGetDevicePath,
WINDOWS_JoystickGetDeviceSteamVirtualGamepadSlot,
WINDOWS_JoystickGetDevicePlayerIndex, WINDOWS_JoystickGetDevicePlayerIndex,
WINDOWS_JoystickSetDevicePlayerIndex, WINDOWS_JoystickSetDevicePlayerIndex,
WINDOWS_JoystickGetDeviceGUID, WINDOWS_JoystickGetDeviceGUID,

View file

@ -43,6 +43,7 @@ typedef struct JoyStick_DeviceData
Uint8 XInputUserId; Uint8 XInputUserId;
DIDEVICEINSTANCE dxdevice; DIDEVICEINSTANCE dxdevice;
char path[MAX_PATH]; char path[MAX_PATH];
int steam_virtual_gamepad_slot;
struct JoyStick_DeviceData *pNext; struct JoyStick_DeviceData *pNext;
} JoyStick_DeviceData; } JoyStick_DeviceData;

View file

@ -129,13 +129,31 @@ static SDL_bool GetXInputDeviceInfo(Uint8 userid, Uint16 *pVID, Uint16 *pPID, Ui
capabilities.ProductId = USB_PRODUCT_XBOX360_XUSB_CONTROLLER; capabilities.ProductId = USB_PRODUCT_XBOX360_XUSB_CONTROLLER;
} }
*pVID = capabilities.VendorId; if (pVID) {
*pPID = capabilities.ProductId; *pVID = capabilities.VendorId;
*pVersion = capabilities.ProductVersion; }
if (pPID) {
*pPID = capabilities.ProductId;
}
if (pVersion) {
*pVersion = capabilities.ProductVersion;
}
return SDL_TRUE; return SDL_TRUE;
} }
int SDL_XINPUT_GetSteamVirtualGamepadSlot(Uint8 userid)
{
XINPUT_CAPABILITIES_EX capabilities;
if (XINPUTGETCAPABILITIESEX &&
XINPUTGETCAPABILITIESEX(1, userid, 0, &capabilities) == ERROR_SUCCESS &&
capabilities.VendorId == USB_VENDOR_VALVE &&
capabilities.ProductId == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD) {
return (int)capabilities.unk2;
}
return -1;
}
static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext) static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext)
{ {
Uint16 vendor = 0; Uint16 vendor = 0;

View file

@ -36,6 +36,7 @@ extern Uint32 SDL_XINPUT_JoystickGetCapabilities(SDL_Joystick *joystick);
extern void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick); extern void SDL_XINPUT_JoystickUpdate(SDL_Joystick *joystick);
extern void SDL_XINPUT_JoystickClose(SDL_Joystick *joystick); extern void SDL_XINPUT_JoystickClose(SDL_Joystick *joystick);
extern void SDL_XINPUT_JoystickQuit(void); extern void SDL_XINPUT_JoystickQuit(void);
extern int SDL_XINPUT_GetSteamVirtualGamepadSlot(Uint8 userid);
/* Ends C function definitions when using C++ */ /* Ends C function definitions when using C++ */
#ifdef __cplusplus #ifdef __cplusplus