test_device_input() now takes properly sized appdata expected value and can be used to send any keyboard event. It also drains device's queue so it can be called multiple times on a single device instance.
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com --- dlls/dinput8/tests/device.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index 2fc04358cc1..02574961ec1 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -80,7 +80,7 @@ static void flush_events(void) } }
-static void test_device_input(IDirectInputDevice8A *lpdid, DWORD event_type, DWORD event, DWORD expected) +static void test_device_input(IDirectInputDevice8A *lpdid, DWORD event_type, DWORD event, UINT_PTR expected) { HRESULT hr; DIDEVICEOBJECTDATA obj_data; @@ -91,7 +91,7 @@ static void test_device_input(IDirectInputDevice8A *lpdid, DWORD event_type, DWO ok (SUCCEEDED(hr), "Failed to acquire device hr=%08x\n", hr);
if (event_type == INPUT_KEYBOARD) - keybd_event( event, DIK_SPACE, 0, 0); + keybd_event(event, MapVirtualKeyA(event, MAPVK_VK_TO_VSC), 0, 0);
if (event_type == INPUT_MOUSE) mouse_event( event, 0, 0, 0, 0); @@ -107,7 +107,7 @@ static void test_device_input(IDirectInputDevice8A *lpdid, DWORD event_type, DWO return; }
- ok (obj_data.uAppData == expected, "Retrieval of action failed uAppData=%lu expected=%d\n", obj_data.uAppData, expected); + ok (obj_data.uAppData == expected, "Retrieval of action failed uAppData=%lu expected=%lu\n", obj_data.uAppData, expected);
/* Check for buffer overflow */ for (i = 0; i < 17; i++) @@ -132,6 +132,14 @@ static void test_device_input(IDirectInputDevice8A *lpdid, DWORD event_type, DWO hr = IDirectInputDevice8_GetDeviceData(lpdid, sizeof(obj_data), &obj_data, &data_size, 0); ok(hr == DI_OK && data_size == 1, "GetDeviceData() failed: %08x cnt:%d\n", hr, data_size);
+ /* drain device's queue */ + while (data_size == 1) + { + hr = IDirectInputDevice8_GetDeviceData(lpdid, sizeof(obj_data), &obj_data, &data_size, 0); + ok(hr == DI_OK, "GetDeviceData() failed: %08x cnt:%d\n", hr, data_size); + if (hr != DI_OK) break; + } + IDirectInputDevice_Unacquire(lpdid); }
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com --- dlls/dinput/device.c | 18 ++++++++++++------ dlls/dinput8/tests/device.c | 12 ++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 198e903fc2e..14c47dd3c7d 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -833,6 +833,7 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L DWORD username_size = MAX_PATH; int i, action = 0, num_actions = 0; unsigned int offset = 0; + ActionMap *action_map;
if (This->acquired) return DIERR_ACQUIRED;
@@ -848,15 +849,12 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
if (num_actions == 0) return DI_NOEFFECT;
- This->num_actions = num_actions; - /* Construct the dataformat and actionmap */ obj_df = HeapAlloc(GetProcessHeap(), 0, sizeof(DIOBJECTDATAFORMAT)*num_actions); data_format.rgodf = (LPDIOBJECTDATAFORMAT)obj_df; data_format.dwNumObjs = num_actions;
- HeapFree(GetProcessHeap(), 0, This->action_map); - This->action_map = HeapAlloc(GetProcessHeap(), 0, sizeof(ActionMap)*num_actions); + action_map = HeapAlloc(GetProcessHeap(), 0, sizeof(ActionMap)*num_actions);
for (i = 0; i < lpdiaf->dwNumActions; i++) { @@ -873,8 +871,8 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
memcpy(&obj_df[action], obj, df->dwObjSize);
- This->action_map[action].uAppData = lpdiaf->rgoAction[i].uAppData; - This->action_map[action].offset = offset; + action_map[action].uAppData = lpdiaf->rgoAction[i].uAppData; + action_map[action].offset = offset; obj_df[action].dwOfs = offset; offset += (type & DIDFT_BUTTON) ? 1 : 4;
@@ -884,6 +882,9 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
IDirectInputDevice8_SetDataFormat(iface, &data_format);
+ This->action_map = action_map; + This->num_actions = num_actions; + HeapFree(GetProcessHeap(), 0, obj_df);
/* Set the device properties according to the action format */ @@ -962,6 +963,7 @@ void queue_event(LPDIRECTINPUTDEVICE8A iface, int inst_id, DWORD data, DWORD tim This->data_queue[This->queue_head].dwData = data; This->data_queue[This->queue_head].dwTimeStamp = time; This->data_queue[This->queue_head].dwSequence = seq; + This->data_queue[This->queue_head].uAppData = -1;
/* Set uAppData by means of action mapping */ if (This->num_actions > 0) @@ -1063,6 +1065,10 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetDataFormat(LPDIRECTINPUTDEVICE8W ifac
EnterCriticalSection(&This->crit);
+ HeapFree(GetProcessHeap(), 0, This->action_map); + This->action_map = NULL; + This->num_actions = 0; + release_DataFormat(&This->data_format); res = create_DataFormat(df, &This->data_format);
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index 02574961ec1..4a766280982 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -362,6 +362,18 @@ static void test_action_mapping(void) /* Test keyboard input */ test_device_input(data.keyboard, INPUT_KEYBOARD, VK_SPACE, 2);
+ /* setting format should reset action map */ + hr = IDirectInputDevice8_SetDataFormat(data.keyboard, &c_dfDIKeyboard); + ok (SUCCEEDED(hr), "IDirectInputDevice8_SetDataFormat failed: %08x\n", hr); + + test_device_input(data.keyboard, INPUT_KEYBOARD, VK_SPACE, -1); + + /* back to action map */ + hr = IDirectInputDevice8_SetActionMap(data.keyboard, data.lpdiaf, NULL, 0); + ok (SUCCEEDED(hr), "SetActionMap should succeed hr=%08x\n", hr); + + test_device_input(data.keyboard, INPUT_KEYBOARD, VK_SPACE, 2); + /* Test BuildActionMap with no suitable actions for a device */ IDirectInputDevice_Unacquire(data.keyboard); af.dwDataSize = 4 * DITEST_KEYBOARDSPACE;
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com --- include/dinput.h | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/include/dinput.h b/include/dinput.h index 92c6255cf37..2d183bbc944 100644 --- a/include/dinput.h +++ b/include/dinput.h @@ -876,6 +876,12 @@ typedef struct DIPROPSTRING { } DIPROPSTRING, *LPDIPROPSTRING; typedef const DIPROPSTRING *LPCDIPROPSTRING;
+typedef struct DIPROPPOINTER { + DIPROPHEADER diph; + UINT_PTR uData; +} DIPROPPOINTER, *LPDIPROPPOINTER; +typedef const DIPROPPOINTER *LPCDIPROPPOINTER; + /* special property GUIDs */ #ifdef __cplusplus #define MAKEDIPROP(prop) (*(const GUID *)(prop))
This fixes not working analog inputs on game controllers in Slay the Spire.
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com --- dlls/dinput/device.c | 71 +++++++++++++++++ dlls/dinput8/tests/device.c | 147 ++++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 14c47dd3c7d..f1b334680e8 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -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,44 @@ 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 +1501,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; diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index 4a766280982..3e6da23b4ab 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -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(); }
Hi,
On Mon, 8 Mar 2021, Arkadiusz Hiler wrote:
This fixes not working analog inputs on game controllers in Slay the Spire.
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com
This commit is causing a new failure on w10pro64-fr, and only on that machine: https://bugs.winehq.org//show_bug.cgi?id=50987
Do you have any insight or even a fix for it?
On 5/25/21 9:21 PM, Francois Gouget wrote:
Hi,
On Mon, 8 Mar 2021, Arkadiusz Hiler wrote:
This fixes not working analog inputs on game controllers in Slay the Spire.
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com
This commit is causing a new failure on w10pro64-fr, and only on that machine: https://bugs.winehq.org//show_bug.cgi?id=50987
Do you have any insight or even a fix for it?
As it's on fr windows and the test registers DIK_A / sends 'A' key event, I'd say it's most likely related to the layout.
I noticed there's some other dinput test which fails, on Wine, because of French layout too [1].
I think it's going to be hard to write tests robust enough to pass with all the possible layouts, and if the tests aren't meant to validate some localization aspect, they could perhaps be skipped on non-US locales.
[1] https://test.winehq.org/data/dff85646517526562644c23648d11596daeb26d0/linux_...
On Tue, May 25, 2021 at 09:41:12PM +0200, Rémi Bernon wrote:
On 5/25/21 9:21 PM, Francois Gouget wrote:
Hi,
On Mon, 8 Mar 2021, Arkadiusz Hiler wrote:
This fixes not working analog inputs on game controllers in Slay the Spire.
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com
This commit is causing a new failure on w10pro64-fr, and only on that machine: https://bugs.winehq.org//show_bug.cgi?id=50987
Do you have any insight or even a fix for it?
As it's on fr windows and the test registers DIK_A / sends 'A' key event, I'd say it's most likely related to the layout.
I noticed there's some other dinput test which fails, on Wine, because of French layout too [1].
I think it's going to be hard to write tests robust enough to pass with all the possible layouts, and if the tests aren't meant to validate some localization aspect, they could perhaps be skipped on non-US locales.
[1] https://test.winehq.org/data/dff85646517526562644c23648d11596daeb26d0/linux_...
Yep, it's because AZERTY is a thing + the test code I've extended is not layout aware.
The simple hack to make the test pass would be to pick up a different letter than the unfortunate A, but Rémi is right... This may cause more problems in the long run and we either need to make those layout aware or we should start skipping a bunch of fake input tests on non-US locale.
I'll look into that. Thanks!
On Tue, May 25, 2021 at 11:30:50PM +0300, Arkadiusz Hiler wrote:
On Tue, May 25, 2021 at 09:41:12PM +0200, Rémi Bernon wrote:
On 5/25/21 9:21 PM, Francois Gouget wrote:
Hi,
On Mon, 8 Mar 2021, Arkadiusz Hiler wrote:
This fixes not working analog inputs on game controllers in Slay the Spire.
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com
This commit is causing a new failure on w10pro64-fr, and only on that machine: https://bugs.winehq.org//show_bug.cgi?id=50987
Do you have any insight or even a fix for it?
As it's on fr windows and the test registers DIK_A / sends 'A' key event, I'd say it's most likely related to the layout.
I noticed there's some other dinput test which fails, on Wine, because of French layout too [1].
https://testbot.winehq.org/JobDetails.pl?Key=91255&f202=exe32.report&...
This one looks like an actual bug/missing feature. The test is keyboard layout aware and tests the French mapping explicitly.
'keyboard.c:53: Loading keyboard layout 0000040c'
So we think that we have a standard French layout.
The culprit is the following call: MapVirtualKeyExA(vkey, MAPVK_VK_TO_VSC, hkl);
On FR Wine: keyboard.c:422: vkey 41 mapped to scan 1e 'A' maps to scancode for 'A'
On FR Windows: keyboard.c:422: vkey 41 mapped to scan 10 'A' maps to scancode for 'Q'
On Linux/X11 MapVirtualKeyEx implementation is backed by X11Drv_MapVirtualKeyEx[0] and there's something off with either locale matching or code that populates keyc2vkey.
[0]: https://source.winehq.org/git/wine.git/blob/refs/heads/master:/dlls/winex11....
Cheers, Arek
I think it's going to be hard to write tests robust enough to pass with all the possible layouts, and if the tests aren't meant to validate some localization aspect, they could perhaps be skipped on non-US locales.
[1] https://test.winehq.org/data/dff85646517526562644c23648d11596daeb26d0/linux_...
Yep, it's because AZERTY is a thing + the test code I've extended is not layout aware.
The simple hack to make the test pass would be to pick up a different letter than the unfortunate A, but Rémi is right... This may cause more problems in the long run and we either need to make those layout aware or we should start skipping a bunch of fake input tests on non-US locale.
I'll look into that. Thanks!
-- Cheers, Arek