diff --git a/src/core/windows/gameinput/gameinput.cpp b/src/core/windows/gameinput/gameinput.cpp index 16483316c065a..aa7f2009c7d64 100644 --- a/src/core/windows/gameinput/gameinput.cpp +++ b/src/core/windows/gameinput/gameinput.cpp @@ -62,6 +62,40 @@ namespace GameInput { +// +// GDK Compatibility +// + +/* SDL modifications: use typedef for c++98 copatibility */ +typedef DWORD (WINAPI * Gi_GetFileVersionInfoSizeWFn)( + _In_ LPCWSTR lptstrFilename, + _Out_opt_ LPDWORD lpdwHandle); + +typedef BOOL (WINAPI * Gi_GetFileVersionInfoWFn)( + _In_ LPCWSTR lptstrFilename, + _Reserved_ DWORD dwHandle, + _In_ DWORD dwLen, + _Out_writes_bytes_(dwLen) LPVOID lpData); + +typedef BOOL (WINAPI * Gi_VerQueryValueWFn)( + _In_ LPCVOID pBlock, + _In_ LPCWSTR lpSubBlock, + _Outptr_result_buffer_(_Inexpressible_("buffer can be PWSTR or DWORD*")) LPVOID* lplpBuffer, + _Out_ PUINT puLen); + +typedef LSTATUS (WINAPI * Gi_RegGetValueWFn)( + _In_ HKEY hkey, + _In_opt_ LPCWSTR lpSubKey, + _In_opt_ LPCWSTR lpValue, + _In_ DWORD dwFlags, + _Out_opt_ LPDWORD pdwType, + _Out_writes_bytes_to_opt_(*pcbData, *pcbData) PVOID pvData, + _Inout_opt_ LPDWORD pcbData); + +static const DWORD GI_RRF_RT_REG_SZ = 0x00000002; +static const DWORD GI_RRF_SUBKEY_WOW6432KEY = 0x00020000; + + // // Constants // @@ -93,15 +127,6 @@ static HMODULE g_versionDll = nullptr; #define RETURN_LAST_ERROR_IF(condition) { bool _condition = (condition); if(_condition) { RETURN_WIN32(GetLastError()); } } #define RETURN_LAST_ERROR_IF_NULL(ptr) RETURN_LAST_ERROR_IF((ptr) == NULL) -#define RETURN_NTSTATUS(status) { NTSTATUS _value = (status); return NT_SUCCESS(_value) ? S_OK : (HRESULT)((_value) | FACILITY_NT_BIT); } -#define RETURN_IF_NTSTATUS_FAILED(status) { NTSTATUS _status = (status); if (!NT_SUCCESS(_status)) { RETURN_NTSTATUS(_status); } } - -#define FAIL_FAST_HR(hr) { __fastfail(hr); } -#define FAIL_FAST() FAIL_FAST_HR(E_UNEXPECTED) -#define FAIL_FAST_IF(condition) { if (condition) { FAIL_FAST_HR(E_UNEXPECTED); } } -#define FAIL_FAST_IF_FAILED(x) { HRESULT _hr = (x); if (FAILED(_hr)) { FAIL_FAST_HR(_hr); } } -#define FAIL_FAST_IF_WIN32_BOOL_FALSE(condition) { if (condition == FALSE) { FAIL_FAST_HR(HRESULT_FROM_WIN32(GetLastError())); } } - // // Containers @@ -112,7 +137,7 @@ class Vector { public: Vector() - : m_data(nullptr) + : m_data(nullptr) /* SDL modification: c++98 compatibility */ , m_count(0) , m_capacity(0) { @@ -246,11 +271,6 @@ class String return m_string; } - const T& GetFront() const noexcept - { - return m_string[0]; - } - const T& GetBack() const noexcept { return m_string[m_string.GetCount() - 1]; @@ -260,8 +280,7 @@ class String Vector m_string; }; -typedef String WString; -typedef String AString; +typedef String WString; /* SDL modification: c++98 compatibility */ // @@ -291,7 +310,7 @@ static HRESULT LoadSystemModuleProc( if (*module == nullptr) { - *module = LoadLibraryEx(path, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); + *module = LoadLibraryExW(path, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); RETURN_LAST_ERROR_IF_NULL(*module); } @@ -303,11 +322,11 @@ static HRESULT LoadSystemModuleProc( static HRESULT GetSystemDirectory( _Inout_ WString* systemDir) noexcept { - uint32_t length = ::GetSystemDirectory(nullptr, 0); + uint32_t length = ::GetSystemDirectoryW(nullptr, 0); RETURN_LAST_ERROR_IF(length == 0); RETURN_IF_FAILED(systemDir->Resize(length)); - length = ::GetSystemDirectory(*systemDir, length) + 1; + length = ::GetSystemDirectoryW(*systemDir, length) + 1; RETURN_LAST_ERROR_IF(length == 0); RETURN_IF_FAILED(systemDir->Resize(length)); @@ -328,7 +347,7 @@ static HRESULT GetApplicationDirectory( RETURN_IF_FAILED(appDir->Resize(capacity)); SetLastError(ERROR_SUCCESS); - length = ::GetModuleFileName(nullptr, *appDir, capacity + 1); + length = ::GetModuleFileNameW(nullptr, *appDir, capacity + 1); RETURN_LAST_ERROR_IF(length == 0); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) @@ -360,11 +379,18 @@ static HRESULT GetApplicationDirectory( static HRESULT GetRedistDirectory( _Inout_ WString* redistDir) noexcept { - static const wchar_t* RedistDirRegPath = L"SOFTWARE\\Microsoft\\GameInput"; - static const wchar_t* RedistDirValueName = L"RedistDir"; + static const wchar_t RedistDirRegPath[] = L"SOFTWARE\\Microsoft\\GameInput"; /* SDL modification: c++98 compatibility */ + +#if defined(_M_IX86) + // RedistDir names the 64-bit folder and cannot be repurposed - copies of this file + // are statically linked into shipped titles. RedistDirX86 is additive instead, so + // an installer predating it simply fails the lookup and the caller moves on. + static const wchar_t RedistDirValueName[] = L"RedistDirX86"; /* SDL modification: c++98 compatibility */ +#else + static const wchar_t RedistDirValueName[] = L"RedistDir"; /* SDL modification: c++98 compatibility */ +#endif - typedef LONG (WINAPI *RegGetValueW_t)(HKEY,LPCWSTR,LPCWSTR,DWORD,LPDWORD,PVOID,LPDWORD); - RegGetValueW_t regGetValue = nullptr; + Gi_RegGetValueWFn regGetValue = nullptr; RETURN_IF_FAILED(LoadSystemModuleProc( &g_advapi32Dll, L"advapi32.dll", @@ -376,7 +402,7 @@ static HRESULT GetRedistDirectory( HKEY_LOCAL_MACHINE, RedistDirRegPath, RedistDirValueName, - RRF_RT_REG_SZ | RRF_SUBKEY_WOW6432KEY, + GI_RRF_RT_REG_SZ | GI_RRF_SUBKEY_WOW6432KEY, nullptr, nullptr, &cbSize))); @@ -387,7 +413,7 @@ static HRESULT GetRedistDirectory( HKEY_LOCAL_MACHINE, RedistDirRegPath, RedistDirValueName, - RRF_RT_REG_SZ | RRF_SUBKEY_WOW6432KEY, + GI_RRF_RT_REG_SZ | GI_RRF_SUBKEY_WOW6432KEY, nullptr, *redistDir, &cbSize))); @@ -403,24 +429,21 @@ static HRESULT GetFileVersion( { *version = 0; - typedef DWORD (WINAPI *GetFileVersionInfoSizeW_t)(LPCWSTR,LPDWORD); - GetFileVersionInfoSizeW_t getFileVersionInfoSize = nullptr; + Gi_GetFileVersionInfoSizeWFn getFileVersionInfoSize = nullptr; RETURN_IF_FAILED(LoadSystemModuleProc( &g_versionDll, L"version.dll", "GetFileVersionInfoSizeW", &getFileVersionInfoSize)); - typedef BOOL (WINAPI *GetFileVersionInfoW_t)(LPCWSTR,DWORD,DWORD,LPVOID); - GetFileVersionInfoW_t getFileVersionInfo = nullptr; + Gi_GetFileVersionInfoWFn getFileVersionInfo = nullptr; RETURN_IF_FAILED(LoadSystemModuleProc( &g_versionDll, L"version.dll", "GetFileVersionInfoW", &getFileVersionInfo)); - typedef BOOL (WINAPI *VerQueryValueW_t)(LPCVOID,LPCWSTR,LPVOID*,PUINT); - VerQueryValueW_t verQueryValue = nullptr; + Gi_VerQueryValueWFn verQueryValue = nullptr; RETURN_IF_FAILED(LoadSystemModuleProc( &g_versionDll, L"version.dll", @@ -539,23 +562,43 @@ static HRESULT LoadGameInputDll( SUCCEEDED(PathJoin(systemDir, L"GameInput.dll", &inboxPath)) && GetFileInfo(inboxPath, &inboxVersion); + // GameInputRedist.dll can be found in System32 and Program Files; + // check both locations for improved compatibility. + + WString redistDir; WString redistPath; uint64_t redistVersion = 0; + +#if defined(_M_IX86) + // Only the 64-bit redist is ever deployed to the system directory, and copies of it + // exist in SysWOW64, which is where a 32-bit process resolves that directory. Probe + // the architecture-specific Program Files location first so a wrong-bitness file + // cannot mask it and leave the loader with a module it is unable to load. + bool validRedist = - SUCCEEDED(PathJoin(systemDir, L"GameInputRedist.dll", &redistPath)) && + SUCCEEDED(GetRedistDirectory(&redistDir)) && + SUCCEEDED(PathJoin(redistDir, L"GameInputRedist.dll", &redistPath)) && GetFileInfo(redistPath, &redistVersion); if (!validRedist) { - // GameInputRedist.dll can be found in System32 and Program Files; - // check both locations for improved compatibility. + validRedist = + SUCCEEDED(PathJoin(systemDir, L"GameInputRedist.dll", &redistPath)) && + GetFileInfo(redistPath, &redistVersion); + } +#else + bool validRedist = + SUCCEEDED(PathJoin(systemDir, L"GameInputRedist.dll", &redistPath)) && + GetFileInfo(redistPath, &redistVersion); - WString redistDir; + if (!validRedist) + { validRedist = SUCCEEDED(GetRedistDirectory(&redistDir)) && SUCCEEDED(PathJoin(redistDir, L"GameInputRedist.dll", &redistPath)) && GetFileInfo(redistPath, &redistVersion); } +#endif WString appDir; WString sideloadedPath; @@ -589,7 +632,7 @@ static HRESULT LoadGameInputDll( RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), path); - *module = LoadLibrary(path); + *module = LoadLibraryW(path); RETURN_LAST_ERROR_IF_NULL(*module); return S_OK; diff --git a/src/core/windows/gameinput/gameinput.h b/src/core/windows/gameinput/gameinput.h index 0193878f656ac..9074808e7c866 100644 --- a/src/core/windows/gameinput/gameinput.h +++ b/src/core/windows/gameinput/gameinput.h @@ -32,9 +32,9 @@ #pragma region Application Family or OneCore Family or Games Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) -#define GAMEINPUT_API_VERSION 3 +#define GAMEINPUT_API_VERSION 4 -namespace GameInput { namespace v3 { +namespace GameInput { namespace v4 { enum GameInputKind { @@ -51,30 +51,22 @@ enum GameInputKind GameInputKindFlightStick = 0x00020000, GameInputKindGamepad = 0x00040000, GameInputKindRacingWheel = 0x00080000, + GameInputKindLighting = 0x00100000, + GameInputKindSystemButton = 0x00200000, + GameInputKindTouch = 0x00400000, }; DEFINE_ENUM_FLAG_OPERATORS(GameInputKind) -enum GameInputEnumerationKind +enum GameInputDeviceEvent { - GameInputNoEnumeration = 0, - GameInputAsyncEnumeration = 1, - GameInputBlockingEnumeration = 2 + GameInputDeviceEventConnected = 0, + GameInputDeviceEventDisconnected = 1, + GameInputDeviceEventKeyboardLayoutUpdated = 2, + GameInputDeviceEventHapticInfoUpdated = 3, + GameInputDeviceEventXInputIndexUpdated = 4, }; -enum GameInputFocusPolicy -{ - GameInputDefaultFocusPolicy = 0x00000000, - GameInputExclusiveForegroundInput = 0x00000002, - GameInputExclusiveForegroundGuideButton = 0x00000008, - GameInputExclusiveForegroundShareButton = 0x00000020, - GameInputEnableBackgroundInput = 0x00000040, - GameInputEnableBackgroundGuideButton = 0x00000080, - GameInputEnableBackgroundShareButton = 0x00000100 -}; - -DEFINE_ENUM_FLAG_OPERATORS(GameInputFocusPolicy) - enum GameInputSwitchKind { GameInputUnknownSwitchKind = -1, @@ -150,21 +142,23 @@ enum GameInputSensorAccuracy enum GameInputArcadeStickButtons { - GameInputArcadeStickNone = 0x00000000, - GameInputArcadeStickMenu = 0x00000001, - GameInputArcadeStickView = 0x00000002, - GameInputArcadeStickUp = 0x00000004, - GameInputArcadeStickDown = 0x00000008, - GameInputArcadeStickLeft = 0x00000010, - GameInputArcadeStickRight = 0x00000020, - GameInputArcadeStickAction1 = 0x00000040, - GameInputArcadeStickAction2 = 0x00000080, - GameInputArcadeStickAction3 = 0x00000100, - GameInputArcadeStickAction4 = 0x00000200, - GameInputArcadeStickAction5 = 0x00000400, - GameInputArcadeStickAction6 = 0x00000800, - GameInputArcadeStickSpecial1 = 0x00001000, - GameInputArcadeStickSpecial2 = 0x00002000 + GameInputArcadeStickNone = 0x00000000, + GameInputArcadeStickMenu = 0x00000001, + GameInputArcadeStickView = 0x00000002, + GameInputArcadeStickUp = 0x00000004, + GameInputArcadeStickDown = 0x00000008, + GameInputArcadeStickLeft = 0x00000010, + GameInputArcadeStickRight = 0x00000020, + GameInputArcadeStickAction1 = 0x00000040, + GameInputArcadeStickAction2 = 0x00000080, + GameInputArcadeStickAction3 = 0x00000100, + GameInputArcadeStickAction4 = 0x00000200, + GameInputArcadeStickAction5 = 0x00000400, + GameInputArcadeStickAction6 = 0x00000800, + GameInputArcadeStickSpecial1 = 0x00001000, + GameInputArcadeStickSpecial2 = 0x00002000, + GameInputArcadeStickLeftThumbstick = 0x00004000, + GameInputArcadeStickRightThumbstick = 0x00008000 }; DEFINE_ENUM_FLAG_OPERATORS(GameInputArcadeStickButtons) @@ -231,6 +225,7 @@ enum GameInputRawDeviceReportKind { GameInputRawInputReport = 0, GameInputRawOutputReport = 1, + GameInputRawFeatureReport = 2, }; // Gamepad modules (Groupings of gamepad elements commonly found together) @@ -363,16 +358,6 @@ enum GameInputRacingWheelAxes DEFINE_ENUM_FLAG_OPERATORS(GameInputRacingWheelAxes) -enum GameInputDeviceStatus -{ - GameInputDeviceNoStatus = 0x00000000, - GameInputDeviceConnected = 0x00000001, - GameInputDeviceHapticInfoReady = 0x00200000, - GameInputDeviceAnyStatus = 0xFFFFFFFF -}; - -DEFINE_ENUM_FLAG_OPERATORS(GameInputDeviceStatus) - enum GameInputDeviceFamily { GameInputFamilyVirtual = -1, @@ -384,6 +369,22 @@ enum GameInputDeviceFamily GameInputFamilyAggregate = 5, }; +enum GameInputLightingGroups +{ + GameInputLightingGroupUnknown = 0x00000000, + GameInputLightingGroupLeftThumbstick = 0x00000001, + GameInputLightingGroupRightThumbstick = 0x00000002, + GameInputLightingGroupDPad = 0x00000004, + GameInputLightingGroupFaceButtons = 0x00000008, + GameInputLightingGroupCenterLight = 0x00000010, + GameInputLightingGroupKeyboardKey = 0x00000020, + GameInputLightingGroupLeftHeadset = 0x00000040, + GameInputLightingGroupRightHeadset = 0x00000080, + GameInputLightingGroupAll = 0xFFFFFFFF, +}; + +DEFINE_ENUM_FLAG_OPERATORS(GameInputLightingGroups) + enum GameInputLabel { GameInputLabelUnknown = -1, @@ -511,6 +512,22 @@ enum GameInputLabel GameInputLabelPaddleLeft2 = 122, GameInputLabelPaddleRight1 = 123, GameInputLabelPaddleRight2 = 124, + GameInputLabelTouchpadButton = 125, + GameInputLabelLeftThumbstickX = 126, + GameInputLabelLeftThumbstickY = 127, + GameInputLabelRightThumbstickX = 128, + GameInputLabelRightThumbstickY = 129, + GameInputLabelRoll = 130, + GameInputLabelPitch = 131, + GameInputLabelYaw = 132, + GameInputLabelThrottle = 133, + GameInputLabelSteering = 134, + GameInputLabelBrake = 135, + GameInputLabelClutch = 136, + GameInputLabelHandbrake = 137, + GameInputLabelPatternShifter = 138, + GameInputLabelFirePrimary = 139, + GameInputLabelFireSecondary = 140, }; enum GameInputFeedbackAxes @@ -579,10 +596,11 @@ constexpr GUID GAMEINPUT_HAPTIC_LOCATION_TRIGGER_RIGHT = { 0xff0cb557, 0x3af5, 0 // start SDL modifications #endif // end SDL modifications - const uint32_t GAMEINPUT_HAPTIC_MAX_LOCATIONS = 8; const uint32_t GAMEINPUT_HAPTIC_MAX_AUDIO_ENDPOINT_ID_SIZE = 256; +const uint32_t GAMEINPUT_LIGHTING_GROUP_ORDER_INDEX_ALL = 0xFFFFFFFF; + typedef void (CALLBACK* GameInputReadingCallback)( _In_ GameInputCallbackToken callbackToken, _In_ void* context, @@ -591,26 +609,8 @@ typedef void (CALLBACK* GameInputReadingCallback)( typedef void (CALLBACK* GameInputDeviceCallback)( _In_ GameInputCallbackToken callbackToken, _In_ void* context, - _In_ IGameInputDevice* device, - _In_ uint64_t timestamp, - _In_ GameInputDeviceStatus currentStatus, - _In_ GameInputDeviceStatus previousStatus); - -typedef void (CALLBACK* GameInputSystemButtonCallback)( - _In_ GameInputCallbackToken callbackToken, - _In_ void* context, - _In_ IGameInputDevice* device, - _In_ uint64_t timestamp, - _In_ GameInputSystemButtons currentButtons, - _In_ GameInputSystemButtons previousButtons); - -typedef void (CALLBACK* GameInputKeyboardLayoutCallback)( - _In_ GameInputCallbackToken callbackToken, - _In_ void* context, - _In_ IGameInputDevice* device, - _In_ uint64_t timestamp, - _In_ uint32_t currentLayout, - _In_ uint32_t previousLayout); + _In_ GameInputDeviceEvent deviceEvent, + _In_ IGameInputDevice* device); struct GameInputKeyState { @@ -663,6 +663,15 @@ struct GameInputSensorsState float orientationZ; }; +struct GameInputTouchContact +{ + uint64_t contactId; + int32_t screenX; + int32_t screenY; + uint32_t padX; + uint32_t padY; +}; + struct GameInputArcadeStickState { GameInputArcadeStickButtons buttons; @@ -714,16 +723,6 @@ struct GameInputControllerSwitchInfo GameInputSwitchKind kind; }; -struct GameInputControllerInfo -{ - uint32_t controllerAxisCount; - _Field_size_full_(controllerAxisCount) const GameInputLabel* controllerAxisLabels; - uint32_t controllerButtonCount; - _Field_size_full_(controllerButtonCount) const GameInputLabel* controllerButtonLabels; - uint32_t controllerSwitchCount; - _Field_size_full_(controllerSwitchCount) const GameInputControllerSwitchInfo* controllerSwitchInfo; -}; - struct GameInputKeyboardInfo { GameInputKeyboardKind kind; @@ -748,6 +747,21 @@ struct GameInputSensorsInfo GameInputSensorsKind supportedSensors; }; +enum GameInputTouchSurfaceType +{ + GameInputTouchSurfaceTypeUnknown = 0, + GameInputTouchSurfaceTypeTouchscreen = 1, + GameInputTouchSurfaceTypeTouchpad = 2, +}; + +struct GameInputTouchSurfaceInfo +{ + uint32_t maxContactCount; + uint32_t padWidth; + uint32_t padHeight; + GameInputTouchSurfaceType type; +}; + struct GameInputArcadeStickInfo { GameInputLabel menuButtonLabel; @@ -764,6 +778,8 @@ struct GameInputArcadeStickInfo GameInputLabel actionButton6Label; GameInputLabel specialButton1Label; GameInputLabel specialButton2Label; + GameInputLabel leftThumbstickButtonLabel; + GameInputLabel rightThumbstickButtonLabel; uint32_t extraButtonCount; uint32_t extraAxisCount; }; @@ -784,6 +800,10 @@ struct GameInputFlightStickInfo GameInputLabel yButtonLabel; GameInputLabel leftShoulderButtonLabel; GameInputLabel rightShoulderButtonLabel; + GameInputLabel rollLabel; + GameInputLabel pitchLabel; + GameInputLabel yawLabel; + GameInputLabel throttleLabel; uint32_t extraButtonCount; uint32_t extraAxisCount; }; @@ -807,6 +827,16 @@ struct GameInputGamepadInfo GameInputLabel rightShoulderButtonLabel; GameInputLabel leftThumbstickButtonLabel; GameInputLabel rightThumbstickButtonLabel; + GameInputLabel paddleLeft1Label; + GameInputLabel paddleLeft2Label; + GameInputLabel paddleRight1Label; + GameInputLabel paddleRight2Label; + GameInputLabel leftTriggerLabel; + GameInputLabel rightTriggerLabel; + GameInputLabel leftThumbstickXLabel; + GameInputLabel leftThumbstickYLabel; + GameInputLabel rightThumbstickXLabel; + GameInputLabel rightThumbstickYLabel; uint32_t extraButtonCount; uint32_t extraAxisCount; }; @@ -827,6 +857,11 @@ struct GameInputRacingWheelInfo GameInputLabel yButtonLabel; GameInputLabel leftThumbstickButtonLabel; GameInputLabel rightThumbstickButtonLabel; + GameInputLabel steeringLabel; + GameInputLabel throttleLabel; + GameInputLabel brakeLabel; + GameInputLabel clutchLabel; + GameInputLabel handbrakeLabel; bool hasClutch; bool hasHandbrake; bool hasPatternShifter; @@ -860,43 +895,6 @@ struct GameInputRawDeviceReportInfo uint32_t size; }; -struct GameInputDeviceInfo -{ - uint16_t vendorId; - uint16_t productId; - uint16_t revisionNumber; - GameInputUsage usage; - GameInputVersion hardwareVersion; - GameInputVersion firmwareVersion; - APP_LOCAL_DEVICE_ID deviceId; - APP_LOCAL_DEVICE_ID deviceRootId; - GameInputDeviceFamily deviceFamily; - GameInputKind supportedInput; - GameInputRumbleMotors supportedRumbleMotors; - GameInputSystemButtons supportedSystemButtons; - GUID containerId; - const char* displayName; - const char* pnpPath; - - _Field_size_full_opt_(1) const GameInputKeyboardInfo* keyboardInfo; - _Field_size_full_opt_(1) const GameInputMouseInfo* mouseInfo; - _Field_size_full_opt_(1) const GameInputSensorsInfo* sensorsInfo; - _Field_size_full_opt_(1) const GameInputControllerInfo* controllerInfo; - _Field_size_full_opt_(1) const GameInputArcadeStickInfo* arcadeStickInfo; - _Field_size_full_opt_(1) const GameInputFlightStickInfo* flightStickInfo; - _Field_size_full_opt_(1) const GameInputGamepadInfo* gamepadInfo; - _Field_size_full_opt_(1) const GameInputRacingWheelInfo* racingWheelInfo; - - uint32_t forceFeedbackMotorCount; - _Field_size_full_(forceFeedbackMotorCount) const GameInputForceFeedbackMotorInfo* forceFeedbackMotorInfo; - - uint32_t inputReportCount; - _Field_size_full_opt_(inputReportCount) const GameInputRawDeviceReportInfo* inputReportInfo; - - uint32_t outputReportCount; - _Field_size_full_opt_(outputReportCount) const GameInputRawDeviceReportInfo* outputReportInfo; -}; - struct GameInputHapticInfo { _Field_z_ wchar_t audioEndpointId[GAMEINPUT_HAPTIC_MAX_AUDIO_ENDPOINT_ID_SIZE]; @@ -987,6 +985,13 @@ struct GameInputRumbleParams float rightTrigger; }; +struct GameInputColor +{ + uint8_t r; + uint8_t g; + uint8_t b; +}; + enum GameInputElementKind { GameInputElementKindNone = 0, @@ -1025,9 +1030,9 @@ struct GameInputButtonMapping GameInputSwitchPosition switchPosition; }; -const IID IID_IGameInput = {0x20efc1c7, 0x5d9a, 0x43ba, {0xb2, 0x6f, 0xb8, 0x07, 0xfa, 0x48, 0x60, 0x9c}}; +const IID IID_IGameInput = {0xf2daae4c, 0x4d21, 0x4250, {0x89, 0x53, 0x4f, 0x79, 0x1e, 0x62, 0x79, 0xab}}; -DECLARE_INTERFACE_IID_(IGameInput, IUnknown, "20EFC1C7-5D9A-43BA-B26F-B807FA48609C") +DECLARE_INTERFACE_IID_(IGameInput, IUnknown, "F2DAAE4C-4D21-4250-8953-4F791E6279AB") { IFACEMETHOD_(uint64_t, GetCurrentTimestamp)() PURE; @@ -1058,28 +1063,10 @@ DECLARE_INTERFACE_IID_(IGameInput, IUnknown, "20EFC1C7-5D9A-43BA-B26F-B807FA4860 IFACEMETHOD(RegisterDeviceCallback)( _In_opt_ IGameInputDevice* device, _In_ GameInputKind inputKind, - _In_ GameInputDeviceStatus statusFilter, - _In_ GameInputEnumerationKind enumerationKind, _In_opt_ void* context, _In_ GameInputDeviceCallback callbackFunc, _Out_opt_ _Result_zeroonfailure_ GameInputCallbackToken* callbackToken) PURE; - IFACEMETHOD(RegisterSystemButtonCallback)( - _In_opt_ IGameInputDevice* device, - _In_ GameInputSystemButtons buttonFilter, - _In_opt_ void* context, - _In_ GameInputSystemButtonCallback callbackFunc, - _Out_opt_ _Result_zeroonfailure_ GameInputCallbackToken* callbackToken) PURE; - - IFACEMETHOD(RegisterKeyboardLayoutCallback)( - _In_opt_ IGameInputDevice* device, - _In_opt_ void* context, - _In_ GameInputKeyboardLayoutCallback callbackFunc, - _Out_opt_ _Result_zeroonfailure_ GameInputCallbackToken* callbackToken) PURE; - - IFACEMETHOD_(void, StopCallback)( - _In_ GameInputCallbackToken callbackToken) PURE; - IFACEMETHOD_(bool, UnregisterCallback)( _In_ GameInputCallbackToken callbackToken) PURE; @@ -1094,8 +1081,8 @@ DECLARE_INTERFACE_IID_(IGameInput, IUnknown, "20EFC1C7-5D9A-43BA-B26F-B807FA4860 _In_ LPCWSTR value, _COM_Outptr_ IGameInputDevice** device) PURE; - IFACEMETHOD_(void, SetFocusPolicy)( - _In_ GameInputFocusPolicy policy) PURE; + IFACEMETHOD_(void, EnableBackgroundInput)( + bool enable) PURE; IFACEMETHOD(CreateAggregateDevice)( _In_ GameInputKind inputKind, @@ -1105,7 +1092,7 @@ DECLARE_INTERFACE_IID_(IGameInput, IUnknown, "20EFC1C7-5D9A-43BA-B26F-B807FA4860 _In_ const APP_LOCAL_DEVICE_ID* deviceId) PURE; }; -DECLARE_INTERFACE_IID_(IGameInputRawDeviceReport, IUnknown, "05A42D89-2CB6-45A3-874D-E635723587AB") +DECLARE_INTERFACE_IID_(IGameInputRawDeviceReport, IUnknown, "E35550A9-8507-404B-823C-2035958A6936") { IFACEMETHOD_(void, GetDevice)( _Outptr_ IGameInputDevice** device) PURE; @@ -1124,7 +1111,7 @@ DECLARE_INTERFACE_IID_(IGameInputRawDeviceReport, IUnknown, "05A42D89-2CB6-45A3- _In_reads_(bufferSize) const void* buffer) PURE; }; -DECLARE_INTERFACE_IID_(IGameInputReading, IUnknown, "C81C4CDE-ED1A-4631-A30F-C556A6241A1F") +DECLARE_INTERFACE_IID_(IGameInputReading, IUnknown, "0DFAA2A2-688B-4A9C-A3A9-0FEB4F90EE12") { IFACEMETHOD_(GameInputKind, GetInputKind)() PURE; @@ -1177,17 +1164,135 @@ DECLARE_INTERFACE_IID_(IGameInputReading, IUnknown, "C81C4CDE-ED1A-4631-A30F-C55 IFACEMETHOD_(bool, GetRawReport)( _Outptr_result_maybenull_ IGameInputRawDeviceReport** report) PURE; + + IFACEMETHOD_(bool, GetSystemButtonState)( + _Out_ GameInputSystemButtons* buttons) PURE; + + IFACEMETHOD_(uint32_t, GetTouchContactCount)( + uint32_t surfaceIndex) PURE; + + IFACEMETHOD_(uint32_t, GetTouchSurfaceState)( + uint32_t surfaceIndex, + uint32_t contactArrayCount, + _Out_writes_to_opt_(contactArrayCount, return) GameInputTouchContact* contactArray) PURE; }; -DECLARE_INTERFACE_IID_(IGameInputDevice, IUnknown, "63E2F38B-A399-4275-8AE7-D4C6E524D12A") +DECLARE_INTERFACE_IID_(IGameInputDevice, IUnknown, "4420F01D-8918-49D4-B302-DBEAD986105F") { - IFACEMETHOD(GetDeviceInfo)( - _Outptr_ const GameInputDeviceInfo** info) PURE; + IFACEMETHOD_(uint16_t, GetVendorId)() PURE; + + IFACEMETHOD_(uint16_t, GetProductId)() PURE; + + IFACEMETHOD_(uint16_t, GetRevisionNumber)() PURE; + + IFACEMETHOD_(void, GetUsage)( + _Out_ GameInputUsage* usage) PURE; + + IFACEMETHOD_(void, GetHardwareVersion)( + _Out_ GameInputVersion* version) PURE; + + IFACEMETHOD_(void, GetFirmwareVersion)( + _Out_ GameInputVersion* version) PURE; + + IFACEMETHOD_(void, GetDeviceId)( + _Out_ APP_LOCAL_DEVICE_ID* deviceId) PURE; + + IFACEMETHOD_(void, GetDeviceRootId)( + _Out_ APP_LOCAL_DEVICE_ID* deviceRootId) PURE; + + IFACEMETHOD_(GameInputDeviceFamily, GetDeviceFamily)() PURE; + + IFACEMETHOD_(GameInputKind, GetSupportedInput)() PURE; + + IFACEMETHOD_(GameInputRumbleMotors, GetSupportedRumbleMotors)() PURE; + + IFACEMETHOD_(GameInputSystemButtons, GetSupportedSystemButtons)() PURE; + + IFACEMETHOD_(GameInputLightingGroups, GetSupportedLightingGroups)() PURE; + + IFACEMETHOD_(uint32_t, GetSupportedLightingGroupSize)(GameInputLightingGroups group) PURE; + + IFACEMETHOD_(void, GetContainerId)( + _Out_ GUID* containerId) PURE; + + IFACEMETHOD_(uint32_t, GetDisplayName)( + _In_ uint32_t bufferByteCount, + _Out_writes_bytes_opt_(bufferByteCount) char* buffer) PURE; + + IFACEMETHOD_(uint32_t, GetPnpPath)( + _In_ uint32_t bufferByteCount, + _Out_writes_bytes_opt_(bufferByteCount) char* buffer) PURE; + + IFACEMETHOD_(bool, GetXInputDeviceIndex)( + _Out_ uint32_t* index) PURE; + + IFACEMETHOD_(bool, GetKeyboardInfo)( + _Out_ GameInputKeyboardInfo* info) PURE; + + IFACEMETHOD_(bool, GetMouseInfo)( + _Out_ GameInputMouseInfo* info) PURE; + + IFACEMETHOD_(bool, GetSensorsInfo)( + _Out_ GameInputSensorsInfo* info) PURE; + + IFACEMETHOD_(uint32_t, GetControllerAxisCount)() PURE; + + IFACEMETHOD_(uint32_t, GetControllerAxisLabels)( + _In_ uint32_t labelArrayCount, + _Out_writes_to_opt_(labelArrayCount, return) GameInputLabel* labelArray) PURE; + + IFACEMETHOD_(uint32_t, GetControllerButtonCount)() PURE; + + IFACEMETHOD_(uint32_t, GetControllerButtonLabels)( + _In_ uint32_t labelArrayCount, + _Out_writes_to_opt_(labelArrayCount, return) GameInputLabel* labelArray) PURE; + + IFACEMETHOD_(uint32_t, GetControllerSwitchCount)() PURE; + + IFACEMETHOD_(uint32_t, GetControllerSwitchInfo)( + _In_ uint32_t infoArrayCount, + _Out_writes_to_opt_(infoArrayCount, return) GameInputControllerSwitchInfo* infoArray) PURE; + + IFACEMETHOD_(bool, GetArcadeStickInfo)( + _Out_ GameInputArcadeStickInfo* info) PURE; + + IFACEMETHOD_(bool, GetFlightStickInfo)( + _Out_ GameInputFlightStickInfo* info) PURE; + + IFACEMETHOD_(bool, GetGamepadInfo)( + _Out_ GameInputGamepadInfo* info) PURE; + + IFACEMETHOD_(bool, GetRacingWheelInfo)( + _Out_ GameInputRacingWheelInfo* info) PURE; + + IFACEMETHOD_(uint32_t, GetForceFeedbackMotorCount)() PURE; + + IFACEMETHOD_(uint32_t, GetForceFeedbackMotorInfo)( + _In_ uint32_t infoArrayCount, + _Out_writes_to_opt_(infoArrayCount, return) GameInputForceFeedbackMotorInfo* infoArray) PURE; + + IFACEMETHOD_(uint32_t, GetInputReportCount)() PURE; + + IFACEMETHOD_(uint32_t, GetInputReportInfo)( + _In_ uint32_t infoArrayCount, + _Out_writes_to_opt_(infoArrayCount, return) GameInputRawDeviceReportInfo* infoArray) PURE; + + IFACEMETHOD_(uint32_t, GetOutputReportCount)() PURE; + + IFACEMETHOD_(uint32_t, GetOutputReportInfo)( + _In_ uint32_t infoArrayCount, + _Out_writes_to_opt_(infoArrayCount, return) GameInputRawDeviceReportInfo* infoArray) PURE; + + IFACEMETHOD_(uint32_t, GetFeatureReportCount)() PURE; + + IFACEMETHOD_(uint32_t, GetFeatureReportInfo)( + _In_ uint32_t infoArrayCount, + _Out_writes_to_opt_(infoArrayCount, return) GameInputRawDeviceReportInfo* infoArray) PURE; IFACEMETHOD(GetHapticInfo)( _Out_ GameInputHapticInfo* info) PURE; - IFACEMETHOD_(GameInputDeviceStatus, GetDeviceStatus)() PURE; + IFACEMETHOD_(bool, IsConnected)() PURE; IFACEMETHOD(CreateForceFeedbackEffect)( _In_ uint32_t motorIndex, @@ -1238,8 +1343,30 @@ DECLARE_INTERFACE_IID_(IGameInputDevice, IUnknown, "63E2F38B-A399-4275-8AE7-D4C6 _In_ GameInputRawDeviceReportKind reportKind, _COM_Outptr_ IGameInputRawDeviceReport** report) PURE; + IFACEMETHOD(GetRawDeviceFeature)( + _In_ uint32_t reportId, + _COM_Outptr_ IGameInputRawDeviceReport** report) PURE; + + IFACEMETHOD(SetRawDeviceFeature)( + _In_ IGameInputRawDeviceReport* report) PURE; + IFACEMETHOD(SendRawDeviceOutput)( _In_ IGameInputRawDeviceReport* report) PURE; + + IFACEMETHOD_(void, SetLightingColor)( + GameInputColor color, + GameInputLightingGroups group, + _In_opt_ uint32_t groupOrderIndex = GAMEINPUT_LIGHTING_GROUP_ORDER_INDEX_ALL) PURE; + + IFACEMETHOD_(void, ApplyLightingColors)() PURE; + + IFACEMETHOD_(void, ApplyLightingSystemDefault)() PURE; + + IFACEMETHOD_(uint32_t, GetTouchSurfaceCount)() PURE; + + IFACEMETHOD(GetTouchSurfaceInfo)( + uint32_t surfaceIndex, + _Out_ GameInputTouchSurfaceInfo* info) PURE; }; DECLARE_INTERFACE_IID_(IGameInputDispatcher, IUnknown, "415EED2E-98CB-42C2-8F28-B94601074E31") @@ -1251,7 +1378,7 @@ DECLARE_INTERFACE_IID_(IGameInputDispatcher, IUnknown, "415EED2E-98CB-42C2-8F28- _Outptr_result_nullonfailure_ HANDLE* waitHandle) PURE; }; -DECLARE_INTERFACE_IID_(IGameInputForceFeedbackEffect, IUnknown, "FF61096A-3373-4093-A1DF-6D31846B3511") +DECLARE_INTERFACE_IID_(IGameInputForceFeedbackEffect, IUnknown, "BB3500C0-4B43-44CA-81A2-382FC63AE0E9") { IFACEMETHOD_(void, GetDevice)( _Outptr_ IGameInputDevice** device) PURE; @@ -1331,7 +1458,7 @@ const HRESULT GAMEINPUT_E_HAPTIC_INFO_NOT_FOUND = _HRESULT_TYPEDEF_( const HRESULT GAMEINPUT_E_AGGREGATE_OPERATION_NOT_SUPPORTED = _HRESULT_TYPEDEF_(0x838A000BL); const HRESULT GAMEINPUT_E_INPUT_KIND_NOT_PRESENT = _HRESULT_TYPEDEF_(0x838A000CL); -}} // namespace GameInput::v3 +}} // namespace GameInput::v4 #endif // #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) #pragma endregion // Application Family or OneCore Family or Games Family diff --git a/src/joystick/gdk/SDL_gameinputjoystick.cpp b/src/joystick/gdk/SDL_gameinputjoystick.cpp index a92ef06ab3cf8..525ff1cb7b88e 100644 --- a/src/joystick/gdk/SDL_gameinputjoystick.cpp +++ b/src/joystick/gdk/SDL_gameinputjoystick.cpp @@ -53,7 +53,9 @@ typedef struct GAMEINPUT_InternalDevice char *name; SDL_GUID guid; // generated by SDL SDL_JoystickID device_instance; // generated by SDL +#if GAMEINPUT_API_VERSION < 4 const GameInputDeviceInfo *info; +#endif Uint16 vendor; Uint16 product; int raw_type; @@ -73,7 +75,9 @@ typedef struct joystick_hwdata GAMEINPUT_InternalDevice *devref; bool report_sensors; GameInputRumbleParams rumbleParams; +#if GAMEINPUT_API_VERSION < 4 // g_pGameInput->RegisterSystemButtonCallback no longer exists in GameInput v4, so no need for a callback token GameInputCallbackToken system_button_callback_token; +#endif } GAMEINPUT_InternalJoystickHwdata; static GAMEINPUT_InternalList g_GameInputList = { NULL }; @@ -81,23 +85,52 @@ static IGameInput *g_pGameInput = NULL; static GameInputCallbackToken g_GameInputCallbackToken = 0; static Uint64 g_GameInputTimestampOffset; - -static bool GAMEINPUT_InternalIsGamepad(const GameInputDeviceInfo *info) +#if GAMEINPUT_API_VERSION < 4 +static const GameInputDeviceInfo *GAMEINPUT_GetGameInputDeviceInfo(IGameInputDevice *pDevice) { - if (info->supportedInput & GameInputKindGamepad) { - return true; + const GameInputDeviceInfo *info = NULL; +#if GAMEINPUT_API_VERSION >= 1 + HRESULT hr = pDevice->GetDeviceInfo(&info); + if (FAILED(hr)) { + WIN_SetErrorFromHRESULT("IGameInputDevice::GetDeviceInfo", hr); + return NULL; } - return false; +#else + info = pDevice->GetDeviceInfo(); +#endif + return info; } +#endif -static Uint8 GAMEINPUT_GetDeviceRawType(const GameInputDeviceInfo *info) +static bool GAMEINPUT_InternalIsGamepad(IGameInputDevice *pDevice) +{ +#if GAMEINPUT_API_VERSION >= 4 + GameInputKind supportedInput = pDevice->GetSupportedInput(); +#else + GameInputKind supportedInput = GAMEINPUT_GetGameInputDeviceInfo(pDevice)->supportedInput; +#endif + return (supportedInput & GameInputKindGamepad) != 0; +} + +static Uint8 GAMEINPUT_GetDeviceRawType(IGameInputDevice *pDevice) { #if GAMEINPUT_API_VERSION >= 3 + +#if GAMEINPUT_API_VERSION >= 4 + GameInputKind supportedInput = pDevice->GetSupportedInput(); + uint16_t vendorId = pDevice->GetVendorId(); + uint16_t productId = pDevice->GetProductId(); +#else + const GameInputDeviceInfo *info = GAMEINPUT_GetGameInputDeviceInfo(pDevice); GameInputKind supportedInput = info->supportedInput; + uint16_t vendorId = info->vendorId; + uint16_t productId = info->productId; +#endif + if (supportedInput & GameInputKindRawDeviceReport) { - switch (info->vendorId) { + switch (vendorId) { case USB_VENDOR_MADCATZ: - switch (info->productId) { + switch (productId) { case USB_PRODUCT_MADCATZ_XB1_STRATOCASTER_GUITAR: return SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR; case USB_PRODUCT_MADCATZ_XB1_DRUM_KIT: @@ -109,7 +142,7 @@ static Uint8 GAMEINPUT_GetDeviceRawType(const GameInputDeviceInfo *info) } break; case USB_VENDOR_PDP: - switch (info->productId) { + switch (productId) { case USB_PRODUCT_PDP_XB1_JAGUAR_GUITAR: case USB_PRODUCT_PDP_XB1_RIFFMASTER_GUITAR: return SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR; @@ -120,7 +153,7 @@ static Uint8 GAMEINPUT_GetDeviceRawType(const GameInputDeviceInfo *info) } break; case USB_VENDOR_CRKD: - switch (info->productId) { + switch (productId) { case USB_PRODUCT_RED_OCTANE_XB1_STAGE_TOUR_GUITAR: return SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR; default: @@ -128,7 +161,7 @@ static Uint8 GAMEINPUT_GetDeviceRawType(const GameInputDeviceInfo *info) } break; case USB_VENDOR_RED_OCTANE: - switch (info->productId) { + switch (productId) { case USB_PRODUCT_RED_OCTANE_XB1_GUITAR_HERO_LIVE_GUITAR: return SDL_GAMEINPUT_RAWTYPE_GUITAR_HERO_LIVE_GUITAR; default: @@ -136,7 +169,7 @@ static Uint8 GAMEINPUT_GetDeviceRawType(const GameInputDeviceInfo *info) } break; case USB_VENDOR_RED_OCTANE_GAMES: - switch (info->productId) { + switch (productId) { case USB_PRODUCT_RED_OCTANE_XB1_STAGE_TOUR_GUITAR: return SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR; case USB_PRODUCT_RED_OCTANE_XB1_STAGE_TOUR_DRUMS: @@ -150,10 +183,14 @@ static Uint8 GAMEINPUT_GetDeviceRawType(const GameInputDeviceInfo *info) #endif // GAMEINPUT_API_VERSION >= 3 return SDL_GAMEINPUT_RAWTYPE_NONE; } -static Uint8 GAMEINPUT_GetDeviceSubtype(const GameInputDeviceInfo *info) +static Uint8 GAMEINPUT_GetDeviceSubtype(IGameInputDevice *pDevice) { - GameInputKind supportedInput = info->supportedInput; - Uint8 rawType = GAMEINPUT_GetDeviceRawType(info); +#if GAMEINPUT_API_VERSION >= 4 + GameInputKind supportedInput = pDevice->GetSupportedInput(); +#else + GameInputKind supportedInput = GAMEINPUT_GetGameInputDeviceInfo(pDevice)->supportedInput; +#endif + Uint8 rawType = GAMEINPUT_GetDeviceRawType(pDevice); if (rawType == SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR || rawType == SDL_GAMEINPUT_RAWTYPE_GUITAR_HERO_LIVE_GUITAR) { return SDL_JOYSTICK_TYPE_GUITAR; } @@ -200,9 +237,9 @@ static bool IsXbox360WirelessAdapter(Uint16 vendor, Uint16 product) return false; } -static void QueryDeviceName(const GameInputDeviceInfo *info, Uint16 vendor_id, Uint16 product_id, char **manufacturer_string, char **product_string) +static void QueryDeviceName(IGameInputDevice *pDevice, Uint16 vendor_id, Uint16 product_id, char **manufacturer_string, char **product_string) { - if (!info || !manufacturer_string || !product_string) { + if (!pDevice || !manufacturer_string || !product_string) { return; } @@ -215,6 +252,15 @@ static void QueryDeviceName(const GameInputDeviceInfo *info, Uint16 vendor_id, U #endif *manufacturer_string = NULL; +#if GAMEINPUT_API_VERSION >= 4 + char buffer[256]; + if (pDevice->GetDisplayName(sizeof(buffer), buffer) > 0) { + *product_string = SDL_strdup(buffer); + } else { + *product_string = NULL; + } +#else + const GameInputDeviceInfo *info = GAMEINPUT_GetGameInputDeviceInfo(pDevice); #if GAMEINPUT_API_VERSION >= 1 if (info->displayName) { *product_string = SDL_strdup(info->displayName); @@ -227,13 +273,16 @@ static void QueryDeviceName(const GameInputDeviceInfo *info, Uint16 vendor_id, U if (!info->displayName) { *product_string = NULL; } +#endif } static void GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice) { GAMEINPUT_InternalDevice **devicelist = NULL; GAMEINPUT_InternalDevice *elem = NULL; +#if GAMEINPUT_API_VERSION < 4 const GameInputDeviceInfo *info = NULL; +#endif Uint16 bus = SDL_HARDWARE_BUS_USB; Uint16 vendor = 0; Uint16 product = 0; @@ -248,6 +297,10 @@ static void GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice) SDL_AssertJoysticksLocked(); +#if GAMEINPUT_API_VERSION >= 4 + vendor = pDevice->GetVendorId(); + product = pDevice->GetProductId(); +#else #if GAMEINPUT_API_VERSION >= 1 HRESULT hr = pDevice->GetDeviceInfo(&info); if (FAILED(hr)) { @@ -257,18 +310,20 @@ static void GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice) #else info = pDevice->GetDeviceInfo(); #endif + vendor = info->vendorId; + product = info->productId; +#endif + if (false /*info->capabilities & GameInputDeviceCapabilityWireless*/) { bus = SDL_HARDWARE_BUS_BLUETOOTH; } else { bus = SDL_HARDWARE_BUS_USB; } - vendor = info->vendorId; - product = info->productId; //version = (info->firmwareVersion.major << 8) | info->firmwareVersion.minor; - subtype = GAMEINPUT_GetDeviceSubtype(info); - raw_type = GAMEINPUT_GetDeviceRawType(info); + subtype = GAMEINPUT_GetDeviceSubtype(pDevice); + raw_type = GAMEINPUT_GetDeviceRawType(pDevice); - QueryDeviceName(info, vendor, product, &manufacturer_string, &product_string); + QueryDeviceName(pDevice, vendor, product, &manufacturer_string, &product_string); if (IsXbox360WirelessAdapter(vendor, product) || SDL_ShouldIgnoreJoystick(vendor, product, version, product_string) || @@ -278,12 +333,18 @@ static void GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice) #if defined(SDL_JOYSTICK_DINPUT) && defined(SDL_HAPTIC_DINPUT) // This joystick backend currently doesn't provide a haptic backend, so fallback to DirectInput for haptic-capable devices. - if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_DIRECTINPUT, true) && info->forceFeedbackMotorCount > 0 && pDevice->IsForceFeedbackMotorPoweredOn(0)) { + if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_DIRECTINPUT, true) && +#if GAMEINPUT_API_VERSION >= 4 + pDevice->GetForceFeedbackMotorCount() > 0 && +#else + info->forceFeedbackMotorCount > 0 && +#endif + pDevice->IsForceFeedbackMotorPoweredOn(0)) { goto done; } #endif - if (GAMEINPUT_InternalIsGamepad(info)) { + if (GAMEINPUT_InternalIsGamepad(pDevice)) { if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_GAMEINPUT, SDL_GAMEINPUT_DEFAULT)) { goto done; } @@ -294,7 +355,12 @@ static void GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice) goto done; } #endif - if (info->supportedInput & GameInputKindController) { +#if GAMEINPUT_API_VERSION >= 4 + if (pDevice->GetSupportedInput() & GameInputKindController) +#else + if (info->supportedInput & GameInputKindController) +#endif + { // Maintain GUID compatibility with DirectInput controller mappings. driver_signature = 0; subtype = 0; @@ -325,21 +391,36 @@ static void GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice) } // Generate a device path +#if GAMEINPUT_API_VERSION >= 4 + APP_LOCAL_DEVICE_ID deviceId; + pDevice->GetDeviceId(&deviceId); + for (idx = 0; idx < APP_LOCAL_DEVICE_ID_SIZE; ++idx) { + SDL_snprintf(tmp, SDL_arraysize(tmp), "%02X", deviceId.value[idx]); + SDL_strlcat(elem->path, tmp, SDL_arraysize(elem->path)); + } +#else for (idx = 0; idx < APP_LOCAL_DEVICE_ID_SIZE; ++idx) { SDL_snprintf(tmp, SDL_arraysize(tmp), "%02X", info->deviceId.value[idx]); SDL_strlcat(elem->path, tmp, SDL_arraysize(elem->path)); } +#endif pDevice->AddRef(); elem->device = pDevice; elem->name = SDL_CreateJoystickName(vendor, product, manufacturer_string, product_string); elem->guid = SDL_CreateJoystickGUID(bus, vendor, product, version, manufacturer_string, product_string, driver_signature, subtype); elem->device_instance = SDL_GetNextObjectID(); +#if GAMEINPUT_API_VERSION < 4 elem->info = info; +#endif elem->vendor = vendor; elem->product = product; elem->raw_type = raw_type; -#if GAMEINPUT_API_VERSION >= 1 +#if GAMEINPUT_API_VERSION >= 4 + char pnpPath[256]; + pDevice->GetPnpPath(sizeof(pnpPath), pnpPath); + elem->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(pnpPath); +#elif GAMEINPUT_API_VERSION >= 1 elem->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(info->pnpPath); #else elem->steam_virtual_gamepad_slot = -1; @@ -399,10 +480,15 @@ static GAMEINPUT_InternalDevice *GAMEINPUT_InternalFindByIndex(int idx) static void CALLBACK GAMEINPUT_InternalJoystickDeviceCallback( _In_ GameInputCallbackToken callbackToken, _In_ void *context, +#if GAMEINPUT_API_VERSION >= 4 + _In_ GameInputDeviceEvent deviceEvent, + _In_ IGameInputDevice* device) +#else _In_ IGameInputDevice *device, _In_ uint64_t timestamp, _In_ GameInputDeviceStatus currentStatus, _In_ GameInputDeviceStatus previousStatus) +#endif { int idx = 0; GAMEINPUT_InternalDevice *elem = NULL; @@ -414,7 +500,12 @@ static void CALLBACK GAMEINPUT_InternalJoystickDeviceCallback( SDL_LockJoysticks(); - if (currentStatus & GameInputDeviceConnected) { +#if GAMEINPUT_API_VERSION >= 4 + if (device->IsConnected()) +#else + if (currentStatus & GameInputDeviceConnected) +#endif + { GAMEINPUT_InternalAddOrFind(device); } else { for (idx = 0; idx < g_GameInputList.count; ++idx) { @@ -454,9 +545,11 @@ static bool GAMEINPUT_JoystickInit(void) return false; } -#if GAMEINPUT_API_VERSION >= 2 // Allow background controller input // SDL manages focus policy at a higher level, so we can set this unconditionally. +#if GAMEINPUT_API_VERSION >= 4 + g_pGameInput->EnableBackgroundInput(true); +#elif GAMEINPUT_API_VERSION >= 2 g_pGameInput->SetFocusPolicy(GameInputEnableBackgroundInput | GameInputEnableBackgroundGuideButton | GameInputEnableBackgroundShareButton); #endif @@ -472,8 +565,10 @@ static bool GAMEINPUT_JoystickInit(void) hr = g_pGameInput->RegisterDeviceCallback(NULL, kind, +#if GAMEINPUT_API_VERSION < 4 GameInputDeviceConnected, GameInputBlockingEnumeration, +#endif NULL, GAMEINPUT_InternalJoystickDeviceCallback, &g_GameInputCallbackToken); @@ -503,6 +598,7 @@ static void GAMEINPUT_JoystickDetect(void) { int idx; GAMEINPUT_InternalDevice *elem = NULL; + bool connected; SDL_AssertJoysticksLocked(); @@ -517,7 +613,12 @@ static void GAMEINPUT_JoystickDetect(void) elem->isAdded = true; } - if (elem->isDeleteRequested || !(elem->device->GetDeviceStatus() & GameInputDeviceConnected)) { +#if GAMEINPUT_API_VERSION >= 4 + connected = elem->device->IsConnected(); +#else + connected = elem->device->GetDeviceStatus() & GameInputDeviceConnected; +#endif + if (elem->isDeleteRequested || !connected) { SDL_PrivateJoystickRemoved(elem->device_instance); GAMEINPUT_InternalRemoveByIndex(idx--); } @@ -539,7 +640,12 @@ static bool GAMEINPUT_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_i for (int i = 0; i < g_GameInputList.count; ++i) { GAMEINPUT_InternalDevice *elem = g_GameInputList.devices[i]; - if (elem && vendor_id == elem->info->vendorId && product_id == elem->info->productId) { +#if GAMEINPUT_API_VERSION >= 4 + if (elem && vendor_id == elem->device->GetVendorId() && product_id == elem->device->GetProductId()) +#else + if (elem && vendor_id == elem->info->vendorId && product_id == elem->info->productId) +#endif + { return true; } } @@ -616,7 +722,7 @@ static void GAMEINPUT_UpdatePowerInfo(SDL_Joystick *joystick, IGameInputDevice * #endif } -#if GAMEINPUT_API_VERSION >= 1 +#if GAMEINPUT_API_VERSION >= 1 && GAMEINPUT_API_VERSION < 4 static void CALLBACK GAMEINPUT_InternalSystemButtonCallback( _In_ GameInputCallbackToken callbackToken, _In_ void * context, @@ -648,13 +754,18 @@ static void CALLBACK GAMEINPUT_InternalSystemButtonCallback( static bool GAMEINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) { GAMEINPUT_InternalDevice *elem = GAMEINPUT_InternalFindByIndex(device_index); +#if GAMEINPUT_API_VERSION < 4 const GameInputDeviceInfo *info = elem->info; +#endif GAMEINPUT_InternalJoystickHwdata *hwdata = NULL; - + GameInputRumbleMotors supportedRumbleMotors; + IGameInputDevice *device; if (!elem) { return false; } + device = elem->device; + hwdata = (GAMEINPUT_InternalJoystickHwdata *)SDL_calloc(1, sizeof(*hwdata)); if (!hwdata) { return false; @@ -663,12 +774,17 @@ static bool GAMEINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) hwdata->devref = elem; joystick->hwdata = hwdata; - if (GAMEINPUT_InternalIsGamepad(info) || GAMEINPUT_GetDeviceRawType(info) != SDL_GAMEINPUT_RAWTYPE_NONE) { + if (GAMEINPUT_InternalIsGamepad(device) || GAMEINPUT_GetDeviceRawType(device) != SDL_GAMEINPUT_RAWTYPE_NONE) { joystick->naxes = 6; joystick->nbuttons = 11; joystick->nhats = 1; -#if GAMEINPUT_API_VERSION >= 1 +#if GAMEINPUT_API_VERSION >= 4 + if (SDL_IsJoystickXboxSeriesX(elem->vendor, elem->product) && + device->GetSupportedSystemButtons() & GameInputSystemButtonShare) { + ++joystick->nbuttons; + } +#elif GAMEINPUT_API_VERSION >= 1 if (info->supportedSystemButtons != GameInputSystemButtonNone) { GameInputSystemButtons buttons = GameInputSystemButtonGuide; @@ -682,7 +798,11 @@ static bool GAMEINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) } #endif // GAMEINPUT_API_VERSION >= 1 } else { -#if GAMEINPUT_API_VERSION >= 3 +#if GAMEINPUT_API_VERSION >= 4 + joystick->naxes = device->GetControllerAxisCount(); + joystick->nbuttons = device->GetControllerButtonCount(); + joystick->nhats = device->GetControllerSwitchCount(); +#elif GAMEINPUT_API_VERSION >= 3 joystick->naxes = info->controllerInfo->controllerAxisCount; joystick->nbuttons = info->controllerInfo->controllerButtonCount; joystick->nhats = info->controllerInfo->controllerSwitchCount; @@ -693,14 +813,30 @@ static bool GAMEINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index) #endif // GAMEINPUT_API_VERSION >= 3 } - if (info->supportedRumbleMotors & (GameInputRumbleLowFrequency | GameInputRumbleHighFrequency)) { +#if GAMEINPUT_API_VERSION >= 4 + supportedRumbleMotors = device->GetSupportedRumbleMotors(); +#else + supportedRumbleMotors = info->supportedRumbleMotors; +#endif + if (supportedRumbleMotors & (GameInputRumbleLowFrequency | GameInputRumbleHighFrequency)) { SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, true); } - if (info->supportedRumbleMotors & (GameInputRumbleLeftTrigger | GameInputRumbleRightTrigger)) { + if (supportedRumbleMotors & (GameInputRumbleLeftTrigger | GameInputRumbleRightTrigger)) { SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN, true); } -#if GAMEINPUT_API_VERSION >= 3 +#if GAMEINPUT_API_VERSION >= 4 + if (device->GetSupportedInput() & GameInputKindSensors) { + GameInputSensorsInfo sensorsInfo; + device->GetSensorsInfo(&sensorsInfo); + if (sensorsInfo.supportedSensors & GameInputSensorsGyrometer) { + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 60.0f); + } + if (sensorsInfo.supportedSensors & GameInputSensorsAccelerometer) { + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 60.0f); + } + } +#elif GAMEINPUT_API_VERSION >= 3 if (info->supportedInput & GameInputKindSensors) { if (info->sensorsInfo->supportedSensors & GameInputSensorsGyrometer) { SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 60.0f); @@ -875,6 +1011,15 @@ static void GAMEINPUT_GamepadUpdate(SDL_Joystick *joystick, IGameInputReading *r bool down = ((state.buttons & button_mask) != 0); SDL_SendJoystickButton(timestamp, joystick, btnidx, down); } +#if GAMEINPUT_API_VERSION >= 4 + GameInputSystemButtons systemButtons; + if (reading->GetSystemButtonState(&systemButtons)) { + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (systemButtons & GameInputSystemButtonGuide) != 0); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GAMEINPUT_SHARE, (systemButtons & GameInputSystemButtonShare) != 0); + } +#else + // GAMEINPUT_InternalSystemButtonCallback is used instead +#endif if (state.buttons & GameInputGamepadDPadUp) { hat |= SDL_HAT_UP; @@ -975,12 +1120,18 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick) GAMEINPUT_InternalJoystickHwdata *hwdata = joystick->hwdata; GAMEINPUT_InternalDevice *internal_device = hwdata->devref; IGameInputDevice *device = hwdata->devref->device; +#if GAMEINPUT_API_VERSION < 4 const GameInputDeviceInfo *info = hwdata->devref->info; +#endif IGameInputReading *reading = NULL; Uint64 timestamp; HRESULT hr; +#if GAMEINPUT_API_VERSION >= 4 + hr = g_pGameInput->GetCurrentReading(device->GetSupportedInput(), device, &reading); +#else hr = g_pGameInput->GetCurrentReading(info->supportedInput, device, &reading); +#endif if (FAILED(hr)) { // don't SetError here since there can be a legitimate case when there's no reading avail return; @@ -991,7 +1142,7 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick) GAMEINPUT_GuitarUpdate(joystick, reading, timestamp); } else if (internal_device->raw_type == SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_DRUM_KIT) { GAMEINPUT_DrumUpdate(joystick, reading, timestamp); - } else if (GAMEINPUT_InternalIsGamepad(info)) { + } else if (GAMEINPUT_InternalIsGamepad(device)) { GAMEINPUT_GamepadUpdate(joystick, reading, timestamp); } else { GAMEINPUT_ControllerUpdate(joystick, reading, timestamp); @@ -1002,7 +1153,15 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick) GameInputSensorsState sensor_state; if (reading->GetSensorsState(&sensor_state)) { - if ((info->sensorsInfo->supportedSensors & GameInputSensorsGyrometer) != 0) { + GameInputSensorsKind supportedSensors; +#if GAMEINPUT_API_VERSION >= 4 + GameInputSensorsInfo sensorsInfo; + device->GetSensorsInfo(&sensorsInfo); + supportedSensors = sensorsInfo.supportedSensors; +#else + supportedSensors = info->sensorsInfo->supportedSensors; +#endif + if ((supportedSensors & GameInputSensorsGyrometer) != 0) { float data[3] = { sensor_state.angularVelocityInRadPerSecX, sensor_state.angularVelocityInRadPerSecY, @@ -1010,7 +1169,7 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick) }; SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, timestamp, data, SDL_arraysize(data)); } - if ((info->sensorsInfo->supportedSensors & GameInputSensorsAccelerometer) != 0) { + if ((supportedSensors & GameInputSensorsAccelerometer) != 0) { float data[3] = { sensor_state.accelerationInGX * SDL_STANDARD_GRAVITY, sensor_state.accelerationInGY * SDL_STANDARD_GRAVITY, @@ -1032,6 +1191,7 @@ static void GAMEINPUT_JoystickClose(SDL_Joystick *joystick) { GAMEINPUT_InternalJoystickHwdata *hwdata = joystick->hwdata; +#if GAMEINPUT_API_VERSION < 4 if (hwdata->system_button_callback_token) { #if GAMEINPUT_API_VERSION >= 1 g_pGameInput->UnregisterCallback(hwdata->system_button_callback_token); @@ -1039,6 +1199,7 @@ static void GAMEINPUT_JoystickClose(SDL_Joystick *joystick) g_pGameInput->UnregisterCallback(hwdata->system_button_callback_token, 10000); #endif } +#endif SDL_free(hwdata); joystick->hwdata = NULL; @@ -1071,7 +1232,7 @@ static bool GAMEINPUT_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap { GAMEINPUT_InternalDevice *elem = GAMEINPUT_InternalFindByIndex(device_index); - if (!GAMEINPUT_InternalIsGamepad(elem->info) && elem->raw_type == SDL_GAMEINPUT_RAWTYPE_NONE) { + if (!GAMEINPUT_InternalIsGamepad(elem->device) && elem->raw_type == SDL_GAMEINPUT_RAWTYPE_NONE) { return false; } @@ -1091,13 +1252,18 @@ static bool GAMEINPUT_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap out->back.target = SDL_GAMEPAD_BUTTON_BACK; #if GAMEINPUT_API_VERSION >= 1 - if (elem->info->supportedSystemButtons & GameInputSystemButtonGuide) { +#if GAMEINPUT_API_VERSION >= 4 + GameInputSystemButtons supportedSystemButtons = elem->device->GetSupportedSystemButtons(); +#else + GameInputSystemButtons supportedSystemButtons = elem->info->supportedSystemButtons; +#endif + if (supportedSystemButtons & GameInputSystemButtonGuide) { out->guide.kind = EMappingKind_Button; out->guide.target = SDL_GAMEPAD_BUTTON_GUIDE; } if (SDL_IsJoystickXboxSeriesX(elem->vendor, elem->product) && - (elem->info->supportedSystemButtons & GameInputSystemButtonShare)) { + (supportedSystemButtons & GameInputSystemButtonShare)) { out->misc1.kind = EMappingKind_Button; out->misc1.target = SDL_GAMEPAD_BUTTON_GAMEINPUT_SHARE; } diff --git a/src/video/windows/SDL_windowsgameinput.cpp b/src/video/windows/SDL_windowsgameinput.cpp index 62edcdb8e46cd..f40b18e418767 100644 --- a/src/video/windows/SDL_windowsgameinput.cpp +++ b/src/video/windows/SDL_windowsgameinput.cpp @@ -46,7 +46,9 @@ static const Uint8 GAMEINPUT_button_map[MAX_GAMEINPUT_BUTTONS] = { typedef struct GAMEINPUT_Device { IGameInputDevice *pDevice; +#if GAMEINPUT_API_VERSION < 4 const GameInputDeviceInfo *info; +#endif char *name; Uint32 instance_id; // generated by SDL bool registered; @@ -70,8 +72,9 @@ static bool GAMEINPUT_InternalAddOrFind(WIN_GameInputData *data, IGameInputDevic { GAMEINPUT_Device **devicelist = NULL; GAMEINPUT_Device *device = NULL; - const GameInputDeviceInfo *info; bool result = false; +#if GAMEINPUT_API_VERSION < 4 + const GameInputDeviceInfo *info; #if GAMEINPUT_API_VERSION >= 1 HRESULT hr = pDevice->GetDeviceInfo(&info); @@ -80,6 +83,7 @@ static bool GAMEINPUT_InternalAddOrFind(WIN_GameInputData *data, IGameInputDevic } #else info = pDevice->GetDeviceInfo(); +#endif #endif SDL_LockMutex(data->lock); @@ -105,14 +109,22 @@ static bool GAMEINPUT_InternalAddOrFind(WIN_GameInputData *data, IGameInputDevic goto done; } - if (info->displayName) { +#if GAMEINPUT_API_VERSION >= 4 + char buffer[256]; + if (pDevice->GetDisplayName(sizeof(buffer), buffer) > 0) +#else + if (info->displayName) +#endif + { // This could give us a product string, but it's NULL for all the devices I've tested } pDevice->AddRef(); device->pDevice = pDevice; device->instance_id = SDL_GetNextObjectID(); +#if GAMEINPUT_API_VERSION < 4 device->info = info; +#endif data->devices = devicelist; data->devices[data->num_devices++] = device; @@ -141,12 +153,21 @@ static bool GAMEINPUT_InternalRemoveByIndex(WIN_GameInputData *data, int idx) device = data->devices[idx]; if (device) { if (device->registered) { +#if GAMEINPUT_API_VERSION >= 4 + if (device->pDevice->GetSupportedInput() & GameInputKindMouse) { + SDL_RemoveMouse(device->instance_id); + } + if (device->pDevice->GetSupportedInput() & GameInputKindKeyboard) { + SDL_RemoveKeyboard(device->instance_id); + } +#else if (device->info->supportedInput & GameInputKindMouse) { SDL_RemoveMouse(device->instance_id); } if (device->info->supportedInput & GameInputKindKeyboard) { SDL_RemoveKeyboard(device->instance_id); } +#endif if (device->last_mouse_reading) { device->last_mouse_reading->Release(); device->last_mouse_reading = NULL; @@ -186,10 +207,15 @@ static bool GAMEINPUT_InternalRemoveByIndex(WIN_GameInputData *data, int idx) static void CALLBACK GAMEINPUT_InternalDeviceCallback( _In_ GameInputCallbackToken callbackToken, _In_ void *context, +#if GAMEINPUT_API_VERSION >= 4 + _In_ GameInputDeviceEvent deviceEvent, + _In_ IGameInputDevice *pDevice) +#else _In_ IGameInputDevice *pDevice, _In_ uint64_t timestamp, _In_ GameInputDeviceStatus currentStatus, _In_ GameInputDeviceStatus previousStatus) +#endif { WIN_GameInputData *data = (WIN_GameInputData *)context; int idx = 0; @@ -200,7 +226,12 @@ static void CALLBACK GAMEINPUT_InternalDeviceCallback( return; } - if (currentStatus & GameInputDeviceConnected) { +#if GAMEINPUT_API_VERSION >= 4 + if (pDevice->IsConnected()) +#else + if (currentStatus & GameInputDeviceConnected) +#endif + { GAMEINPUT_InternalAddOrFind(data, pDevice); } else { for (idx = 0; idx < data->num_devices; ++idx) { @@ -243,8 +274,10 @@ bool WIN_InitGameInput(SDL_VideoDevice *_this) hr = data->pGameInput->RegisterDeviceCallback(NULL, (GameInputKindMouse | GameInputKindKeyboard), +#if GAMEINPUT_API_VERSION < 4 GameInputDeviceConnected, GameInputBlockingEnumeration, +#endif data, GAMEINPUT_InternalDeviceCallback, &data->gameinput_callback_token); @@ -347,7 +380,13 @@ static void GAMEINPUT_InitialKeyboardReading(WIN_GameInputData *data, SDL_Window Uint64 timestamp = SDL_US_TO_NS(reading->GetTimestamp() + data->timestamp_offset); SDL_KeyboardID keyboardID = device->instance_id; +#if GAMEINPUT_API_VERSION >= 4 + GameInputKeyboardInfo keyboardInfo; + device->pDevice->GetKeyboardInfo(&keyboardInfo); + uint32_t max_keys = keyboardInfo.maxSimultaneousKeys; +#else uint32_t max_keys = device->info->keyboardInfo->maxSimultaneousKeys; +#endif GameInputKeyState *keys = SDL_stack_alloc(GameInputKeyState, max_keys); if (!keys) { return; @@ -392,7 +431,13 @@ static void GAMEINPUT_HandleKeyboardDelta(WIN_GameInputData *data, SDL_Window *w Uint64 timestamp = SDL_US_TO_NS(reading->GetTimestamp() + data->timestamp_offset); SDL_KeyboardID keyboardID = device->instance_id; +#if GAMEINPUT_API_VERSION >= 4 + GameInputKeyboardInfo keyboardInfo; + device->pDevice->GetKeyboardInfo(&keyboardInfo); + uint32_t max_keys = keyboardInfo.maxSimultaneousKeys; +#else uint32_t max_keys = device->info->keyboardInfo->maxSimultaneousKeys; +#endif GameInputKeyState *last = SDL_stack_alloc(GameInputKeyState, max_keys); GameInputKeyState *keys = SDL_stack_alloc(GameInputKeyState, max_keys); if (!last || !keys) { @@ -445,12 +490,21 @@ void WIN_UpdateGameInput(SDL_VideoDevice *_this) IGameInputReading *reading; if (!device->registered) { +#if GAMEINPUT_API_VERSION >= 4 + if (device->pDevice->GetSupportedInput() & GameInputKindMouse) { + SDL_AddMouse(device->instance_id, device->name); + } + if (device->pDevice->GetSupportedInput() & GameInputKindKeyboard) { + SDL_AddKeyboard(device->instance_id, device->name); + } +#else if (device->info->supportedInput & GameInputKindMouse) { SDL_AddMouse(device->instance_id, device->name); } if (device->info->supportedInput & GameInputKindKeyboard) { SDL_AddKeyboard(device->instance_id, device->name); } +#endif device->registered = true; } @@ -458,8 +512,13 @@ void WIN_UpdateGameInput(SDL_VideoDevice *_this) GAMEINPUT_InternalRemoveByIndex(data, i--); continue; } - - if (!(device->info->supportedInput & data->enabled_input)) { + +#if GAMEINPUT_API_VERSION >= 4 + if (!(device->pDevice->GetSupportedInput() & data->enabled_input)) +#else + if (!(device->info->supportedInput & data->enabled_input)) +#endif + { continue; }