[PATCH v2 2/6] windows.gaming.input: Implement IGamepadStatics_get_Gamepads.

Rémi Bernon rbernon at codeweavers.com
Thu Mar 10 06:05:48 CST 2022


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/dinput/tests/joystick8.c       |  1 +
 dlls/windows.gaming.input/gamepad.c | 82 +++++++++++++++++++++++------
 2 files changed, 68 insertions(+), 15 deletions(-)

diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c
index e74e76482f9..c4cfceeee3e 100644
--- a/dlls/dinput/tests/joystick8.c
+++ b/dlls/dinput/tests/joystick8.c
@@ -3356,6 +3356,7 @@ static void test_windows_gaming_input(void)
     ok( hr == S_OK, "get_Gamepads returned %#lx\n", hr );
     hr = IVectorView_Gamepad_get_Size( gamepads_view, &size );
     ok( hr == S_OK, "get_Size returned %#lx\n", hr );
+    todo_wine /* but Wine currently intentionally does */
     ok( size == 0, "got size %u\n", size );
     IVectorView_Gamepad_Release( gamepads_view );
     IGamepadStatics_Release( gamepad_statics );
diff --git a/dlls/windows.gaming.input/gamepad.c b/dlls/windows.gaming.input/gamepad.c
index 172ca74e3f6..70c9f4cd792 100644
--- a/dlls/windows.gaming.input/gamepad.c
+++ b/dlls/windows.gaming.input/gamepad.c
@@ -24,6 +24,36 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(input);
 
+static CRITICAL_SECTION gamepad_cs;
+static CRITICAL_SECTION_DEBUG gamepad_cs_debug =
+{
+    0, 0, &gamepad_cs,
+    { &gamepad_cs_debug.ProcessLocksList, &gamepad_cs_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": gamepad_cs") }
+};
+static CRITICAL_SECTION gamepad_cs = { &gamepad_cs_debug, -1, 0, 0, 0, 0 };
+
+static IVector_Gamepad *gamepads;
+
+static HRESULT init_gamepads(void)
+{
+    static const struct vector_iids iids =
+    {
+        .vector = &IID_IVector_Gamepad,
+        .view = &IID_IVectorView_Gamepad,
+        .iterable = &IID_IIterable_Gamepad,
+        .iterator = &IID_IIterator_Gamepad,
+    };
+    HRESULT hr;
+
+    EnterCriticalSection( &gamepad_cs );
+    if (gamepads) hr = S_OK;
+    else hr = vector_create( &iids, (void **)&gamepads );
+    LeaveCriticalSection( &gamepad_cs );
+
+    return hr;
+}
+
 struct gamepad
 {
     IGameControllerImpl IGameControllerImpl_iface;
@@ -118,13 +148,19 @@ static HRESULT WINAPI controller_Initialize( IGameControllerImpl *iface, IGameCo
                                              IGameControllerProvider *provider )
 {
     struct gamepad *impl = impl_from_IGameControllerImpl( iface );
+    HRESULT hr;
 
     TRACE( "iface %p, outer %p, provider %p.\n", iface, outer, provider );
 
     impl->IGameController_outer = outer;
     IGameControllerProvider_AddRef( (impl->provider = provider) );
 
-    return S_OK;
+    EnterCriticalSection( &gamepad_cs );
+    if (SUCCEEDED(hr = init_gamepads()))
+        hr = IVector_Gamepad_Append( gamepads, &impl->IGamepad_iface );
+    LeaveCriticalSection( &gamepad_cs );
+
+    return hr;
 }
 
 static const struct IGameControllerImplVtbl controller_vtbl =
@@ -341,23 +377,14 @@ static HRESULT WINAPI statics_remove_GamepadRemoved( IGamepadStatics *iface, Eve
 
 static HRESULT WINAPI statics_get_Gamepads( IGamepadStatics *iface, IVectorView_Gamepad **value )
 {
-    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( &iids, (void **)&gamepads )))
-    {
+    EnterCriticalSection( &gamepad_cs );
+    if (SUCCEEDED(hr = init_gamepads()))
         hr = IVector_Gamepad_GetView( gamepads, value );
-        IVector_Gamepad_Release( gamepads );
-    }
+    LeaveCriticalSection( &gamepad_cs );
 
     return hr;
 }
@@ -440,8 +467,33 @@ static HRESULT WINAPI controller_factory_OnGameControllerAdded( ICustomGameContr
 
 static HRESULT WINAPI controller_factory_OnGameControllerRemoved( ICustomGameControllerFactory *iface, IGameController *value )
 {
-    FIXME( "iface %p, value %p stub!\n", iface, value );
-    return E_NOTIMPL;
+    IGamepad *gamepad;
+    BOOLEAN found;
+    UINT32 index;
+    HRESULT hr;
+
+    TRACE( "iface %p, value %p.\n", iface, value );
+
+    if (FAILED(hr = IGameController_QueryInterface( value, &IID_IGamepad, (void **)&gamepad )))
+        return hr;
+
+    EnterCriticalSection( &gamepad_cs );
+    if (SUCCEEDED(hr = init_gamepads()))
+    {
+        if (FAILED(hr = IVector_Gamepad_IndexOf( gamepads, gamepad, &index, &found )) || !found)
+            WARN( "Could not find gamepad %p, hr %#lx!\n", gamepad, hr );
+        else
+            hr = IVector_Gamepad_RemoveAt( gamepads, index );
+    }
+    LeaveCriticalSection( &gamepad_cs );
+
+    if (FAILED(hr))
+        WARN( "Failed to remove gamepad %p, hr %#lx!\n", gamepad, hr );
+    else if (found)
+        TRACE( "Removed gamepad %p.\n", gamepad );
+    IGamepad_Release( gamepad );
+
+    return S_OK;
 }
 
 static const struct ICustomGameControllerFactoryVtbl controller_factory_vtbl =
-- 
2.35.1




More information about the wine-devel mailing list