From 6ab32d28bf30f30cf0df3ca382de407c5a59889b Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sat, 3 Jun 2017 18:05:46 +0000 Subject: [PATCH] [DINPUT] Sync with Wine Staging 2.9. CORE-13362 e87ccb8 dinput: Assume a 1-to-1 axes map when no axes match. 41b126b dinput: Handle username in EnumDevicesBySemantics. 967399e dinput: Keep username same between device objects. svn path=/trunk/; revision=74776 --- reactos/dll/directx/wine/dinput/device.c | 38 +++++- .../dll/directx/wine/dinput/device_private.h | 1 - reactos/dll/directx/wine/dinput/dinput_main.c | 117 +++++++++++++++--- .../dll/directx/wine/dinput/dinput_private.h | 7 ++ .../dll/directx/wine/dinput/joystick_linux.c | 19 ++- reactos/media/doc/README.WINE | 2 +- 6 files changed, 163 insertions(+), 21 deletions(-) diff --git a/reactos/dll/directx/wine/dinput/device.c b/reactos/dll/directx/wine/dinput/device.c index d183066b323..d9f95b913b9 100644 --- a/reactos/dll/directx/wine/dinput/device.c +++ b/reactos/dll/directx/wine/dinput/device.c @@ -1294,11 +1294,24 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, case (DWORD_PTR) DIPROP_USERNAME: { LPDIPROPSTRING ps = (LPDIPROPSTRING)pdiph; + struct DevicePlayer *device_player; if (pdiph->dwSize != sizeof(DIPROPSTRING)) return DIERR_INVALIDPARAM; - lstrcpynW(ps->wsz, This->username, sizeof(ps->wsz)/sizeof(WCHAR)); - break; + LIST_FOR_EACH_ENTRY(device_player, &This->dinput->device_players, + struct DevicePlayer, entry) + { + if (IsEqualGUID(&device_player->instance_guid, &This->guid)) + { + if (*device_player->username) + { + lstrcpynW(ps->wsz, device_player->username, sizeof(ps->wsz)/sizeof(WCHAR)); + return DI_OK; + } + else break; + } + } + return S_FALSE; } case (DWORD_PTR) DIPROP_VIDPID: FIXME("DIPROP_VIDPID not implemented\n"); @@ -1376,10 +1389,29 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty( case (DWORD_PTR) DIPROP_USERNAME: { LPCDIPROPSTRING ps = (LPCDIPROPSTRING)pdiph; + struct DevicePlayer *device_player; + BOOL found = FALSE; if (pdiph->dwSize != sizeof(DIPROPSTRING)) return DIERR_INVALIDPARAM; - lstrcpynW(This->username, ps->wsz, sizeof(This->username)/sizeof(WCHAR)); + LIST_FOR_EACH_ENTRY(device_player, &This->dinput->device_players, + struct DevicePlayer, entry) + { + if (IsEqualGUID(&device_player->instance_guid, &This->guid)) + { + found = TRUE; + break; + } + } + if (!found && (device_player = + HeapAlloc(GetProcessHeap(), 0, sizeof(struct DevicePlayer)))) + { + list_add_tail(&This->dinput->device_players, &device_player->entry); + device_player->instance_guid = This->guid; + } + if (device_player) + lstrcpynW(device_player->username, ps->wsz, + sizeof(device_player->username)/sizeof(WCHAR)); break; } default: diff --git a/reactos/dll/directx/wine/dinput/device_private.h b/reactos/dll/directx/wine/dinput/device_private.h index 3d89f60facc..bf227fd7f26 100644 --- a/reactos/dll/directx/wine/dinput/device_private.h +++ b/reactos/dll/directx/wine/dinput/device_private.h @@ -73,7 +73,6 @@ struct IDirectInputDeviceImpl /* Action mapping */ int num_actions; /* number of actions mapped */ ActionMap *action_map; /* array of mappings */ - WCHAR username[MAX_PATH]; }; extern BOOL get_app_key(HKEY*, HKEY*) DECLSPEC_HIDDEN; diff --git a/reactos/dll/directx/wine/dinput/dinput_main.c b/reactos/dll/directx/wine/dinput/dinput_main.c index 5127371cdd3..fc6d979c1de 100644 --- a/reactos/dll/directx/wine/dinput/dinput_main.c +++ b/reactos/dll/directx/wine/dinput/dinput_main.c @@ -558,6 +558,7 @@ static HRESULT initialize_directinput_instance(IDirectInputImpl *This, DWORD dwV This->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectInputImpl*->crit"); list_init( &This->devices_list ); + list_init( &This->device_players ); /* Add self to the list of the IDirectInputs */ EnterCriticalSection( &dinput_hook_crit ); @@ -580,11 +581,16 @@ static void uninitialize_directinput_instance(IDirectInputImpl *This) { if (This->initialized) { + struct DevicePlayer *device_player, *device_player2; /* Remove self from the list of the IDirectInputs */ EnterCriticalSection( &dinput_hook_crit ); list_remove( &This->entry ); LeaveCriticalSection( &dinput_hook_crit ); + LIST_FOR_EACH_ENTRY_SAFE( device_player, device_player2, + &This->device_players, struct DevicePlayer, entry ) + HeapFree(GetProcessHeap(), 0, device_player); + check_hook_thread(); This->crit.DebugInfo->Spare[0] = 0; @@ -898,6 +904,47 @@ static HRESULT WINAPI IDirectInput8WImpl_FindDevice(LPDIRECTINPUT8W iface, REFGU return IDirectInput2WImpl_FindDevice( &This->IDirectInput7W_iface, rguid, pszName, pguidInstance ); } +static BOOL should_enumerate_device(const WCHAR *username, DWORD dwFlags, + struct list *device_players, REFGUID guid) +{ + BOOL should_enumerate = TRUE; + struct DevicePlayer *device_player; + + /* Check if user owns this device */ + if (dwFlags & DIEDBSFL_THISUSER && username && *username) + { + should_enumerate = FALSE; + LIST_FOR_EACH_ENTRY(device_player, device_players, struct DevicePlayer, entry) + { + if (IsEqualGUID(&device_player->instance_guid, guid)) + { + if (*device_player->username && !lstrcmpW(username, device_player->username)) + return TRUE; /* Device username matches */ + break; + } + } + } + + /* Check if this device is not owned by anyone */ + if (dwFlags & DIEDBSFL_AVAILABLEDEVICES) { + BOOL found = FALSE; + should_enumerate = FALSE; + LIST_FOR_EACH_ENTRY(device_player, device_players, struct DevicePlayer, entry) + { + if (IsEqualGUID(&device_player->instance_guid, guid)) + { + if (*device_player->username) + found = TRUE; + break; + } + } + if (!found) + return TRUE; /* Device does not have a username */ + } + + return should_enumerate; +} + static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics( LPDIRECTINPUT8A iface, LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat, LPDIENUMDEVICESBYSEMANTICSCBA lpCallback, @@ -914,6 +961,7 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics( int device_count = 0; int remain; DIDEVICEINSTANCEA *didevis = 0; + WCHAR *username_w = 0; FIXME("(this=%p,%s,%p,%p,%p,%04x): semi-stub\n", This, debugstr_a(ptszUserName), lpdiActionFormat, lpCallback, pvRef, dwFlags); @@ -930,6 +978,14 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics( didevi.dwSize = sizeof(didevi); + if (ptszUserName) + { + int len = MultiByteToWideChar(CP_ACP, 0, ptszUserName, -1, 0, 0); + + username_w = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len); + MultiByteToWideChar(CP_ACP, 0, ptszUserName, -1, username_w, len); + } + /* Enumerate all the joysticks */ for (i = 0; i < NB_DINPUT_DEVICES; i++) { @@ -943,7 +999,8 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics( /* Default behavior is to enumerate attached game controllers */ enumSuccess = dinput_devices[i]->enum_deviceA(DI8DEVCLASS_GAMECTRL, DIEDFL_ATTACHEDONLY | dwFlags, &didevi, This->dwVersion, j); - if (enumSuccess == S_OK) + if (enumSuccess == S_OK && + should_enumerate_device(username_w, dwFlags, &This->device_players, &didevi.guidInstance)) { if (device_count++) didevis = HeapReAlloc(GetProcessHeap(), 0, didevis, sizeof(DIDEVICEINSTANCEA)*device_count); @@ -955,8 +1012,15 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics( } remain = device_count; + /* Add keyboard and mouse to remaining device count */ if (!(dwFlags & DIEDBSFL_FORCEFEEDBACK)) - remain += sizeof(guids)/sizeof(guids[0]); + { + for (i = 0; i < sizeof(guids) / sizeof(guids[0]); i++) + { + if (should_enumerate_device(username_w, dwFlags, &This->device_players, guids[i])) + remain++; + } + } for (i = 0; i < device_count; i++) { @@ -966,26 +1030,38 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics( if (lpCallback(&didevis[i], lpdid, callbackFlags, --remain, pvRef) == DIENUM_STOP) { HeapFree(GetProcessHeap(), 0, didevis); + HeapFree(GetProcessHeap(), 0, username_w); return DI_OK; } } HeapFree(GetProcessHeap(), 0, didevis); - if (dwFlags & DIEDBSFL_FORCEFEEDBACK) return DI_OK; + if (dwFlags & DIEDBSFL_FORCEFEEDBACK) + { + HeapFree(GetProcessHeap(), 0, username_w); + return DI_OK; + } /* Enumerate keyboard and mouse */ for(i=0; i < sizeof(guids)/sizeof(guids[0]); i++) { - callbackFlags = diactionformat_priorityA(lpdiActionFormat, actionMasks[i]); + if (should_enumerate_device(username_w, dwFlags, &This->device_players, guids[i])) + { + callbackFlags = diactionformat_priorityA(lpdiActionFormat, actionMasks[i]); - IDirectInput_CreateDevice(iface, guids[i], &lpdid, NULL); - IDirectInputDevice_GetDeviceInfo(lpdid, &didevi); + IDirectInput_CreateDevice(iface, guids[i], &lpdid, NULL); + IDirectInputDevice_GetDeviceInfo(lpdid, &didevi); - if (lpCallback(&didevi, lpdid, callbackFlags, sizeof(guids)/sizeof(guids[0]) - (i+1), pvRef) == DIENUM_STOP) - return DI_OK; + if (lpCallback(&didevi, lpdid, callbackFlags, --remain, pvRef) == DIENUM_STOP) + { + HeapFree(GetProcessHeap(), 0, username_w); + return DI_OK; + } + } } + HeapFree(GetProcessHeap(), 0, username_w); return DI_OK; } @@ -1024,7 +1100,8 @@ static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics( /* Default behavior is to enumerate attached game controllers */ enumSuccess = dinput_devices[i]->enum_deviceW(DI8DEVCLASS_GAMECTRL, DIEDFL_ATTACHEDONLY | dwFlags, &didevi, This->dwVersion, j); - if (enumSuccess == S_OK) + if (enumSuccess == S_OK && + should_enumerate_device(ptszUserName, dwFlags, &This->device_players, &didevi.guidInstance)) { if (device_count++) didevis = HeapReAlloc(GetProcessHeap(), 0, didevis, sizeof(DIDEVICEINSTANCEW)*device_count); @@ -1036,8 +1113,15 @@ static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics( } remain = device_count; + /* Add keyboard and mouse to remaining device count */ if (!(dwFlags & DIEDBSFL_FORCEFEEDBACK)) - remain += sizeof(guids)/sizeof(guids[0]); + { + for (i = 0; i < sizeof(guids) / sizeof(guids[0]); i++) + { + if (should_enumerate_device(ptszUserName, dwFlags, &This->device_players, guids[i])) + remain++; + } + } for (i = 0; i < device_count; i++) { @@ -1058,13 +1142,16 @@ static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics( /* Enumerate keyboard and mouse */ for(i=0; i < sizeof(guids)/sizeof(guids[0]); i++) { - callbackFlags = diactionformat_priorityW(lpdiActionFormat, actionMasks[i]); + if (should_enumerate_device(ptszUserName, dwFlags, &This->device_players, guids[i])) + { + callbackFlags = diactionformat_priorityW(lpdiActionFormat, actionMasks[i]); - IDirectInput_CreateDevice(iface, guids[i], &lpdid, NULL); - IDirectInputDevice_GetDeviceInfo(lpdid, &didevi); + IDirectInput_CreateDevice(iface, guids[i], &lpdid, NULL); + IDirectInputDevice_GetDeviceInfo(lpdid, &didevi); - if (lpCallback(&didevi, lpdid, callbackFlags, sizeof(guids)/sizeof(guids[0]) - (i+1), pvRef) == DIENUM_STOP) - return DI_OK; + if (lpCallback(&didevi, lpdid, callbackFlags, --remain, pvRef) == DIENUM_STOP) + return DI_OK; + } } return DI_OK; diff --git a/reactos/dll/directx/wine/dinput/dinput_private.h b/reactos/dll/directx/wine/dinput/dinput_private.h index a4692a44eb1..fb8c32ef17e 100644 --- a/reactos/dll/directx/wine/dinput/dinput_private.h +++ b/reactos/dll/directx/wine/dinput/dinput_private.h @@ -62,6 +62,7 @@ struct IDirectInputImpl DWORD evsequence; /* unique sequence number for events */ DWORD dwVersion; /* direct input version number */ struct list devices_list; /* list of all created dinput devices */ + struct list device_players; /* device instance guid to player name */ }; /* Function called by all devices that Wine supports */ @@ -72,6 +73,12 @@ struct dinput_device { HRESULT (*create_device)(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode); }; +struct DevicePlayer { + GUID instance_guid; + WCHAR username[MAX_PATH]; + struct list entry; +}; + extern const struct dinput_device mouse_device DECLSPEC_HIDDEN; extern const struct dinput_device keyboard_device DECLSPEC_HIDDEN; extern const struct dinput_device joystick_linux_device DECLSPEC_HIDDEN; diff --git a/reactos/dll/directx/wine/dinput/joystick_linux.c b/reactos/dll/directx/wine/dinput/joystick_linux.c index aba499d0a72..054e088d87b 100644 --- a/reactos/dll/directx/wine/dinput/joystick_linux.c +++ b/reactos/dll/directx/wine/dinput/joystick_linux.c @@ -208,19 +208,36 @@ static INT find_joystick_devices(void) else if ((joydev.dev_axes_map = HeapAlloc(GetProcessHeap(), 0, joydev.axis_count * sizeof(int)))) { - INT j; + INT j, found_axes = 0; /* Remap to DI numbers */ for (j = 0; j < joydev.axis_count; j++) + { if (axes_map[j] < 8) + { /* Axis match 1-to-1 */ joydev.dev_axes_map[j] = j; + found_axes++; + } else if (axes_map[j] == 16 || axes_map[j] == 17) + { /* POV axis */ joydev.dev_axes_map[j] = 8; + found_axes++; + } else joydev.dev_axes_map[j] = -1; + } + + /* If no axes were configured but there are axes assume a 1-to-1 (wii controller) */ + if (joydev.axis_count && !found_axes) + { + ERR("Incoherent joystick data, advertised %d axes, detected 0. Assuming 1-to-1.\n", + joydev.axis_count); + for (j = 0; j < joydev.axis_count; j++) + joydev.dev_axes_map[j] = j; + } } /* Find vendor_id and product_id in sysfs */ diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 415119b76c1..d0416140a14 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -30,7 +30,7 @@ reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-1.9.4 reactos/dll/directx/wine/d3dxof # Synced to WineStaging-1.9.23 reactos/dll/directx/wine/ddraw # Synced to WineStaging-1.9.4 reactos/dll/directx/wine/devenum # Synced to WineStaging-2.9 -reactos/dll/directx/wine/dinput # Synced to WineStaging-2.2 +reactos/dll/directx/wine/dinput # Synced to WineStaging-2.9 reactos/dll/directx/wine/dinput8 # Synced to WineStaging-1.9.23 reactos/dll/directx/wine/dmusic # Synced to WineStaging-1.9.23 reactos/dll/directx/wine/dplay # Synced to WineStaging-1.9.23