From: Rémi Bernon rbernon@codeweavers.com
--- dlls/joy.cpl/joy.rc | 2 + dlls/joy.cpl/joy_private.h | 4 ++ dlls/joy.cpl/main.c | 8 +++ dlls/joy.cpl/resource.h | 2 + dlls/joy.cpl/wginput.c | 87 ++++++++++++++++++++++++ dlls/joy.cpl/xinput.c | 134 +++++++++++++++++++------------------ 6 files changed, 172 insertions(+), 65 deletions(-)
diff --git a/dlls/joy.cpl/joy.rc b/dlls/joy.cpl/joy.rc index be6aa8bd09c..452b5abf527 100644 --- a/dlls/joy.cpl/joy.rc +++ b/dlls/joy.cpl/joy.rc @@ -107,6 +107,8 @@ FONT 8, "Ms Shell Dlg" { COMBOBOX IDC_WGI_DEVICES, 15, 10, 150, 60, CBS_DROPDOWNLIST | CBS_HASSTRINGS COMBOBOX IDC_WGI_INTERFACE, 175, 10, 131, 60, CBS_DROPDOWNLIST | CBS_HASSTRINGS + GROUPBOX "", IDC_WGI_GAMEPAD, 15, 30, 291, 60 + AUTOCHECKBOX "Rumble", IDC_WGI_RUMBLE, 260, 30, 40, 10 }
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL diff --git a/dlls/joy.cpl/joy_private.h b/dlls/joy.cpl/joy_private.h index fa320bff423..94f651e130a 100644 --- a/dlls/joy.cpl/joy_private.h +++ b/dlls/joy.cpl/joy_private.h @@ -27,9 +27,12 @@ #include "winbase.h"
#include "dinput.h" +#include "xinput.h"
#include "resource.h"
+extern void paint_gamepad_view( HWND hwnd, XINPUT_STATE *state ); + extern INT_PTR CALLBACK test_di_dialog_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ); extern LRESULT CALLBACK test_di_axes_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ); extern LRESULT CALLBACK test_di_povs_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ); @@ -39,5 +42,6 @@ extern INT_PTR CALLBACK test_xi_dialog_proc( HWND hwnd, UINT msg, WPARAM wparam, extern LRESULT CALLBACK test_xi_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam );
extern INT_PTR CALLBACK test_wgi_dialog_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ); +extern LRESULT CALLBACK test_wgi_gamepad_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam );
#endif /* __JOY_PRIVATE_H */ diff --git a/dlls/joy.cpl/main.c b/dlls/joy.cpl/main.c index d6936180063..8cd51bcc5bf 100644 --- a/dlls/joy.cpl/main.c +++ b/dlls/joy.cpl/main.c @@ -518,15 +518,23 @@ static void register_window_class(void) .lpfnWndProc = &test_di_buttons_window_proc, .lpszClassName = L"JoyCplDInputButtons", }; + WNDCLASSW wgi_gamepad_class = + { + .hInstance = hcpl, + .lpfnWndProc = &test_wgi_gamepad_window_proc, + .lpszClassName = L"JoyCplWGIGamepad", + };
RegisterClassW( &xi_class ); RegisterClassW( &di_axes_class ); RegisterClassW( &di_povs_class ); RegisterClassW( &di_buttons_class ); + RegisterClassW( &wgi_gamepad_class ); }
static void unregister_window_class(void) { + UnregisterClassW( L"JoyCplWGIGamepad", hcpl ); UnregisterClassW( L"JoyCplDInputAxes", hcpl ); UnregisterClassW( L"JoyCplDInputPOVs", hcpl ); UnregisterClassW( L"JoyCplDInputButtons", hcpl ); diff --git a/dlls/joy.cpl/resource.h b/dlls/joy.cpl/resource.h index 6b4b865f182..c1782ba49b7 100644 --- a/dlls/joy.cpl/resource.h +++ b/dlls/joy.cpl/resource.h @@ -72,6 +72,8 @@
#define IDC_WGI_DEVICES 2300 #define IDC_WGI_INTERFACE 2301 +#define IDC_WGI_GAMEPAD 2302 +#define IDC_WGI_RUMBLE 2303
#define ICO_MAIN 100
diff --git a/dlls/joy.cpl/wginput.c b/dlls/joy.cpl/wginput.c index d7d4fde8594..621d38ca693 100644 --- a/dlls/joy.cpl/wginput.c +++ b/dlls/joy.cpl/wginput.c @@ -206,6 +206,50 @@ static DWORD WINAPI input_thread_proc( void *param ) return 0; }
+LRESULT CALLBACK test_wgi_gamepad_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + TRACE( "hwnd %p, msg %#x, wparam %#Ix, lparam %#Ix\n", hwnd, msg, wparam, lparam ); + + if (msg == WM_PAINT) + { + struct device_state state; + XINPUT_STATE xstate = {0}; + + get_device_state( &state ); + + xstate.Gamepad.sThumbLX = state.gamepad.LeftThumbstickX * 0x7fff; + xstate.Gamepad.sThumbLY = state.gamepad.LeftThumbstickY * 0x7fff; + if (state.gamepad.Buttons & GamepadButtons_LeftThumbstick) xstate.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_THUMB; + + xstate.Gamepad.sThumbRX = state.gamepad.RightThumbstickX * 0x7fff; + xstate.Gamepad.sThumbRY = state.gamepad.RightThumbstickY * 0x7fff; + if (state.gamepad.Buttons & GamepadButtons_RightThumbstick) xstate.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_THUMB; + + xstate.Gamepad.bLeftTrigger = state.gamepad.LeftTrigger * 0xff; + xstate.Gamepad.bRightTrigger = state.gamepad.RightTrigger * 0xff; + + if (state.gamepad.Buttons & GamepadButtons_DPadUp) xstate.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP; + if (state.gamepad.Buttons & GamepadButtons_LeftShoulder) xstate.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_SHOULDER; + if (state.gamepad.Buttons & GamepadButtons_RightShoulder) xstate.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; + if (state.gamepad.Buttons & GamepadButtons_Y) xstate.Gamepad.wButtons |= XINPUT_GAMEPAD_Y; + + if (state.gamepad.Buttons & GamepadButtons_DPadLeft) xstate.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT; + if (state.gamepad.Buttons & GamepadButtons_DPadRight) xstate.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT; + if (state.gamepad.Buttons & GamepadButtons_X) xstate.Gamepad.wButtons |= XINPUT_GAMEPAD_X; + if (state.gamepad.Buttons & GamepadButtons_B) xstate.Gamepad.wButtons |= XINPUT_GAMEPAD_B; + + if (state.gamepad.Buttons & GamepadButtons_DPadDown) xstate.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN; + if (state.gamepad.Buttons & GamepadButtons_View) xstate.Gamepad.wButtons |= XINPUT_GAMEPAD_BACK; + if (state.gamepad.Buttons & GamepadButtons_Menu) xstate.Gamepad.wButtons |= XINPUT_GAMEPAD_START; + if (state.gamepad.Buttons & GamepadButtons_A) xstate.Gamepad.wButtons |= XINPUT_GAMEPAD_A; + + paint_gamepad_view( hwnd, &xstate ); + return 0; + } + + return DefWindowProcW( hwnd, msg, wparam, lparam ); +} + static void handle_wgi_interface_change( HWND hwnd ) { IGameController *iface; @@ -405,8 +449,50 @@ static void update_wgi_devices( HWND hwnd ) } }
+static void update_device_views( HWND hwnd ) +{ + HWND gamepad, rumble; + struct device_state state; + + get_device_state( &state ); + + gamepad = GetDlgItem( hwnd, IDC_WGI_GAMEPAD ); + rumble = GetDlgItem( hwnd, IDC_WGI_RUMBLE ); + + if (!IsEqualGUID( state.iid, &IID_IGamepad )) + { + ShowWindow( gamepad, SW_HIDE ); + ShowWindow( rumble, SW_HIDE ); + } + else + { + InvalidateRect( gamepad, NULL, TRUE ); + InvalidateRect( rumble, NULL, TRUE ); + ShowWindow( gamepad, SW_SHOW ); + ShowWindow( rumble, SW_SHOW ); + } +} + static void create_device_views( HWND hwnd ) { + HINSTANCE instance = (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ); + HWND gamepad, rumble; + LONG margin; + RECT rect; + + gamepad = GetDlgItem( hwnd, IDC_WGI_GAMEPAD ); + rumble = GetDlgItem( hwnd, IDC_WGI_RUMBLE ); + ShowWindow( gamepad, SW_HIDE ); + ShowWindow( rumble, SW_HIDE ); + + GetClientRect( gamepad, &rect ); + rect.top += 10; + + margin = (rect.bottom - rect.top) * 15 / 100; + InflateRect( &rect, -margin, -margin ); + + CreateWindowW( L"JoyCplWGIGamepad", NULL, WS_CHILD | WS_VISIBLE, rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, gamepad, NULL, NULL, instance ); }
extern INT_PTR CALLBACK test_wgi_dialog_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) @@ -474,6 +560,7 @@ extern INT_PTR CALLBACK test_wgi_dialog_proc( HWND hwnd, UINT msg, WPARAM wparam return TRUE;
case WM_USER: + update_device_views( hwnd ); return TRUE; }
diff --git a/dlls/joy.cpl/xinput.c b/dlls/joy.cpl/xinput.c index 2285485ae44..977c3ecd2d6 100644 --- a/dlls/joy.cpl/xinput.c +++ b/dlls/joy.cpl/xinput.c @@ -247,6 +247,74 @@ static void draw_button_view( HDC hdc, RECT rect, BOOL set, const WCHAR *name ) SelectObject( hdc, font ); }
+void paint_gamepad_view( HWND hwnd, XINPUT_STATE *state ) +{ + UINT axis_size, trigger_size, button_size, horiz_space; + RECT rect, tmp_rect; + PAINTSTRUCT paint; + HDC hdc; + + GetClientRect( hwnd, &rect ); + axis_size = rect.bottom - rect.top; + button_size = (axis_size - 1) / 3; + trigger_size = axis_size / 4; + horiz_space = (rect.right - rect.left - axis_size * 2 - trigger_size * 2 - button_size * 5) / 10; + + hdc = BeginPaint( hwnd, &paint ); + + rect.right = rect.left + axis_size; + OffsetRect( &rect, horiz_space, 0 ); + draw_axis_view( hdc, rect, state->Gamepad.sThumbLX, state->Gamepad.sThumbLY, + state->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB ); + OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); + draw_axis_view( hdc, rect, state->Gamepad.sThumbRX, state->Gamepad.sThumbRY, + state->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB ); + + OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); + rect.right = rect.left + trigger_size; + draw_trigger_view( hdc, rect, state->Gamepad.bLeftTrigger ); + OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); + draw_trigger_view( hdc, rect, state->Gamepad.bRightTrigger ); + + OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); + rect.right = rect.left + button_size; + rect.bottom = rect.top + button_size; + tmp_rect = rect; + OffsetRect( &rect, (rect.right - rect.left + horiz_space) / 2, 0 ); + draw_button_view( hdc, rect, state->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP, L"^" ); + OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); + draw_button_view( hdc, rect, state->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER, L"L" ); + OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); + draw_button_view( hdc, rect, state->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER, L"R" ); + OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); + draw_button_view( hdc, rect, state->Gamepad.wButtons & XINPUT_GAMEPAD_Y, L"Y" ); + + rect = tmp_rect; + OffsetRect( &rect, 0, rect.bottom - rect.top ); + tmp_rect = rect; + draw_button_view( hdc, rect, state->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT, L"<" ); + OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); + draw_button_view( hdc, rect, state->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT, L">" ); + OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); + draw_button_view( hdc, rect, state->Gamepad.wButtons & 0x0400, L"@" ); + OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); + draw_button_view( hdc, rect, state->Gamepad.wButtons & XINPUT_GAMEPAD_X, L"X" ); + OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); + draw_button_view( hdc, rect, state->Gamepad.wButtons & XINPUT_GAMEPAD_B, L"B" ); + + rect = tmp_rect; + OffsetRect( &rect, (rect.right - rect.left + horiz_space) / 2, rect.bottom - rect.top ); + draw_button_view( hdc, rect, state->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN, L"v" ); + OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); + draw_button_view( hdc, rect, state->Gamepad.wButtons & XINPUT_GAMEPAD_BACK, L"#" ); + OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); + draw_button_view( hdc, rect, state->Gamepad.wButtons & XINPUT_GAMEPAD_START, L"=" ); + OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); + draw_button_view( hdc, rect, state->Gamepad.wButtons & XINPUT_GAMEPAD_A, L"A" ); + + EndPaint( hwnd, &paint ); +} + LRESULT CALLBACK test_xi_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { TRACE( "hwnd %p, msg %#x, wparam %#Ix, lparam %#Ix\n", hwnd, msg, wparam, lparam ); @@ -254,74 +322,10 @@ LRESULT CALLBACK test_xi_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM if (msg == WM_PAINT) { DWORD index = GetWindowLongW( hwnd, GWLP_USERDATA ); - UINT axis_size, trigger_size, button_size, horiz_space; struct device_state state; - RECT rect, tmp_rect; - PAINTSTRUCT paint; - HDC hdc; - - GetClientRect( hwnd, &rect ); - axis_size = rect.bottom - rect.top; - button_size = (axis_size - 1) / 3; - trigger_size = axis_size / 4; - horiz_space = (rect.right - rect.left - axis_size * 2 - trigger_size * 2 - button_size * 5) / 10;
get_device_state( index, &state ); - - hdc = BeginPaint( hwnd, &paint ); - - rect.right = rect.left + axis_size; - OffsetRect( &rect, horiz_space, 0 ); - draw_axis_view( hdc, rect, state.state.Gamepad.sThumbLX, state.state.Gamepad.sThumbLY, - state.state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB ); - OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); - draw_axis_view( hdc, rect, state.state.Gamepad.sThumbRX, state.state.Gamepad.sThumbRY, - state.state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB ); - - OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); - rect.right = rect.left + trigger_size; - draw_trigger_view( hdc, rect, state.state.Gamepad.bLeftTrigger ); - OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); - draw_trigger_view( hdc, rect, state.state.Gamepad.bRightTrigger ); - - OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); - rect.right = rect.left + button_size; - rect.bottom = rect.top + button_size; - tmp_rect = rect; - OffsetRect( &rect, (rect.right - rect.left + horiz_space) / 2, 0 ); - draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP, L"^" ); - OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); - draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER, L"L" ); - OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); - draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER, L"R" ); - OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); - draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_Y, L"Y" ); - - rect = tmp_rect; - OffsetRect( &rect, 0, rect.bottom - rect.top ); - tmp_rect = rect; - draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT, L"<" ); - OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); - draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT, L">" ); - OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); - draw_button_view( hdc, rect, state.state.Gamepad.wButtons & 0x0400, L"@" ); - OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); - draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_X, L"X" ); - OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); - draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_B, L"B" ); - - rect = tmp_rect; - OffsetRect( &rect, (rect.right - rect.left + horiz_space) / 2, rect.bottom - rect.top ); - draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN, L"v" ); - OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); - draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK, L"#" ); - OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); - draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_START, L"=" ); - OffsetRect( &rect, rect.right - rect.left + horiz_space, 0 ); - draw_button_view( hdc, rect, state.state.Gamepad.wButtons & XINPUT_GAMEPAD_A, L"A" ); - - EndPaint( hwnd, &paint ); - + paint_gamepad_view( hwnd, &state.state ); return 0; }