From: Rémi Bernon rbernon@codeweavers.com
--- dlls/joy.cpl/joy.rc | 5 +++++ dlls/joy.cpl/resource.h | 4 ++++ dlls/joy.cpl/xinput.c | 43 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+)
diff --git a/dlls/joy.cpl/joy.rc b/dlls/joy.cpl/joy.rc index dca694e5347..d19651e340c 100644 --- a/dlls/joy.cpl/joy.rc +++ b/dlls/joy.cpl/joy.rc @@ -92,6 +92,11 @@ FONT 8, "Ms Shell Dlg" "gamepad is plugged in, and not overriden for " \ "DInput in the Joysticks tab.", IDC_XI_NO_USER_3, 15, 220, 291, 60 + + AUTOCHECKBOX "Rumble", IDC_XI_RUMBLE_0, 260, 10, 40, 10 + AUTOCHECKBOX "Rumble", IDC_XI_RUMBLE_1, 260, 80, 40, 10 + AUTOCHECKBOX "Rumble", IDC_XI_RUMBLE_2, 260, 150, 40, 10 + AUTOCHECKBOX "Rumble", IDC_XI_RUMBLE_3, 260, 220, 40, 10 }
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL diff --git a/dlls/joy.cpl/resource.h b/dlls/joy.cpl/resource.h index 714fcca664d..17acd178984 100644 --- a/dlls/joy.cpl/resource.h +++ b/dlls/joy.cpl/resource.h @@ -61,6 +61,10 @@ #define IDC_XI_NO_USER_1 2211 #define IDC_XI_NO_USER_2 2212 #define IDC_XI_NO_USER_3 2213 +#define IDC_XI_RUMBLE_0 2220 +#define IDC_XI_RUMBLE_1 2221 +#define IDC_XI_RUMBLE_2 2222 +#define IDC_XI_RUMBLE_3 2223
#define ICO_MAIN 100
diff --git a/dlls/joy.cpl/xinput.c b/dlls/joy.cpl/xinput.c index 9ca7fac3fa4..abaf8bb856c 100644 --- a/dlls/joy.cpl/xinput.c +++ b/dlls/joy.cpl/xinput.c @@ -19,6 +19,7 @@
#include <stdarg.h> #include <stddef.h> +#include <stdlib.h> #include <math.h>
#include "windef.h" @@ -40,6 +41,7 @@ struct device_state XINPUT_CAPABILITIES caps; XINPUT_STATE state; DWORD status; + BOOL rumble; };
static CRITICAL_SECTION state_cs; @@ -65,6 +67,7 @@ static void set_device_state( DWORD index, struct device_state *state ) BOOL modified;
EnterCriticalSection( &state_cs ); + state->rumble = devices_state[index].rumble; modified = memcmp( devices_state + index, state, sizeof(*state) ); devices_state[index] = *state; LeaveCriticalSection( &state_cs ); @@ -88,10 +91,22 @@ static DWORD WINAPI input_thread_proc( void *param ) { for (i = 0; i < ARRAY_SIZE(devices_state); ++i) { + XINPUT_VIBRATION vibration = {0}; struct device_state state = {0}; + state.status = XInputGetCapabilities( i, 0, &state.caps ); if (!state.status) state.status = XInputGetState( i, &state.state ); set_device_state( i, &state ); + + if (state.rumble) + { + vibration.wLeftMotorSpeed = 2 * max( abs( state.state.Gamepad.sThumbLX ), + abs( state.state.Gamepad.sThumbLY ) ) - 1; + vibration.wRightMotorSpeed = 2 * max( abs( state.state.Gamepad.sThumbRX ), + abs( state.state.Gamepad.sThumbRY ) ) - 1; + } + + XInputSetState( i, &vibration ); } }
@@ -333,6 +348,9 @@ static void create_user_view( HWND hwnd, DWORD index ) SetWindowLongW( view, GWLP_USERDATA, index );
ShowWindow( parent, SW_HIDE ); + + parent = GetDlgItem( hwnd, IDC_XI_RUMBLE_0 + index ); + ShowWindow( parent, SW_HIDE ); }
static void update_user_view( HWND hwnd, DWORD index ) @@ -345,6 +363,9 @@ static void update_user_view( HWND hwnd, DWORD index ) parent = GetDlgItem( hwnd, IDC_XI_NO_USER_0 + index ); ShowWindow( parent, state.status ? SW_SHOW : SW_HIDE );
+ parent = GetDlgItem( hwnd, IDC_XI_RUMBLE_0 + index ); + ShowWindow( parent, state.status ? SW_HIDE : SW_SHOW ); + parent = GetDlgItem( hwnd, IDC_XI_USER_0 + index ); ShowWindow( parent, state.status ? SW_HIDE : SW_SHOW );
@@ -355,6 +376,19 @@ static void update_user_view( HWND hwnd, DWORD index ) } }
+static void update_rumble_state( HWND hwnd, DWORD index ) +{ + HWND parent; + LRESULT res; + + parent = GetDlgItem( hwnd, IDC_XI_RUMBLE_0 + index ); + res = SendMessageW( parent, BM_GETCHECK, 0, 0 ); + + EnterCriticalSection( &state_cs ); + devices_state[index].rumble = res == BST_CHECKED; + LeaveCriticalSection( &state_cs ); +} + extern INT_PTR CALLBACK test_xi_dialog_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { static HANDLE thread, thread_stop; @@ -371,6 +405,15 @@ extern INT_PTR CALLBACK test_xi_dialog_proc( HWND hwnd, UINT msg, WPARAM wparam, return TRUE;
case WM_COMMAND: + switch (LOWORD(wparam)) + { + case IDC_XI_RUMBLE_0: + case IDC_XI_RUMBLE_1: + case IDC_XI_RUMBLE_2: + case IDC_XI_RUMBLE_3: + update_rumble_state( hwnd, LOWORD(wparam) - IDC_XI_RUMBLE_0 ); + break; + } return TRUE;
case WM_NOTIFY: