Arkadiusz Hiler : dinput: Don't add 'default value 0' entries to the data transform.

Alexandre Julliard julliard at winehq.org
Thu Jul 8 16:43:51 CDT 2021


Module: wine
Branch: master
Commit: d10887b8f56792ebcca717ccc28a289f7bcaf107
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=d10887b8f56792ebcca717ccc28a289f7bcaf107

Author: Arkadiusz Hiler <ahiler at codeweavers.com>
Date:   Thu Jul  8 13:03:21 2021 +0300

dinput: Don't add 'default value 0' entries to the data transform.

This helps when dealing with the quirky c_dfDIJoystick2 format,
which defines all the sliders as overlapping, i.e. rglSlider[2],
rglVSlider[2], rglASlider[2] and rglFSlider[2] all share the same
offset.

With the Linux backends, if the device exposes enough axes (e.g. some
HOTAS) we end up using rglSlider.

Let's make sure we don't unnecessarily override the values there.

Signed-off-by: Arkadiusz Hiler <ahiler at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/dinput/device.c       |  14 +++---
 dlls/dinput/tests/device.c | 122 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 129 insertions(+), 7 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 29a569ca9f1..ac60a21326c 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -526,20 +526,20 @@ static HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *forma
 	    TRACE("         "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n");
             TRACE("       * dwFlags: 0x%08x\n", asked_format->rgodf[j].dwFlags);
 	    TRACE("         "); _dump_ObjectDataFormat_flags(asked_format->rgodf[j].dwFlags); TRACE("\n");
-	    
+
+            same = 0;
+
+            if (!(asked_format->rgodf[j].dwType & DIDFT_POV))
+                continue; /* fill_DataFormat memsets the buffer to 0 */
+
 	    if (asked_format->rgodf[j].dwType & DIDFT_BUTTON)
 		dt[index].size = sizeof(BYTE);
 	    else
 		dt[index].size = sizeof(DWORD);
 	    dt[index].offset_in  = -1;
 	    dt[index].offset_out = asked_format->rgodf[j].dwOfs;
-            if (asked_format->rgodf[j].dwType & DIDFT_POV)
-                dt[index].value = -1;
-            else
-                dt[index].value = 0;
+            dt[index].value      = -1;
 	    index++;
-
-	    same = 0;
 	}
     }
     
diff --git a/dlls/dinput/tests/device.c b/dlls/dinput/tests/device.c
index 485acca4f61..6307957b6e2 100644
--- a/dlls/dinput/tests/device.c
+++ b/dlls/dinput/tests/device.c
@@ -292,6 +292,126 @@ static BOOL CALLBACK enum_devices(const DIDEVICEINSTANCEA *lpddi, void *pvRef)
     return DIENUM_CONTINUE;
 }
 
+struct overlapped_state
+{
+        BYTE  keys[4];
+        DWORD extra_element;
+};
+
+static const DIOBJECTDATAFORMAT obj_overlapped_slider_format[] = {
+    { &GUID_Key,    0, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(DIK_A),0},
+    { &GUID_Key,    1, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(DIK_S),0},
+    { &GUID_Key,    2, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(DIK_D),0},
+    { &GUID_Key,    3, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(DIK_F),0},
+    { &GUID_Slider, 0, DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION},
+};
+
+static const DIDATAFORMAT overlapped_slider_format = {
+    sizeof(DIDATAFORMAT),
+    sizeof(DIOBJECTDATAFORMAT),
+    DIDF_ABSAXIS,
+    sizeof(struct overlapped_state),
+    ARRAY_SIZE(obj_overlapped_slider_format),
+    (LPDIOBJECTDATAFORMAT)obj_overlapped_slider_format
+};
+
+static const DIOBJECTDATAFORMAT obj_overlapped_pov_format[] = {
+    { &GUID_Key,    0, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(DIK_A),0},
+    { &GUID_Key,    1, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(DIK_S),0},
+    { &GUID_Key,    2, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(DIK_D),0},
+    { &GUID_Key,    3, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(DIK_F),0},
+    { &GUID_POV,    0, DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0},
+};
+
+static const DIDATAFORMAT overlapped_pov_format = {
+    sizeof(DIDATAFORMAT),
+    sizeof(DIOBJECTDATAFORMAT),
+    DIDF_ABSAXIS,
+    sizeof(struct overlapped_state),
+    ARRAY_SIZE(obj_overlapped_pov_format),
+    (LPDIOBJECTDATAFORMAT)obj_overlapped_pov_format
+};
+
+static void pump_messages(void)
+{
+    MSG msg;
+
+    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+    {
+        TranslateMessage(&msg);
+        DispatchMessageA(&msg);
+    }
+}
+
+void overlapped_format_tests(IDirectInputA *pDI, HWND hwnd)
+{
+    HRESULT hr;
+    struct overlapped_state state;
+    IDirectInputDeviceA *keyboard = NULL;
+
+    hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &keyboard, NULL);
+    ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
+
+    /* test overlapped slider - default value 0 */
+    hr = IDirectInputDevice_SetDataFormat(keyboard, &overlapped_slider_format);
+    ok(SUCCEEDED(hr), "IDirectInputDevice_SetDataFormat() failed: %08x\n", hr);
+    hr = IDirectInputDevice_Acquire(keyboard);
+    ok(SUCCEEDED(hr), "IDirectInputDevice_Acquire() failed: %08x\n", hr);
+
+    SetFocus(hwnd);
+    pump_messages();
+
+    /* press D */
+    keybd_event(0, DIK_D, KEYEVENTF_SCANCODE, 0);
+    pump_messages();
+
+    memset(&state, 0xFF, sizeof(state));
+    hr = IDirectInputDevice_GetDeviceState(keyboard, sizeof(state), &state);
+    ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState() failed: %08x\n", hr);
+
+    ok(state.keys[0] == 0x00, "key A should be still up\n");
+    ok(state.keys[1] == 0x00, "key S should be still up\n");
+    ok(state.keys[2] == 0x80, "keydown for D did not register\n");
+    ok(state.keys[3] == 0x00, "key F should be still up\n");
+    ok(state.extra_element == 0, "State struct was not memset to zero\n");
+
+    /* release D */
+    keybd_event(0, DIK_D, KEYEVENTF_SCANCODE|KEYEVENTF_KEYUP, 0);
+    pump_messages();
+
+    hr = IDirectInputDevice_Unacquire(keyboard);
+    ok(SUCCEEDED(hr), "IDirectInputDevice_Unacquire() failed: %08x\n", hr);
+
+    /* test overlapped pov - default value - 0xFFFFFFFF */
+    hr = IDirectInputDevice_SetDataFormat(keyboard, &overlapped_pov_format);
+    ok(SUCCEEDED(hr), "IDirectInputDevice_SetDataFormat() failed: %08x\n", hr);
+    hr = IDirectInputDevice_Acquire(keyboard);
+    ok(SUCCEEDED(hr), "IDirectInputDevice_Acquire() failed: %08x\n", hr);
+
+    SetFocus(hwnd);
+    pump_messages();
+
+    /* press D */
+    keybd_event(0, DIK_D, KEYEVENTF_SCANCODE, 0);
+    pump_messages();
+
+    memset(&state, 0xFF, sizeof(state));
+    hr = IDirectInputDevice_GetDeviceState(keyboard, sizeof(state), &state);
+    ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState() failed: %08x\n", hr);
+
+    ok(state.keys[0] == 0xFF, "key state should have been overwritten by the overlapped POV\n");
+    ok(state.keys[1] == 0xFF, "key state should have been overwritten by the overlapped POV\n");
+    ok(state.keys[2] == 0xFF, "key state should have been overwritten by the overlapped POV\n");
+    ok(state.keys[3] == 0xFF, "key state should have been overwritten by the overlapped POV\n");
+    ok(state.extra_element == 0, "State struct was not memset to zero\n");
+
+    /* release D */
+    keybd_event(0, DIK_D, KEYEVENTF_SCANCODE|KEYEVENTF_KEYUP, 0);
+    pump_messages();
+
+    if (keyboard) IUnknown_Release(keyboard);
+}
+
 static void device_tests(void)
 {
     HRESULT hr;
@@ -342,6 +462,8 @@ static void device_tests(void)
             if (device) IUnknown_Release(device);
         }
 
+        overlapped_format_tests(pDI, hwnd);
+
         DestroyWindow(hwnd);
     }
     if (obj) IUnknown_Release(obj);




More information about the wine-cvs mailing list