mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
Added dinput-joy-mappings patchset
This commit is contained in:
parent
a3faa8ac8a
commit
d6ab62c2be
@ -0,0 +1,79 @@
|
||||
From d5ea6db794ad1c943b4f8b03a3a5e0424a210ed3 Mon Sep 17 00:00:00 2001
|
||||
From: Jetro Jormalainen <jje-wine@jv.jetro.fi>
|
||||
Date: Tue, 30 Apr 2019 09:20:20 +1000
|
||||
Subject: [PATCH 1/3] dinput: Load users Joystick mappings.
|
||||
|
||||
---
|
||||
dlls/dinput/device.c | 2 +-
|
||||
dlls/dinput/device_private.h | 2 ++
|
||||
dlls/dinput/joystick.c | 18 ++++++++++++++++++
|
||||
3 files changed, 21 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
|
||||
index 6c44616..2150db7 100644
|
||||
--- a/dlls/dinput/device.c
|
||||
+++ b/dlls/dinput/device.c
|
||||
@@ -714,7 +714,7 @@ static HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORM
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
-static BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username)
|
||||
+BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username)
|
||||
{
|
||||
HKEY hkey;
|
||||
WCHAR *guid_str;
|
||||
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
|
||||
index d9e2997..af8d99d 100644
|
||||
--- a/dlls/dinput/device_private.h
|
||||
+++ b/dlls/dinput/device_private.h
|
||||
@@ -123,6 +123,8 @@ extern const char *_dump_dinput_GUID(const GUID *guid) DECLSPEC_HIDDEN;
|
||||
|
||||
extern LPDIOBJECTDATAFORMAT dataformat_to_odf_by_type(LPCDIDATAFORMAT df, int n, DWORD type) DECLSPEC_HIDDEN;
|
||||
|
||||
+extern BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username) DECLSPEC_HIDDEN;
|
||||
+
|
||||
extern HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, DWORD devMask, LPCDIDATAFORMAT df) DECLSPEC_HIDDEN;
|
||||
extern HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, LPCDIDATAFORMAT df) DECLSPEC_HIDDEN;
|
||||
|
||||
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
|
||||
index 4809831..b146712 100644
|
||||
--- a/dlls/dinput/joystick.c
|
||||
+++ b/dlls/dinput/joystick.c
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
+#include "device_private.h"
|
||||
#include "joystick_private.h"
|
||||
#include "wine/debug.h"
|
||||
#include "winreg.h"
|
||||
@@ -782,9 +783,26 @@ HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
|
||||
JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
unsigned int i, j;
|
||||
BOOL has_actions = FALSE;
|
||||
+ WCHAR username[MAX_PATH];
|
||||
+ DWORD username_size = MAX_PATH;
|
||||
+ BOOL load_success = FALSE;
|
||||
|
||||
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
|
||||
|
||||
+ /* Unless asked the contrary by these flags, try to load a previous mapping */
|
||||
+ if (!(dwFlags & DIDBAM_HWDEFAULTS))
|
||||
+ {
|
||||
+ /* Retrieve logged user name if necessary */
|
||||
+ if (lpszUserName == NULL)
|
||||
+ GetUserNameW(username, &username_size);
|
||||
+ else
|
||||
+ lstrcpynW(username, lpszUserName, MAX_PATH);
|
||||
+
|
||||
+ load_success = load_mapping_settings((IDirectInputDeviceImpl *) This, lpdiaf, username);
|
||||
+ }
|
||||
+
|
||||
+ if (load_success) return DI_OK;
|
||||
+
|
||||
for (i=0; i < lpdiaf->dwNumActions; i++)
|
||||
{
|
||||
DWORD inst = (0x000000ff & (lpdiaf->rgoAction[i].dwSemantic)) - 1;
|
||||
--
|
||||
1.9.1
|
||||
|
@ -0,0 +1,305 @@
|
||||
From 920014b62ddd2218477e3d82f45c4515742f9e28 Mon Sep 17 00:00:00 2001
|
||||
From: Jetro Jormalainen <jje-wine@jv.jetro.fi>
|
||||
Date: Tue, 30 Apr 2019 09:20:54 +1000
|
||||
Subject: [PATCH 2/3] dinput: Allow empty Joystick mappings.
|
||||
|
||||
---
|
||||
dlls/dinput/device.c | 82 +++++++++++++++++++++++++++++++++++++--------
|
||||
dlls/dinput/joystick.c | 2 ++
|
||||
dlls/dinput/keyboard.c | 2 ++
|
||||
dlls/dinput/mouse.c | 2 ++
|
||||
dlls/dinput8/tests/device.c | 50 +++++++++++++++++++++++++++
|
||||
5 files changed, 124 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
|
||||
index 2150db7..a7cfe36 100644
|
||||
--- a/dlls/dinput/device.c
|
||||
+++ b/dlls/dinput/device.c
|
||||
@@ -643,12 +643,30 @@ static DWORD semantic_to_obj_id(IDirectInputDeviceImpl* This, DWORD dwSemantic)
|
||||
return type | (0x0000ff00 & (obj_instance << 8));
|
||||
}
|
||||
|
||||
+static void del_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid) {
|
||||
+ static const WCHAR subkey[] = {
|
||||
+ 'S','o','f','t','w','a','r','e','\\',
|
||||
+ 'W','i','n','e','\\',
|
||||
+ 'D','i','r','e','c','t','I','n','p','u','t','\\',
|
||||
+ 'M','a','p','p','i','n','g','s','\\','%','s','\\','%','s','\\','%','s','\0'};
|
||||
+ WCHAR *keyname;
|
||||
+
|
||||
+ keyname = HeapAlloc(GetProcessHeap(), 0,
|
||||
+ sizeof(WCHAR) * (lstrlenW(subkey) + strlenW(username) + strlenW(device) + strlenW(guid)));
|
||||
+ sprintfW(keyname, subkey, username, device, guid);
|
||||
+
|
||||
+ /* Remove old key mappings so there will be no overlapping mappings */
|
||||
+ RegDeleteKeyW(HKEY_CURRENT_USER, keyname);
|
||||
+
|
||||
+ HeapFree(GetProcessHeap(), 0, keyname);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* get_mapping_key
|
||||
* Retrieves an open registry key to save the mapping, parametrized for an username,
|
||||
* specific device and specific action mapping guid.
|
||||
*/
|
||||
-static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid)
|
||||
+static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid, BOOL create)
|
||||
{
|
||||
static const WCHAR subkey[] = {
|
||||
'S','o','f','t','w','a','r','e','\\',
|
||||
@@ -663,8 +681,11 @@ static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WC
|
||||
sprintfW(keyname, subkey, username, device, guid);
|
||||
|
||||
/* The key used is HKCU\Software\Wine\DirectInput\Mappings\[username]\[device]\[mapping_guid] */
|
||||
- if (RegCreateKeyW(HKEY_CURRENT_USER, keyname, &hkey))
|
||||
- hkey = 0;
|
||||
+ if (create) {
|
||||
+ if (RegCreateKeyW(HKEY_CURRENT_USER, keyname, &hkey))
|
||||
+ hkey = 0;
|
||||
+ } else if (RegOpenKeyW(HKEY_CURRENT_USER, keyname, &hkey))
|
||||
+ hkey = 0;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, keyname);
|
||||
|
||||
@@ -684,7 +705,9 @@ static HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORM
|
||||
if (StringFromCLSID(&lpdiaf->guidActionMap, &guid_str) != S_OK)
|
||||
return DI_SETTINGSNOTSAVED;
|
||||
|
||||
- hkey = get_mapping_key(didev.tszInstanceName, lpszUsername, guid_str);
|
||||
+ del_mapping_key(didev.tszInstanceName, lpszUsername, guid_str);
|
||||
+
|
||||
+ hkey = get_mapping_key(didev.tszInstanceName, lpszUsername, guid_str, TRUE);
|
||||
|
||||
if (!hkey)
|
||||
{
|
||||
@@ -719,7 +742,7 @@ BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdia
|
||||
HKEY hkey;
|
||||
WCHAR *guid_str;
|
||||
DIDEVICEINSTANCEW didev;
|
||||
- int i, mapped = 0;
|
||||
+ int i;
|
||||
|
||||
didev.dwSize = sizeof(didev);
|
||||
IDirectInputDevice8_GetDeviceInfo(&This->IDirectInputDevice8W_iface, &didev);
|
||||
@@ -727,7 +750,7 @@ BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdia
|
||||
if (StringFromCLSID(&lpdiaf->guidActionMap, &guid_str) != S_OK)
|
||||
return FALSE;
|
||||
|
||||
- hkey = get_mapping_key(didev.tszInstanceName, username, guid_str);
|
||||
+ hkey = get_mapping_key(didev.tszInstanceName, username, guid_str, FALSE);
|
||||
|
||||
if (!hkey)
|
||||
{
|
||||
@@ -748,15 +771,21 @@ BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdia
|
||||
{
|
||||
lpdiaf->rgoAction[i].dwObjID = id;
|
||||
lpdiaf->rgoAction[i].guidInstance = didev.guidInstance;
|
||||
- lpdiaf->rgoAction[i].dwHow = DIAH_DEFAULT;
|
||||
- mapped += 1;
|
||||
+ lpdiaf->rgoAction[i].dwHow = DIAH_USERCONFIG;
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ memset(&lpdiaf->rgoAction[i].guidInstance, 0, sizeof(GUID));
|
||||
+ lpdiaf->rgoAction[i].dwHow = DIAH_UNMAPPED;
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
RegCloseKey(hkey);
|
||||
CoTaskMemFree(guid_str);
|
||||
|
||||
- return mapped > 0;
|
||||
+ /* On Windows BuildActionMap can open empty mapping, so always return TRUE if get_mapping_key is success */
|
||||
+ return TRUE;
|
||||
}
|
||||
|
||||
HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, DWORD devMask, LPCDIDATAFORMAT df)
|
||||
@@ -779,13 +808,18 @@ HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf,
|
||||
load_success = load_mapping_settings(This, lpdiaf, username);
|
||||
}
|
||||
|
||||
- if (load_success) return DI_OK;
|
||||
+ if (load_success) {
|
||||
+ /* Update dwCRC to track if action format has changed */
|
||||
+ for (i=0; i < lpdiaf->dwNumActions; i++)
|
||||
+ {
|
||||
+ lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2));
|
||||
+ lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5)));
|
||||
+ }
|
||||
+ return DI_OK;
|
||||
+ }
|
||||
|
||||
for (i=0; i < lpdiaf->dwNumActions; i++)
|
||||
{
|
||||
- /* Don't touch a user configured action */
|
||||
- if (lpdiaf->rgoAction[i].dwHow == DIAH_USERCONFIG) continue;
|
||||
-
|
||||
if ((lpdiaf->rgoAction[i].dwSemantic & devMask) == devMask)
|
||||
{
|
||||
DWORD obj_id = semantic_to_obj_id(This, lpdiaf->rgoAction[i].dwSemantic);
|
||||
@@ -816,6 +850,14 @@ HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf,
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Update dwCRC to track if action format has changed */
|
||||
+ lpdiaf->dwCRC = 0;
|
||||
+ for (i=0; i < lpdiaf->dwNumActions; i++)
|
||||
+ {
|
||||
+ lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2));
|
||||
+ lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5)));
|
||||
+ }
|
||||
+
|
||||
if (!has_actions) return DI_NOEFFECT;
|
||||
|
||||
return IDirectInputDevice8WImpl_BuildActionMap(iface, lpdiaf, lpszUserName, dwFlags);
|
||||
@@ -831,6 +873,7 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
|
||||
DIPROPSTRING dps;
|
||||
WCHAR username[MAX_PATH];
|
||||
DWORD username_size = MAX_PATH;
|
||||
+ DWORD new_crc = 0;
|
||||
int i, action = 0, num_actions = 0;
|
||||
unsigned int offset = 0;
|
||||
|
||||
@@ -841,12 +884,23 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
|
||||
data_format.dwFlags = DIDF_RELAXIS;
|
||||
data_format.dwDataSize = lpdiaf->dwDataSize;
|
||||
|
||||
+ /* Calculate checksum for actionformat */
|
||||
+ for (i=0; i < lpdiaf->dwNumActions; i++)
|
||||
+ {
|
||||
+ new_crc ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2));
|
||||
+ new_crc ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5)));
|
||||
+ }
|
||||
+
|
||||
/* Count the actions */
|
||||
for (i=0; i < lpdiaf->dwNumActions; i++)
|
||||
if (IsEqualGUID(&This->guid, &lpdiaf->rgoAction[i].guidInstance))
|
||||
num_actions++;
|
||||
|
||||
- if (num_actions == 0) return DI_NOEFFECT;
|
||||
+ /* Should return DI_NOEFFECT if we dont have any actions and actionformat has not changed */
|
||||
+ if (num_actions == 0 && lpdiaf->dwCRC == new_crc && !(dwFlags & DIDSAM_FORCESAVE)) return DI_NOEFFECT;
|
||||
+
|
||||
+ /* update dwCRC to track if action format has changed */
|
||||
+ lpdiaf->dwCRC = new_crc;
|
||||
|
||||
This->num_actions = num_actions;
|
||||
|
||||
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
|
||||
index b146712..267f932 100644
|
||||
--- a/dlls/dinput/joystick.c
|
||||
+++ b/dlls/dinput/joystick.c
|
||||
@@ -907,6 +907,8 @@ HRESULT WINAPI JoystickAGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
|
||||
|
||||
hr = JoystickWGenericImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
|
||||
|
||||
+ lpdiaf->dwCRC = diafW.dwCRC;
|
||||
+
|
||||
HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
|
||||
HeapFree(GetProcessHeap(), 0, lpszUserNameW);
|
||||
|
||||
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
|
||||
index 42c0759..5c5aa14 100644
|
||||
--- a/dlls/dinput/keyboard.c
|
||||
+++ b/dlls/dinput/keyboard.c
|
||||
@@ -693,6 +693,8 @@ static HRESULT WINAPI SysKeyboardAImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
|
||||
|
||||
hr = SysKeyboardWImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
|
||||
|
||||
+ lpdiaf->dwCRC = diafW.dwCRC;
|
||||
+
|
||||
HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
|
||||
HeapFree(GetProcessHeap(), 0, lpszUserNameW);
|
||||
|
||||
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
|
||||
index f3ec8e4..0adba03 100644
|
||||
--- a/dlls/dinput/mouse.c
|
||||
+++ b/dlls/dinput/mouse.c
|
||||
@@ -863,6 +863,8 @@ static HRESULT WINAPI SysMouseAImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
|
||||
|
||||
hr = SysMouseWImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
|
||||
|
||||
+ lpdiaf->dwCRC = diafW.dwCRC;
|
||||
+
|
||||
HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
|
||||
HeapFree(GetProcessHeap(), 0, lpszUserNameW);
|
||||
|
||||
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
|
||||
index 1bfb34a..46a1e4a 100644
|
||||
--- a/dlls/dinput8/tests/device.c
|
||||
+++ b/dlls/dinput8/tests/device.c
|
||||
@@ -38,6 +38,8 @@ struct enum_data {
|
||||
/* Dummy GUID */
|
||||
static const GUID ACTION_MAPPING_GUID = { 0x1, 0x2, 0x3, { 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb } };
|
||||
|
||||
+static const GUID NULL_GUID = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
+
|
||||
enum {
|
||||
DITEST_AXIS,
|
||||
DITEST_BUTTON,
|
||||
@@ -365,6 +367,17 @@ static void test_action_mapping(void)
|
||||
hr = IDirectInputDevice8_SetActionMap(data.keyboard, data.lpdiaf, NULL, 0);
|
||||
ok (hr == DI_NOEFFECT, "SetActionMap should have no effect with no actions to map hr=%08x\n", hr);
|
||||
|
||||
+ /* Test that after changing actionformat SetActionMap has effect and that second
|
||||
+ * SetActionMap call with same empty actionformat has no effect */
|
||||
+ af.dwDataSize = 4 * 1;
|
||||
+ af.dwNumActions = 1;
|
||||
+
|
||||
+ hr = IDirectInputDevice8_SetActionMap(data.keyboard, data.lpdiaf, NULL, 0);
|
||||
+ ok (hr != DI_NOEFFECT, "SetActionMap should have effect as actionformat has changed hr=%08x\n", hr);
|
||||
+
|
||||
+ hr = IDirectInputDevice8_SetActionMap(data.keyboard, data.lpdiaf, NULL, 0);
|
||||
+ ok (hr == DI_NOEFFECT, "SetActionMap should have no effect with no actions to map hr=%08x\n", hr);
|
||||
+
|
||||
af.dwDataSize = 4 * ARRAY_SIZE(actionMapping);
|
||||
af.dwNumActions = ARRAY_SIZE(actionMapping);
|
||||
|
||||
@@ -556,6 +569,43 @@ static void test_save_settings(void)
|
||||
"Mapped incorrectly expected: 0x%08x got: 0x%08x\n", other_results[1], af.rgoAction[1].dwObjID);
|
||||
ok (IsEqualGUID(&GUID_SysKeyboard, &af.rgoAction[1].guidInstance), "Action should be mapped to keyboard\n");
|
||||
|
||||
+ /* Save and load empty mapping */
|
||||
+ af.rgoAction[0].dwObjID = 0;
|
||||
+ af.rgoAction[0].dwHow = 0;
|
||||
+ memset(&af.rgoAction[0].guidInstance, 0, sizeof(GUID));
|
||||
+ af.rgoAction[1].dwObjID = 0;
|
||||
+ af.rgoAction[1].dwHow = 0;
|
||||
+ memset(&af.rgoAction[1].guidInstance, 0, sizeof(GUID));
|
||||
+
|
||||
+ hr = IDirectInputDevice8_SetActionMap(pKey, &af, NULL, DIDSAM_FORCESAVE);
|
||||
+ ok (SUCCEEDED(hr), "SetActionMap failed hr=%08x\n", hr);
|
||||
+
|
||||
+ if (hr == DI_SETTINGSNOTSAVED)
|
||||
+ {
|
||||
+ skip ("Can't test saving settings if SetActionMap returns DI_SETTINGSNOTSAVED\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ af.rgoAction[0].dwObjID = other_results[0];
|
||||
+ af.rgoAction[0].dwHow = DIAH_USERCONFIG;
|
||||
+ af.rgoAction[0].guidInstance = GUID_SysKeyboard;
|
||||
+ af.rgoAction[1].dwObjID = other_results[1];
|
||||
+ af.rgoAction[1].dwHow = DIAH_USERCONFIG;
|
||||
+ af.rgoAction[1].guidInstance = GUID_SysKeyboard;
|
||||
+
|
||||
+ hr = IDirectInputDevice8_BuildActionMap(pKey, &af, NULL, 0);
|
||||
+ ok (SUCCEEDED(hr), "BuildActionMap failed hr=%08x\n", hr);
|
||||
+
|
||||
+ ok (other_results[0] == af.rgoAction[0].dwObjID,
|
||||
+ "Mapped incorrectly expected: 0x%08x got: 0x%08x\n", other_results[0], af.rgoAction[0].dwObjID);
|
||||
+ ok (af.rgoAction[0].dwHow == DIAH_UNMAPPED, "dwHow should have been DIAH_UNMAPPED\n");
|
||||
+ ok (IsEqualGUID(&NULL_GUID, &af.rgoAction[0].guidInstance), "Action should not be mapped\n");
|
||||
+
|
||||
+ ok (other_results[1] == af.rgoAction[1].dwObjID,
|
||||
+ "Mapped incorrectly expected: 0x%08x got: 0x%08x\n", other_results[1], af.rgoAction[1].dwObjID);
|
||||
+ ok (af.rgoAction[1].dwHow == DIAH_UNMAPPED, "dwHow should have been DIAH_UNMAPPED\n");
|
||||
+ ok (IsEqualGUID(&NULL_GUID, &af.rgoAction[1].guidInstance), "Action should not be mapped\n");
|
||||
+
|
||||
IDirectInputDevice_Release(pKey);
|
||||
IDirectInput_Release(pDI);
|
||||
}
|
||||
--
|
||||
1.9.1
|
||||
|
@ -0,0 +1,428 @@
|
||||
From 9b284de24a4bb4972f7f165cdc41281d35dab492 Mon Sep 17 00:00:00 2001
|
||||
From: Jetro Jormalainen <jje-wine@jv.jetro.fi>
|
||||
Date: Tue, 30 Apr 2019 09:21:24 +1000
|
||||
Subject: [PATCH 3/3] dinput: Support username in Config dialog.
|
||||
|
||||
---
|
||||
dlls/dinput/config.c | 183 ++++++++++++++++++++++++++++++-------------
|
||||
dlls/dinput/device.c | 2 +-
|
||||
dlls/dinput/device_private.h | 1 +
|
||||
dlls/dinput/dinput_main.c | 27 +++++++
|
||||
4 files changed, 156 insertions(+), 57 deletions(-)
|
||||
|
||||
diff --git a/dlls/dinput/config.c b/dlls/dinput/config.c
|
||||
index db5878b..f42a44a 100644
|
||||
--- a/dlls/dinput/config.c
|
||||
+++ b/dlls/dinput/config.c
|
||||
@@ -29,6 +29,9 @@ typedef struct {
|
||||
IDirectInputDevice8W *lpdid;
|
||||
DIDEVICEINSTANCEW ddi;
|
||||
DIDEVICEOBJECTINSTANCEW ddo[256];
|
||||
+ /* ActionFormat for every user.
|
||||
+ * In same order as ConfigureDevicesData usernames */
|
||||
+ DIACTIONFORMATW *user_afs;
|
||||
} DeviceData;
|
||||
|
||||
typedef struct {
|
||||
@@ -38,10 +41,11 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
IDirectInput8W *lpDI;
|
||||
- LPDIACTIONFORMATW lpdiaf;
|
||||
LPDIACTIONFORMATW original_lpdiaf;
|
||||
DIDevicesData devices_data;
|
||||
int display_only;
|
||||
+ int nusernames;
|
||||
+ WCHAR **usernames;
|
||||
} ConfigureDevicesData;
|
||||
|
||||
/*
|
||||
@@ -57,27 +61,42 @@ static BOOL CALLBACK collect_objects(LPCDIDEVICEOBJECTINSTANCEW lpddo, LPVOID pv
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
-static BOOL CALLBACK count_devices(LPCDIDEVICEINSTANCEW lpddi, IDirectInputDevice8W *lpdid, DWORD dwFlags, DWORD dwRemaining, LPVOID pvRef)
|
||||
+static BOOL CALLBACK collect_devices(LPCDIDEVICEINSTANCEW lpddi, IDirectInputDevice8W *lpdid, DWORD dwFlags, DWORD dwRemaining, LPVOID pvRef)
|
||||
{
|
||||
- DIDevicesData *data = (DIDevicesData*) pvRef;
|
||||
+ ConfigureDevicesData *data = (ConfigureDevicesData*) pvRef;
|
||||
+ DeviceData *device;
|
||||
+ int i, j;
|
||||
|
||||
- data->ndevices++;
|
||||
- return DIENUM_CONTINUE;
|
||||
-}
|
||||
+ IDirectInputDevice_AddRef(lpdid);
|
||||
|
||||
-static BOOL CALLBACK collect_devices(LPCDIDEVICEINSTANCEW lpddi, IDirectInputDevice8W *lpdid, DWORD dwFlags, DWORD dwRemaining, LPVOID pvRef)
|
||||
-{
|
||||
- DIDevicesData *data = (DIDevicesData*) pvRef;
|
||||
- DeviceData *device = &data->devices[data->ndevices];
|
||||
+ /* alloc array for devices if this is our first device */
|
||||
+ if (!data->devices_data.ndevices)
|
||||
+ data->devices_data.devices = HeapAlloc(GetProcessHeap(), 0, sizeof(DeviceData) * (dwRemaining + 1));
|
||||
+ device = &data->devices_data.devices[data->devices_data.ndevices];
|
||||
device->lpdid = lpdid;
|
||||
device->ddi = *lpddi;
|
||||
|
||||
- IDirectInputDevice_AddRef(lpdid);
|
||||
-
|
||||
device->nobjects = 0;
|
||||
IDirectInputDevice_EnumObjects(lpdid, collect_objects, (LPVOID) device, DIDFT_ALL);
|
||||
|
||||
- data->ndevices++;
|
||||
+ device->user_afs = HeapAlloc(GetProcessHeap(), 0, sizeof(*device->user_afs)*data->nusernames);
|
||||
+ memset(device->user_afs, 0, sizeof(*device->user_afs)*data->nusernames);
|
||||
+ for (i = 0; i < data->nusernames; i++)
|
||||
+ {
|
||||
+ DIACTIONFORMATW *user_af = &device->user_afs[i];
|
||||
+ user_af->dwNumActions = data->original_lpdiaf->dwNumActions;
|
||||
+ user_af->guidActionMap = data->original_lpdiaf->guidActionMap;
|
||||
+ user_af->rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*data->original_lpdiaf->dwNumActions);
|
||||
+ memset(user_af->rgoAction, 0, sizeof(DIACTIONW)*data->original_lpdiaf->dwNumActions);
|
||||
+ for (j = 0; j < user_af->dwNumActions; j++)
|
||||
+ {
|
||||
+ user_af->rgoAction[j].dwSemantic = data->original_lpdiaf->rgoAction[j].dwSemantic;
|
||||
+ user_af->rgoAction[j].u.lptszActionName = data->original_lpdiaf->rgoAction[j].u.lptszActionName;
|
||||
+ }
|
||||
+ IDirectInputDevice8_BuildActionMap(lpdid, user_af, data->usernames[i], 0);
|
||||
+ }
|
||||
+
|
||||
+ data->devices_data.ndevices++;
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -170,10 +189,18 @@ static DeviceData* get_cur_device(HWND dialog)
|
||||
return &data->devices_data.devices[sel];
|
||||
}
|
||||
|
||||
-static LPDIACTIONFORMATW get_cur_lpdiaf(HWND dialog)
|
||||
+static DIACTIONFORMATW *get_cur_lpdiaf(HWND dialog)
|
||||
+{
|
||||
+ ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
|
||||
+ int controller_sel = SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_GETCURSEL, 0, 0);
|
||||
+ int player_sel = SendDlgItemMessageW(dialog, IDC_PLAYERCOMBO, CB_GETCURSEL, 0, 0);
|
||||
+ return &data->devices_data.devices[controller_sel].user_afs[player_sel];
|
||||
+}
|
||||
+
|
||||
+static DIACTIONFORMATW *get_original_lpdiaf(HWND dialog)
|
||||
{
|
||||
ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
|
||||
- return data->lpdiaf;
|
||||
+ return data->original_lpdiaf;
|
||||
}
|
||||
|
||||
static int dialog_display_only(HWND dialog)
|
||||
@@ -182,40 +209,36 @@ static int dialog_display_only(HWND dialog)
|
||||
return data->display_only;
|
||||
}
|
||||
|
||||
-static void init_devices(HWND dialog, IDirectInput8W *lpDI, DIDevicesData *data, LPDIACTIONFORMATW lpdiaf)
|
||||
+static void init_devices(HWND dialog, ConfigureDevicesData *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
- /* Count devices */
|
||||
- data->ndevices = 0;
|
||||
- IDirectInput8_EnumDevicesBySemantics(lpDI, NULL, lpdiaf, count_devices, (LPVOID) data, 0);
|
||||
-
|
||||
- /* Allocate devices */
|
||||
- data->devices = HeapAlloc(GetProcessHeap(), 0, sizeof(DeviceData) * data->ndevices);
|
||||
-
|
||||
/* Collect and insert */
|
||||
- data->ndevices = 0;
|
||||
- IDirectInput8_EnumDevicesBySemantics(lpDI, NULL, lpdiaf, collect_devices, (LPVOID) data, 0);
|
||||
+ data->devices_data.ndevices = 0;
|
||||
+ IDirectInput8_EnumDevicesBySemantics(data->lpDI, NULL, data->original_lpdiaf, collect_devices, (LPVOID) data, 0);
|
||||
|
||||
- for (i=0; i < data->ndevices; i++)
|
||||
- SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_ADDSTRING, 0, (LPARAM) data->devices[i].ddi.tszProductName );
|
||||
+ for (i = 0; i < data->devices_data.ndevices; i++)
|
||||
+ SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_ADDSTRING, 0, (LPARAM) data->devices_data.devices[i].ddi.tszProductName );
|
||||
+ for (i = 0; i < data->nusernames; i++)
|
||||
+ SendDlgItemMessageW(dialog, IDC_PLAYERCOMBO, CB_ADDSTRING, 0, (LPARAM) data->usernames[i]);
|
||||
}
|
||||
|
||||
static void destroy_data(HWND dialog)
|
||||
{
|
||||
- int i;
|
||||
+ int i, j;
|
||||
ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
|
||||
DIDevicesData *devices_data = &data->devices_data;
|
||||
|
||||
/* Free the devices */
|
||||
for (i=0; i < devices_data->ndevices; i++)
|
||||
+ {
|
||||
IDirectInputDevice8_Release(devices_data->devices[i].lpdid);
|
||||
+ for (j=0; j < data->nusernames; j++)
|
||||
+ HeapFree(GetProcessHeap(), 0, devices_data->devices[i].user_afs[j].rgoAction);
|
||||
+ HeapFree(GetProcessHeap(), 0, devices_data->devices[i].user_afs);
|
||||
+ }
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, devices_data->devices);
|
||||
-
|
||||
- /* Free the backup LPDIACTIONFORMATW */
|
||||
- HeapFree(GetProcessHeap(), 0, data->original_lpdiaf->rgoAction);
|
||||
- HeapFree(GetProcessHeap(), 0, data->original_lpdiaf);
|
||||
}
|
||||
|
||||
static void fill_device_object_list(HWND dialog)
|
||||
@@ -231,6 +254,7 @@ static void fill_device_object_list(HWND dialog)
|
||||
/* Add each object */
|
||||
for (i=0; i < device->nobjects; i++)
|
||||
{
|
||||
+ DWORD ddo_inst, ddo_type;
|
||||
int action = -1;
|
||||
|
||||
item.mask = LVIF_TEXT | LVIF_PARAM;
|
||||
@@ -241,12 +265,20 @@ static void fill_device_object_list(HWND dialog)
|
||||
|
||||
/* Add the item */
|
||||
SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_INSERTITEMW, 0, (LPARAM) &item);
|
||||
+ ddo_inst = DIDFT_GETINSTANCE(device->ddo[i].dwType);
|
||||
+ ddo_type = DIDFT_GETTYPE(device->ddo[i].dwType);
|
||||
|
||||
- /* Search for an assigned action for this device */
|
||||
+ /* Search for an assigned action for this device */
|
||||
for (j=0; j < lpdiaf->dwNumActions; j++)
|
||||
{
|
||||
+ DWORD af_inst = DIDFT_GETINSTANCE(lpdiaf->rgoAction[j].dwObjID);
|
||||
+ DWORD af_type = DIDFT_GETTYPE(lpdiaf->rgoAction[j].dwObjID);
|
||||
+ if (af_type == DIDFT_PSHBUTTON) af_type = DIDFT_BUTTON;
|
||||
+ if (af_type == DIDFT_RELAXIS) af_type = DIDFT_AXIS;
|
||||
+ /* NOTE previously compared dwType == dwObjId but default buildActionMap actions
|
||||
+ * were PSHBUTTON and RELAXS and didnt show up on config */
|
||||
if (IsEqualGUID(&lpdiaf->rgoAction[j].guidInstance, &device->ddi.guidInstance) &&
|
||||
- lpdiaf->rgoAction[j].dwObjID == device->ddo[i].dwType)
|
||||
+ ddo_inst == af_inst && ddo_type & af_type)
|
||||
{
|
||||
action = j;
|
||||
break;
|
||||
@@ -260,7 +292,7 @@ static void fill_device_object_list(HWND dialog)
|
||||
static void show_suitable_actions(HWND dialog)
|
||||
{
|
||||
DeviceData *device = get_cur_device(dialog);
|
||||
- LPDIACTIONFORMATW lpdiaf = get_cur_lpdiaf(dialog);
|
||||
+ LPDIACTIONFORMATW lpdiaf = get_original_lpdiaf(dialog);
|
||||
int i, added = 0;
|
||||
int obj = lv_get_cur_item(dialog);
|
||||
|
||||
@@ -329,24 +361,35 @@ static void assign_action(HWND dialog)
|
||||
lv_set_action(dialog, obj, action, lpdiaf);
|
||||
}
|
||||
|
||||
-static void copy_actions(LPDIACTIONFORMATW to, LPDIACTIONFORMATW from)
|
||||
+static void reset_actions(HWND dialog)
|
||||
{
|
||||
- DWORD i;
|
||||
- for (i=0; i < from->dwNumActions; i++)
|
||||
+ ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
|
||||
+ DIDevicesData *ddata = (DIDevicesData*) &data->devices_data;
|
||||
+ unsigned i, j;
|
||||
+
|
||||
+ for (i = 0; i < data->devices_data.ndevices; i++)
|
||||
{
|
||||
- to->rgoAction[i].guidInstance = from->rgoAction[i].guidInstance;
|
||||
- to->rgoAction[i].dwObjID = from->rgoAction[i].dwObjID;
|
||||
- to->rgoAction[i].dwHow = from->rgoAction[i].dwHow;
|
||||
- to->rgoAction[i].u.lptszActionName = from->rgoAction[i].u.lptszActionName;
|
||||
+ DeviceData *device = &ddata->devices[i];
|
||||
+ for (j = 0; j < data->nusernames; j++)
|
||||
+ IDirectInputDevice8_BuildActionMap(device->lpdid, &device->user_afs[j], data->usernames[j], DIDBAM_HWDEFAULTS);
|
||||
}
|
||||
}
|
||||
|
||||
-static void reset_actions(HWND dialog)
|
||||
-{
|
||||
+static void save_actions(HWND dialog) {
|
||||
ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
|
||||
- LPDIACTIONFORMATW to = data->lpdiaf, from = data->original_lpdiaf;
|
||||
-
|
||||
- copy_actions(to, from);
|
||||
+ DIDevicesData *ddata = (DIDevicesData*) &data->devices_data;
|
||||
+ unsigned i, j;
|
||||
+ if (!data->display_only) {
|
||||
+ for (i = 0; i < ddata->ndevices; i++)
|
||||
+ {
|
||||
+ DeviceData *device = &ddata->devices[i];
|
||||
+ for (j = 0; j < data->nusernames; j++)
|
||||
+ {
|
||||
+ if (save_mapping_settings(device->lpdid, &device->user_afs[j], data->usernames[j]) != DI_OK)
|
||||
+ MessageBoxA(dialog, "Could not save settings", 0, MB_ICONERROR);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK ConfigureDevicesDlgProc(HWND dialog, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
@@ -358,21 +401,16 @@ static INT_PTR CALLBACK ConfigureDevicesDlgProc(HWND dialog, UINT uMsg, WPARAM w
|
||||
ConfigureDevicesData *data = (ConfigureDevicesData*) lParam;
|
||||
|
||||
/* Initialize action format and enumerate devices */
|
||||
- init_devices(dialog, data->lpDI, &data->devices_data, data->lpdiaf);
|
||||
+ init_devices(dialog, data);
|
||||
|
||||
/* Store information in the window */
|
||||
SetWindowLongPtrW(dialog, DWLP_USER, (LONG_PTR) data);
|
||||
|
||||
init_listview_columns(dialog);
|
||||
|
||||
- /* Create a backup action format for CANCEL and RESET operations */
|
||||
- data->original_lpdiaf = HeapAlloc(GetProcessHeap(), 0, sizeof(*data->original_lpdiaf));
|
||||
- data->original_lpdiaf->dwNumActions = data->lpdiaf->dwNumActions;
|
||||
- data->original_lpdiaf->rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*data->lpdiaf->dwNumActions);
|
||||
- copy_actions(data->original_lpdiaf, data->lpdiaf);
|
||||
-
|
||||
/* Select the first device and show its actions */
|
||||
SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_SETCURSEL, 0, 0);
|
||||
+ SendDlgItemMessageW(dialog, IDC_PLAYERCOMBO, CB_SETCURSEL, 0, 0);
|
||||
fill_device_object_list(dialog);
|
||||
|
||||
break;
|
||||
@@ -408,6 +446,7 @@ static INT_PTR CALLBACK ConfigureDevicesDlgProc(HWND dialog, UINT uMsg, WPARAM w
|
||||
break;
|
||||
|
||||
case IDC_CONTROLLERCOMBO:
|
||||
+ case IDC_PLAYERCOMBO:
|
||||
|
||||
switch (HIWORD(wParam))
|
||||
{
|
||||
@@ -418,12 +457,12 @@ static INT_PTR CALLBACK ConfigureDevicesDlgProc(HWND dialog, UINT uMsg, WPARAM w
|
||||
break;
|
||||
|
||||
case IDOK:
|
||||
+ save_actions(dialog);
|
||||
EndDialog(dialog, 0);
|
||||
destroy_data(dialog);
|
||||
break;
|
||||
|
||||
case IDCANCEL:
|
||||
- reset_actions(dialog);
|
||||
EndDialog(dialog, 0);
|
||||
destroy_data(dialog);
|
||||
break;
|
||||
@@ -446,15 +485,47 @@ HRESULT _configure_devices(IDirectInput8W *iface,
|
||||
LPVOID pvRefData
|
||||
)
|
||||
{
|
||||
+ int i;
|
||||
+ DWORD default_username_size = MAX_PATH;
|
||||
+ WCHAR *default_username = 0;
|
||||
ConfigureDevicesData data;
|
||||
data.lpDI = iface;
|
||||
- data.lpdiaf = lpdiCDParams->lprgFormats;
|
||||
+ data.original_lpdiaf = lpdiCDParams->lprgFormats;
|
||||
data.display_only = !(dwFlags & DICD_EDIT);
|
||||
+ data.nusernames = lpdiCDParams->dwcUsers;
|
||||
+ if (lpdiCDParams->lptszUserNames == NULL)
|
||||
+ {
|
||||
+ /* Get default user name */
|
||||
+ default_username = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*MAX_PATH);
|
||||
+ data.nusernames = 1;
|
||||
+ data.usernames = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *));
|
||||
+ data.usernames[0] = default_username;
|
||||
+ GetUserNameW(default_username, &default_username_size);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ WCHAR *p = lpdiCDParams->lptszUserNames;
|
||||
+ data.usernames = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *)*data.nusernames);
|
||||
+ for (i = 0; i < data.nusernames; i++)
|
||||
+ {
|
||||
+ if (*p)
|
||||
+ {
|
||||
+ data.usernames[i] = p;
|
||||
+ while (*(p++));
|
||||
+ }
|
||||
+ else
|
||||
+ /* Return if there is an empty string */
|
||||
+ return DIERR_INVALIDPARAM;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
InitCommonControls();
|
||||
|
||||
DialogBoxParamW(DINPUT_instance, (const WCHAR *)MAKEINTRESOURCE(IDD_CONFIGUREDEVICES),
|
||||
lpdiCDParams->hwnd, ConfigureDevicesDlgProc, (LPARAM)&data);
|
||||
|
||||
+ HeapFree(GetProcessHeap(), 0, default_username);
|
||||
+ HeapFree(GetProcessHeap(), 0, data.usernames);
|
||||
+
|
||||
return DI_OK;
|
||||
}
|
||||
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
|
||||
index a7cfe36..63eb868 100644
|
||||
--- a/dlls/dinput/device.c
|
||||
+++ b/dlls/dinput/device.c
|
||||
@@ -692,7 +692,7 @@ static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WC
|
||||
return hkey;
|
||||
}
|
||||
|
||||
-static HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername)
|
||||
+HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername)
|
||||
{
|
||||
WCHAR *guid_str = NULL;
|
||||
DIDEVICEINSTANCEW didev;
|
||||
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
|
||||
index af8d99d..36b71f7 100644
|
||||
--- a/dlls/dinput/device_private.h
|
||||
+++ b/dlls/dinput/device_private.h
|
||||
@@ -123,6 +123,7 @@ extern const char *_dump_dinput_GUID(const GUID *guid) DECLSPEC_HIDDEN;
|
||||
|
||||
extern LPDIOBJECTDATAFORMAT dataformat_to_odf_by_type(LPCDIDATAFORMAT df, int n, DWORD type) DECLSPEC_HIDDEN;
|
||||
|
||||
+extern HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername) DECLSPEC_HIDDEN;
|
||||
extern BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username) DECLSPEC_HIDDEN;
|
||||
|
||||
extern HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, DWORD devMask, LPCDIDATAFORMAT df) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
|
||||
index 1b2020c..9e837bd 100644
|
||||
--- a/dlls/dinput/dinput_main.c
|
||||
+++ b/dlls/dinput/dinput_main.c
|
||||
@@ -1264,9 +1264,34 @@ static HRESULT WINAPI IDirectInput8AImpl_ConfigureDevices(
|
||||
|
||||
/* Copy parameters */
|
||||
diCDParamsW.dwSize = sizeof(DICONFIGUREDEVICESPARAMSW);
|
||||
+ diCDParamsW.dwcUsers = lpdiCDParams->dwcUsers;
|
||||
diCDParamsW.dwcFormats = lpdiCDParams->dwcFormats;
|
||||
diCDParamsW.lprgFormats = &diafW;
|
||||
diCDParamsW.hwnd = lpdiCDParams->hwnd;
|
||||
+ diCDParamsW.lptszUserNames = NULL;
|
||||
+
|
||||
+ if (lpdiCDParams->lptszUserNames) {
|
||||
+ char *start = lpdiCDParams->lptszUserNames;
|
||||
+ WCHAR *to = NULL;
|
||||
+ int total_len = 0;
|
||||
+ for (i = 0; i < lpdiCDParams->dwcUsers; i++)
|
||||
+ {
|
||||
+ char *end = start + 1;
|
||||
+ int len;
|
||||
+ while (*(end++));
|
||||
+ len = MultiByteToWideChar(CP_ACP, 0, start, end - start, NULL, 0);
|
||||
+ total_len += len + 2; /* length of string and two null char */
|
||||
+ if (to)
|
||||
+ to = HeapReAlloc(GetProcessHeap(), 0, to, sizeof(WCHAR) * total_len);
|
||||
+ else
|
||||
+ to = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * total_len);
|
||||
+
|
||||
+ MultiByteToWideChar(CP_ACP, 0, start, end - start, to + (total_len - len - 2), len);
|
||||
+ to[total_len] = 0;
|
||||
+ to[total_len - 1] = 0;
|
||||
+ }
|
||||
+ diCDParamsW.lptszUserNames = to;
|
||||
+ }
|
||||
|
||||
diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiCDParams->lprgFormats->dwNumActions);
|
||||
_copy_diactionformatAtoW(&diafW, lpdiCDParams->lprgFormats);
|
||||
@@ -1294,6 +1319,8 @@ static HRESULT WINAPI IDirectInput8AImpl_ConfigureDevices(
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
|
||||
|
||||
+ HeapFree(GetProcessHeap(), 0, (void*) diCDParamsW.lptszUserNames);
|
||||
+
|
||||
return hr;
|
||||
}
|
||||
|
||||
--
|
||||
1.9.1
|
||||
|
1
patches/dinput-joy-mappings/definition
Normal file
1
patches/dinput-joy-mappings/definition
Normal file
@ -0,0 +1 @@
|
||||
Fixes: [34108] dinput: Improve support for user Joystick configuration.
|
@ -130,6 +130,7 @@ patch_enable_all ()
|
||||
enable_ddraw_Write_Vtable="$1"
|
||||
enable_ddraw_version_check="$1"
|
||||
enable_dinput_axis_recalc="$1"
|
||||
enable_dinput_joy_mappings="$1"
|
||||
enable_dinput_reconnect_joystick="$1"
|
||||
enable_dinput_remap_joystick="$1"
|
||||
enable_dsound_EAX="$1"
|
||||
@ -522,6 +523,9 @@ patch_enable ()
|
||||
dinput-axis-recalc)
|
||||
enable_dinput_axis_recalc="$2"
|
||||
;;
|
||||
dinput-joy-mappings)
|
||||
enable_dinput_joy_mappings="$2"
|
||||
;;
|
||||
dinput-reconnect-joystick)
|
||||
enable_dinput_reconnect_joystick="$2"
|
||||
;;
|
||||
@ -3075,6 +3079,26 @@ if test "$enable_dinput_axis_recalc" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset dinput-joy-mappings
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#34108] dinput: Improve support for user Joystick configuration.
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/dinput/config.c, dlls/dinput/device.c, dlls/dinput/device_private.h, dlls/dinput/dinput_main.c,
|
||||
# | dlls/dinput/joystick.c, dlls/dinput/keyboard.c, dlls/dinput/mouse.c, dlls/dinput8/tests/device.c
|
||||
# |
|
||||
if test "$enable_dinput_joy_mappings" -eq 1; then
|
||||
patch_apply dinput-joy-mappings/0001-dinput-Load-users-Joystick-mappings.patch
|
||||
patch_apply dinput-joy-mappings/0002-dinput-Allow-empty-Joystick-mappings.patch
|
||||
patch_apply dinput-joy-mappings/0003-dinput-Support-username-in-Config-dialog.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Jetro Jormalainen", "dinput: Load users Joystick mappings.", 1 },';
|
||||
printf '%s\n' '+ { "Jetro Jormalainen", "dinput: Allow empty Joystick mappings.", 1 },';
|
||||
printf '%s\n' '+ { "Jetro Jormalainen", "dinput: Support username in Config dialog.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset dinput-reconnect-joystick
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
Loading…
Reference in New Issue
Block a user