Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/windows.gaming.input/controller.c | 242 ++++++++++++++++++++++++- dlls/windows.gaming.input/manager.c | 36 +++- dlls/windows.gaming.input/private.h | 34 ++-- 3 files changed, 288 insertions(+), 24 deletions(-)
diff --git a/dlls/windows.gaming.input/controller.c b/dlls/windows.gaming.input/controller.c index 94343c0927d..9b08528b01b 100644 --- a/dlls/windows.gaming.input/controller.c +++ b/dlls/windows.gaming.input/controller.c @@ -18,11 +18,237 @@ */
#include "private.h" +#include "provider.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(input);
+struct controller +{ + IGameControllerImpl IGameControllerImpl_iface; + IGameControllerInputSink IGameControllerInputSink_iface; + IRawGameController IRawGameController_iface; + IGameController *IGameController_outer; + LONG ref; + + IGameControllerProvider *provider; +}; + +static inline struct controller *impl_from_IGameControllerImpl( IGameControllerImpl *iface ) +{ + return CONTAINING_RECORD( iface, struct controller, IGameControllerImpl_iface ); +} + +static HRESULT WINAPI controller_QueryInterface( IGameControllerImpl *iface, REFIID iid, void **out ) +{ + struct controller *impl = impl_from_IGameControllerImpl( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IGameControllerImpl )) + { + IInspectable_AddRef( (*out = &impl->IGameControllerImpl_iface) ); + return S_OK; + } + + if (IsEqualGUID( iid, &IID_IGameControllerInputSink )) + { + IInspectable_AddRef( (*out = &impl->IGameControllerInputSink_iface) ); + return S_OK; + } + + if (IsEqualGUID( iid, &IID_IRawGameController )) + { + IInspectable_AddRef( (*out = &impl->IRawGameController_iface) ); + return S_OK; + } + + WARN( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI controller_AddRef( IGameControllerImpl *iface ) +{ + struct controller *impl = impl_from_IGameControllerImpl( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI controller_Release( IGameControllerImpl *iface ) +{ + struct controller *impl = impl_from_IGameControllerImpl( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) + { + IGameControllerProvider_Release( impl->provider ); + free( impl ); + } + + return ref; +} + +static HRESULT WINAPI controller_GetIids( IGameControllerImpl *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI controller_GetRuntimeClassName( IGameControllerImpl *iface, HSTRING *class_name ) +{ + return WindowsCreateString( RuntimeClass_Windows_Gaming_Input_RawGameController, + ARRAY_SIZE(RuntimeClass_Windows_Gaming_Input_RawGameController), + class_name ); +} + +static HRESULT WINAPI controller_GetTrustLevel( IGameControllerImpl *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI controller_Initialize( IGameControllerImpl *iface, IGameController *outer, + IGameControllerProvider *provider ) +{ + struct controller *impl = impl_from_IGameControllerImpl( iface ); + + TRACE( "iface %p, outer %p, provider %p.\n", iface, outer, provider ); + + impl->IGameController_outer = outer; + IGameControllerProvider_AddRef( (impl->provider = provider) ); + + return S_OK; +} + +static const struct IGameControllerImplVtbl controller_vtbl = +{ + controller_QueryInterface, + controller_AddRef, + controller_Release, + /* IInspectable methods */ + controller_GetIids, + controller_GetRuntimeClassName, + controller_GetTrustLevel, + /* IGameControllerImpl methods */ + controller_Initialize, +}; + +DEFINE_IINSPECTABLE_OUTER( input_sink, IGameControllerInputSink, struct controller, IGameController_outer ) + +static HRESULT WINAPI input_sink_OnInputResumed( IGameControllerInputSink *iface, UINT64 timestamp ) +{ + FIXME( "iface %p, timestamp %I64u stub!\n", iface, timestamp ); + return E_NOTIMPL; +} + +static HRESULT WINAPI input_sink_OnInputSuspended( IGameControllerInputSink *iface, UINT64 timestamp ) +{ + FIXME( "iface %p, timestamp %I64u stub!\n", iface, timestamp ); + return E_NOTIMPL; +} + +static const struct IGameControllerInputSinkVtbl input_sink_vtbl = +{ + input_sink_QueryInterface, + input_sink_AddRef, + input_sink_Release, + /* IInspectable methods */ + input_sink_GetIids, + input_sink_GetRuntimeClassName, + input_sink_GetTrustLevel, + /* IGameControllerInputSink methods */ + input_sink_OnInputResumed, + input_sink_OnInputSuspended, +}; + +DEFINE_IINSPECTABLE_OUTER( raw_controller, IRawGameController, struct controller, IGameController_outer ) + +static HRESULT WINAPI raw_controller_get_AxisCount( IRawGameController *iface, INT32 *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI raw_controller_get_ButtonCount( IRawGameController *iface, INT32 *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI raw_controller_get_ForceFeedbackMotors( IRawGameController *iface, IVectorView_ForceFeedbackMotor **value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI raw_controller_get_HardwareProductId( IRawGameController *iface, UINT16 *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI raw_controller_get_HardwareVendorId( IRawGameController *iface, UINT16 *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI raw_controller_get_SwitchCount( IRawGameController *iface, INT32 *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI raw_controller_GetButtonLabel( IRawGameController *iface, INT32 index, + enum GameControllerButtonLabel *value ) +{ + FIXME( "iface %p, index %d, value %p stub!\n", iface, index, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI raw_controller_GetCurrentReading( IRawGameController *iface, UINT32 buttons_size, BOOLEAN *buttons, + 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", + iface, buttons_size, buttons, switches_size, switches, axes_size, axes, timestamp ); + return E_NOTIMPL; +} + +static HRESULT WINAPI raw_controller_GetSwitchKind( IRawGameController *iface, INT32 index, enum GameControllerSwitchKind *value ) +{ + FIXME( "iface %p, index %d, value %p stub!\n", iface, index, value ); + return E_NOTIMPL; +} + +static const struct IRawGameControllerVtbl raw_controller_vtbl = +{ + raw_controller_QueryInterface, + raw_controller_AddRef, + raw_controller_Release, + /* IInspectable methods */ + raw_controller_GetIids, + raw_controller_GetRuntimeClassName, + raw_controller_GetTrustLevel, + /* IRawGameController methods */ + raw_controller_get_AxisCount, + raw_controller_get_ButtonCount, + raw_controller_get_ForceFeedbackMotors, + raw_controller_get_HardwareProductId, + raw_controller_get_HardwareVendorId, + raw_controller_get_SwitchCount, + raw_controller_GetButtonLabel, + raw_controller_GetCurrentReading, + raw_controller_GetSwitchKind, +}; + struct controller_statics { IActivationFactory IActivationFactory_iface; @@ -213,8 +439,20 @@ DEFINE_IINSPECTABLE( controller_factory, ICustomGameControllerFactory, struct co static HRESULT WINAPI controller_factory_CreateGameController( ICustomGameControllerFactory *iface, IGameControllerProvider *provider, IInspectable **value ) { - FIXME( "iface %p, provider %p, value %p stub!\n", iface, provider, value ); - return E_NOTIMPL; + struct controller *impl; + + TRACE( "iface %p, provider %p, value %p.\n", iface, provider, value ); + + if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY; + impl->IGameControllerImpl_iface.lpVtbl = &controller_vtbl; + impl->IGameControllerInputSink_iface.lpVtbl = &input_sink_vtbl; + impl->IRawGameController_iface.lpVtbl = &raw_controller_vtbl; + impl->ref = 1; + + TRACE( "created RawGameController %p\n", impl ); + + *value = (IInspectable *)&impl->IGameControllerImpl_iface; + return S_OK; }
static HRESULT WINAPI controller_factory_OnGameControllerAdded( ICustomGameControllerFactory *iface, IGameController *value ) diff --git a/dlls/windows.gaming.input/manager.c b/dlls/windows.gaming.input/manager.c index f5b5654a4c6..489588a68ab 100644 --- a/dlls/windows.gaming.input/manager.c +++ b/dlls/windows.gaming.input/manager.c @@ -40,6 +40,7 @@ struct controller { IGameController IGameController_iface; IGameControllerBatteryInfo IGameControllerBatteryInfo_iface; + IInspectable *IInspectable_inner; LONG ref;
struct list entry; @@ -73,9 +74,7 @@ static HRESULT WINAPI controller_QueryInterface( IGameController *iface, REFIID return S_OK; }
- FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); - *out = NULL; - return E_NOINTERFACE; + return IInspectable_QueryInterface( impl->IInspectable_inner, iid, out ); }
static ULONG WINAPI controller_AddRef( IGameController *iface ) @@ -95,6 +94,9 @@ static ULONG WINAPI controller_Release( IGameController *iface )
if (!ref) { + /* guard against re-entry if inner releases an outer iface */ + InterlockedIncrement( &impl->ref ); + IInspectable_Release( impl->IInspectable_inner ); ICustomGameControllerFactory_Release( impl->factory ); IGameControllerProvider_Release( impl->provider ); free( impl ); @@ -111,14 +113,14 @@ static HRESULT WINAPI controller_GetIids( IGameController *iface, ULONG *iid_cou
static HRESULT WINAPI controller_GetRuntimeClassName( IGameController *iface, HSTRING *class_name ) { - FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); - return E_NOTIMPL; + struct controller *impl = impl_from_IGameController( iface ); + return IInspectable_GetRuntimeClassName( impl->IInspectable_inner, class_name ); }
static HRESULT WINAPI controller_GetTrustLevel( IGameController *iface, TrustLevel *trust_level ) { - FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); - return E_NOTIMPL; + struct controller *impl = impl_from_IGameController( iface ); + return IInspectable_GetTrustLevel( impl->IInspectable_inner, trust_level ); }
static HRESULT WINAPI controller_add_HeadsetConnected( IGameController *iface, ITypedEventHandler_IGameController_Headset *handler, @@ -421,13 +423,33 @@ IGameControllerFactoryManagerStatics2 *manager_factory = &manager_statics.IGameC static HRESULT controller_create( ICustomGameControllerFactory *factory, IGameControllerProvider *provider, struct controller **out ) { + IGameControllerImpl *inner_impl; struct controller *impl; + HRESULT hr;
if (!(impl = malloc(sizeof(*impl)))) return E_OUTOFMEMORY; impl->IGameController_iface.lpVtbl = &controller_vtbl; impl->IGameControllerBatteryInfo_iface.lpVtbl = &battery_vtbl; impl->ref = 1;
+ if (FAILED(hr = ICustomGameControllerFactory_CreateGameController( factory, provider, &impl->IInspectable_inner ))) + WARN( "Failed to create game controller, hr %#lx\n", hr ); + else if (FAILED(hr = IInspectable_QueryInterface( impl->IInspectable_inner, &IID_IGameControllerImpl, (void **)&inner_impl ))) + WARN( "Failed to find IGameControllerImpl iface, hr %#lx\n", hr ); + else + { + if (FAILED(hr = IGameControllerImpl_Initialize( inner_impl, &impl->IGameController_iface, provider ))) + WARN( "Failed to initialize game controller, hr %#lx\n", hr ); + IGameControllerImpl_Release( inner_impl ); + } + + if (FAILED(hr)) + { + if (impl->IInspectable_inner) IInspectable_Release( impl->IInspectable_inner ); + free( impl ); + return hr; + } + ICustomGameControllerFactory_AddRef( (impl->factory = factory) ); IGameControllerProvider_AddRef( (impl->provider = provider) );
diff --git a/dlls/windows.gaming.input/private.h b/dlls/windows.gaming.input/private.h index 56d03abad44..e3da45621b4 100644 --- a/dlls/windows.gaming.input/private.h +++ b/dlls/windows.gaming.input/private.h @@ -49,38 +49,42 @@ extern void provider_remove( const WCHAR *device_path ); extern void manager_on_provider_created( IGameControllerProvider *provider ); extern void manager_on_provider_removed( IGameControllerProvider *provider );
-#define DEFINE_IINSPECTABLE( pfx, iface_type, impl_type, base_iface ) \ - static inline impl_type *impl_from_##iface_type( iface_type *iface ) \ +#define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \ + static inline impl_type *impl_from( iface_type *iface ) \ { \ - return CONTAINING_RECORD( iface, impl_type, iface_type##_iface ); \ + return CONTAINING_RECORD( iface, impl_type, iface_mem ); \ } \ static HRESULT WINAPI pfx##_QueryInterface( iface_type *iface, REFIID iid, void **out ) \ { \ - impl_type *impl = impl_from_##iface_type( iface ); \ - return IInspectable_QueryInterface( (IInspectable *)&impl->base_iface, iid, out ); \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_QueryInterface( (IInspectable *)(expr), iid, out ); \ } \ static ULONG WINAPI pfx##_AddRef( iface_type *iface ) \ { \ - impl_type *impl = impl_from_##iface_type( iface ); \ - return IInspectable_AddRef( (IInspectable *)&impl->base_iface ); \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_AddRef( (IInspectable *)(expr) ); \ } \ static ULONG WINAPI pfx##_Release( iface_type *iface ) \ { \ - impl_type *impl = impl_from_##iface_type( iface ); \ - return IInspectable_Release( (IInspectable *)&impl->base_iface ); \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_Release( (IInspectable *)(expr) ); \ } \ static HRESULT WINAPI pfx##_GetIids( iface_type *iface, ULONG *iid_count, IID **iids ) \ { \ - impl_type *impl = impl_from_##iface_type( iface ); \ - return IInspectable_GetIids( (IInspectable *)&impl->base_iface, iid_count, iids ); \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetIids( (IInspectable *)(expr), iid_count, iids ); \ } \ static HRESULT WINAPI pfx##_GetRuntimeClassName( iface_type *iface, HSTRING *class_name ) \ { \ - impl_type *impl = impl_from_##iface_type( iface ); \ - return IInspectable_GetRuntimeClassName( (IInspectable *)&impl->base_iface, class_name ); \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetRuntimeClassName( (IInspectable *)(expr), class_name ); \ } \ static HRESULT WINAPI pfx##_GetTrustLevel( iface_type *iface, TrustLevel *trust_level ) \ { \ - impl_type *impl = impl_from_##iface_type( iface ); \ - return IInspectable_GetTrustLevel( (IInspectable *)&impl->base_iface, trust_level ); \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetTrustLevel( (IInspectable *)(expr), trust_level ); \ } +#define DEFINE_IINSPECTABLE( pfx, iface_type, impl_type, base_iface ) \ + DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, &impl->base_iface ) +#define DEFINE_IINSPECTABLE_OUTER( pfx, iface_type, impl_type, outer_iface ) \ + DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, impl->outer_iface )
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/windows.gaming.input/gamepad.c | 195 +++++++++++++++++++++++++++- 1 file changed, 193 insertions(+), 2 deletions(-)
diff --git a/dlls/windows.gaming.input/gamepad.c b/dlls/windows.gaming.input/gamepad.c index 50008541281..3fdf852ac1f 100644 --- a/dlls/windows.gaming.input/gamepad.c +++ b/dlls/windows.gaming.input/gamepad.c @@ -18,11 +18,190 @@ */
#include "private.h" +#include "provider.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(input);
+struct gamepad +{ + IGameControllerImpl IGameControllerImpl_iface; + IGameControllerInputSink IGameControllerInputSink_iface; + IGamepad IGamepad_iface; + IGameController *IGameController_outer; + LONG ref; + + IGameControllerProvider *provider; +}; + +static inline struct gamepad *impl_from_IGameControllerImpl( IGameControllerImpl *iface ) +{ + return CONTAINING_RECORD( iface, struct gamepad, IGameControllerImpl_iface ); +} + +static HRESULT WINAPI controller_QueryInterface( IGameControllerImpl *iface, REFIID iid, void **out ) +{ + struct gamepad *impl = impl_from_IGameControllerImpl( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IGameControllerImpl )) + { + IInspectable_AddRef( (*out = &impl->IGameControllerImpl_iface) ); + return S_OK; + } + + if (IsEqualGUID( iid, &IID_IGameControllerInputSink )) + { + IInspectable_AddRef( (*out = &impl->IGameControllerInputSink_iface) ); + return S_OK; + } + + if (IsEqualGUID( iid, &IID_IGamepad )) + { + IInspectable_AddRef( (*out = &impl->IGamepad_iface) ); + return S_OK; + } + + WARN( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI controller_AddRef( IGameControllerImpl *iface ) +{ + struct gamepad *impl = impl_from_IGameControllerImpl( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI controller_Release( IGameControllerImpl *iface ) +{ + struct gamepad *impl = impl_from_IGameControllerImpl( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) + { + IGameControllerProvider_Release( impl->provider ); + free( impl ); + } + + return ref; +} + +static HRESULT WINAPI controller_GetIids( IGameControllerImpl *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI controller_GetRuntimeClassName( IGameControllerImpl *iface, HSTRING *class_name ) +{ + return WindowsCreateString( RuntimeClass_Windows_Gaming_Input_Gamepad, + ARRAY_SIZE(RuntimeClass_Windows_Gaming_Input_Gamepad), + class_name ); +} + +static HRESULT WINAPI controller_GetTrustLevel( IGameControllerImpl *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI controller_Initialize( IGameControllerImpl *iface, IGameController *outer, + IGameControllerProvider *provider ) +{ + struct gamepad *impl = impl_from_IGameControllerImpl( iface ); + + TRACE( "iface %p, outer %p, provider %p.\n", iface, outer, provider ); + + impl->IGameController_outer = outer; + IGameControllerProvider_AddRef( (impl->provider = provider) ); + + return S_OK; +} + +static const struct IGameControllerImplVtbl controller_vtbl = +{ + controller_QueryInterface, + controller_AddRef, + controller_Release, + /* IInspectable methods */ + controller_GetIids, + controller_GetRuntimeClassName, + controller_GetTrustLevel, + /* IGameControllerImpl methods */ + controller_Initialize, +}; + +DEFINE_IINSPECTABLE_OUTER( input_sink, IGameControllerInputSink, struct gamepad, IGameController_outer ) + +static HRESULT WINAPI input_sink_OnInputResumed( IGameControllerInputSink *iface, UINT64 timestamp ) +{ + FIXME( "iface %p, timestamp %I64u stub!\n", iface, timestamp ); + return E_NOTIMPL; +} + +static HRESULT WINAPI input_sink_OnInputSuspended( IGameControllerInputSink *iface, UINT64 timestamp ) +{ + FIXME( "iface %p, timestamp %I64u stub!\n", iface, timestamp ); + return E_NOTIMPL; +} + +static const struct IGameControllerInputSinkVtbl input_sink_vtbl = +{ + input_sink_QueryInterface, + input_sink_AddRef, + input_sink_Release, + /* IInspectable methods */ + input_sink_GetIids, + input_sink_GetRuntimeClassName, + input_sink_GetTrustLevel, + /* IGameControllerInputSink methods */ + input_sink_OnInputResumed, + input_sink_OnInputSuspended, +}; + +DEFINE_IINSPECTABLE_OUTER( gamepad, IGamepad, struct gamepad, IGameController_outer ) + +static HRESULT WINAPI gamepad_get_Vibration( IGamepad *iface, struct GamepadVibration *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI gamepad_put_Vibration( IGamepad *iface, struct GamepadVibration value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, &value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI gamepad_GetCurrentReading( IGamepad *iface, struct GamepadReading *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL;} + +static const struct IGamepadVtbl gamepad_vtbl = +{ + gamepad_QueryInterface, + gamepad_AddRef, + gamepad_Release, + /* IInspectable methods */ + gamepad_GetIids, + gamepad_GetRuntimeClassName, + gamepad_GetTrustLevel, + /* IGamepad methods */ + gamepad_get_Vibration, + gamepad_put_Vibration, + gamepad_GetCurrentReading, +}; + struct gamepad_statics { IActivationFactory IActivationFactory_iface; @@ -232,8 +411,20 @@ DEFINE_IINSPECTABLE( controller_factory, ICustomGameControllerFactory, struct ga static HRESULT WINAPI controller_factory_CreateGameController( ICustomGameControllerFactory *iface, IGameControllerProvider *provider, IInspectable **value ) { - FIXME( "iface %p, provider %p, value %p stub!\n", iface, provider, value ); - return E_NOTIMPL; + struct gamepad *impl; + + TRACE( "iface %p, provider %p, value %p.\n", iface, provider, value ); + + if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY; + impl->IGameControllerImpl_iface.lpVtbl = &controller_vtbl; + impl->IGameControllerInputSink_iface.lpVtbl = &input_sink_vtbl; + impl->IGamepad_iface.lpVtbl = &gamepad_vtbl; + impl->ref = 1; + + TRACE( "created Gamepad %p\n", impl ); + + *value = (IInspectable *)&impl->IGameControllerImpl_iface; + return S_OK; }
static HRESULT WINAPI controller_factory_OnGameControllerAdded( ICustomGameControllerFactory *iface, IGameController *value )
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/windows.foundation.collections.idl | 4 +++- include/windows.foundation.idl | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/include/windows.foundation.collections.idl b/include/windows.foundation.collections.idl index ed1f5e30793..5ed60ed176e 100644 --- a/include/windows.foundation.collections.idl +++ b/include/windows.foundation.collections.idl @@ -93,7 +93,7 @@ cpp_quote("#endif") [propget] HRESULT Current([out, retval] T *value); [propget] HRESULT HasCurrent([out, retval] BOOL *value); HRESULT MoveNext([out, retval] BOOL *value); - HRESULT GetMany([in] UINT32 count, [in] UINT32 items_size, [out] T *items, [out, retval] UINT32 *value); + HRESULT GetMany([in] UINT32 items_size, [out] T *items, [out, retval] UINT32 *value); }
[ @@ -134,6 +134,7 @@ cpp_quote("#endif") uuid(bbe1fa4c-b0e3-4583-baef-1f1b2e483e56) ] interface IVectorView<T> : IInspectable + requires Windows.Foundation.Collections.IIterable<T> { HRESULT GetAt([in] UINT32 index, [out, retval] T *value); [propget] HRESULT Size([out, retval] UINT32 *value); @@ -146,6 +147,7 @@ cpp_quote("#endif") uuid(913337e9-11a1-4345-a3a2-4e7f956e222d) ] interface IVector<T> : IInspectable + requires Windows.Foundation.Collections.IIterable<T> { HRESULT GetAt([in, optional] UINT32 index, [out, retval] T *value); [propget] HRESULT Size([out, retval] UINT32 *value); diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl index a92a5d82424..e0fd35e45eb 100644 --- a/include/windows.foundation.idl +++ b/include/windows.foundation.idl @@ -159,7 +159,9 @@ namespace Windows { namespace Foundation { declare { interface Windows.Foundation.Collections.IIterable<HSTRING>; + interface Windows.Foundation.Collections.IIterable<IInspectable *>; interface Windows.Foundation.Collections.IIterator<HSTRING>; + interface Windows.Foundation.Collections.IIterator<IInspectable *>; interface Windows.Foundation.Collections.IVectorView<HSTRING>; interface Windows.Foundation.Collections.IVectorView<IInspectable *>; interface Windows.Foundation.Collections.IVector<HSTRING>;
For the generic vector implementation.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/windows.gaming.input/controller.c | 11 +- dlls/windows.gaming.input/gamepad.c | 11 +- dlls/windows.gaming.input/private.h | 9 +- dlls/windows.gaming.input/vector.c | 243 +++++++++++++++++++++++-- include/windows.gaming.input.idl | 8 +- 5 files changed, 259 insertions(+), 23 deletions(-)
diff --git a/dlls/windows.gaming.input/controller.c b/dlls/windows.gaming.input/controller.c index 9b08528b01b..9fb1b1a69a2 100644 --- a/dlls/windows.gaming.input/controller.c +++ b/dlls/windows.gaming.input/controller.c @@ -381,14 +381,19 @@ static HRESULT WINAPI statics_remove_RawGameControllerRemoved( IRawGameControlle
static HRESULT WINAPI statics_get_RawGameControllers( IRawGameControllerStatics *iface, IVectorView_RawGameController **value ) { - static const GUID *view_iid = &IID_IVectorView_RawGameController; - static const GUID *iid = &IID_IVector_RawGameController; + static const struct vector_iids iids = + { + .vector = &IID_IVector_RawGameController, + .view = &IID_IVectorView_RawGameController, + .iterable = &IID_IIterable_RawGameController, + .iterator = &IID_IIterator_RawGameController, + }; IVector_RawGameController *controllers; HRESULT hr;
TRACE( "iface %p, value %p.\n", iface, value );
- if (SUCCEEDED(hr = vector_create( iid, view_iid, (void **)&controllers ))) + if (SUCCEEDED(hr = vector_create( &iids, (void **)&controllers ))) { hr = IVector_RawGameController_GetView( controllers, value ); IVector_RawGameController_Release( controllers ); diff --git a/dlls/windows.gaming.input/gamepad.c b/dlls/windows.gaming.input/gamepad.c index 3fdf852ac1f..172ca74e3f6 100644 --- a/dlls/windows.gaming.input/gamepad.c +++ b/dlls/windows.gaming.input/gamepad.c @@ -341,14 +341,19 @@ static HRESULT WINAPI statics_remove_GamepadRemoved( IGamepadStatics *iface, Eve
static HRESULT WINAPI statics_get_Gamepads( IGamepadStatics *iface, IVectorView_Gamepad **value ) { - static const GUID *view_iid = &IID_IVectorView_Gamepad; - static const GUID *iid = &IID_IVector_Gamepad; + static const struct vector_iids iids = + { + .vector = &IID_IVector_Gamepad, + .view = &IID_IVectorView_Gamepad, + .iterable = &IID_IIterable_Gamepad, + .iterator = &IID_IIterator_Gamepad, + }; IVector_Gamepad *gamepads; HRESULT hr;
TRACE( "iface %p, value %p.\n", iface, value );
- if (SUCCEEDED(hr = vector_create( iid, view_iid, (void **)&gamepads ))) + if (SUCCEEDED(hr = vector_create( &iids, (void **)&gamepads ))) { hr = IVector_Gamepad_GetView( gamepads, value ); IVector_Gamepad_Release( gamepads ); diff --git a/dlls/windows.gaming.input/private.h b/dlls/windows.gaming.input/private.h index e3da45621b4..5d5f48d12e7 100644 --- a/dlls/windows.gaming.input/private.h +++ b/dlls/windows.gaming.input/private.h @@ -41,7 +41,14 @@ extern ICustomGameControllerFactory *controller_factory; extern ICustomGameControllerFactory *gamepad_factory; extern IGameControllerFactoryManagerStatics2 *manager_factory;
-extern HRESULT vector_create( REFIID iid, REFIID view_iid, void **out ); +struct vector_iids +{ + const GUID *vector; + const GUID *view; + const GUID *iterable; + const GUID *iterator; +}; +extern HRESULT vector_create( const struct vector_iids *iids, void **out );
extern void provider_create( const WCHAR *device_path ); extern void provider_remove( const WCHAR *device_path ); diff --git a/dlls/windows.gaming.input/vector.c b/dlls/windows.gaming.input/vector.c index 441c13dab4c..10dac5a5547 100644 --- a/dlls/windows.gaming.input/vector.c +++ b/dlls/windows.gaming.input/vector.c @@ -23,10 +23,144 @@
WINE_DEFAULT_DEBUG_CHANNEL(combase);
+struct iterator +{ + IIterator_IInspectable IIterator_IInspectable_iface; + const GUID *iid; + LONG ref; + + IVectorView_IInspectable *view; + UINT32 index; + UINT32 size; +}; + +static inline struct iterator *impl_from_IIterator_IInspectable( IIterator_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct iterator, IIterator_IInspectable_iface ); +} + +static HRESULT WINAPI iterator_QueryInterface( IIterator_IInspectable *iface, REFIID iid, void **out ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, impl->iid )) + { + IInspectable_AddRef( (*out = &impl->IIterator_IInspectable_iface) ); + return S_OK; + } + + WARN( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI iterator_AddRef( IIterator_IInspectable *iface ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI iterator_Release( IIterator_IInspectable *iface ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) + { + IVectorView_IInspectable_Release( impl->view ); + free( impl ); + } + + return ref; +} + +static HRESULT WINAPI iterator_GetIids( IIterator_IInspectable *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI iterator_GetRuntimeClassName( IIterator_IInspectable *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI iterator_GetTrustLevel( IIterator_IInspectable *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI iterator_get_Current( IIterator_IInspectable *iface, IInspectable **value ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + + FIXME("\n"); + + return IVectorView_IInspectable_GetAt( impl->view, impl->index, value ); +} + +static HRESULT WINAPI iterator_get_HasCurrent( IIterator_IInspectable *iface, BOOL *value ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + + FIXME("\n"); + + *value = impl->index < impl->size; + return S_OK; +} + +static HRESULT WINAPI iterator_MoveNext( IIterator_IInspectable *iface, BOOL *value ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + + FIXME("\n"); + + if ((*value = impl->index < impl->size)) impl->index++; + return S_OK; +} + +static HRESULT WINAPI iterator_GetMany( IIterator_IInspectable *iface, UINT32 items_size, + IInspectable **items, UINT *count ) +{ + struct iterator *impl = impl_from_IIterator_IInspectable( iface ); + + FIXME("\n"); + + return IVectorView_IInspectable_GetMany( impl->view, impl->index, items_size, items, count ); +} + +static const IIterator_IInspectableVtbl iterator_vtbl = +{ + iterator_QueryInterface, + iterator_AddRef, + iterator_Release, + /* IInspectable methods */ + iterator_GetIids, + iterator_GetRuntimeClassName, + iterator_GetTrustLevel, + /* IIterator<IInspectable*> methods */ + iterator_get_Current, + iterator_get_HasCurrent, + iterator_MoveNext, + iterator_GetMany, +}; + struct vector_view { IVectorView_IInspectable IVectorView_IInspectable_iface; - const GUID *iid; + IIterable_IInspectable IIterable_IInspectable_iface; + struct vector_iids iids; LONG ref;
UINT32 size; @@ -47,10 +181,15 @@ static HRESULT WINAPI vector_view_QueryInterface( IVectorView_IInspectable *ifac if (IsEqualGUID( iid, &IID_IUnknown ) || IsEqualGUID( iid, &IID_IInspectable ) || IsEqualGUID( iid, &IID_IAgileObject ) || - IsEqualGUID( iid, impl->iid )) + IsEqualGUID( iid, impl->iids.view )) { - IUnknown_AddRef( iface ); - *out = iface; + IInspectable_AddRef( (*out = &impl->IVectorView_IInspectable_iface) ); + return S_OK; + } + + if (IsEqualGUID( iid, impl->iids.iterable )) + { + IInspectable_AddRef( (*out = &impl->IIterable_IInspectable_iface) ); return S_OK; }
@@ -176,11 +315,46 @@ static const struct IVectorView_IInspectableVtbl vector_view_vtbl = vector_view_GetMany, };
+DEFINE_IINSPECTABLE_( iterable_view, IIterable_IInspectable, struct vector_view, view_impl_from_IIterable_IInspectable, + IIterable_IInspectable_iface, &impl->IVectorView_IInspectable_iface ) + +static HRESULT WINAPI iterable_view_First( IIterable_IInspectable *iface, IIterator_IInspectable **value ) +{ + struct vector_view *impl = view_impl_from_IIterable_IInspectable( iface ); + struct iterator *iter; + + TRACE( "iface %p, value %p.\n", iface, value ); + + if (!(iter = calloc( 1, sizeof(struct iterator) ))) return E_OUTOFMEMORY; + iter->IIterator_IInspectable_iface.lpVtbl = &iterator_vtbl; + iter->iid = impl->iids.iterator; + iter->ref = 1; + + IVectorView_IInspectable_AddRef( (iter->view = &impl->IVectorView_IInspectable_iface) ); + iter->size = impl->size; + + *value = &iter->IIterator_IInspectable_iface; + return S_OK; +} + +static const struct IIterable_IInspectableVtbl iterable_view_vtbl = +{ + iterable_view_QueryInterface, + iterable_view_AddRef, + iterable_view_Release, + /* IInspectable methods */ + iterable_view_GetIids, + iterable_view_GetRuntimeClassName, + iterable_view_GetTrustLevel, + /* IIterable<T> methods */ + iterable_view_First, +}; + struct vector { IVector_IInspectable IVector_IInspectable_iface; - const GUID *iid; - const GUID *view_iid; + IIterable_IInspectable IIterable_IInspectable_iface; + struct vector_iids iids; LONG ref;
UINT32 size; @@ -202,10 +376,15 @@ static HRESULT WINAPI vector_QueryInterface( IVector_IInspectable *iface, REFIID if (IsEqualGUID( iid, &IID_IUnknown ) || IsEqualGUID( iid, &IID_IInspectable ) || IsEqualGUID( iid, &IID_IAgileObject ) || - IsEqualGUID( iid, impl->iid )) + IsEqualGUID( iid, impl->iids.vector )) { - IUnknown_AddRef( iface ); - *out = iface; + IInspectable_AddRef( (*out = &impl->IVector_IInspectable_iface) ); + return S_OK; + } + + if (IsEqualGUID( iid, impl->iids.iterable )) + { + IInspectable_AddRef( (*out = &impl->IIterable_IInspectable_iface) ); return S_OK; }
@@ -287,7 +466,8 @@ static HRESULT WINAPI vector_GetView( IVector_IInspectable *iface, IVectorView_I
if (!(view = calloc( 1, offsetof( struct vector_view, elements[impl->size] ) ))) return E_OUTOFMEMORY; view->IVectorView_IInspectable_iface.lpVtbl = &vector_view_vtbl; - view->iid = impl->view_iid; + view->IIterable_IInspectable_iface.lpVtbl = &iterable_view_vtbl; + view->iids = impl->iids; view->ref = 1;
for (i = 0; i < impl->size; ++i) IInspectable_AddRef( (view->elements[view->size++] = impl->elements[i]) ); @@ -446,16 +626,51 @@ static const struct IVector_IInspectableVtbl vector_vtbl = vector_ReplaceAll, };
-HRESULT vector_create( REFIID iid, REFIID view_iid, void **out ) +DEFINE_IINSPECTABLE( iterable, IIterable_IInspectable, struct vector, IVector_IInspectable_iface ) + +static HRESULT WINAPI iterable_First( IIterable_IInspectable *iface, IIterator_IInspectable **value ) +{ + struct vector *impl = impl_from_IIterable_IInspectable( iface ); + IIterable_IInspectable *iterable; + IVectorView_IInspectable *view; + HRESULT hr; + + TRACE("\n"); + + if (FAILED(hr = IVector_IInspectable_GetView( &impl->IVector_IInspectable_iface, &view ))) return hr; + + hr = IVectorView_IInspectable_QueryInterface( view, impl->iids.iterable, (void **)&iterable ); + IVectorView_IInspectable_Release( view ); + if (FAILED(hr)) return hr; + + hr = IIterable_IInspectable_First( iterable, value ); + IIterable_IInspectable_Release( iterable ); + return hr; +} + +static const struct IIterable_IInspectableVtbl iterable_vtbl = +{ + iterable_QueryInterface, + iterable_AddRef, + iterable_Release, + /* IInspectable methods */ + iterable_GetIids, + iterable_GetRuntimeClassName, + iterable_GetTrustLevel, + /* IIterable<T> methods */ + iterable_First, +}; + +HRESULT vector_create( const struct vector_iids *iids, void **out ) { struct vector *impl;
- TRACE( "iid %s, out %p.\n", debugstr_guid( iid ), out ); + TRACE( "iid %s, out %p.\n", debugstr_guid( iids->vector ), out );
if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY; impl->IVector_IInspectable_iface.lpVtbl = &vector_vtbl; - impl->iid = iid; - impl->view_iid = view_iid; + impl->IIterable_IInspectable_iface.lpVtbl = &iterable_vtbl; + impl->iids = *iids; impl->ref = 1;
*out = &impl->IVector_IInspectable_iface; diff --git a/include/windows.gaming.input.idl b/include/windows.gaming.input.idl index 5bf94f78820..4e9bb6e2465 100644 --- a/include/windows.gaming.input.idl +++ b/include/windows.gaming.input.idl @@ -56,8 +56,12 @@ namespace Windows.Gaming.Input { interface Windows.Foundation.EventHandler<Windows.Gaming.Input.RawGameController *>; interface Windows.Foundation.TypedEventHandler<Windows.Gaming.Input.IGameController *, Windows.Gaming.Input.Headset *>; interface Windows.Foundation.TypedEventHandler<Windows.Gaming.Input.IGameController *, Windows.System.UserChangedEventArgs *>; - interface Windows.Foundation.Collections.IVectorView<Gamepad *>; - interface Windows.Foundation.Collections.IVector<Gamepad *>; + interface Windows.Foundation.Collections.IIterator<Windows.Gaming.Input.Gamepad *>; + interface Windows.Foundation.Collections.IIterable<Windows.Gaming.Input.Gamepad *>; + interface Windows.Foundation.Collections.IVectorView<Windows.Gaming.Input.Gamepad *>; + interface Windows.Foundation.Collections.IVector<Windows.Gaming.Input.Gamepad *>; + interface Windows.Foundation.Collections.IIterator<Windows.Gaming.Input.RawGameController *>; + interface Windows.Foundation.Collections.IIterable<Windows.Gaming.Input.RawGameController *>; interface Windows.Foundation.Collections.IVectorView<Windows.Gaming.Input.RawGameController *>; interface Windows.Foundation.Collections.IVector<Windows.Gaming.Input.RawGameController *>; }