1 /* WinRT Windows.Gaming.Input implementation
3 * Copyright 2021 RĂ©mi Bernon for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(input
);
27 static CRITICAL_SECTION controller_cs
;
28 static CRITICAL_SECTION_DEBUG controller_cs_debug
=
31 { &controller_cs_debug
.ProcessLocksList
, &controller_cs_debug
.ProcessLocksList
},
32 0, 0, { (DWORD_PTR
)(__FILE__
": controller_cs") }
34 static CRITICAL_SECTION controller_cs
= { &controller_cs_debug
, -1, 0, 0, 0, 0 };
36 static IVector_RawGameController
*controllers
;
37 static struct list controller_added_handlers
= LIST_INIT( controller_added_handlers
);
38 static struct list controller_removed_handlers
= LIST_INIT( controller_removed_handlers
);
40 static HRESULT
init_controllers(void)
42 static const struct vector_iids iids
=
44 .vector
= &IID_IVector_RawGameController
,
45 .view
= &IID_IVectorView_RawGameController
,
46 .iterable
= &IID_IIterable_RawGameController
,
47 .iterator
= &IID_IIterator_RawGameController
,
51 EnterCriticalSection( &controller_cs
);
52 if (controllers
) hr
= S_OK
;
53 else hr
= vector_create( &iids
, (void **)&controllers
);
54 LeaveCriticalSection( &controller_cs
);
61 IGameControllerImpl IGameControllerImpl_iface
;
62 IGameControllerInputSink IGameControllerInputSink_iface
;
63 IRawGameController IRawGameController_iface
;
64 IGameController
*IGameController_outer
;
67 IGameControllerProvider
*provider
;
68 IWineGameControllerProvider
*wine_provider
;
71 static inline struct controller
*impl_from_IGameControllerImpl( IGameControllerImpl
*iface
)
73 return CONTAINING_RECORD( iface
, struct controller
, IGameControllerImpl_iface
);
76 static HRESULT WINAPI
controller_QueryInterface( IGameControllerImpl
*iface
, REFIID iid
, void **out
)
78 struct controller
*impl
= impl_from_IGameControllerImpl( iface
);
80 TRACE( "iface %p, iid %s, out %p.\n", iface
, debugstr_guid( iid
), out
);
82 if (IsEqualGUID( iid
, &IID_IUnknown
) ||
83 IsEqualGUID( iid
, &IID_IInspectable
) ||
84 IsEqualGUID( iid
, &IID_IGameControllerImpl
))
86 IInspectable_AddRef( (*out
= &impl
->IGameControllerImpl_iface
) );
90 if (IsEqualGUID( iid
, &IID_IGameControllerInputSink
))
92 IInspectable_AddRef( (*out
= &impl
->IGameControllerInputSink_iface
) );
96 if (IsEqualGUID( iid
, &IID_IRawGameController
))
98 IInspectable_AddRef( (*out
= &impl
->IRawGameController_iface
) );
102 FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid
) );
104 return E_NOINTERFACE
;
107 static ULONG WINAPI
controller_AddRef( IGameControllerImpl
*iface
)
109 struct controller
*impl
= impl_from_IGameControllerImpl( iface
);
110 ULONG ref
= InterlockedIncrement( &impl
->ref
);
111 TRACE( "iface %p increasing refcount to %lu.\n", iface
, ref
);
115 static ULONG WINAPI
controller_Release( IGameControllerImpl
*iface
)
117 struct controller
*impl
= impl_from_IGameControllerImpl( iface
);
118 ULONG ref
= InterlockedDecrement( &impl
->ref
);
120 TRACE( "iface %p decreasing refcount to %lu.\n", iface
, ref
);
124 if (impl
->wine_provider
)
125 IWineGameControllerProvider_Release( impl
->wine_provider
);
126 IGameControllerProvider_Release( impl
->provider
);
133 static HRESULT WINAPI
controller_GetIids( IGameControllerImpl
*iface
, ULONG
*iid_count
, IID
**iids
)
135 FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface
, iid_count
, iids
);
139 static HRESULT WINAPI
controller_GetRuntimeClassName( IGameControllerImpl
*iface
, HSTRING
*class_name
)
141 return WindowsCreateString( RuntimeClass_Windows_Gaming_Input_RawGameController
,
142 ARRAY_SIZE(RuntimeClass_Windows_Gaming_Input_RawGameController
),
146 static HRESULT WINAPI
controller_GetTrustLevel( IGameControllerImpl
*iface
, TrustLevel
*trust_level
)
148 FIXME( "iface %p, trust_level %p stub!\n", iface
, trust_level
);
152 static HRESULT WINAPI
controller_Initialize( IGameControllerImpl
*iface
, IGameController
*outer
,
153 IGameControllerProvider
*provider
)
155 struct controller
*impl
= impl_from_IGameControllerImpl( iface
);
158 TRACE( "iface %p, outer %p, provider %p.\n", iface
, outer
, provider
);
160 impl
->IGameController_outer
= outer
;
161 IGameControllerProvider_AddRef( (impl
->provider
= provider
) );
163 hr
= IGameControllerProvider_QueryInterface( provider
, &IID_IWineGameControllerProvider
,
164 (void **)&impl
->wine_provider
);
165 if (FAILED(hr
)) return hr
;
167 EnterCriticalSection( &controller_cs
);
168 if (SUCCEEDED(hr
= init_controllers()))
169 hr
= IVector_RawGameController_Append( controllers
, &impl
->IRawGameController_iface
);
170 LeaveCriticalSection( &controller_cs
);
175 static const struct IGameControllerImplVtbl controller_vtbl
=
177 controller_QueryInterface
,
180 /* IInspectable methods */
182 controller_GetRuntimeClassName
,
183 controller_GetTrustLevel
,
184 /* IGameControllerImpl methods */
185 controller_Initialize
,
188 DEFINE_IINSPECTABLE_OUTER( input_sink
, IGameControllerInputSink
, struct controller
, IGameController_outer
)
190 static HRESULT WINAPI
input_sink_OnInputResumed( IGameControllerInputSink
*iface
, UINT64 timestamp
)
192 FIXME( "iface %p, timestamp %I64u stub!\n", iface
, timestamp
);
196 static HRESULT WINAPI
input_sink_OnInputSuspended( IGameControllerInputSink
*iface
, UINT64 timestamp
)
198 FIXME( "iface %p, timestamp %I64u stub!\n", iface
, timestamp
);
202 static const struct IGameControllerInputSinkVtbl input_sink_vtbl
=
204 input_sink_QueryInterface
,
207 /* IInspectable methods */
209 input_sink_GetRuntimeClassName
,
210 input_sink_GetTrustLevel
,
211 /* IGameControllerInputSink methods */
212 input_sink_OnInputResumed
,
213 input_sink_OnInputSuspended
,
216 DEFINE_IINSPECTABLE_OUTER( raw_controller
, IRawGameController
, struct controller
, IGameController_outer
)
218 static HRESULT WINAPI
raw_controller_get_AxisCount( IRawGameController
*iface
, INT32
*value
)
220 struct controller
*impl
= impl_from_IRawGameController( iface
);
221 return IWineGameControllerProvider_get_AxisCount( impl
->wine_provider
, value
);
224 static HRESULT WINAPI
raw_controller_get_ButtonCount( IRawGameController
*iface
, INT32
*value
)
226 struct controller
*impl
= impl_from_IRawGameController( iface
);
227 return IWineGameControllerProvider_get_ButtonCount( impl
->wine_provider
, value
);
230 static HRESULT WINAPI
raw_controller_get_ForceFeedbackMotors( IRawGameController
*iface
, IVectorView_ForceFeedbackMotor
**value
)
232 static const struct vector_iids iids
=
234 .vector
= &IID_IVector_ForceFeedbackMotor
,
235 .view
= &IID_IVectorView_ForceFeedbackMotor
,
236 .iterable
= &IID_IIterable_ForceFeedbackMotor
,
237 .iterator
= &IID_IIterator_ForceFeedbackMotor
,
239 struct controller
*impl
= impl_from_IRawGameController( iface
);
240 IVector_ForceFeedbackMotor
*vector
;
241 IForceFeedbackMotor
*motor
;
244 TRACE( "iface %p, value %p\n", iface
, value
);
246 if (FAILED(hr
= vector_create( &iids
, (void **)&vector
))) return hr
;
248 if (SUCCEEDED(IWineGameControllerProvider_get_ForceFeedbackMotor( impl
->wine_provider
, &motor
)) && motor
)
250 hr
= IVector_ForceFeedbackMotor_Append( vector
, motor
);
251 IForceFeedbackMotor_Release( motor
);
254 if (SUCCEEDED(hr
)) hr
= IVector_ForceFeedbackMotor_GetView( vector
, value
);
255 IVector_ForceFeedbackMotor_Release( vector
);
260 static HRESULT WINAPI
raw_controller_get_HardwareProductId( IRawGameController
*iface
, UINT16
*value
)
262 struct controller
*impl
= impl_from_IRawGameController( iface
);
263 return IGameControllerProvider_get_HardwareProductId( impl
->provider
, value
);
266 static HRESULT WINAPI
raw_controller_get_HardwareVendorId( IRawGameController
*iface
, UINT16
*value
)
268 struct controller
*impl
= impl_from_IRawGameController( iface
);
269 return IGameControllerProvider_get_HardwareVendorId( impl
->provider
, value
);
272 static HRESULT WINAPI
raw_controller_get_SwitchCount( IRawGameController
*iface
, INT32
*value
)
274 struct controller
*impl
= impl_from_IRawGameController( iface
);
275 return IWineGameControllerProvider_get_SwitchCount( impl
->wine_provider
, value
);
278 static HRESULT WINAPI
raw_controller_GetButtonLabel( IRawGameController
*iface
, INT32 index
,
279 enum GameControllerButtonLabel
*value
)
281 FIXME( "iface %p, index %d, value %p stub!\n", iface
, index
, value
);
285 static HRESULT WINAPI
raw_controller_GetCurrentReading( IRawGameController
*iface
, UINT32 buttons_size
, BOOLEAN
*buttons
,
286 UINT32 switches_size
, enum GameControllerSwitchPosition
*switches
,
287 UINT32 axes_size
, DOUBLE
*axes
, UINT64
*timestamp
)
289 struct controller
*impl
= impl_from_IRawGameController( iface
);
290 WineGameControllerState state
;
293 TRACE( "iface %p, buttons_size %u, buttons %p, switches_size %u, switches %p, axes_size %u, axes %p, timestamp %p.\n",
294 iface
, buttons_size
, buttons
, switches_size
, switches
, axes_size
, axes
, timestamp
);
296 if (FAILED(hr
= IWineGameControllerProvider_get_State( impl
->wine_provider
, &state
))) return hr
;
298 memcpy( axes
, state
.axes
, axes_size
* sizeof(*axes
) );
299 memcpy( buttons
, state
.buttons
, buttons_size
* sizeof(*buttons
) );
300 memcpy( switches
, state
.switches
, switches_size
* sizeof(*switches
) );
301 *timestamp
= state
.timestamp
;
306 static HRESULT WINAPI
raw_controller_GetSwitchKind( IRawGameController
*iface
, INT32 index
, enum GameControllerSwitchKind
*value
)
308 FIXME( "iface %p, index %d, value %p stub!\n", iface
, index
, value
);
312 static const struct IRawGameControllerVtbl raw_controller_vtbl
=
314 raw_controller_QueryInterface
,
315 raw_controller_AddRef
,
316 raw_controller_Release
,
317 /* IInspectable methods */
318 raw_controller_GetIids
,
319 raw_controller_GetRuntimeClassName
,
320 raw_controller_GetTrustLevel
,
321 /* IRawGameController methods */
322 raw_controller_get_AxisCount
,
323 raw_controller_get_ButtonCount
,
324 raw_controller_get_ForceFeedbackMotors
,
325 raw_controller_get_HardwareProductId
,
326 raw_controller_get_HardwareVendorId
,
327 raw_controller_get_SwitchCount
,
328 raw_controller_GetButtonLabel
,
329 raw_controller_GetCurrentReading
,
330 raw_controller_GetSwitchKind
,
333 struct controller_statics
335 IActivationFactory IActivationFactory_iface
;
336 IRawGameControllerStatics IRawGameControllerStatics_iface
;
337 ICustomGameControllerFactory ICustomGameControllerFactory_iface
;
341 static inline struct controller_statics
*impl_from_IActivationFactory( IActivationFactory
*iface
)
343 return CONTAINING_RECORD( iface
, struct controller_statics
, IActivationFactory_iface
);
346 static HRESULT WINAPI
factory_QueryInterface( IActivationFactory
*iface
, REFIID iid
, void **out
)
348 struct controller_statics
*impl
= impl_from_IActivationFactory( iface
);
350 TRACE( "iface %p, iid %s, out %p.\n", iface
, debugstr_guid( iid
), out
);
352 if (IsEqualGUID( iid
, &IID_IUnknown
) ||
353 IsEqualGUID( iid
, &IID_IInspectable
) ||
354 IsEqualGUID( iid
, &IID_IAgileObject
) ||
355 IsEqualGUID( iid
, &IID_IActivationFactory
))
357 IInspectable_AddRef( (*out
= &impl
->IActivationFactory_iface
) );
361 if (IsEqualGUID( iid
, &IID_IRawGameControllerStatics
))
363 IInspectable_AddRef( (*out
= &impl
->IRawGameControllerStatics_iface
) );
367 if (IsEqualGUID( iid
, &IID_ICustomGameControllerFactory
))
369 IInspectable_AddRef( (*out
= &impl
->ICustomGameControllerFactory_iface
) );
373 FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid
) );
375 return E_NOINTERFACE
;
378 static ULONG WINAPI
factory_AddRef( IActivationFactory
*iface
)
380 struct controller_statics
*impl
= impl_from_IActivationFactory( iface
);
381 ULONG ref
= InterlockedIncrement( &impl
->ref
);
382 TRACE( "iface %p increasing refcount to %lu.\n", iface
, ref
);
386 static ULONG WINAPI
factory_Release( IActivationFactory
*iface
)
388 struct controller_statics
*impl
= impl_from_IActivationFactory( iface
);
389 ULONG ref
= InterlockedDecrement( &impl
->ref
);
390 TRACE( "iface %p decreasing refcount to %lu.\n", iface
, ref
);
394 static HRESULT WINAPI
factory_GetIids( IActivationFactory
*iface
, ULONG
*iid_count
, IID
**iids
)
396 FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface
, iid_count
, iids
);
400 static HRESULT WINAPI
factory_GetRuntimeClassName( IActivationFactory
*iface
, HSTRING
*class_name
)
402 FIXME( "iface %p, class_name %p stub!\n", iface
, class_name
);
406 static HRESULT WINAPI
factory_GetTrustLevel( IActivationFactory
*iface
, TrustLevel
*trust_level
)
408 FIXME( "iface %p, trust_level %p stub!\n", iface
, trust_level
);
412 static HRESULT WINAPI
factory_ActivateInstance( IActivationFactory
*iface
, IInspectable
**instance
)
414 FIXME( "iface %p, instance %p stub!\n", iface
, instance
);
418 static const struct IActivationFactoryVtbl factory_vtbl
=
420 factory_QueryInterface
,
423 /* IInspectable methods */
425 factory_GetRuntimeClassName
,
426 factory_GetTrustLevel
,
427 /* IActivationFactory methods */
428 factory_ActivateInstance
,
431 DEFINE_IINSPECTABLE( statics
, IRawGameControllerStatics
, struct controller_statics
, IActivationFactory_iface
)
433 static HRESULT WINAPI
statics_add_RawGameControllerAdded( IRawGameControllerStatics
*iface
,
434 IEventHandler_RawGameController
*handler
,
435 EventRegistrationToken
*token
)
437 TRACE( "iface %p, handler %p, token %p.\n", iface
, handler
, token
);
438 if (!handler
) return E_INVALIDARG
;
439 return event_handlers_append( &controller_added_handlers
, (IEventHandler_IInspectable
*)handler
, token
);
442 static HRESULT WINAPI
statics_remove_RawGameControllerAdded( IRawGameControllerStatics
*iface
, EventRegistrationToken token
)
444 TRACE( "iface %p, token %#I64x.\n", iface
, token
.value
);
445 return event_handlers_remove( &controller_added_handlers
, &token
);
448 static HRESULT WINAPI
statics_add_RawGameControllerRemoved( IRawGameControllerStatics
*iface
,
449 IEventHandler_RawGameController
*handler
,
450 EventRegistrationToken
*token
)
452 TRACE( "iface %p, handler %p, token %p.\n", iface
, handler
, token
);
453 if (!handler
) return E_INVALIDARG
;
454 return event_handlers_append( &controller_removed_handlers
, (IEventHandler_IInspectable
*)handler
, token
);
457 static HRESULT WINAPI
statics_remove_RawGameControllerRemoved( IRawGameControllerStatics
*iface
, EventRegistrationToken token
)
459 TRACE( "iface %p, token %#I64x.\n", iface
, token
.value
);
460 return event_handlers_remove( &controller_removed_handlers
, &token
);
463 static HRESULT WINAPI
statics_get_RawGameControllers( IRawGameControllerStatics
*iface
, IVectorView_RawGameController
**value
)
467 TRACE( "iface %p, value %p.\n", iface
, value
);
469 EnterCriticalSection( &controller_cs
);
470 if (SUCCEEDED(hr
= init_controllers()))
471 hr
= IVector_RawGameController_GetView( controllers
, value
);
472 LeaveCriticalSection( &controller_cs
);
477 static HRESULT WINAPI
statics_FromGameController( IRawGameControllerStatics
*iface
, IGameController
*game_controller
,
478 IRawGameController
**value
)
480 struct controller_statics
*impl
= impl_from_IRawGameControllerStatics( iface
);
481 IGameController
*controller
;
484 TRACE( "iface %p, game_controller %p, value %p.\n", iface
, game_controller
, value
);
487 hr
= IGameControllerFactoryManagerStatics2_TryGetFactoryControllerFromGameController( manager_factory
, &impl
->ICustomGameControllerFactory_iface
,
488 game_controller
, &controller
);
489 if (FAILED(hr
) || !controller
) return hr
;
491 hr
= IGameController_QueryInterface( controller
, &IID_IRawGameController
, (void **)value
);
492 IGameController_Release( controller
);
497 static const struct IRawGameControllerStaticsVtbl statics_vtbl
=
499 statics_QueryInterface
,
502 /* IInspectable methods */
504 statics_GetRuntimeClassName
,
505 statics_GetTrustLevel
,
506 /* IRawGameControllerStatics methods */
507 statics_add_RawGameControllerAdded
,
508 statics_remove_RawGameControllerAdded
,
509 statics_add_RawGameControllerRemoved
,
510 statics_remove_RawGameControllerRemoved
,
511 statics_get_RawGameControllers
,
512 statics_FromGameController
,
515 DEFINE_IINSPECTABLE( controller_factory
, ICustomGameControllerFactory
, struct controller_statics
, IActivationFactory_iface
)
517 static HRESULT WINAPI
controller_factory_CreateGameController( ICustomGameControllerFactory
*iface
, IGameControllerProvider
*provider
,
518 IInspectable
**value
)
520 struct controller
*impl
;
522 TRACE( "iface %p, provider %p, value %p.\n", iface
, provider
, value
);
524 if (!(impl
= calloc( 1, sizeof(*impl
) ))) return E_OUTOFMEMORY
;
525 impl
->IGameControllerImpl_iface
.lpVtbl
= &controller_vtbl
;
526 impl
->IGameControllerInputSink_iface
.lpVtbl
= &input_sink_vtbl
;
527 impl
->IRawGameController_iface
.lpVtbl
= &raw_controller_vtbl
;
530 TRACE( "created RawGameController %p\n", impl
);
532 *value
= (IInspectable
*)&impl
->IGameControllerImpl_iface
;
536 static HRESULT WINAPI
controller_factory_OnGameControllerAdded( ICustomGameControllerFactory
*iface
, IGameController
*value
)
538 IRawGameController
*controller
;
541 TRACE( "iface %p, value %p.\n", iface
, value
);
543 if (FAILED(hr
= IGameController_QueryInterface( value
, &IID_IRawGameController
, (void **)&controller
)))
545 event_handlers_notify( &controller_added_handlers
, (IInspectable
*)controller
);
546 IRawGameController_Release( controller
);
551 static HRESULT WINAPI
controller_factory_OnGameControllerRemoved( ICustomGameControllerFactory
*iface
, IGameController
*value
)
553 IRawGameController
*controller
;
558 TRACE( "iface %p, value %p.\n", iface
, value
);
560 if (FAILED(hr
= IGameController_QueryInterface( value
, &IID_IRawGameController
, (void **)&controller
)))
563 EnterCriticalSection( &controller_cs
);
564 if (SUCCEEDED(hr
= init_controllers()))
566 if (FAILED(hr
= IVector_RawGameController_IndexOf( controllers
, controller
, &index
, &found
)) || !found
)
567 WARN( "Could not find controller %p, hr %#lx!\n", controller
, hr
);
569 hr
= IVector_RawGameController_RemoveAt( controllers
, index
);
571 LeaveCriticalSection( &controller_cs
);
574 WARN( "Failed to remove controller %p, hr %#lx!\n", controller
, hr
);
577 TRACE( "Removed controller %p.\n", controller
);
578 event_handlers_notify( &controller_removed_handlers
, (IInspectable
*)controller
);
580 IRawGameController_Release( controller
);
585 static const struct ICustomGameControllerFactoryVtbl controller_factory_vtbl
=
587 controller_factory_QueryInterface
,
588 controller_factory_AddRef
,
589 controller_factory_Release
,
590 /* IInspectable methods */
591 controller_factory_GetIids
,
592 controller_factory_GetRuntimeClassName
,
593 controller_factory_GetTrustLevel
,
594 /* ICustomGameControllerFactory methods */
595 controller_factory_CreateGameController
,
596 controller_factory_OnGameControllerAdded
,
597 controller_factory_OnGameControllerRemoved
,
600 static struct controller_statics controller_statics
=
604 {&controller_factory_vtbl
},
608 ICustomGameControllerFactory
*controller_factory
= &controller_statics
.ICustomGameControllerFactory_iface
;