From 73273d9d13a1cbf6eff1e1e26164f9db11d00377 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 26 Aug 2019 16:06:59 +0200
Subject: [PATCH] dinput8: Use rawinput interface for mouse device.

---
 dlls/dinput/dinput_main.c    | 10 ++++
 dlls/dinput/dinput_private.h |  1 +
 dlls/dinput/mouse.c          | 90 ++++++++++++++++++++++++++++++++++++
 dlls/dinput8/tests/device.c  | 11 ++---
 4 files changed, 104 insertions(+), 8 deletions(-)

diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index d0937d35e5b..c333ed7d3d0 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -654,6 +654,16 @@ static LRESULT WINAPI di_em_win_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPAR
     {
         if (GetRawInputData( (HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER) ) > sizeof(ri))
             WARN( "Unable to read raw input data\n" );
+        else if (ri.header.dwType == RIM_TYPEMOUSE)
+        {
+            EnterCriticalSection( &dinput_hook_crit );
+            LIST_FOR_EACH_ENTRY( dev, &acquired_mouse_list, IDirectInputDeviceImpl, entry )
+            {
+                if (!dev->use_raw_input) continue;
+                dinput_mouse_rawinput_hook( &dev->IDirectInputDevice8A_iface, wparam, lparam, &ri );
+            }
+            LeaveCriticalSection( &dinput_hook_crit );
+        }
     }
 
     return DefWindowProcW(hwnd, msg, wparam, lparam);
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index 06a439d6a41..c0c88da9674 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -73,6 +73,7 @@ extern void dinput_hooks_acquire_device(LPDIRECTINPUTDEVICE8W iface);
 extern void dinput_hooks_unacquire_device(LPDIRECTINPUTDEVICE8W iface);
 extern int dinput_mouse_hook(LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam);
 extern int dinput_keyboard_hook(LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam);
+extern void dinput_mouse_rawinput_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam, RAWINPUT *raw );
 
 extern void check_dinput_hooks(LPDIRECTINPUTDEVICE8W, BOOL) DECLSPEC_HIDDEN;
 extern void check_dinput_events(void) DECLSPEC_HIDDEN;
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index 5e6f34f0eca..429271e8f43 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -239,6 +239,13 @@ static SysMouseImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
     newDevice->base.data_format.wine_df = df;
     IDirectInput_AddRef(&newDevice->base.dinput->IDirectInput7A_iface);
 
+    if (dinput->dwVersion >= 0x0800)
+    {
+        newDevice->base.use_raw_input = TRUE;
+        newDevice->base.raw_device.usUsagePage = 1; /* HID generic device page */
+        newDevice->base.raw_device.usUsage = 2; /* HID generic mouse */
+    }
+
     return newDevice;
 
 failed:
@@ -306,6 +313,89 @@ const struct dinput_device mouse_device = {
  *	SysMouseA (DInput Mouse support)
  */
 
+void dinput_mouse_rawinput_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam, RAWINPUT *ri )
+{
+    SysMouseImpl* This = impl_from_IDirectInputDevice8A(iface);
+    POINT rel, pt;
+    DWORD seq;
+    int i, wdata = 0;
+
+    static const USHORT mouse_button_flags[] =
+    {
+        RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP,
+        RI_MOUSE_BUTTON_2_DOWN, RI_MOUSE_BUTTON_2_UP,
+        RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP,
+        RI_MOUSE_BUTTON_4_DOWN, RI_MOUSE_BUTTON_4_UP,
+        RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP
+    };
+
+    TRACE("(%p) wp %08lx, lp %08lx\n", iface, wparam, lparam);
+
+    if (ri->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP)
+        FIXME( "Unimplemented MOUSE_VIRTUAL_DESKTOP flag\n" );
+    if (ri->data.mouse.usFlags & MOUSE_ATTRIBUTES_CHANGED)
+        FIXME( "Unimplemented MOUSE_ATTRIBUTES_CHANGED flag\n" );
+
+    EnterCriticalSection(&This->base.crit);
+    seq = This->base.dinput->evsequence++;
+
+    rel.x = ri->data.mouse.lLastX;
+    rel.y = ri->data.mouse.lLastY;
+    if (ri->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
+    {
+        GetCursorPos(&pt);
+        rel.x -= pt.x;
+        rel.y -= pt.y;
+    }
+
+    This->m_state.lX += rel.x;
+    This->m_state.lY += rel.y;
+
+    if (This->base.data_format.user_df->dwFlags & DIDF_ABSAXIS)
+    {
+        pt.x = This->m_state.lX;
+        pt.y = This->m_state.lY;
+    }
+    else
+    {
+        pt = rel;
+    }
+
+    if (rel.x)
+        queue_event(iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS,
+                    pt.x, GetCurrentTime(), seq);
+
+    if (rel.y)
+        queue_event(iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS,
+                    pt.y, GetCurrentTime(), seq);
+
+    if (rel.x || rel.y)
+    {
+        if ((This->warp_override == WARP_FORCE_ON) ||
+            (This->warp_override != WARP_DISABLE && (This->base.dwCoopLevel & DISCL_EXCLUSIVE)))
+            This->need_warp = TRUE;
+    }
+
+    if (ri->data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
+    {
+        This->m_state.lZ += (wdata = (SHORT)ri->data.mouse.usButtonData);
+        queue_event(iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_Z_AXIS_INSTANCE) | DIDFT_RELAXIS,
+                    wdata, GetCurrentTime(), seq);
+    }
+
+    for (i = 0; i < ARRAY_SIZE(mouse_button_flags); ++i)
+    {
+        if (ri->data.mouse.usButtonFlags & mouse_button_flags[i])
+        {
+            This->m_state.rgbButtons[i / 2] = 0x80 - (i % 2) * 0x80;
+            queue_event(iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + (i / 2)) | DIDFT_PSHBUTTON,
+                        This->m_state.rgbButtons[i / 2], GetCurrentTime(), seq);
+        }
+    }
+
+    LeaveCriticalSection(&This->base.crit);
+}
+
 /* low-level mouse hook */
 int dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam )
 {
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
index 6fe9a635510..80a7fe26c3b 100644
--- a/dlls/dinput8/tests/device.c
+++ b/dlls/dinput8/tests/device.c
@@ -646,13 +646,9 @@ static void test_mouse_keyboard(void)
     raw_devices_count = ARRAY_SIZE(raw_devices);
     memset(raw_devices, 0, sizeof(raw_devices));
     hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE));
-    todo_wine
     ok(hr == 1, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
-    todo_wine
     ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage);
-    todo_wine
     ok(raw_devices[0].usUsage == 2, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage);
-    todo_wine
     ok(raw_devices[0].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
     todo_wine
     ok(raw_devices[0].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
@@ -662,6 +658,9 @@ static void test_mouse_keyboard(void)
     GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE));
     ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count);
 
+    if (raw_devices[0].hwndTarget != NULL)
+        di_hwnd = raw_devices[0].hwndTarget;
+
     /* expect dinput8 to take over any activated raw input devices */
     raw_devices[0].usUsagePage = 0x01;
     raw_devices[0].usUsage = 0x05;
@@ -689,9 +688,7 @@ static void test_mouse_keyboard(void)
     ok(hr == 3, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
     ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage);
     ok(raw_devices[0].usUsage == 2, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage);
-    todo_wine
     ok(raw_devices[0].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
-    todo_wine
     ok(raw_devices[0].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
     ok(raw_devices[1].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[1].usUsagePage);
     ok(raw_devices[1].usUsage == 5, "Unexpected raw device usage: %x\n", raw_devices[1].usUsage);
@@ -723,7 +720,6 @@ static void test_mouse_keyboard(void)
     memset(raw_devices, 0, sizeof(raw_devices));
     hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE));
     ok(hr == 3, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
-    todo_wine
     ok(raw_devices[0].dwFlags == (RIDEV_CAPTUREMOUSE|RIDEV_NOLEGACY), "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
     todo_wine
     ok(raw_devices[2].dwFlags == (RIDEV_NOHOTKEYS|RIDEV_NOLEGACY), "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags);
@@ -737,7 +733,6 @@ static void test_mouse_keyboard(void)
     todo_wine
     ok(hr == 1, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
     ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage);
-    todo_wine
     ok(raw_devices[0].usUsage == 5, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage);
     ok(raw_devices[0].dwFlags == 0, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
     ok(raw_devices[0].hwndTarget == hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
-- 
2.27.0

