windows.gaming.input: Implement Controller(Added|Removed) event support.
Using a generic EventHandler<IInspectable *> implementation. This adds several todo_wine because we currently do not implement custom game controller factories. Signed-off-by: Rémi Bernon <rbernon@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e609c640a2
commit
1e9b83a440
|
@ -927,6 +927,7 @@ static LRESULT CALLBACK windows_gaming_input_wndproc( HWND hwnd, UINT msg, WPARA
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ok( wparam == DBT_DEVICEARRIVAL, "got wparam %#Ix\n", wparam );
|
ok( wparam == DBT_DEVICEARRIVAL, "got wparam %#Ix\n", wparam );
|
||||||
|
todo_wine /* Wine currently listens to WINEXINPUT device arrival, which is received earlier than HID */
|
||||||
ok( !controller_added.invoked, "controller added handler not invoked\n" );
|
ok( !controller_added.invoked, "controller added handler not invoked\n" );
|
||||||
ok( !controller_removed.invoked, "controller removed handler invoked\n" );
|
ok( !controller_removed.invoked, "controller removed handler invoked\n" );
|
||||||
}
|
}
|
||||||
|
@ -967,6 +968,7 @@ static void test_windows_gaming_input(void)
|
||||||
HSTRING str;
|
HSTRING str;
|
||||||
UINT32 size;
|
UINT32 size;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
DWORD ret;
|
||||||
MSG msg;
|
MSG msg;
|
||||||
|
|
||||||
if (!load_combase_functions()) return;
|
if (!load_combase_functions()) return;
|
||||||
|
@ -1007,9 +1009,7 @@ static void test_windows_gaming_input(void)
|
||||||
hr = IRawGameControllerStatics_add_RawGameControllerAdded( statics, &controller_added.IEventHandler_RawGameController_iface,
|
hr = IRawGameControllerStatics_add_RawGameControllerAdded( statics, &controller_added.IEventHandler_RawGameController_iface,
|
||||||
&controller_added_token );
|
&controller_added_token );
|
||||||
ok( hr == S_OK, "add_RawGameControllerAdded returned %#lx\n", hr );
|
ok( hr == S_OK, "add_RawGameControllerAdded returned %#lx\n", hr );
|
||||||
todo_wine
|
|
||||||
ok( controller_added_token.value, "got token %I64u\n", controller_added_token.value );
|
ok( controller_added_token.value, "got token %I64u\n", controller_added_token.value );
|
||||||
if (!controller_added_token.value) return;
|
|
||||||
|
|
||||||
hr = IRawGameControllerStatics_add_RawGameControllerRemoved( statics, &controller_removed.IEventHandler_RawGameController_iface,
|
hr = IRawGameControllerStatics_add_RawGameControllerRemoved( statics, &controller_removed.IEventHandler_RawGameController_iface,
|
||||||
&controller_removed_token );
|
&controller_removed_token );
|
||||||
|
@ -1038,6 +1038,7 @@ static void test_windows_gaming_input(void)
|
||||||
|
|
||||||
ok( controller_added.invoked, "controller added handler not invoked\n" );
|
ok( controller_added.invoked, "controller added handler not invoked\n" );
|
||||||
ok( !controller_removed.invoked, "controller removed handler invoked\n" );
|
ok( !controller_removed.invoked, "controller removed handler invoked\n" );
|
||||||
|
todo_wine
|
||||||
ok( custom_factory.create_controller_called, "CreateGameController not called\n" );
|
ok( custom_factory.create_controller_called, "CreateGameController not called\n" );
|
||||||
|
|
||||||
hr = IVectorView_RawGameController_get_Size( controller_view, &size );
|
hr = IVectorView_RawGameController_get_Size( controller_view, &size );
|
||||||
|
@ -1058,6 +1059,7 @@ static void test_windows_gaming_input(void)
|
||||||
|
|
||||||
hr = IGameControllerFactoryManagerStatics2_TryGetFactoryControllerFromGameController( manager_statics2,
|
hr = IGameControllerFactoryManagerStatics2_TryGetFactoryControllerFromGameController( manager_statics2,
|
||||||
&custom_factory.ICustomGameControllerFactory_iface, game_controller, &tmp_game_controller );
|
&custom_factory.ICustomGameControllerFactory_iface, game_controller, &tmp_game_controller );
|
||||||
|
todo_wine
|
||||||
ok( hr == S_OK, "TryGetFactoryControllerFromGameController returned %#lx\n", hr );
|
ok( hr == S_OK, "TryGetFactoryControllerFromGameController returned %#lx\n", hr );
|
||||||
ok( !tmp_game_controller, "got controller %p\n", tmp_game_controller );
|
ok( !tmp_game_controller, "got controller %p\n", tmp_game_controller );
|
||||||
|
|
||||||
|
@ -1111,7 +1113,9 @@ static void test_windows_gaming_input(void)
|
||||||
thread = CreateThread( NULL, 0, dinput_test_device_thread, stop_event, 0, NULL );
|
thread = CreateThread( NULL, 0, dinput_test_device_thread, stop_event, 0, NULL );
|
||||||
ok( !!thread, "CreateThread failed, error %lu\n", GetLastError() );
|
ok( !!thread, "CreateThread failed, error %lu\n", GetLastError() );
|
||||||
wait_for_events( 1, &controller_added.event, INFINITE );
|
wait_for_events( 1, &controller_added.event, INFINITE );
|
||||||
wait_for_events( 1, &custom_factory.added_event, INFINITE );
|
ret = wait_for_events( 1, &custom_factory.added_event, 500 );
|
||||||
|
todo_wine
|
||||||
|
ok( !ret, "wait_for_events returned %#lx\n", ret );
|
||||||
hr = IRawGameControllerStatics_get_RawGameControllers( statics, &controller_view );
|
hr = IRawGameControllerStatics_get_RawGameControllers( statics, &controller_view );
|
||||||
ok( hr == S_OK, "get_RawGameControllers returned %#lx\n", hr );
|
ok( hr == S_OK, "get_RawGameControllers returned %#lx\n", hr );
|
||||||
hr = IVectorView_RawGameController_GetAt( controller_view, 0, &raw_controller );
|
hr = IVectorView_RawGameController_GetAt( controller_view, 0, &raw_controller );
|
||||||
|
@ -1122,8 +1126,10 @@ static void test_windows_gaming_input(void)
|
||||||
|
|
||||||
hr = IGameControllerFactoryManagerStatics2_TryGetFactoryControllerFromGameController( manager_statics2,
|
hr = IGameControllerFactoryManagerStatics2_TryGetFactoryControllerFromGameController( manager_statics2,
|
||||||
&custom_factory.ICustomGameControllerFactory_iface, game_controller, &tmp_game_controller );
|
&custom_factory.ICustomGameControllerFactory_iface, game_controller, &tmp_game_controller );
|
||||||
|
todo_wine
|
||||||
ok( hr == S_OK, "TryGetFactoryControllerFromGameController returned %#lx\n", hr );
|
ok( hr == S_OK, "TryGetFactoryControllerFromGameController returned %#lx\n", hr );
|
||||||
ok( tmp_game_controller == custom_controller.IGameController_outer, "got controller %p\n", tmp_game_controller );
|
ok( tmp_game_controller == custom_controller.IGameController_outer, "got controller %p\n", tmp_game_controller );
|
||||||
|
if (hr != S_OK) goto next;
|
||||||
hr = IGameController_QueryInterface( tmp_game_controller, &IID_IInspectable, (void **)&tmp_inspectable );
|
hr = IGameController_QueryInterface( tmp_game_controller, &IID_IInspectable, (void **)&tmp_inspectable );
|
||||||
ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
|
ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
|
||||||
ok( tmp_inspectable == (void *)tmp_game_controller, "got inspectable %p\n", tmp_inspectable );
|
ok( tmp_inspectable == (void *)tmp_game_controller, "got inspectable %p\n", tmp_inspectable );
|
||||||
|
@ -1145,15 +1151,20 @@ static void test_windows_gaming_input(void)
|
||||||
|
|
||||||
IGameController_Release( tmp_game_controller );
|
IGameController_Release( tmp_game_controller );
|
||||||
|
|
||||||
|
next:
|
||||||
hr = IRawGameControllerStatics_FromGameController( statics, custom_controller.IGameController_outer, &tmp_raw_controller );
|
hr = IRawGameControllerStatics_FromGameController( statics, custom_controller.IGameController_outer, &tmp_raw_controller );
|
||||||
|
todo_wine
|
||||||
ok( hr == S_OK, "FromGameController returned %#lx\n", hr );
|
ok( hr == S_OK, "FromGameController returned %#lx\n", hr );
|
||||||
|
todo_wine
|
||||||
ok( tmp_raw_controller == raw_controller, "got controller %p\n", tmp_raw_controller );
|
ok( tmp_raw_controller == raw_controller, "got controller %p\n", tmp_raw_controller );
|
||||||
IRawGameController_Release( tmp_raw_controller );
|
if (hr == S_OK) IRawGameController_Release( tmp_raw_controller );
|
||||||
|
|
||||||
IGameController_Release( game_controller );
|
IGameController_Release( game_controller );
|
||||||
IRawGameController_Release( raw_controller );
|
IRawGameController_Release( raw_controller );
|
||||||
SetEvent( stop_event );
|
SetEvent( stop_event );
|
||||||
wait_for_events( 1, &custom_factory.removed_event, INFINITE );
|
ret = wait_for_events( 1, &custom_factory.removed_event, 500 );
|
||||||
|
todo_wine
|
||||||
|
ok( !ret, "wait_for_events returned %#lx\n", ret );
|
||||||
wait_for_events( 1, &controller_removed.event, INFINITE );
|
wait_for_events( 1, &controller_removed.event, INFINITE );
|
||||||
|
|
||||||
hr = IRawGameControllerStatics_remove_RawGameControllerAdded( statics, controller_added_token );
|
hr = IRawGameControllerStatics_remove_RawGameControllerAdded( statics, controller_added_token );
|
||||||
|
|
|
@ -3,6 +3,7 @@ IMPORTS = combase uuid user32 dinput8 setupapi hid
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
controller.c \
|
controller.c \
|
||||||
|
event_handlers.c \
|
||||||
gamepad.c \
|
gamepad.c \
|
||||||
main.c \
|
main.c \
|
||||||
manager.c \
|
manager.c \
|
||||||
|
|
|
@ -34,6 +34,8 @@ static CRITICAL_SECTION_DEBUG controller_cs_debug =
|
||||||
static CRITICAL_SECTION controller_cs = { &controller_cs_debug, -1, 0, 0, 0, 0 };
|
static CRITICAL_SECTION controller_cs = { &controller_cs_debug, -1, 0, 0, 0, 0 };
|
||||||
|
|
||||||
static IVector_RawGameController *controllers;
|
static IVector_RawGameController *controllers;
|
||||||
|
static struct list controller_added_handlers = LIST_INIT( controller_added_handlers );
|
||||||
|
static struct list controller_removed_handlers = LIST_INIT( controller_removed_handlers );
|
||||||
|
|
||||||
static HRESULT init_controllers(void)
|
static HRESULT init_controllers(void)
|
||||||
{
|
{
|
||||||
|
@ -385,34 +387,34 @@ static const struct IActivationFactoryVtbl factory_vtbl =
|
||||||
|
|
||||||
DEFINE_IINSPECTABLE( statics, IRawGameControllerStatics, struct controller_statics, IActivationFactory_iface )
|
DEFINE_IINSPECTABLE( statics, IRawGameControllerStatics, struct controller_statics, IActivationFactory_iface )
|
||||||
|
|
||||||
static HRESULT WINAPI statics_add_RawGameControllerAdded( IRawGameControllerStatics *iface, IEventHandler_RawGameController *value,
|
static HRESULT WINAPI statics_add_RawGameControllerAdded( IRawGameControllerStatics *iface,
|
||||||
|
IEventHandler_RawGameController *handler,
|
||||||
EventRegistrationToken *token )
|
EventRegistrationToken *token )
|
||||||
{
|
{
|
||||||
FIXME( "iface %p, value %p, token %p stub!\n", iface, value, token );
|
TRACE( "iface %p, handler %p, token %p.\n", iface, handler, token );
|
||||||
if (!value) return E_INVALIDARG;
|
if (!handler) return E_INVALIDARG;
|
||||||
token->value = 0;
|
return event_handlers_append( &controller_added_handlers, (IEventHandler_IInspectable *)handler, token );
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI statics_remove_RawGameControllerAdded( IRawGameControllerStatics *iface, EventRegistrationToken token )
|
static HRESULT WINAPI statics_remove_RawGameControllerAdded( IRawGameControllerStatics *iface, EventRegistrationToken token )
|
||||||
{
|
{
|
||||||
FIXME( "iface %p, token %#I64x stub!\n", iface, token.value );
|
TRACE( "iface %p, token %#I64x.\n", iface, token.value );
|
||||||
return S_OK;
|
return event_handlers_remove( &controller_added_handlers, &token );
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI statics_add_RawGameControllerRemoved( IRawGameControllerStatics *iface, IEventHandler_RawGameController *value,
|
static HRESULT WINAPI statics_add_RawGameControllerRemoved( IRawGameControllerStatics *iface,
|
||||||
|
IEventHandler_RawGameController *handler,
|
||||||
EventRegistrationToken *token )
|
EventRegistrationToken *token )
|
||||||
{
|
{
|
||||||
FIXME( "iface %p, value %p, token %p stub!\n", iface, value, token );
|
TRACE( "iface %p, handler %p, token %p.\n", iface, handler, token );
|
||||||
if (!value) return E_INVALIDARG;
|
if (!handler) return E_INVALIDARG;
|
||||||
token->value = 0;
|
return event_handlers_append( &controller_removed_handlers, (IEventHandler_IInspectable *)handler, token );
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI statics_remove_RawGameControllerRemoved( IRawGameControllerStatics *iface, EventRegistrationToken token )
|
static HRESULT WINAPI statics_remove_RawGameControllerRemoved( IRawGameControllerStatics *iface, EventRegistrationToken token )
|
||||||
{
|
{
|
||||||
FIXME( "iface %p, token %#I64x stub!\n", iface, token.value );
|
TRACE( "iface %p, token %#I64x.\n", iface, token.value );
|
||||||
return S_OK;
|
return event_handlers_remove( &controller_removed_handlers, &token );
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI statics_get_RawGameControllers( IRawGameControllerStatics *iface, IVectorView_RawGameController **value )
|
static HRESULT WINAPI statics_get_RawGameControllers( IRawGameControllerStatics *iface, IVectorView_RawGameController **value )
|
||||||
|
@ -489,8 +491,17 @@ static HRESULT WINAPI controller_factory_CreateGameController( ICustomGameContro
|
||||||
|
|
||||||
static HRESULT WINAPI controller_factory_OnGameControllerAdded( ICustomGameControllerFactory *iface, IGameController *value )
|
static HRESULT WINAPI controller_factory_OnGameControllerAdded( ICustomGameControllerFactory *iface, IGameController *value )
|
||||||
{
|
{
|
||||||
FIXME( "iface %p, value %p stub!\n", iface, value );
|
IRawGameController *controller;
|
||||||
return E_NOTIMPL;
|
HRESULT hr;
|
||||||
|
|
||||||
|
TRACE( "iface %p, value %p.\n", iface, value );
|
||||||
|
|
||||||
|
if (FAILED(hr = IGameController_QueryInterface( value, &IID_IRawGameController, (void **)&controller )))
|
||||||
|
return hr;
|
||||||
|
event_handlers_notify( &controller_added_handlers, (IInspectable *)controller );
|
||||||
|
IRawGameController_Release( controller );
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI controller_factory_OnGameControllerRemoved( ICustomGameControllerFactory *iface, IGameController *value )
|
static HRESULT WINAPI controller_factory_OnGameControllerRemoved( ICustomGameControllerFactory *iface, IGameController *value )
|
||||||
|
@ -518,7 +529,10 @@ static HRESULT WINAPI controller_factory_OnGameControllerRemoved( ICustomGameCon
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
WARN( "Failed to remove controller %p, hr %#lx!\n", controller, hr );
|
WARN( "Failed to remove controller %p, hr %#lx!\n", controller, hr );
|
||||||
else if (found)
|
else if (found)
|
||||||
|
{
|
||||||
TRACE( "Removed controller %p.\n", controller );
|
TRACE( "Removed controller %p.\n", controller );
|
||||||
|
event_handlers_notify( &controller_removed_handlers, (IInspectable *)controller );
|
||||||
|
}
|
||||||
IRawGameController_Release( controller );
|
IRawGameController_Release( controller );
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
/* WinRT Windows.Gaming.Input implementation
|
||||||
|
*
|
||||||
|
* Copyright 2022 Rémi Bernon for CodeWeavers
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
static CRITICAL_SECTION handlers_cs;
|
||||||
|
static CRITICAL_SECTION_DEBUG handlers_cs_debug =
|
||||||
|
{
|
||||||
|
0, 0, &handlers_cs,
|
||||||
|
{ &handlers_cs_debug.ProcessLocksList, &handlers_cs_debug.ProcessLocksList },
|
||||||
|
0, 0, { (DWORD_PTR)(__FILE__ ": handlers_cs") }
|
||||||
|
};
|
||||||
|
static CRITICAL_SECTION handlers_cs = { &handlers_cs_debug, -1, 0, 0, 0, 0 };
|
||||||
|
static EventRegistrationToken next_token = {.value = 1};
|
||||||
|
|
||||||
|
struct handler_entry
|
||||||
|
{
|
||||||
|
struct list entry;
|
||||||
|
EventRegistrationToken token;
|
||||||
|
IEventHandler_IInspectable *handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT event_handlers_append( struct list *list, IEventHandler_IInspectable *handler, EventRegistrationToken *token )
|
||||||
|
{
|
||||||
|
struct handler_entry *entry;
|
||||||
|
|
||||||
|
if (!(entry = calloc( 1, sizeof(*entry) ))) return E_OUTOFMEMORY;
|
||||||
|
IEventHandler_IInspectable_AddRef( (entry->handler = handler) );
|
||||||
|
|
||||||
|
EnterCriticalSection( &handlers_cs );
|
||||||
|
|
||||||
|
*token = entry->token = next_token;
|
||||||
|
next_token.value++;
|
||||||
|
list_add_tail( list, &entry->entry );
|
||||||
|
|
||||||
|
LeaveCriticalSection( &handlers_cs );
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT event_handlers_remove( struct list *list, EventRegistrationToken *token )
|
||||||
|
{
|
||||||
|
struct handler_entry *entry;
|
||||||
|
BOOL found = FALSE;
|
||||||
|
|
||||||
|
EnterCriticalSection( &handlers_cs );
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY( entry, list, struct handler_entry, entry )
|
||||||
|
if ((found = !memcmp( &entry->token, token, sizeof(*token) ))) break;
|
||||||
|
if (found) list_remove( &entry->entry );
|
||||||
|
|
||||||
|
LeaveCriticalSection( &handlers_cs );
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
IEventHandler_IInspectable_Release( entry->handler );
|
||||||
|
free( entry );
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void event_handlers_notify( struct list *list, IInspectable *element )
|
||||||
|
{
|
||||||
|
struct handler_entry *entry;
|
||||||
|
|
||||||
|
EnterCriticalSection( &handlers_cs );
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY( entry, list, struct handler_entry, entry )
|
||||||
|
IEventHandler_IInspectable_Invoke( entry->handler, NULL, element );
|
||||||
|
|
||||||
|
LeaveCriticalSection( &handlers_cs );
|
||||||
|
}
|
|
@ -34,6 +34,8 @@ static CRITICAL_SECTION_DEBUG gamepad_cs_debug =
|
||||||
static CRITICAL_SECTION gamepad_cs = { &gamepad_cs_debug, -1, 0, 0, 0, 0 };
|
static CRITICAL_SECTION gamepad_cs = { &gamepad_cs_debug, -1, 0, 0, 0, 0 };
|
||||||
|
|
||||||
static IVector_Gamepad *gamepads;
|
static IVector_Gamepad *gamepads;
|
||||||
|
static struct list gamepad_added_handlers = LIST_INIT( gamepad_added_handlers );
|
||||||
|
static struct list gamepad_removed_handlers = LIST_INIT( gamepad_removed_handlers );
|
||||||
|
|
||||||
static HRESULT init_gamepads(void)
|
static HRESULT init_gamepads(void)
|
||||||
{
|
{
|
||||||
|
@ -345,34 +347,32 @@ static const struct IActivationFactoryVtbl factory_vtbl =
|
||||||
|
|
||||||
DEFINE_IINSPECTABLE( statics, IGamepadStatics, struct gamepad_statics, IActivationFactory_iface )
|
DEFINE_IINSPECTABLE( statics, IGamepadStatics, struct gamepad_statics, IActivationFactory_iface )
|
||||||
|
|
||||||
static HRESULT WINAPI statics_add_GamepadAdded( IGamepadStatics *iface, IEventHandler_Gamepad *value,
|
static HRESULT WINAPI statics_add_GamepadAdded( IGamepadStatics *iface, IEventHandler_Gamepad *handler,
|
||||||
EventRegistrationToken *token )
|
EventRegistrationToken *token )
|
||||||
{
|
{
|
||||||
FIXME( "iface %p, value %p, token %p stub!\n", iface, value, token );
|
TRACE( "iface %p, handler %p, token %p.\n", iface, handler, token );
|
||||||
if (!value) return E_INVALIDARG;
|
if (!handler) return E_INVALIDARG;
|
||||||
token->value = 0;
|
return event_handlers_append( &gamepad_added_handlers, (IEventHandler_IInspectable *)handler, token );
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI statics_remove_GamepadAdded( IGamepadStatics *iface, EventRegistrationToken token )
|
static HRESULT WINAPI statics_remove_GamepadAdded( IGamepadStatics *iface, EventRegistrationToken token )
|
||||||
{
|
{
|
||||||
FIXME( "iface %p, token %#I64x stub!\n", iface, token.value );
|
TRACE( "iface %p, token %#I64x.\n", iface, token.value );
|
||||||
return S_OK;
|
return event_handlers_remove( &gamepad_added_handlers, &token );
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI statics_add_GamepadRemoved( IGamepadStatics *iface, IEventHandler_Gamepad *value,
|
static HRESULT WINAPI statics_add_GamepadRemoved( IGamepadStatics *iface, IEventHandler_Gamepad *handler,
|
||||||
EventRegistrationToken *token )
|
EventRegistrationToken *token )
|
||||||
{
|
{
|
||||||
FIXME( "iface %p, value %p, token %p stub!\n", iface, value, token );
|
TRACE( "iface %p, handler %p, token %p.\n", iface, handler, token );
|
||||||
if (!value) return E_INVALIDARG;
|
if (!handler) return E_INVALIDARG;
|
||||||
token->value = 0;
|
return event_handlers_append( &gamepad_removed_handlers, (IEventHandler_IInspectable *)handler, token );
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI statics_remove_GamepadRemoved( IGamepadStatics *iface, EventRegistrationToken token )
|
static HRESULT WINAPI statics_remove_GamepadRemoved( IGamepadStatics *iface, EventRegistrationToken token )
|
||||||
{
|
{
|
||||||
FIXME( "iface %p, token %#I64x stub!\n", iface, token.value );
|
TRACE( "iface %p, token %#I64x.\n", iface, token.value );
|
||||||
return S_OK;
|
return event_handlers_remove( &gamepad_removed_handlers, &token );
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI statics_get_Gamepads( IGamepadStatics *iface, IVectorView_Gamepad **value )
|
static HRESULT WINAPI statics_get_Gamepads( IGamepadStatics *iface, IVectorView_Gamepad **value )
|
||||||
|
@ -461,8 +461,17 @@ static HRESULT WINAPI controller_factory_CreateGameController( ICustomGameContro
|
||||||
|
|
||||||
static HRESULT WINAPI controller_factory_OnGameControllerAdded( ICustomGameControllerFactory *iface, IGameController *value )
|
static HRESULT WINAPI controller_factory_OnGameControllerAdded( ICustomGameControllerFactory *iface, IGameController *value )
|
||||||
{
|
{
|
||||||
FIXME( "iface %p, value %p stub!\n", iface, value );
|
IGamepad *gamepad;
|
||||||
return E_NOTIMPL;
|
HRESULT hr;
|
||||||
|
|
||||||
|
TRACE( "iface %p, value %p.\n", iface, value );
|
||||||
|
|
||||||
|
if (FAILED(hr = IGameController_QueryInterface( value, &IID_IGamepad, (void **)&gamepad )))
|
||||||
|
return hr;
|
||||||
|
event_handlers_notify( &gamepad_added_handlers, (IInspectable *)gamepad );
|
||||||
|
IGamepad_Release( gamepad );
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI controller_factory_OnGameControllerRemoved( ICustomGameControllerFactory *iface, IGameController *value )
|
static HRESULT WINAPI controller_factory_OnGameControllerRemoved( ICustomGameControllerFactory *iface, IGameController *value )
|
||||||
|
@ -490,7 +499,10 @@ static HRESULT WINAPI controller_factory_OnGameControllerRemoved( ICustomGameCon
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
WARN( "Failed to remove gamepad %p, hr %#lx!\n", gamepad, hr );
|
WARN( "Failed to remove gamepad %p, hr %#lx!\n", gamepad, hr );
|
||||||
else if (found)
|
else if (found)
|
||||||
|
{
|
||||||
TRACE( "Removed gamepad %p.\n", gamepad );
|
TRACE( "Removed gamepad %p.\n", gamepad );
|
||||||
|
event_handlers_notify( &gamepad_removed_handlers, (IInspectable *)gamepad );
|
||||||
|
}
|
||||||
IGamepad_Release( gamepad );
|
IGamepad_Release( gamepad );
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "provider.h"
|
#include "provider.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "wine/list.h"
|
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(input);
|
WINE_DEFAULT_DEBUG_CHANNEL(input);
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,8 @@
|
||||||
#define WIDL_using_Windows_Gaming_Input_Custom
|
#define WIDL_using_Windows_Gaming_Input_Custom
|
||||||
#include "windows.gaming.input.custom.h"
|
#include "windows.gaming.input.custom.h"
|
||||||
|
|
||||||
|
#include "wine/list.h"
|
||||||
|
|
||||||
extern HINSTANCE windows_gaming_input;
|
extern HINSTANCE windows_gaming_input;
|
||||||
extern ICustomGameControllerFactory *controller_factory;
|
extern ICustomGameControllerFactory *controller_factory;
|
||||||
extern ICustomGameControllerFactory *gamepad_factory;
|
extern ICustomGameControllerFactory *gamepad_factory;
|
||||||
|
@ -56,6 +58,10 @@ extern void provider_remove( const WCHAR *device_path );
|
||||||
extern void manager_on_provider_created( IGameControllerProvider *provider );
|
extern void manager_on_provider_created( IGameControllerProvider *provider );
|
||||||
extern void manager_on_provider_removed( IGameControllerProvider *provider );
|
extern void manager_on_provider_removed( IGameControllerProvider *provider );
|
||||||
|
|
||||||
|
extern HRESULT event_handlers_append( struct list *list, IEventHandler_IInspectable *handler, EventRegistrationToken *token );
|
||||||
|
extern HRESULT event_handlers_remove( struct list *list, EventRegistrationToken *token );
|
||||||
|
extern void event_handlers_notify( struct list *list, IInspectable *element );
|
||||||
|
|
||||||
#define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \
|
#define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \
|
||||||
static inline impl_type *impl_from( iface_type *iface ) \
|
static inline impl_type *impl_from( iface_type *iface ) \
|
||||||
{ \
|
{ \
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "provider.h"
|
#include "provider.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "wine/list.h"
|
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(input);
|
WINE_DEFAULT_DEBUG_CHANNEL(input);
|
||||||
|
|
||||||
|
|
|
@ -167,6 +167,7 @@ namespace Windows {
|
||||||
interface Windows.Foundation.Collections.IVector<HSTRING>;
|
interface Windows.Foundation.Collections.IVector<HSTRING>;
|
||||||
interface Windows.Foundation.Collections.IVector<IInspectable *>;
|
interface Windows.Foundation.Collections.IVector<IInspectable *>;
|
||||||
interface Windows.Foundation.Collections.IMapView<HSTRING, Windows.Foundation.Collections.IVectorView<HSTRING>*>;
|
interface Windows.Foundation.Collections.IMapView<HSTRING, Windows.Foundation.Collections.IVectorView<HSTRING>*>;
|
||||||
|
interface Windows.Foundation.EventHandler<IInspectable *>;
|
||||||
interface Windows.Foundation.AsyncOperationCompletedHandler<boolean>;
|
interface Windows.Foundation.AsyncOperationCompletedHandler<boolean>;
|
||||||
interface Windows.Foundation.IAsyncOperation<boolean>;
|
interface Windows.Foundation.IAsyncOperation<boolean>;
|
||||||
interface Windows.Foundation.IReference<INT32>;
|
interface Windows.Foundation.IReference<INT32>;
|
||||||
|
|
Loading…
Reference in New Issue