Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
v2: Rebased on top of upstream.
dlls/joy.cpl/joy.h | 25 +++++++++++++---------- dlls/joy.cpl/joy.rc | 16 ++++++++------- dlls/joy.cpl/main.c | 50 +++++++++++++++++++++++++++++++++++++-------- 3 files changed, 64 insertions(+), 27 deletions(-)
diff --git a/dlls/joy.cpl/joy.h b/dlls/joy.cpl/joy.h index ec7af4f7879..ffba9cd1220 100644 --- a/dlls/joy.cpl/joy.h +++ b/dlls/joy.cpl/joy.h @@ -41,6 +41,7 @@ struct Joystick { int num_buttons; int num_axes; BOOL forcefeedback; + BOOL is_xinput; int num_effects; int cur_effect; int chosen_effect; @@ -82,17 +83,19 @@ struct JoystickData { #define IDD_FORCEFEEDBACK 1002
#define IDC_JOYSTICKLIST 2000 -#define IDC_BUTTONDISABLE 2001 -#define IDC_BUTTONENABLE 2002 -#define IDC_DISABLEDLIST 2003 -#define IDC_TESTSELECTCOMBO 2004 -#define IDC_TESTGROUPXY 2005 -#define IDC_TESTGROUPRXRY 2006 -#define IDC_TESTGROUPZRZ 2007 -#define IDC_TESTGROUPPOV 2008 - -#define IDC_FFSELECTCOMBO 2009 -#define IDC_FFEFFECTLIST 2010 +#define IDC_DISABLEDLIST 2001 +#define IDC_XINPUTLIST 2002 +#define IDC_BUTTONDISABLE 2010 +#define IDC_BUTTONENABLE 2011 + +#define IDC_TESTSELECTCOMBO 2100 +#define IDC_TESTGROUPXY 2101 +#define IDC_TESTGROUPRXRY 2102 +#define IDC_TESTGROUPZRZ 2103 +#define IDC_TESTGROUPPOV 2104 + +#define IDC_FFSELECTCOMBO 2200 +#define IDC_FFEFFECTLIST 2201
#define ICO_MAIN 100
diff --git a/dlls/joy.cpl/joy.rc b/dlls/joy.cpl/joy.rc index a4a780276bb..d425ea76440 100644 --- a/dlls/joy.cpl/joy.rc +++ b/dlls/joy.cpl/joy.rc @@ -31,21 +31,23 @@ BEGIN IDS_CPL_INFO "Test and configure game controllers." END
-IDD_LIST DIALOG 0, 0, 320, 220 +IDD_LIST DIALOG 0, 0, 320, 300 STYLE WS_CAPTION | WS_CHILD | WS_DISABLED CAPTION "Joysticks" FONT 8, "Ms Shell Dlg" { PUSHBUTTON "&Disable", IDC_BUTTONDISABLE, 200, 20, 60, 15 - PUSHBUTTON "&Enable", IDC_BUTTONENABLE, 200, 105, 60, 15 + PUSHBUTTON "&Enable", IDC_BUTTONENABLE, 200, 190, 60, 15 LTEXT "Connected", IDC_STATIC, 10, 10, 100, 10 LISTBOX IDC_JOYSTICKLIST, 10, 20, 180, 70, WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY - LTEXT "Disabled", IDC_STATIC, 10, 95, 100, 10 - LISTBOX IDC_DISABLEDLIST, 10, 105, 180, 70, WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY - LTEXT "After disabling or enabling a device, the connected joysticks won't be updated here until you restart this applet.", IDC_STATIC, 10, 175, 200, 25 + LTEXT "Connected (xinput device)", IDC_STATIC, 10, 90, 100, 10 + LISTBOX IDC_XINPUTLIST, 10, 100, 180, 70, WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY + LTEXT "Disabled", IDC_STATIC, 10, 180, 100, 10 + LISTBOX IDC_DISABLEDLIST, 10, 190, 180, 70, WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY + LTEXT "After disabling or enabling a device, the connected joysticks won't be updated here until you restart this applet.", IDC_STATIC, 10, 270, 200, 25 }
-IDD_TEST DIALOG 0, 0, 320, 220 +IDD_TEST DIALOG 0, 0, 320, 300 STYLE WS_CAPTION | WS_CHILD | WS_DISABLED CAPTION "Test Joystick" FONT 8, "Ms Shell Dlg" @@ -58,7 +60,7 @@ FONT 8, "Ms Shell Dlg" GROUPBOX "", IDC_TESTGROUPPOV, 246, 30, 60, 60 }
-IDD_FORCEFEEDBACK DIALOG 0, 0, 320, 220 +IDD_FORCEFEEDBACK DIALOG 0, 0, 320, 300 STYLE WS_CAPTION | WS_CHILD | WS_DISABLED CAPTION "Test Force Feedback" FONT 8, "Ms Shell Dlg" diff --git a/dlls/joy.cpl/main.c b/dlls/joy.cpl/main.c index dbe84963c5d..91280f2c2c5 100644 --- a/dlls/joy.cpl/main.c +++ b/dlls/joy.cpl/main.c @@ -63,6 +63,15 @@ BOOL WINAPI DllMain(HINSTANCE hdll, DWORD reason, LPVOID reserved) static BOOL CALLBACK ff_effects_callback(const DIEFFECTINFOW *pdei, void *pvRef); static BOOL CALLBACK enum_callback(const DIDEVICEINSTANCEW *instance, void *context) { + DIPROPGUIDANDPATH prop_guid_path = + { + .diph = + { + .dwSize = sizeof(DIPROPGUIDANDPATH), + .dwHeaderSize = sizeof(DIPROPHEADER), + .dwHow = DIPH_DEVICE, + }, + }; struct JoystickData *data = context; struct Joystick *joystick; DIPROPRANGE proprange; @@ -90,6 +99,9 @@ static BOOL CALLBACK enum_callback(const DIDEVICEINSTANCEW *instance, void *cont joystick->forcefeedback = caps.dwFlags & DIDC_FORCEFEEDBACK; joystick->num_effects = 0;
+ IDirectInputDevice8_GetProperty(joystick->device, DIPROP_GUIDANDPATH, &prop_guid_path.diph); + joystick->is_xinput = wcsstr(prop_guid_path.wszPath, L"&IG_") != NULL; + if (joystick->forcefeedback) data->num_ff++;
/* Set axis range to ease the GUI visualization */ @@ -233,9 +245,13 @@ static void refresh_joystick_list(HWND hwnd, struct JoystickData *data)
SendDlgItemMessageW(hwnd, IDC_JOYSTICKLIST, LB_RESETCONTENT, 0, 0); SendDlgItemMessageW(hwnd, IDC_DISABLEDLIST, LB_RESETCONTENT, 0, 0); + SendDlgItemMessageW(hwnd, IDC_XINPUTLIST, LB_RESETCONTENT, 0, 0);
for (joy = data->joysticks, joy_end = joy + data->num_joysticks; joy != joy_end; ++joy) - SendDlgItemMessageW(hwnd, IDC_JOYSTICKLIST, LB_ADDSTRING, 0, (LPARAM) joy->instance.tszInstanceName); + { + if (joy->is_xinput) SendDlgItemMessageW(hwnd, IDC_XINPUTLIST, LB_ADDSTRING, 0, (LPARAM) joy->instance.tszInstanceName); + else SendDlgItemMessageW(hwnd, IDC_JOYSTICKLIST, LB_ADDSTRING, 0, (LPARAM) joy->instance.tszInstanceName); + }
/* Search for disabled joysticks */ get_app_key(&hkey, &appkey); @@ -262,7 +278,10 @@ static void refresh_joystick_list(HWND hwnd, struct JoystickData *data) */ static INT_PTR CALLBACK list_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + WCHAR instance_name[MAX_PATH] = {0}; static struct JoystickData *data; + int sel; + TRACE("(%p, 0x%08x/%d, 0x%lx)\n", hwnd, msg, msg, lparam); switch (msg) { @@ -287,11 +306,14 @@ static INT_PTR CALLBACK list_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM { case IDC_BUTTONDISABLE: { - int sel = SendDlgItemMessageW(hwnd, IDC_JOYSTICKLIST, LB_GETCURSEL, 0, 0); + if ((sel = SendDlgItemMessageW(hwnd, IDC_JOYSTICKLIST, LB_GETCURSEL, 0, 0)) >= 0) + SendDlgItemMessageW(hwnd, IDC_JOYSTICKLIST, LB_GETTEXT, sel, (LPARAM)instance_name); + if ((sel = SendDlgItemMessageW(hwnd, IDC_XINPUTLIST, LB_GETCURSEL, 0, 0)) >= 0) + SendDlgItemMessageW(hwnd, IDC_XINPUTLIST, LB_GETTEXT, sel, (LPARAM)instance_name);
- if (sel >= 0) + if (instance_name[0]) { - enable_joystick(data->joysticks[sel].instance.tszInstanceName, FALSE); + enable_joystick(instance_name, FALSE); refresh_joystick_list(hwnd, data); } } @@ -299,24 +321,34 @@ static INT_PTR CALLBACK list_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
case IDC_BUTTONENABLE: { - int sel = SendDlgItemMessageW(hwnd, IDC_DISABLEDLIST, LB_GETCURSEL, 0, 0); + if ((sel = SendDlgItemMessageW(hwnd, IDC_DISABLEDLIST, LB_GETCURSEL, 0, 0)) >= 0) + SendDlgItemMessageW(hwnd, IDC_DISABLEDLIST, LB_GETTEXT, sel, (LPARAM)instance_name);
- if (sel >= 0) + if (instance_name[0]) { - WCHAR text[MAX_PATH]; - SendDlgItemMessageW(hwnd, IDC_DISABLEDLIST, LB_GETTEXT, sel, (LPARAM) text); - enable_joystick(text, TRUE); + enable_joystick(instance_name, TRUE); refresh_joystick_list(hwnd, data); } } break;
case IDC_JOYSTICKLIST: + SendDlgItemMessageW(hwnd, IDC_DISABLEDLIST, LB_SETCURSEL, -1, 0); + SendDlgItemMessageW(hwnd, IDC_XINPUTLIST, LB_SETCURSEL, -1, 0); + EnableWindow(GetDlgItem(hwnd, IDC_BUTTONENABLE), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_BUTTONDISABLE), TRUE); + break; + + case IDC_XINPUTLIST: + SendDlgItemMessageW(hwnd, IDC_JOYSTICKLIST, LB_SETCURSEL, -1, 0); + SendDlgItemMessageW(hwnd, IDC_DISABLEDLIST, LB_SETCURSEL, -1, 0); EnableWindow(GetDlgItem(hwnd, IDC_BUTTONENABLE), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_BUTTONDISABLE), TRUE); break;
case IDC_DISABLEDLIST: + SendDlgItemMessageW(hwnd, IDC_JOYSTICKLIST, LB_SETCURSEL, -1, 0); + SendDlgItemMessageW(hwnd, IDC_XINPUTLIST, LB_SETCURSEL, -1, 0); EnableWindow(GetDlgItem(hwnd, IDC_BUTTONENABLE), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_BUTTONDISABLE), FALSE); break;
So DirectInput registry keys can match both the gamepad and the internal device.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winexinput.sys/main.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/dlls/winexinput.sys/main.c b/dlls/winexinput.sys/main.c index 667ce867269..79c566e7cc8 100644 --- a/dlls/winexinput.sys/main.c +++ b/dlls/winexinput.sys/main.c @@ -323,14 +323,14 @@ struct device_strings
static const struct device_strings device_strings[] = { - { .id = L"VID_045E&PID_028E&IG_00", .product = L"Controller (XBOX 360 For Windows)" }, - { .id = L"VID_045E&PID_028F&IG_00", .product = L"Controller (XBOX 360 For Windows)" }, - { .id = L"VID_045E&PID_02D1&IG_00", .product = L"Controller (XBOX One For Windows)" }, - { .id = L"VID_045E&PID_02DD&IG_00", .product = L"Controller (XBOX One For Windows)" }, - { .id = L"VID_045E&PID_02E3&IG_00", .product = L"Controller (XBOX One For Windows)" }, - { .id = L"VID_045E&PID_02EA&IG_00", .product = L"Controller (XBOX One For Windows)" }, - { .id = L"VID_045E&PID_02FD&IG_00", .product = L"Controller (XBOX One For Windows)" }, - { .id = L"VID_045E&PID_0719&IG_00", .product = L"Controller (XBOX 360 For Windows)" }, + { .id = L"VID_045E&PID_028E", .product = L"Controller (XBOX 360 For Windows)" }, + { .id = L"VID_045E&PID_028F", .product = L"Controller (XBOX 360 For Windows)" }, + { .id = L"VID_045E&PID_02D1", .product = L"Controller (XBOX One For Windows)" }, + { .id = L"VID_045E&PID_02DD", .product = L"Controller (XBOX One For Windows)" }, + { .id = L"VID_045E&PID_02E3", .product = L"Controller (XBOX One For Windows)" }, + { .id = L"VID_045E&PID_02EA", .product = L"Controller (XBOX One For Windows)" }, + { .id = L"VID_045E&PID_02FD", .product = L"Controller (XBOX One For Windows)" }, + { .id = L"VID_045E&PID_0719", .product = L"Controller (XBOX 360 For Windows)" }, };
static const WCHAR *find_product_string(const WCHAR *device_id) @@ -339,7 +339,7 @@ static const WCHAR *find_product_string(const WCHAR *device_id) DWORD i;
for (i = 0; i < ARRAY_SIZE(device_strings); ++i) - if (!wcsicmp(device_strings[i].id, match_id)) + if (!wcsnicmp(device_strings[i].id, match_id, 17)) return device_strings[i].product;
return NULL; @@ -459,7 +459,7 @@ static NTSTATUS WINAPI internal_ioctl(DEVICE_OBJECT *device, IRP *irp) TRACE("device %p, irp %p, code %#x, bus_device %p.\n", device, irp, code, fdo->bus_device);
if (code == IOCTL_HID_READ_REPORT) return try_complete_pending_read(device, irp); - if (impl->is_gamepad) return gamepad_internal_ioctl(device, irp); + if (impl->is_gamepad || code == IOCTL_HID_GET_STRING) return gamepad_internal_ioctl(device, irp);
IoSkipCurrentIrpStackLocation(irp); return IoCallDriver(fdo->bus_device, irp);
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/xinput1_1/Makefile.in | 2 +- dlls/xinput1_2/Makefile.in | 2 +- dlls/xinput1_3/Makefile.in | 2 +- dlls/xinput1_3/main.c | 48 ++++++++++++++++++++++++++++++++++++ dlls/xinput1_4/Makefile.in | 2 +- dlls/xinput9_1_0/Makefile.in | 2 +- 6 files changed, 53 insertions(+), 5 deletions(-)
diff --git a/dlls/xinput1_1/Makefile.in b/dlls/xinput1_1/Makefile.in index a07b0c7c8b6..328435a110f 100644 --- a/dlls/xinput1_1/Makefile.in +++ b/dlls/xinput1_1/Makefile.in @@ -1,6 +1,6 @@ MODULE = xinput1_1.dll PARENTSRC = ../xinput1_3 -DELAYIMPORTS = hid setupapi +DELAYIMPORTS = hid setupapi advapi32
C_SRCS = \ main.c diff --git a/dlls/xinput1_2/Makefile.in b/dlls/xinput1_2/Makefile.in index 4a624521498..e66b6e67261 100644 --- a/dlls/xinput1_2/Makefile.in +++ b/dlls/xinput1_2/Makefile.in @@ -1,6 +1,6 @@ MODULE = xinput1_2.dll PARENTSRC = ../xinput1_3 -DELAYIMPORTS = hid setupapi +DELAYIMPORTS = hid setupapi advapi32
C_SRCS = \ main.c diff --git a/dlls/xinput1_3/Makefile.in b/dlls/xinput1_3/Makefile.in index 7786838b5e7..15ce3a691dd 100644 --- a/dlls/xinput1_3/Makefile.in +++ b/dlls/xinput1_3/Makefile.in @@ -1,6 +1,6 @@ MODULE = xinput1_3.dll IMPORTLIB = xinput -DELAYIMPORTS = hid setupapi +DELAYIMPORTS = hid setupapi advapi32
C_SRCS = \ main.c diff --git a/dlls/xinput1_3/main.c b/dlls/xinput1_3/main.c index 2881a370534..81d11e5d38f 100644 --- a/dlls/xinput1_3/main.c +++ b/dlls/xinput1_3/main.c @@ -394,6 +394,52 @@ failed: return FALSE; }
+static void get_registry_keys(HKEY *defkey, HKEY *appkey) +{ + WCHAR buffer[MAX_PATH + 26], *name = buffer, *tmp; + DWORD len; + HKEY hkey; + + *appkey = 0; + if (RegOpenKeyW(HKEY_CURRENT_USER, L"Software\Wine\DirectInput\Joysticks", defkey)) + *defkey = 0; + + if (!(len = GetModuleFileNameW(0, buffer, MAX_PATH)) || len >= MAX_PATH) + return; + + if (!RegOpenKeyW(HKEY_CURRENT_USER, L"Software\Wine\AppDefaults", &hkey)) + { + if ((tmp = wcsrchr(name, '/'))) name = tmp + 1; + if ((tmp = wcsrchr(name, '\'))) name = tmp + 1; + wcscat(name, L"\DirectInput\Joysticks"); + if (RegOpenKeyW(hkey, name, appkey)) *appkey = 0; + RegCloseKey(hkey); + } +} + +static BOOL device_is_overriden(HANDLE device) +{ + WCHAR name[MAX_PATH], buffer[MAX_PATH]; + DWORD size = sizeof(buffer); + BOOL disable = FALSE; + HKEY defkey, appkey; + + if (!HidD_GetProductString(device, name, MAX_PATH)) return FALSE; + + get_registry_keys(&defkey, &appkey); + if (!defkey && !appkey) return FALSE; + if ((appkey && !RegQueryValueExW(appkey, name, 0, NULL, (LPBYTE)buffer, &size)) || + (defkey && !RegQueryValueExW(defkey, name, 0, NULL, (LPBYTE)buffer, &size))) + { + if ((disable = !wcscmp(buffer, L"override"))) + TRACE("Disabling gamepad '%s' based on registry key.\n", debugstr_w(name)); + } + + if (appkey) RegCloseKey(appkey); + if (defkey) RegCloseKey(defkey); + return disable; +} + static void update_controller_list(void) { char buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR)]; @@ -437,6 +483,8 @@ static void update_controller_list(void) else if (caps.Usage != HID_USAGE_GENERIC_GAMEPAD && caps.Usage != HID_USAGE_GENERIC_JOYSTICK && caps.Usage != HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER) WARN("ignoring HID device, unsupported usage %04x:%04x\n", caps.UsagePage, caps.Usage); + else if (device_is_overriden(device)) + WARN("ignoring HID device, overriden for dinput\n"); else if (!controller_init(&controllers[i], preparsed, &caps, device, detail->DevicePath)) WARN("ignoring HID device, failed to initialize\n"); else diff --git a/dlls/xinput1_4/Makefile.in b/dlls/xinput1_4/Makefile.in index 5e4ab8969e2..b21a3d3ce53 100644 --- a/dlls/xinput1_4/Makefile.in +++ b/dlls/xinput1_4/Makefile.in @@ -1,6 +1,6 @@ MODULE = xinput1_4.dll PARENTSRC = ../xinput1_3 -DELAYIMPORTS = hid setupapi +DELAYIMPORTS = hid setupapi advapi32
C_SRCS = \ main.c diff --git a/dlls/xinput9_1_0/Makefile.in b/dlls/xinput9_1_0/Makefile.in index 6c9e9016537..f014e67dea3 100644 --- a/dlls/xinput9_1_0/Makefile.in +++ b/dlls/xinput9_1_0/Makefile.in @@ -1,6 +1,6 @@ MODULE = xinput9_1_0.dll PARENTSRC = ../xinput1_3 -DELAYIMPORTS = hid setupapi +DELAYIMPORTS = hid setupapi advapi32
C_SRCS = \ main.c
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick.c | 18 +++++++++------- dlls/dinput/joystick_hid.c | 35 ++++++++++++++++++++++++++++--- dlls/dinput/joystick_linux.c | 2 +- dlls/dinput/joystick_linuxinput.c | 2 +- dlls/dinput/joystick_private.h | 4 ++-- 5 files changed, 46 insertions(+), 15 deletions(-)
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c index d4f5b819471..6e573e8741a 100644 --- a/dlls/dinput/joystick.c +++ b/dlls/dinput/joystick.c @@ -271,23 +271,25 @@ void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags) } }
-BOOL device_disabled_registry(const char* name, BOOL disable) +BOOL device_disabled_registry(const char* name) { DIDEVICEINSTANCEW instance;
MultiByteToWideChar( CP_ACP, 0, name, -1, instance.tszInstanceName, MAX_PATH ); - return device_instance_is_disabled( &instance, disable ); + return device_instance_is_disabled( &instance, NULL ); }
-BOOL device_instance_is_disabled( DIDEVICEINSTANCEW *instance, BOOL disable ) +BOOL device_instance_is_disabled( DIDEVICEINSTANCEW *instance, BOOL *override ) { static const WCHAR disabled_str[] = {'d', 'i', 's', 'a', 'b', 'l', 'e', 'd', 0}; - static const WCHAR enabled_str[] = {'e', 'n', 'a', 'b', 'l', 'e', 'd', 0}; + static const WCHAR override_str[] = {'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', 0}; static const WCHAR joystick_key[] = {'J', 'o', 'y', 's', 't', 'i', 'c', 'k', 's', 0}; WCHAR buffer[MAX_PATH]; HKEY hkey, appkey, temp; + BOOL disable = FALSE;
get_app_key(&hkey, &appkey); + if (override) *override = FALSE;
/* Joystick settings are in the 'joysticks' subkey */ if (appkey) @@ -307,15 +309,15 @@ BOOL device_instance_is_disabled( DIDEVICEINSTANCEW *instance, BOOL disable ) /* Look for the "controllername"="disabled" key */ if (!get_config_key( hkey, appkey, instance->tszInstanceName, buffer, sizeof(buffer) )) { - if (!disable && !strcmpW( disabled_str, buffer )) + if (!strcmpW( disabled_str, buffer )) { TRACE( "Disabling joystick '%s' based on registry key.\n", debugstr_w(instance->tszInstanceName) ); disable = TRUE; } - else if (disable && !strcmpW( enabled_str, buffer )) + else if (override && !strcmpW( override_str, buffer )) { - TRACE( "Enabling joystick '%s' based on registry key.\n", debugstr_w(instance->tszInstanceName) ); - disable = FALSE; + TRACE( "Force enabling joystick '%s' based on registry key.\n", debugstr_w(instance->tszInstanceName) ); + *override = TRUE; } }
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 81fa3eefe7a..30e63c16cb8 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -45,6 +45,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(dinput);
+DEFINE_GUID( GUID_DEVINTERFACE_WINEXINPUT,0x6c53d5fd,0x6480,0x440f,0xb6,0x18,0x47,0x67,0x50,0xc5,0xe1,0xa6 ); DEFINE_GUID( hid_joystick_guid, 0x9e573edb, 0x7734, 0x11d2, 0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7 ); DEFINE_DEVPROPKEY( DEVPROPKEY_HID_HANDLE, 0xbc62e415, 0xf4fe, 0x405c, 0x8e, 0xda, 0x63, 0x6f, 0xb5, 0x9f, 0x08, 0x98, 2 );
@@ -1107,13 +1108,17 @@ static HRESULT hid_joystick_device_open( int index, DIDEVICEINSTANCEW *filter, W HANDLE *device, PHIDP_PREPARSED_DATA *preparsed, HIDD_ATTRIBUTES *attrs, HIDP_CAPS *caps, DWORD version ) { + static const WCHAR ig_w[] = {'&','I','G','_',0}; + static const WCHAR xi_w[] = {'&','X','I','_',0}; char buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR)]; SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (void *)buffer; SP_DEVICE_INTERFACE_DATA iface = {.cbSize = sizeof(iface)}; SP_DEVINFO_DATA devinfo = {.cbSize = sizeof(devinfo)}; DIDEVICEINSTANCEW instance = *filter; + WCHAR device_id[MAX_PATH], *tmp; + HDEVINFO set, xi_set; UINT32 i = 0, handle; - HDEVINFO set; + BOOL override; DWORD type; GUID hid;
@@ -1124,6 +1129,7 @@ static HRESULT hid_joystick_device_open( int index, DIDEVICEINSTANCEW *filter, W
set = SetupDiGetClassDevsW( &hid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT ); if (set == INVALID_HANDLE_VALUE) return DIERR_DEVICENOTREG; + xi_set = SetupDiGetClassDevsW( &GUID_DEVINTERFACE_WINEXINPUT, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT );
*device = NULL; *preparsed = NULL; @@ -1140,6 +1146,29 @@ static HRESULT hid_joystick_device_open( int index, DIDEVICEINSTANCEW *filter, W attrs, caps, &instance, version )) continue;
+ if (device_instance_is_disabled( &instance, &override )) + goto next; + + if (override) + { + if (!SetupDiGetDeviceInstanceIdW( set, &devinfo, device_id, MAX_PATH, NULL ) || + !(tmp = strstrW( device_id, ig_w ))) + goto next; + memcpy( tmp, xi_w, sizeof(xi_w) - sizeof(WCHAR) ); + if (!SetupDiOpenDeviceInfoW( xi_set, device_id, NULL, 0, &devinfo )) + goto next; + if (!SetupDiEnumDeviceInterfaces( xi_set, &devinfo, &GUID_DEVINTERFACE_WINEXINPUT, 0, &iface )) + goto next; + if (!SetupDiGetDeviceInterfaceDetailW( xi_set, &iface, detail, sizeof(buffer), NULL, &devinfo )) + goto next; + + CloseHandle( *device ); + HidD_FreePreparsedData( *preparsed ); + if (!hid_joystick_device_try_open( handle, detail->DevicePath, device, preparsed, + attrs, caps, &instance, version )) + continue; + } + /* enumerate device by GUID */ if (index < 0 && IsEqualGUID( &filter->guidProduct, &instance.guidProduct )) break; if (index < 0 && IsEqualGUID( &filter->guidInstance, &instance.guidInstance )) break; @@ -1147,12 +1176,14 @@ static HRESULT hid_joystick_device_open( int index, DIDEVICEINSTANCEW *filter, W /* enumerate all devices */ if (index >= 0 && !index--) break;
+ next: CloseHandle( *device ); HidD_FreePreparsedData( *preparsed ); *device = NULL; *preparsed = NULL; }
+ if (xi_set != INVALID_HANDLE_VALUE) SetupDiDestroyDeviceInfoList( xi_set ); SetupDiDestroyDeviceInfoList( set ); if (!*device || !*preparsed) return DIERR_DEVICENOTREG;
@@ -1187,8 +1218,6 @@ static HRESULT hid_joystick_enum_device( DWORD type, DWORD flags, DIDEVICEINSTAN if (version >= 0x0800 && type != DI8DEVCLASS_ALL && type != DI8DEVCLASS_GAMECTRL) return S_FALSE;
- if (device_instance_is_disabled( instance, FALSE )) return DIERR_DEVICENOTREG; - TRACE( "found device %s, usage %04x:%04x, product %s, instance %s, name %s\n", debugstr_w(device_path), instance->wUsagePage, instance->wUsage, debugstr_guid( &instance->guidProduct ), debugstr_guid( &instance->guidInstance ), debugstr_w(instance->tszInstanceName) ); diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c index c439cca81c3..5b54e352c20 100644 --- a/dlls/dinput/joystick_linux.c +++ b/dlls/dinput/joystick_linux.c @@ -175,7 +175,7 @@ static INT find_joystick_devices(void) /* Append driver name */ strcat(joydev.name, JOYDEVDRIVER);
- if (device_disabled_registry(joydev.name, FALSE)) { + if (device_disabled_registry(joydev.name)) { close(fd); continue; } diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c index 8279ffbf74a..949fd1da081 100644 --- a/dlls/dinput/joystick_linuxinput.c +++ b/dlls/dinput/joystick_linuxinput.c @@ -264,7 +264,7 @@ static void find_joydevs(void) else joydev.name = joydev.device;
- if (device_disabled_registry(joydev.name, FALSE)) { + if (device_disabled_registry(joydev.name)) { close(fd); HeapFree(GetProcessHeap(), 0, joydev.name); if (joydev.name != joydev.device) diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h index 4fe51d17067..32265edef03 100644 --- a/dlls/dinput/joystick_private.h +++ b/dlls/dinput/joystick_private.h @@ -57,8 +57,8 @@ HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_
DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
-BOOL device_disabled_registry(const char* name, BOOL disable) DECLSPEC_HIDDEN; -BOOL device_instance_is_disabled( DIDEVICEINSTANCEW *instance, BOOL disable ) DECLSPEC_HIDDEN; +BOOL device_disabled_registry(const char* name) DECLSPEC_HIDDEN; +BOOL device_instance_is_disabled( DIDEVICEINSTANCEW *instance, BOOL *override ) DECLSPEC_HIDDEN;
ULONG WINAPI JoystickWGenericImpl_Release(LPDIRECTINPUTDEVICE8W iface);
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/joy.cpl/joy.h | 3 +++ dlls/joy.cpl/joy.rc | 2 ++ dlls/joy.cpl/main.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+)
diff --git a/dlls/joy.cpl/joy.h b/dlls/joy.cpl/joy.h index ffba9cd1220..64df21963b9 100644 --- a/dlls/joy.cpl/joy.h +++ b/dlls/joy.cpl/joy.h @@ -42,6 +42,7 @@ struct Joystick { int num_axes; BOOL forcefeedback; BOOL is_xinput; + BOOL has_override; int num_effects; int cur_effect; int chosen_effect; @@ -87,6 +88,8 @@ struct JoystickData { #define IDC_XINPUTLIST 2002 #define IDC_BUTTONDISABLE 2010 #define IDC_BUTTONENABLE 2011 +#define IDC_BUTTONRESET 2012 +#define IDC_BUTTONOVERRIDE 2013
#define IDC_TESTSELECTCOMBO 2100 #define IDC_TESTGROUPXY 2101 diff --git a/dlls/joy.cpl/joy.rc b/dlls/joy.cpl/joy.rc index d425ea76440..77f121c5b1c 100644 --- a/dlls/joy.cpl/joy.rc +++ b/dlls/joy.cpl/joy.rc @@ -37,7 +37,9 @@ CAPTION "Joysticks" FONT 8, "Ms Shell Dlg" { PUSHBUTTON "&Disable", IDC_BUTTONDISABLE, 200, 20, 60, 15 + PUSHBUTTON "&Reset", IDC_BUTTONRESET, 200, 40, 60, 15 PUSHBUTTON "&Enable", IDC_BUTTONENABLE, 200, 190, 60, 15 + PUSHBUTTON "&Override", IDC_BUTTONOVERRIDE, 200, 100, 60, 15 LTEXT "Connected", IDC_STATIC, 10, 10, 100, 10 LISTBOX IDC_JOYSTICKLIST, 10, 20, 180, 70, WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY LTEXT "Connected (xinput device)", IDC_STATIC, 10, 90, 100, 10 diff --git a/dlls/joy.cpl/main.c b/dlls/joy.cpl/main.c index 91280f2c2c5..57c188a5df1 100644 --- a/dlls/joy.cpl/main.c +++ b/dlls/joy.cpl/main.c @@ -272,6 +272,21 @@ static void refresh_joystick_list(HWND hwnd, struct JoystickData *data) if (appkey) RegCloseKey(appkey); }
+static void override_joystick(WCHAR *joy_name, BOOL override) +{ + HKEY hkey, appkey; + + get_app_key(&hkey, &appkey); + + if (override) + set_config_key(hkey, appkey, joy_name, L"override", wcslen(L"override")); + else + set_config_key(hkey, appkey, joy_name, NULL, 0); + + if (hkey) RegCloseKey(hkey); + if (appkey) RegCloseKey(appkey); +} + /********************************************************************* * list_dlgproc [internal] * @@ -293,6 +308,8 @@ static INT_PTR CALLBACK list_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
EnableWindow(GetDlgItem(hwnd, IDC_BUTTONENABLE), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_BUTTONDISABLE), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_BUTTONRESET), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_BUTTONOVERRIDE), FALSE);
/* Store the hwnd to be used with MapDialogRect for unit conversions */ data->graphics.hwnd = hwnd; @@ -332,11 +349,35 @@ static INT_PTR CALLBACK list_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM } break;
+ case IDC_BUTTONRESET: + { + if ((sel = SendDlgItemMessageW(hwnd, IDC_JOYSTICKLIST, LB_GETCURSEL, 0, 0)) >= 0) + { + SendDlgItemMessageW(hwnd, IDC_JOYSTICKLIST, LB_GETTEXT, sel, (LPARAM)instance_name); + override_joystick(instance_name, FALSE); + refresh_joystick_list(hwnd, data); + } + } + break; + + case IDC_BUTTONOVERRIDE: + { + if ((sel = SendDlgItemMessageW(hwnd, IDC_XINPUTLIST, LB_GETCURSEL, 0, 0)) >= 0) + { + SendDlgItemMessageW(hwnd, IDC_XINPUTLIST, LB_GETTEXT, sel, (LPARAM)instance_name); + override_joystick(instance_name, TRUE); + refresh_joystick_list(hwnd, data); + } + } + break; + case IDC_JOYSTICKLIST: SendDlgItemMessageW(hwnd, IDC_DISABLEDLIST, LB_SETCURSEL, -1, 0); SendDlgItemMessageW(hwnd, IDC_XINPUTLIST, LB_SETCURSEL, -1, 0); EnableWindow(GetDlgItem(hwnd, IDC_BUTTONENABLE), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_BUTTONDISABLE), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_BUTTONOVERRIDE), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_BUTTONRESET), TRUE); break;
case IDC_XINPUTLIST: @@ -344,6 +385,8 @@ static INT_PTR CALLBACK list_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM SendDlgItemMessageW(hwnd, IDC_DISABLEDLIST, LB_SETCURSEL, -1, 0); EnableWindow(GetDlgItem(hwnd, IDC_BUTTONENABLE), FALSE); EnableWindow(GetDlgItem(hwnd, IDC_BUTTONDISABLE), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_BUTTONOVERRIDE), TRUE); + EnableWindow(GetDlgItem(hwnd, IDC_BUTTONRESET), FALSE); break;
case IDC_DISABLEDLIST: @@ -351,6 +394,8 @@ static INT_PTR CALLBACK list_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM SendDlgItemMessageW(hwnd, IDC_XINPUTLIST, LB_SETCURSEL, -1, 0); EnableWindow(GetDlgItem(hwnd, IDC_BUTTONENABLE), TRUE); EnableWindow(GetDlgItem(hwnd, IDC_BUTTONDISABLE), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_BUTTONOVERRIDE), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_BUTTONRESET), FALSE); break; }