From bd628ba8c711f19c95ebe8b639e4574c121843e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Thu, 10 Mar 2022 13:05:51 +0100 Subject: [PATCH] windows.gaming.input: Implement GetCurrentReading for the RawGameController runtimeclass. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RĂ©mi Bernon Signed-off-by: Alexandre Julliard --- dlls/windows.gaming.input/controller.c | 16 +++++- dlls/windows.gaming.input/provider.c | 68 ++++++++++++++++++++++++++ dlls/windows.gaming.input/provider.idl | 11 +++++ 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/dlls/windows.gaming.input/controller.c b/dlls/windows.gaming.input/controller.c index 83e4e167ec9..3e00da917e7 100644 --- a/dlls/windows.gaming.input/controller.c +++ b/dlls/windows.gaming.input/controller.c @@ -262,9 +262,21 @@ static HRESULT WINAPI raw_controller_GetCurrentReading( IRawGameController *ifac UINT32 switches_size, enum GameControllerSwitchPosition *switches, UINT32 axes_size, DOUBLE *axes, UINT64 *timestamp ) { - FIXME( "iface %p, buttons_size %u, buttons %p, switches_size %u, switches %p, axes_size %u, axes %p, timestamp %p stub!\n", + struct controller *impl = impl_from_IRawGameController( iface ); + WineGameControllerState state; + HRESULT hr; + + TRACE( "iface %p, buttons_size %u, buttons %p, switches_size %u, switches %p, axes_size %u, axes %p, timestamp %p.\n", iface, buttons_size, buttons, switches_size, switches, axes_size, axes, timestamp ); - return E_NOTIMPL; + + if (FAILED(hr = IWineGameControllerProvider_get_State( impl->wine_provider, &state ))) return hr; + + memcpy( axes, state.axes, axes_size * sizeof(*axes) ); + memcpy( buttons, state.buttons, buttons_size * sizeof(*buttons) ); + memcpy( switches, state.switches, switches_size * sizeof(*switches) ); + *timestamp = state.timestamp; + + return hr; } static HRESULT WINAPI raw_controller_GetSwitchKind( IRawGameController *iface, INT32 index, enum GameControllerSwitchKind *value ) diff --git a/dlls/windows.gaming.input/provider.c b/dlls/windows.gaming.input/provider.c index 7883ec6af68..0877938f774 100644 --- a/dlls/windows.gaming.input/provider.c +++ b/dlls/windows.gaming.input/provider.c @@ -182,6 +182,69 @@ static HRESULT WINAPI wine_provider_get_SwitchCount( IWineGameControllerProvider return hr; } +static HRESULT WINAPI wine_provider_get_State( IWineGameControllerProvider *iface, struct WineGameControllerState *out ) +{ + struct provider *impl = impl_from_IWineGameControllerProvider( iface ); + DIJOYSTATE2 state = {0}; + UINT32 i = 0; + HRESULT hr; + + TRACE( "iface %p, out %p.\n", iface, out ); + + if (FAILED(hr = IDirectInputDevice8_GetDeviceState( impl->dinput_device, sizeof(state), &state ))) + { + WARN( "Failed to read device state, hr %#lx\n", hr ); + return hr; + } + + i = ARRAY_SIZE(state.rgbButtons); + while (i--) out->buttons[i] = (state.rgbButtons[i] != 0); + + i = ARRAY_SIZE(state.rgdwPOV); + while (i--) + { + if (state.rgdwPOV[i] == ~0) out->switches[i] = GameControllerSwitchPosition_Center; + else out->switches[i] = state.rgdwPOV[i] * 8 / 36000 + 1; + } + + i = 0; + out->axes[i++] = state.lX / 65535.; + out->axes[i++] = state.lY / 65535.; + out->axes[i++] = state.lZ / 65535.; + out->axes[i++] = state.lRx / 65535.; + out->axes[i++] = state.lRy / 65535.; + out->axes[i++] = state.lRz / 65535.; + out->axes[i++] = state.rglSlider[0] / 65535.; + out->axes[i++] = state.rglSlider[1] / 65535.; + out->axes[i++] = state.lVX / 65535.; + out->axes[i++] = state.lVY / 65535.; + out->axes[i++] = state.lVZ / 65535.; + out->axes[i++] = state.lVRx / 65535.; + out->axes[i++] = state.lVRy / 65535.; + out->axes[i++] = state.lVRz / 65535.; + out->axes[i++] = state.rglVSlider[0] / 65535.; + out->axes[i++] = state.rglVSlider[1] / 65535.; + out->axes[i++] = state.lAX / 65535.; + out->axes[i++] = state.lAY / 65535.; + out->axes[i++] = state.lAZ / 65535.; + out->axes[i++] = state.lARx / 65535.; + out->axes[i++] = state.lARy / 65535.; + out->axes[i++] = state.lARz / 65535.; + out->axes[i++] = state.rglASlider[0] / 65535.; + out->axes[i++] = state.rglASlider[1] / 65535.; + out->axes[i++] = state.lFX / 65535.; + out->axes[i++] = state.lFY / 65535.; + out->axes[i++] = state.lFZ / 65535.; + out->axes[i++] = state.lFRx / 65535.; + out->axes[i++] = state.lFRy / 65535.; + out->axes[i++] = state.lFRz / 65535.; + out->axes[i++] = state.rglFSlider[0] / 65535.; + out->axes[i++] = state.rglFSlider[1] / 65535.; + out->timestamp = GetTickCount64(); + + return S_OK; +} + static const struct IWineGameControllerProviderVtbl wine_provider_vtbl = { wine_provider_QueryInterface, @@ -196,6 +259,7 @@ static const struct IWineGameControllerProviderVtbl wine_provider_vtbl = wine_provider_get_AxisCount, wine_provider_get_ButtonCount, wine_provider_get_SwitchCount, + wine_provider_get_State, }; DEFINE_IINSPECTABLE( game_provider, IGameControllerProvider, struct provider, IWineGameControllerProvider_iface ) @@ -284,6 +348,10 @@ void provider_create( const WCHAR *device_path ) IDirectInput8_Release( dinput ); if (FAILED(hr)) return; + if (FAILED(hr = IDirectInputDevice8_SetCooperativeLevel( dinput_device, 0, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE ))) goto done; + if (FAILED(hr = IDirectInputDevice8_SetDataFormat( dinput_device, &c_dfDIJoystick2 ))) goto done; + if (FAILED(hr = IDirectInputDevice8_Acquire( dinput_device ))) goto done; + if (!(impl = calloc( 1, sizeof(*impl) ))) goto done; impl->IWineGameControllerProvider_iface.lpVtbl = &wine_provider_vtbl; impl->IGameControllerProvider_iface.lpVtbl = &game_provider_vtbl; diff --git a/dlls/windows.gaming.input/provider.idl b/dlls/windows.gaming.input/provider.idl index 19d5643f767..25191078721 100644 --- a/dlls/windows.gaming.input/provider.idl +++ b/dlls/windows.gaming.input/provider.idl @@ -32,6 +32,7 @@ import "windows.gaming.input.custom.idl"; namespace Windows.Gaming.Input.Custom { typedef enum WineGameControllerType WineGameControllerType; + typedef struct WineGameControllerState WineGameControllerState; interface IWineGameControllerProvider; runtimeclass WineGameControllerProvider; @@ -41,6 +42,14 @@ namespace Windows.Gaming.Input.Custom { Gamepad = 1, }; + struct WineGameControllerState + { + UINT64 timestamp; + DOUBLE axes[32]; + BOOLEAN buttons[128]; + Windows.Gaming.Input.GameControllerSwitchPosition switches[4]; + }; + [ uuid(06e58977-7684-4dc5-bad1-cda52a4aa06d) ] @@ -62,6 +71,8 @@ namespace Windows.Gaming.Input.Custom { [propget] HRESULT AxisCount([out, retval] INT32 *value); [propget] HRESULT ButtonCount([out, retval] INT32 *value); [propget] HRESULT SwitchCount([out, retval] INT32 *value); + + [propget] HRESULT State([out, retval] WineGameControllerState *state); } [