From: Rémi Bernon rbernon@codeweavers.com
--- dlls/joy.cpl/wginput.c | 74 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+)
diff --git a/dlls/joy.cpl/wginput.c b/dlls/joy.cpl/wginput.c index 89dfaac5aa6..d7d4fde8594 100644 --- a/dlls/joy.cpl/wginput.c +++ b/dlls/joy.cpl/wginput.c @@ -55,6 +55,24 @@ struct device IRawGameController *device; };
+struct raw_controller_state +{ + UINT64 timestamp; + double axes[6]; + boolean buttons[32]; + GameControllerSwitchPosition switches[4]; +}; + +struct device_state +{ + const GUID *iid; + union + { + struct raw_controller_state raw_controller; + GamepadReading gamepad; + }; +}; + static CRITICAL_SECTION state_cs; static CRITICAL_SECTION_DEBUG state_cs_debug = { @@ -64,6 +82,7 @@ static CRITICAL_SECTION_DEBUG state_cs_debug = }; static CRITICAL_SECTION state_cs = { &state_cs_debug, -1, 0, 0, 0, 0 };
+static struct device_state device_state; static struct list devices = LIST_INIT( devices ); static struct list ifaces = LIST_INIT( ifaces ); static IGameController *iface_selected; @@ -71,6 +90,25 @@ static IGameController *iface_selected; static HWND dialog_hwnd; static HANDLE state_event;
+static void set_device_state( struct device_state *state ) +{ + BOOL modified; + + EnterCriticalSection( &state_cs ); + modified = memcmp( &device_state, state, sizeof(*state) ); + device_state = *state; + LeaveCriticalSection( &state_cs ); + + if (modified) SendMessageW( dialog_hwnd, WM_USER, 0, 0 ); +} + +static void get_device_state( struct device_state *state ) +{ + EnterCriticalSection( &state_cs ); + *state = device_state; + LeaveCriticalSection( &state_cs ); +} + static void set_selected_interface( IGameController *iface ) { IGameController *previous; @@ -123,10 +161,46 @@ static void clear_devices(void)
static DWORD WINAPI input_thread_proc( void *param ) { + union + { + struct raw_controller_state raw_controller; + GamepadReading gamepad; + } previous = {0}; + HANDLE stop_event = param;
while (WaitForSingleObject( stop_event, 20 ) == WAIT_TIMEOUT) { + IGameController *iface; + + if (!(iface = get_selected_interface())) + memset( &previous, 0, sizeof(previous) ); + else + { + IRawGameController *raw_controller; + IGamepad *gamepad; + + if (SUCCEEDED(IGameController_QueryInterface( iface, &IID_IRawGameController, (void **)&raw_controller ))) + { + struct device_state state = {.iid = &IID_IRawGameController}; + struct raw_controller_state *current = &state.raw_controller; + IRawGameController_GetCurrentReading( raw_controller, ARRAY_SIZE(current->buttons), current->buttons, + ARRAY_SIZE(current->switches), current->switches, + ARRAY_SIZE(current->axes), current->axes, ¤t->timestamp ); + IRawGameController_Release( raw_controller ); + set_device_state( &state ); + } + + if (SUCCEEDED(IGameController_QueryInterface( iface, &IID_IGamepad, (void **)&gamepad ))) + { + struct device_state state = {.iid = &IID_IGamepad}; + IGamepad_GetCurrentReading( gamepad, &state.gamepad ); + IGamepad_Release( gamepad ); + set_device_state( &state ); + } + + IGameController_Release( iface ); + } }
return 0;