dinput: Implement DIPROP_APPDATA.
This fixes not working analog inputs on game controllers in Slay the Spire. Signed-off-by: Arkadiusz Hiler <ahiler@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
fb56afae15
commit
8d206333fd
|
@ -571,6 +571,22 @@ failed:
|
|||
return DIERR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
static int verify_offset(const DataFormat *df, int offset)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!df->offsets)
|
||||
return -1;
|
||||
|
||||
for (i = df->wine_df->dwNumObjs - 1; i >= 0; i--)
|
||||
{
|
||||
if (df->offsets[i] == offset)
|
||||
return offset;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* find an object by its offset in a data format */
|
||||
static int offset_to_object(const DataFormat *df, int offset)
|
||||
{
|
||||
|
@ -759,6 +775,46 @@ static BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMAT
|
|||
return mapped > 0;
|
||||
}
|
||||
|
||||
static BOOL set_app_data(IDirectInputDeviceImpl *dev, int offset, UINT_PTR app_data)
|
||||
{
|
||||
int num_actions = dev->num_actions;
|
||||
ActionMap *action_map = dev->action_map, *target_map = NULL;
|
||||
|
||||
if (num_actions == 0)
|
||||
{
|
||||
num_actions = 1;
|
||||
action_map = HeapAlloc(GetProcessHeap(), 0, sizeof(ActionMap));
|
||||
if (!action_map) return FALSE;
|
||||
target_map = &action_map[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num_actions; i++)
|
||||
{
|
||||
if (dev->action_map[i].offset != offset) continue;
|
||||
target_map = &dev->action_map[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (!target_map)
|
||||
{
|
||||
num_actions++;
|
||||
action_map = HeapReAlloc(GetProcessHeap(), 0, action_map, sizeof(ActionMap)*num_actions);
|
||||
if (!action_map) return FALSE;
|
||||
target_map = &action_map[num_actions-1];
|
||||
}
|
||||
}
|
||||
|
||||
target_map->offset = offset;
|
||||
target_map->uAppData = app_data;
|
||||
|
||||
dev->action_map = action_map;
|
||||
dev->num_actions = num_actions;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, DWORD devMask, LPCDIDATAFORMAT df)
|
||||
{
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
|
@ -1447,6 +1503,23 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty(
|
|||
lstrcpynW(device_player->username, ps->wsz, ARRAY_SIZE(device_player->username));
|
||||
break;
|
||||
}
|
||||
case (DWORD_PTR) DIPROP_APPDATA:
|
||||
{
|
||||
int offset = -1;
|
||||
LPCDIPROPPOINTER pp = (LPCDIPROPPOINTER)pdiph;
|
||||
if (pdiph->dwSize != sizeof(DIPROPPOINTER)) return DIERR_INVALIDPARAM;
|
||||
|
||||
if (pdiph->dwHow == DIPH_BYID)
|
||||
offset = id_to_offset(&This->data_format, pdiph->dwObj);
|
||||
else if (pdiph->dwHow == DIPH_BYOFFSET)
|
||||
offset = verify_offset(&This->data_format, pdiph->dwObj);
|
||||
else
|
||||
return DIERR_UNSUPPORTED;
|
||||
|
||||
if (offset == -1) return DIERR_OBJECTNOTFOUND;
|
||||
if (!set_app_data(This, offset, pp->uData)) return DIERR_OUTOFMEMORY;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WARN("Unknown property %s\n", debugstr_guid(rguid));
|
||||
return DIERR_UNSUPPORTED;
|
||||
|
|
|
@ -294,6 +294,48 @@ static BOOL CALLBACK enumeration_callback(const DIDEVICEINSTANCEA *lpddi, IDirec
|
|||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
static void test_appdata_property_vs_map(struct enum_data *data)
|
||||
{
|
||||
HRESULT hr;
|
||||
DIPROPPOINTER dp;
|
||||
|
||||
dp.diph.dwSize = sizeof(dp);
|
||||
dp.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
dp.diph.dwHow = DIPH_BYID;
|
||||
dp.diph.dwObj = DIDFT_MAKEINSTANCE(DIK_SPACE) | DIDFT_PSHBUTTON;
|
||||
dp.uData = 10;
|
||||
hr = IDirectInputDevice8_SetProperty(data->keyboard, DIPROP_APPDATA, &(dp.diph));
|
||||
ok(SUCCEEDED(hr), "IDirectInputDevice8_SetProperty failed hr=%08x\n", hr);
|
||||
|
||||
test_device_input(data->keyboard, INPUT_KEYBOARD, VK_SPACE, 10);
|
||||
|
||||
dp.diph.dwHow = DIPH_BYID;
|
||||
dp.diph.dwObj = DIDFT_MAKEINSTANCE(DIK_V) | DIDFT_PSHBUTTON;
|
||||
dp.uData = 11;
|
||||
hr = IDirectInputDevice8_SetProperty(data->keyboard, DIPROP_APPDATA, &(dp.diph));
|
||||
ok(hr == DIERR_OBJECTNOTFOUND, "IDirectInputDevice8_SetProperty should not find key that's not in the action map hr=%08x\n", hr);
|
||||
|
||||
/* setting format should reset action map */
|
||||
hr = IDirectInputDevice8_SetDataFormat(data->keyboard, &c_dfDIKeyboard);
|
||||
ok(SUCCEEDED(hr), "SetDataFormat failed: %08x\n", hr);
|
||||
|
||||
test_device_input(data->keyboard, INPUT_KEYBOARD, VK_SPACE, -1);
|
||||
|
||||
dp.diph.dwHow = DIPH_BYID;
|
||||
dp.diph.dwObj = DIDFT_MAKEINSTANCE(DIK_V) | DIDFT_PSHBUTTON;
|
||||
dp.uData = 11;
|
||||
hr = IDirectInputDevice8_SetProperty(data->keyboard, DIPROP_APPDATA, &(dp.diph));
|
||||
ok(SUCCEEDED(hr), "IDirectInputDevice8_SetProperty failed hr=%08x\n", hr);
|
||||
|
||||
test_device_input(data->keyboard, INPUT_KEYBOARD, 'V', 11);
|
||||
|
||||
/* back to action map */
|
||||
hr = IDirectInputDevice8_SetActionMap(data->keyboard, data->lpdiaf, NULL, 0);
|
||||
ok(SUCCEEDED(hr), "SetActionMap failed hr=%08x\n", hr);
|
||||
|
||||
test_device_input(data->keyboard, INPUT_KEYBOARD, VK_SPACE, 2);
|
||||
}
|
||||
|
||||
static void test_action_mapping(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
@ -374,6 +416,8 @@ static void test_action_mapping(void)
|
|||
|
||||
test_device_input(data.keyboard, INPUT_KEYBOARD, VK_SPACE, 2);
|
||||
|
||||
test_appdata_property_vs_map(&data);
|
||||
|
||||
/* Test BuildActionMap with no suitable actions for a device */
|
||||
IDirectInputDevice_Unacquire(data.keyboard);
|
||||
af.dwDataSize = 4 * DITEST_KEYBOARDSPACE;
|
||||
|
@ -865,6 +909,108 @@ static void test_keyboard_events(void)
|
|||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
static void test_appdata_property(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
HINSTANCE hinst = GetModuleHandleA(NULL);
|
||||
IDirectInputDevice8A *di_keyboard;
|
||||
IDirectInput8A *pDI = NULL;
|
||||
HWND hwnd;
|
||||
DIPROPDWORD dw;
|
||||
DIPROPPOINTER dp;
|
||||
|
||||
hr = CoCreateInstance(&CLSID_DirectInput8, 0, CLSCTX_INPROC_SERVER, &IID_IDirectInput8A, (LPVOID*)&pDI);
|
||||
if (hr == DIERR_OLDDIRECTINPUTVERSION ||
|
||||
hr == DIERR_BETADIRECTINPUTVERSION ||
|
||||
hr == REGDB_E_CLASSNOTREG)
|
||||
{
|
||||
win_skip("DIPROP_APPDATA requires dinput8\n");
|
||||
return;
|
||||
}
|
||||
ok(SUCCEEDED(hr), "DirectInput8 Create failed: hr=%08x\n", hr);
|
||||
if (FAILED(hr)) return;
|
||||
|
||||
hr = IDirectInput8_Initialize(pDI,hinst, DIRECTINPUT_VERSION);
|
||||
if (hr == DIERR_OLDDIRECTINPUTVERSION || hr == DIERR_BETADIRECTINPUTVERSION)
|
||||
{
|
||||
win_skip("DIPROP_APPDATA requires dinput8\n");
|
||||
return;
|
||||
}
|
||||
ok(SUCCEEDED(hr), "DirectInput8 Initialize failed: hr=%08x\n", hr);
|
||||
if (FAILED(hr)) return;
|
||||
|
||||
hwnd = CreateWindowExA(WS_EX_TOPMOST, "static", "dinput",
|
||||
WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL);
|
||||
ok(hwnd != NULL, "failed to create window\n");
|
||||
|
||||
hr = IDirectInput8_CreateDevice(pDI, &GUID_SysKeyboard, &di_keyboard, NULL);
|
||||
ok(SUCCEEDED(hr), "IDirectInput8_CreateDevice failed: %08x\n", hr);
|
||||
|
||||
hr = IDirectInputDevice8_SetDataFormat(di_keyboard, &c_dfDIKeyboard);
|
||||
ok(SUCCEEDED(hr), "IDirectInputDevice8_SetDataFormat failed: %08x\n", hr);
|
||||
|
||||
dw.diph.dwSize = sizeof(DIPROPDWORD);
|
||||
dw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
dw.diph.dwObj = 0;
|
||||
dw.diph.dwHow = DIPH_DEVICE;
|
||||
dw.dwData = 32;
|
||||
hr = IDirectInputDevice8_SetProperty(di_keyboard, DIPROP_BUFFERSIZE, &(dw.diph));
|
||||
ok(SUCCEEDED(hr), "IDirectInputDevice8_SetProperty failed hr=%08x\n", hr);
|
||||
|
||||
/* the default value */
|
||||
test_device_input(di_keyboard, INPUT_KEYBOARD, 'A', -1);
|
||||
|
||||
dp.diph.dwHow = DIPH_DEVICE;
|
||||
dp.diph.dwObj = 0;
|
||||
dp.uData = 1;
|
||||
hr = IDirectInputDevice8_SetProperty(di_keyboard, DIPROP_APPDATA, &(dp.diph));
|
||||
ok(hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty APPDATA for the device should be invalid hr=%08x\n", hr);
|
||||
|
||||
dp.diph.dwSize = sizeof(dp);
|
||||
dp.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
dp.diph.dwHow = DIPH_BYUSAGE;
|
||||
dp.diph.dwObj = 2;
|
||||
dp.uData = 2;
|
||||
hr = IDirectInputDevice8_SetProperty(di_keyboard, DIPROP_APPDATA, &(dp.diph));
|
||||
ok(hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_SetProperty APPDATA by usage should be unsupported hr=%08x\n", hr);
|
||||
|
||||
dp.diph.dwHow = DIPH_BYID;
|
||||
dp.diph.dwObj = DIDFT_MAKEINSTANCE(DIK_SPACE) | DIDFT_PSHBUTTON;
|
||||
dp.uData = 3;
|
||||
hr = IDirectInputDevice8_SetProperty(di_keyboard, DIPROP_APPDATA, &(dp.diph));
|
||||
ok(SUCCEEDED(hr), "IDirectInputDevice8_SetProperty failed hr=%08x\n", hr);
|
||||
|
||||
dp.diph.dwHow = DIPH_BYOFFSET;
|
||||
dp.diph.dwObj = DIK_A;
|
||||
dp.uData = 4;
|
||||
hr = IDirectInputDevice8_SetProperty(di_keyboard, DIPROP_APPDATA, &(dp.diph));
|
||||
ok(SUCCEEDED(hr), "IDirectInputDevice8_SetProperty failed hr=%08x\n", hr);
|
||||
|
||||
dp.diph.dwHow = DIPH_BYOFFSET;
|
||||
dp.diph.dwObj = DIK_B;
|
||||
dp.uData = 5;
|
||||
hr = IDirectInputDevice8_SetProperty(di_keyboard, DIPROP_APPDATA, &(dp.diph));
|
||||
ok(SUCCEEDED(hr), "IDirectInputDevice8_SetProperty failed hr=%08x\n", hr);
|
||||
|
||||
test_device_input(di_keyboard, INPUT_KEYBOARD, VK_SPACE, 3);
|
||||
test_device_input(di_keyboard, INPUT_KEYBOARD, 'A', 4);
|
||||
test_device_input(di_keyboard, INPUT_KEYBOARD, 'B', 5);
|
||||
test_device_input(di_keyboard, INPUT_KEYBOARD, 'C', -1);
|
||||
|
||||
/* setting data format resets APPDATA */
|
||||
hr = IDirectInputDevice8_SetDataFormat(di_keyboard, &c_dfDIKeyboard);
|
||||
ok(SUCCEEDED(hr), "IDirectInputDevice8_SetDataFormat failed: %08x\n", hr);
|
||||
|
||||
test_device_input(di_keyboard, INPUT_KEYBOARD, VK_SPACE, -1);
|
||||
test_device_input(di_keyboard, INPUT_KEYBOARD, 'A', -1);
|
||||
test_device_input(di_keyboard, INPUT_KEYBOARD, 'B', -1);
|
||||
test_device_input(di_keyboard, INPUT_KEYBOARD, 'C', -1);
|
||||
|
||||
DestroyWindow(hwnd);
|
||||
IDirectInputDevice_Release(di_keyboard);
|
||||
IDirectInput_Release(pDI);
|
||||
}
|
||||
|
||||
START_TEST(device)
|
||||
{
|
||||
CoInitialize(NULL);
|
||||
|
@ -873,6 +1019,7 @@ START_TEST(device)
|
|||
test_save_settings();
|
||||
test_mouse_keyboard();
|
||||
test_keyboard_events();
|
||||
test_appdata_property();
|
||||
|
||||
CoUninitialize();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue