[PATCH v4 6/6] server: Implement RegisterRawInputDevices RIDEV_INPUTSINK flag.

Rémi Bernon rbernon at codeweavers.com
Wed Jun 24 08:28:42 CDT 2020


This flag allows applications to receive rawinput messages while in
background. They have to specify a target hwnd, which will receive them,
and the messages will carry a RIM_INPUTSINK wparam if the process wasn't
foreground.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/user32/rawinput.c    |  9 ++++++++-
 dlls/user32/tests/input.c |  8 +++-----
 server/queue.c            | 24 ++++++++++++++++++++----
 3 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index 7a9eb6ced17..103835e0e33 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -291,6 +291,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))
         {
@@ -306,7 +313,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 8ae44e4ab92..51b18242444 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -1807,9 +1807,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;
@@ -1884,13 +1882,13 @@ struct rawinput_test rawinput_tests[] =
 
     /* cross-process foreground tests */
     { TRUE,  TRUE,  0,               FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
-    { TRUE,  TRUE,  RIDEV_INPUTSINK, FALSE,  TRUE, FALSE, /* todos: */ FALSE,  TRUE, FALSE },
+    { TRUE,  TRUE,  RIDEV_INPUTSINK, FALSE,  TRUE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
     { TRUE,  TRUE,  0,               FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
 
     /* multi-process rawinput tests */
     { TRUE,  TRUE,  0,               FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
-    { TRUE,  TRUE,  RIDEV_INPUTSINK, FALSE,  TRUE, FALSE, /* todos: */ FALSE,  TRUE, FALSE },
-    { TRUE,  TRUE,  RIDEV_INPUTSINK, FALSE,  TRUE, FALSE, /* todos: */ FALSE,  TRUE, FALSE },
+    { TRUE,  TRUE,  RIDEV_INPUTSINK, FALSE,  TRUE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
+    { TRUE,  TRUE,  RIDEV_INPUTSINK, FALSE,  TRUE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
 
     { TRUE,  TRUE,  RIDEV_EXINPUTSINK, FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
     { TRUE,  TRUE,  RIDEV_EXINPUTSINK, FALSE,  TRUE, FALSE, /* todos: */ FALSE,  TRUE, FALSE },
diff --git a/server/queue.c b/server/queue.c
index 0318e234bd3..0de3f3bf99e 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1656,7 +1656,10 @@ static int queue_rawinput_message( struct process* process, void *arg )
 {
     const struct rawinput_message* raw_msg = arg;
     const struct rawinput_device *device = NULL;
+    struct desktop *target_desktop = NULL;
+    struct thread *target_thread = NULL;
     struct message *msg;
+    int wparam = RIM_INPUT;
 
     if (raw_msg->data.rawinput.type == RIM_TYPEMOUSE)
         device = process->rawinput_mouse;
@@ -1664,16 +1667,29 @@ static int queue_rawinput_message( struct process* process, void *arg )
         device = process->rawinput_kbd;
     if (!device) return 0;
 
+    if (process != raw_msg->foreground->process)
+    {
+        if (!(device->flags & RIDEV_INPUTSINK)) goto done;
+        if (!(target_thread = get_window_thread( device->target ))) goto done;
+        if (!(target_desktop = get_thread_desktop( target_thread, 0 ))) goto done;
+        if (target_desktop != raw_msg->desktop) goto done;
+        wparam = RIM_INPUTSINK;
+    }
+
     if (!(msg = alloc_hardware_message( raw_msg->data.info, raw_msg->source, raw_msg->time )))
-        return 0;
+        goto done;
 
     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(raw_msg->data) );
 
     queue_hardware_message( raw_msg->desktop, msg, 1 );
+
+done:
+    if (target_thread) release_object( target_thread );
+    if (target_desktop) release_object( target_desktop );
     return 0;
 }
 
@@ -1749,7 +1765,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
         msg_data->rawinput.mouse.y    = y - desktop->cursor.y;
         msg_data->rawinput.mouse.data = input->mouse.data;
 
-        queue_rawinput_message( foreground->process, &raw_msg );
+        enum_processes( queue_rawinput_message, &raw_msg );
         release_object( foreground );
     }
 
@@ -1883,7 +1899,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
         msg_data->rawinput.kbd.vkey    = vkey;
         msg_data->rawinput.kbd.scan    = input->kbd.scan;
 
-        queue_rawinput_message( foreground->process, &raw_msg );
+        enum_processes( queue_rawinput_message, &raw_msg );
         release_object( foreground );
     }
 
-- 
2.27.0




More information about the wine-devel mailing list