windows.gaming.input: Implement IForceFeedbackEffect interface for ConstantForceEffect.
Using COM aggregation and a new IWineForceFeedbackEffectImpl interface, deriving from IUnknown as it is only used internally. Signed-off-by: Rémi Bernon <rbernon@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
aa37aad2c8
commit
d5edf656ef
|
@ -5628,10 +5628,8 @@ static void test_windows_gaming_input(void)
|
|||
IActivationFactory_Release( activation_factory );
|
||||
|
||||
hr = IInspectable_QueryInterface( tmp_inspectable, &IID_IForceFeedbackEffect, (void **)&effect );
|
||||
todo_wine
|
||||
ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
|
||||
IInspectable_Release( tmp_inspectable );
|
||||
if (hr != S_OK) goto skip_tests;
|
||||
|
||||
hr = IForceFeedbackEffect_QueryInterface( effect, &IID_IConstantForceEffect, (void **)&constant_effect );
|
||||
ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
|
||||
|
@ -5670,6 +5668,7 @@ static void test_windows_gaming_input(void)
|
|||
hr = IForceFeedbackMotor_LoadEffectAsync( motor, effect, &result_async );
|
||||
todo_wine
|
||||
ok( hr == S_OK, "LoadEffectAsync returned %#lx\n", hr );
|
||||
if (hr != S_OK) goto skip_tests;
|
||||
result_async_handler = default_result_async_handler;
|
||||
result_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL );
|
||||
ok( !!result_async_handler.event, "CreateEventW failed, error %lu\n", GetLastError() );
|
||||
|
|
|
@ -25,6 +25,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(input);
|
|||
struct constant_effect
|
||||
{
|
||||
IConstantForceEffect IConstantForceEffect_iface;
|
||||
IWineForceFeedbackEffectImpl *IWineForceFeedbackEffectImpl_inner;
|
||||
LONG ref;
|
||||
};
|
||||
|
||||
|
@ -48,9 +49,7 @@ static HRESULT WINAPI effect_QueryInterface( IConstantForceEffect *iface, REFIID
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
|
||||
*out = NULL;
|
||||
return E_NOINTERFACE;
|
||||
return IWineForceFeedbackEffectImpl_QueryInterface( impl->IWineForceFeedbackEffectImpl_inner, iid, out );
|
||||
}
|
||||
|
||||
static ULONG WINAPI effect_AddRef( IConstantForceEffect *iface )
|
||||
|
@ -68,7 +67,13 @@ static ULONG WINAPI effect_Release( IConstantForceEffect *iface )
|
|||
|
||||
TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref );
|
||||
|
||||
if (!ref) free( impl );
|
||||
if (!ref)
|
||||
{
|
||||
/* guard against re-entry if inner releases an outer iface */
|
||||
InterlockedIncrement( &impl->ref );
|
||||
IWineForceFeedbackEffectImpl_Release( impl->IWineForceFeedbackEffectImpl_inner );
|
||||
free( impl );
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
@ -192,6 +197,7 @@ static HRESULT WINAPI activation_GetTrustLevel( IActivationFactory *iface, Trust
|
|||
static HRESULT WINAPI activation_ActivateInstance( IActivationFactory *iface, IInspectable **instance )
|
||||
{
|
||||
struct constant_effect *impl;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE( "iface %p, instance %p.\n", iface, instance );
|
||||
|
||||
|
@ -199,6 +205,13 @@ static HRESULT WINAPI activation_ActivateInstance( IActivationFactory *iface, II
|
|||
impl->IConstantForceEffect_iface.lpVtbl = &effect_vtbl;
|
||||
impl->ref = 1;
|
||||
|
||||
if (FAILED(hr = force_feedback_effect_create( (IInspectable *)&impl->IConstantForceEffect_iface,
|
||||
&impl->IWineForceFeedbackEffectImpl_inner )))
|
||||
{
|
||||
free( impl );
|
||||
return hr;
|
||||
}
|
||||
|
||||
*instance = (IInspectable *)&impl->IConstantForceEffect_iface;
|
||||
TRACE( "created ConstantForceEffect %p\n", *instance );
|
||||
return S_OK;
|
||||
|
|
|
@ -27,6 +27,139 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(input);
|
||||
|
||||
struct effect
|
||||
{
|
||||
IWineForceFeedbackEffectImpl IWineForceFeedbackEffectImpl_iface;
|
||||
IForceFeedbackEffect IForceFeedbackEffect_iface;
|
||||
IInspectable *IInspectable_outer;
|
||||
LONG ref;
|
||||
};
|
||||
|
||||
static inline struct effect *impl_from_IWineForceFeedbackEffectImpl( IWineForceFeedbackEffectImpl *iface )
|
||||
{
|
||||
return CONTAINING_RECORD( iface, struct effect, IWineForceFeedbackEffectImpl_iface );
|
||||
}
|
||||
|
||||
static HRESULT WINAPI effect_impl_QueryInterface( IWineForceFeedbackEffectImpl *iface, REFIID iid, void **out )
|
||||
{
|
||||
struct effect *impl = impl_from_IWineForceFeedbackEffectImpl( 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, &IID_IWineForceFeedbackEffectImpl ))
|
||||
{
|
||||
IWineForceFeedbackEffectImpl_AddRef( (*out = &impl->IWineForceFeedbackEffectImpl_iface) );
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualGUID( iid, &IID_IForceFeedbackEffect ))
|
||||
{
|
||||
IInspectable_AddRef( (*out = &impl->IForceFeedbackEffect_iface) );
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
|
||||
*out = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI effect_impl_AddRef( IWineForceFeedbackEffectImpl *iface )
|
||||
{
|
||||
struct effect *impl = impl_from_IWineForceFeedbackEffectImpl( iface );
|
||||
ULONG ref = InterlockedIncrement( &impl->ref );
|
||||
TRACE( "iface %p increasing refcount to %lu.\n", iface, ref );
|
||||
return ref;
|
||||
}
|
||||
|
||||
static ULONG WINAPI effect_impl_Release( IWineForceFeedbackEffectImpl *iface )
|
||||
{
|
||||
struct effect *impl = impl_from_IWineForceFeedbackEffectImpl( iface );
|
||||
ULONG ref = InterlockedDecrement( &impl->ref );
|
||||
|
||||
TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref );
|
||||
|
||||
if (!ref) free( impl );
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static const struct IWineForceFeedbackEffectImplVtbl effect_impl_vtbl =
|
||||
{
|
||||
effect_impl_QueryInterface,
|
||||
effect_impl_AddRef,
|
||||
effect_impl_Release,
|
||||
/* IWineForceFeedbackEffectImpl methods */
|
||||
};
|
||||
|
||||
DEFINE_IINSPECTABLE_OUTER( effect, IForceFeedbackEffect, struct effect, IInspectable_outer )
|
||||
|
||||
static HRESULT WINAPI effect_get_Gain( IForceFeedbackEffect *iface, DOUBLE *value )
|
||||
{
|
||||
FIXME( "iface %p, value %p stub!\n", iface, value );
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI effect_put_Gain( IForceFeedbackEffect *iface, DOUBLE value )
|
||||
{
|
||||
FIXME( "iface %p, value %f stub!\n", iface, value );
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI effect_get_State( IForceFeedbackEffect *iface, ForceFeedbackEffectState *value )
|
||||
{
|
||||
FIXME( "iface %p, value %p stub!\n", iface, value );
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI effect_Start( IForceFeedbackEffect *iface )
|
||||
{
|
||||
FIXME( "iface %p stub!\n", iface );
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI effect_Stop( IForceFeedbackEffect *iface )
|
||||
{
|
||||
FIXME( "iface %p stub!\n", iface );
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static const struct IForceFeedbackEffectVtbl effect_vtbl =
|
||||
{
|
||||
effect_QueryInterface,
|
||||
effect_AddRef,
|
||||
effect_Release,
|
||||
/* IInspectable methods */
|
||||
effect_GetIids,
|
||||
effect_GetRuntimeClassName,
|
||||
effect_GetTrustLevel,
|
||||
/* IForceFeedbackEffect methods */
|
||||
effect_get_Gain,
|
||||
effect_put_Gain,
|
||||
effect_get_State,
|
||||
effect_Start,
|
||||
effect_Stop,
|
||||
};
|
||||
|
||||
HRESULT force_feedback_effect_create( IInspectable *outer, IWineForceFeedbackEffectImpl **out )
|
||||
{
|
||||
struct effect *impl;
|
||||
|
||||
TRACE( "outer %p, out %p\n", outer, out );
|
||||
|
||||
if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY;
|
||||
impl->IWineForceFeedbackEffectImpl_iface.lpVtbl = &effect_impl_vtbl;
|
||||
impl->IForceFeedbackEffect_iface.lpVtbl = &effect_vtbl;
|
||||
impl->IInspectable_outer = outer;
|
||||
impl->ref = 1;
|
||||
|
||||
*out = &impl->IWineForceFeedbackEffectImpl_iface;
|
||||
TRACE( "created ForceFeedbackEffect %p\n", *out );
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
struct motor
|
||||
{
|
||||
IForceFeedbackMotor IForceFeedbackMotor_iface;
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include "wine/debug.h"
|
||||
#include "wine/list.h"
|
||||
|
||||
#include "provider.h"
|
||||
|
||||
extern HINSTANCE windows_gaming_input;
|
||||
extern ICustomGameControllerFactory *controller_factory;
|
||||
extern ICustomGameControllerFactory *gamepad_factory;
|
||||
|
@ -69,6 +71,7 @@ extern HRESULT event_handlers_remove( struct list *list, EventRegistrationToken
|
|||
extern void event_handlers_notify( struct list *list, IInspectable *element );
|
||||
|
||||
extern HRESULT force_feedback_motor_create( IDirectInputDevice8W *device, IForceFeedbackMotor **out );
|
||||
extern HRESULT force_feedback_effect_create( IInspectable *outer, IWineForceFeedbackEffectImpl **out );
|
||||
|
||||
typedef HRESULT (WINAPI *async_operation_callback)( IUnknown *invoker, IUnknown *param, PROPVARIANT *result );
|
||||
extern HRESULT async_operation_boolean_create( IUnknown *invoker, IUnknown *param, async_operation_callback callback,
|
||||
|
|
|
@ -34,6 +34,7 @@ import "windows.gaming.input.forcefeedback.idl";
|
|||
|
||||
namespace Windows.Gaming.Input.Custom {
|
||||
typedef enum WineGameControllerType WineGameControllerType;
|
||||
typedef enum WineForceFeedbackEffectType WineForceFeedbackEffectType;
|
||||
typedef struct WineGameControllerState WineGameControllerState;
|
||||
typedef struct WineGameControllerVibration WineGameControllerVibration;
|
||||
interface IWineGameControllerProvider;
|
||||
|
@ -49,6 +50,11 @@ namespace Windows.Gaming.Input.Custom {
|
|||
RacingWheel = 2,
|
||||
};
|
||||
|
||||
enum WineForceFeedbackEffectType
|
||||
{
|
||||
Constant = 1,
|
||||
};
|
||||
|
||||
struct WineGameControllerState
|
||||
{
|
||||
UINT64 timestamp;
|
||||
|
@ -94,6 +100,14 @@ namespace Windows.Gaming.Input.Custom {
|
|||
[propget] HRESULT ForceFeedbackMotor([out, retval] Windows.Gaming.Input.ForceFeedback.ForceFeedbackMotor **motor);
|
||||
}
|
||||
|
||||
[
|
||||
uuid(27833469-7760-417e-adbe-e011a66e16ee)
|
||||
]
|
||||
interface IWineForceFeedbackEffectImpl : IUnknown
|
||||
requires Windows.Gaming.Input.ForceFeedback.IForceFeedbackEffect
|
||||
{
|
||||
}
|
||||
|
||||
[
|
||||
uuid(83f377ee-c799-11ec-9d64-0242ac120002)
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue