Updated rawinput patchsets

This is a completely updated rawinput patchsets from Rémi Bernon,
replacing the current user32-rawinput.
This commit is contained in:
Alistair Leslie-Hughes
2019-12-23 20:03:44 +11:00
parent a8cb853708
commit 8218a78955
48 changed files with 4509 additions and 1595 deletions

View File

@@ -0,0 +1,82 @@
From 3f8031f89ca79ef5c4dd46666cda2304aa647083 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 4 Nov 2019 23:33:09 +0100
Subject: [PATCH 1/4] dinput: Add DIERR_INPUTLOST error code support for
DISCL_FOREGROUND cooperative level.
---
dlls/dinput/device.c | 2 ++
dlls/dinput/device_private.h | 1 +
dlls/dinput/keyboard.c | 6 ++++++
dlls/dinput/mouse.c | 6 ++++++
4 files changed, 15 insertions(+)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index df7a22a303b..51a536f0892 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -1087,6 +1087,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
EnterCriticalSection(&This->crit);
res = This->acquired ? S_FALSE : DI_OK;
This->acquired = 1;
+ This->inputlost = 0;
LeaveCriticalSection(&This->crit);
if (res == DI_OK)
check_dinput_hooks(iface, TRUE);
@@ -1115,6 +1116,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
EnterCriticalSection(&This->crit);
res = !This->acquired ? DI_NOEFFECT : DI_OK;
This->acquired = 0;
+ This->inputlost = 0;
LeaveCriticalSection(&This->crit);
if (res == DI_OK)
check_dinput_hooks(iface, FALSE);
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 9116aaeab66..70b4ae1ef69 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -68,6 +68,7 @@ struct IDirectInputDeviceImpl
DWORD dwCoopLevel;
HWND win;
int acquired;
+ int inputlost;
DI_EVENT_PROC event_proc; /* function to receive mouse & keyboard events */
BOOL use_raw_input; /* use raw input instead of low-level messages */
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 1ec8003897a..2c62d3eab09 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -371,6 +371,12 @@ static HRESULT WINAPI SysKeyboardWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W ifac
check_dinput_events();
+ if ((This->base.dwCoopLevel & DISCL_FOREGROUND) && This->base.win != GetForegroundWindow())
+ {
+ This->base.acquired = 0;
+ return DIERR_INPUTLOST;
+ }
+
EnterCriticalSection(&This->base.crit);
if (TRACE_ON(dinput)) {
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index b8b88f38c15..06cf78de13a 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -672,6 +672,12 @@ static HRESULT WINAPI SysMouseWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface,
check_dinput_events();
+ if ((This->base.dwCoopLevel & DISCL_FOREGROUND) && This->base.win != GetForegroundWindow())
+ {
+ This->base.acquired = 0;
+ return DIERR_INPUTLOST;
+ }
+
EnterCriticalSection(&This->base.crit);
_dump_mouse_state(&This->m_state);
--
2.24.1

View File

@@ -0,0 +1,146 @@
From 87087e7d92d5cbbaf8e63cdfadead60701d0b360 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 26 Aug 2019 15:32:07 +0200
Subject: [PATCH 2/4] dinput8: Use raw input interface for dinput8 keyboard
device.
---
dlls/dinput/keyboard.c | 69 +++++++++++++++++++++++++++++++++----
dlls/dinput8/tests/device.c | 7 ----
2 files changed, 62 insertions(+), 14 deletions(-)
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 2c62d3eab09..fb0f273bdbe 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -107,17 +107,65 @@ static int KeyboardCallback( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM
{
SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
int dik_code, ret = This->base.dwCoopLevel & DISCL_EXCLUSIVE;
- KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
BYTE new_diks;
+ DWORD vkey_code, scan_code;
+ BOOL is_key_ext, is_key_up;
if (wparam != WM_KEYDOWN && wparam != WM_KEYUP &&
- wparam != WM_SYSKEYDOWN && wparam != WM_SYSKEYUP)
+ wparam != WM_SYSKEYDOWN && wparam != WM_SYSKEYUP &&
+ wparam != RIM_INPUT && wparam != RIM_INPUTSINK)
return 0;
+ if (wparam == RIM_INPUT || wparam == RIM_INPUTSINK)
+ {
+ RAWINPUTHEADER raw_header;
+ RAWINPUT raw_input;
+ UINT size;
+
+ TRACE("(%p) wp %08lx, lp %08lx\n", iface, wparam, lparam);
+
+ size = sizeof(raw_header);
+ if (GetRawInputData( (HRAWINPUT)lparam, RID_HEADER, &raw_header, &size, sizeof(RAWINPUTHEADER) ) != sizeof(raw_header))
+ {
+ WARN( "Unable to read raw input data header\n" );
+ return 0;
+ }
+
+ if (raw_header.dwType != RIM_TYPEKEYBOARD)
+ return 0;
+
+ if (raw_header.dwSize > sizeof(raw_input))
+ {
+ WARN( "Unexpected size for keyboard raw input data\n" );
+ return 0;
+ }
+
+ size = raw_header.dwSize;
+ if (GetRawInputData( (HRAWINPUT)lparam, RID_INPUT, &raw_input, &size, sizeof(RAWINPUTHEADER) ) != raw_header.dwSize )
+ {
+ WARN( "Unable to read raw input data\n" );
+ return 0;
+ }
+
+ vkey_code = raw_input.data.keyboard.VKey;
+ scan_code = raw_input.data.keyboard.MakeCode;
+ is_key_ext = (raw_input.data.keyboard.Flags & RI_KEY_E0);
+ is_key_up = (raw_input.data.keyboard.Flags & RI_KEY_BREAK);
+ }
+ else
+ {
+ KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
+
+ vkey_code = hook->vkCode;
+ scan_code = hook->scanCode;
+ is_key_ext = (hook->flags & LLKHF_EXTENDED);
+ is_key_up = (hook->flags & LLKHF_UP);
+ }
+
TRACE("(%p) wp %08lx, lp %08lx, vk %02x, scan %02x\n",
- iface, wparam, lparam, hook->vkCode, hook->scanCode);
+ iface, wparam, lparam, vkey_code, scan_code);
- switch (hook->vkCode)
+ switch (vkey_code)
{
/* R-Shift is special - it is an extended key with separate scan code */
case VK_RSHIFT : dik_code = DIK_RSHIFT; break;
@@ -125,10 +173,10 @@ static int KeyboardCallback( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM
case VK_NUMLOCK : dik_code = DIK_NUMLOCK; break;
case VK_SUBTRACT: dik_code = DIK_SUBTRACT; break;
default:
- dik_code = map_dik_code(hook->scanCode & 0xff, hook->vkCode, This->subtype);
- if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80;
+ dik_code = map_dik_code(scan_code & 0xff, vkey_code, This->subtype);
+ if (is_key_ext) dik_code |= 0x80;
}
- new_diks = hook->flags & LLKHF_UP ? 0 : 0x80;
+ new_diks = is_key_up ? 0 : 0x80;
/* returns now if key event already known */
if (new_diks == This->DInputKeyState[dik_code])
@@ -295,6 +343,13 @@ static SysKeyboardImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
list_add_tail(&dinput->devices_list, &newDevice->base.entry);
LeaveCriticalSection(&dinput->crit);
+ if (dinput->dwVersion >= 0x800)
+ {
+ newDevice->base.use_raw_input = TRUE;
+ newDevice->base.raw_device.usUsagePage = 1; /* HID generic device page */
+ newDevice->base.raw_device.usUsage = 6; /* HID generic keyboard */
+ }
+
return newDevice;
failed:
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
index 31220db220a..8a6d1997b67 100644
--- a/dlls/dinput8/tests/device.c
+++ b/dlls/dinput8/tests/device.c
@@ -659,15 +659,10 @@ 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 == 6, "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 != NULL, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
hr = IDirectInputDevice8_Unacquire(di_keyboard);
ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
@@ -746,9 +741,7 @@ static void test_mouse_keyboard(void)
ok(raw_devices[1].hwndTarget == hwnd, "Unexpected raw device target: %p\n", raw_devices[1].hwndTarget);
ok(raw_devices[2].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[1].usUsagePage);
ok(raw_devices[2].usUsage == 6, "Unexpected raw device usage: %x\n", raw_devices[1].usUsage);
- todo_wine
ok(raw_devices[2].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags);
- todo_wine
ok(raw_devices[2].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[1].hwndTarget);
hr = IDirectInputDevice8_Unacquire(di_keyboard);
ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
--
2.24.1

View File

@@ -0,0 +1,95 @@
From 31d4d9619c14a37522b99917deae40273f6e3654 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Sat, 7 Sep 2019 09:41:59 +0200
Subject: [PATCH 3/4] user32: Add support for RIDEV_INPUTSINK flag in
RegisterRawInputDevices.
This flag allows applications to receive rawinput messages while in
background. They have to specify a target hwnd in which queue to receive
them and the messages will carry a RIM_INPUTSINK wparam in this case.
---
dlls/user32/rawinput.c | 9 ++++++++-
dlls/user32/tests/input.c | 2 --
server/queue.c | 9 ++++++---
3 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index 72ae91cfcb5..5a238928b24 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -304,6 +304,13 @@ BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(RAWINPUTDEVICE *devices, U
for (i = 0; i < device_count; ++i)
{
+ if ((devices[i].dwFlags & RIDEV_INPUTSINK) &&
+ (devices[i].hwndTarget == NULL))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
if ((devices[i].dwFlags & RIDEV_REMOVE) &&
(devices[i].hwndTarget != NULL))
{
@@ -319,7 +326,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(RAWINPUTDEVICE *devices, U
TRACE("device %u: page %#x, usage %#x, flags %#x, target %p.\n",
i, devices[i].usUsagePage, devices[i].usUsage,
devices[i].dwFlags, devices[i].hwndTarget);
- if (devices[i].dwFlags & ~(RIDEV_REMOVE|RIDEV_NOLEGACY))
+ if (devices[i].dwFlags & ~(RIDEV_REMOVE|RIDEV_NOLEGACY|RIDEV_INPUTSINK))
FIXME("Unhandled flags %#x for device %u.\n", devices[i].dwFlags, i);
d[i].usage_page = devices[i].usUsagePage;
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index a1f983f1960..68d6731551a 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -1812,9 +1812,7 @@ static void test_RegisterRawInputDevices(void)
SetLastError(0xdeadbeef);
res = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
- todo_wine
ok(res == FALSE, "RegisterRawInputDevices failed\n");
- todo_wine
ok(GetLastError() == ERROR_INVALID_PARAMETER, "RegisterRawInputDevices returned %08x\n", GetLastError());
raw_devices[0].hwndTarget = hwnd;
diff --git a/server/queue.c b/server/queue.c
index 85aa896c7bd..145b9c110b1 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1758,6 +1758,7 @@ static int queue_rawinput_message( struct process* process, void* user )
struct thread *thread = NULL, *foreground = NULL;
struct message *msg;
struct hardware_msg_data *msg_data;
+ int wparam = RIM_INPUT;
if (raw_msg->data.rawinput.type == RIM_TYPEMOUSE)
device = process->rawinput_mouse;
@@ -1777,10 +1778,12 @@ static int queue_rawinput_message( struct process* process, void* user )
process != thread->process)
goto done;
- /* FIXME: Implement RIDEV_INPUTSINK */
if (!(foreground = get_window_thread( desktop->foreground_input->active )) ||
thread->process != foreground->process)
- goto done;
+ {
+ if (!(device->flags & RIDEV_INPUTSINK)) goto done;
+ wparam = RIM_INPUTSINK;
+ }
if (!(msg = alloc_hardware_message( raw_msg->data.info, raw_msg->source, raw_msg->time, raw_msg->extra_len )))
goto done;
@@ -1788,7 +1791,7 @@ static int queue_rawinput_message( struct process* process, void* user )
msg->win = device->target;
msg->msg = WM_INPUT;
- msg->wparam = RIM_INPUT;
+ msg->wparam = wparam;
msg->lparam = 0;
memcpy( msg_data, &raw_msg->data, sizeof(*msg_data) );
--
2.24.1

View File

@@ -0,0 +1,119 @@
From 18e2112beb69c8499cdd90b133348ec52502dc6d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 21 Aug 2019 16:37:57 +0200
Subject: [PATCH] winex11.drv: Listen to RawKey* events in the desktop thread.
This adds keyboard input support while Wine windows are in background,
so the events can be translated to raw input messages as on Windows,
which are required to keep dinput8 keyboard state up-to-date when
Alt+Tab is used to switch to a non-Wine window.
---
dlls/winex11.drv/keyboard.c | 40 ++++++++++++++++++++++++++++++++++++-
dlls/winex11.drv/mouse.c | 6 ++++++
dlls/winex11.drv/x11drv.h | 1 +
3 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index 37c96c926f4..4d113d8c184 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -33,6 +33,9 @@
#ifdef HAVE_X11_XKBLIB_H
#include <X11/XKBlib.h>
#endif
+#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
+#include <X11/extensions/XInput2.h>
+#endif
#include <ctype.h>
#include <stdarg.h>
@@ -1148,7 +1151,7 @@ static void X11DRV_send_keyboard_input( HWND hwnd, WORD vkey, WORD scan, DWORD f
input.u.ki.time = time;
input.u.ki.dwExtraInfo = 0;
- __wine_send_input( hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ __wine_send_input( hwnd, &input, SEND_HWMSG_WINDOW );
}
@@ -1417,6 +1420,41 @@ BOOL X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
return TRUE;
}
+#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
+/***********************************************************************
+ * X11DRV_KeyEvent
+ *
+ * Handle a raw XInput2 key event for background windows
+ */
+BOOL X11DRV_RawKeyEvent( XGenericEventCookie *cookie )
+{
+ XIRawEvent *event = cookie->data;
+ DWORD flags;
+ WORD vkey, scan;
+ INPUT input;
+
+ vkey = keyc2vkey[event->detail];
+ scan = keyc2scan[event->detail];
+
+ flags = 0;
+ if ( event->evtype == XI_RawKeyRelease ) flags |= KEYEVENTF_KEYUP;
+ if ( vkey & 0x100 ) flags |= KEYEVENTF_EXTENDEDKEY;
+
+ TRACE_(key)( "vkey=%04x scan=%04x flags=%04x\n", vkey, scan, flags );
+
+ input.type = INPUT_KEYBOARD;
+ input.u.ki.wVk = vkey & 0xff;
+ input.u.ki.wScan = scan & 0xff;
+ input.u.ki.dwFlags = flags;
+ input.u.ki.time = EVENT_x11_time_to_win32_time(event->time);
+ input.u.ki.dwExtraInfo = 0;
+
+ __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT );
+
+ return TRUE;
+}
+#endif
+
/**********************************************************************
* X11DRV_KEYBOARD_DetectLayout
*
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index bc23b9cbba1..2e9b39fcff7 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -406,6 +406,8 @@ void X11DRV_XInput2_Enable(void)
{
XISetMask( mask_bits, XI_RawButtonPress );
XISetMask( mask_bits, XI_RawButtonRelease );
+ XISetMask( mask_bits, XI_RawKeyPress );
+ XISetMask( mask_bits, XI_RawKeyRelease );
data->xi2_rawinput_only = TRUE;
}
else
@@ -2038,6 +2040,10 @@ BOOL X11DRV_GenericEvent( HWND hwnd, XEvent *xev )
case XI_RawButtonRelease:
ret = X11DRV_RawButtonEvent( event );
break;
+ case XI_RawKeyPress:
+ case XI_RawKeyRelease:
+ ret = X11DRV_RawKeyEvent( event );
+ break;
default:
TRACE( "Unhandled event %#x\n", event->evtype );
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index c843cd74ace..f89538a1755 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -518,6 +518,7 @@ extern BOOL X11DRV_ButtonRelease( HWND hwnd, XEvent *event ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_MotionNotify( HWND hwnd, XEvent *event ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_EnterNotify( HWND hwnd, XEvent *event ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_KeyEvent( HWND hwnd, XEvent *event ) DECLSPEC_HIDDEN;
+extern BOOL X11DRV_RawKeyEvent( XGenericEventCookie *cookie ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_KeymapNotify( HWND hwnd, XEvent *event ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_DestroyNotify( HWND hwnd, XEvent *event ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_SelectionRequest( HWND hWnd, XEvent *event ) DECLSPEC_HIDDEN;
--
2.24.0

View File

@@ -0,0 +1 @@
Depends: user32-rawinput-hid