This delivers the rawinput messages to the correct process, regardless of where the input was received.
As for now RIDEV_INPUTSINK is still not implemented, this only fixes the case where input is injected in a background process and where it should not receive rawinput -as in the test- or when cursor moves over a background window and the foreground process should have received rawinput messages.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/tests/input.c | 2 +- server/queue.c | 93 +++++++++++++++++++++++++++++++-------- 2 files changed, 75 insertions(+), 20 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 01733317b2b..6f1fa9b3e9c 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -1885,7 +1885,7 @@ 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, 0, FALSE, FALSE, FALSE, /* todos: */ FALSE, TRUE, TRUE }, + { TRUE, TRUE, 0, FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE },
/* multi-process rawinput tests */ { TRUE, TRUE, 0, FALSE, FALSE, FALSE, /* todos: */ FALSE, FALSE, FALSE }, diff --git a/server/queue.c b/server/queue.c index 84ee0f9a4ea..4a14b1bf554 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1596,13 +1596,68 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa return 1; }
+/* get the foreground thread for a desktop and a window receiving input */ +static struct thread *get_foreground_thread( struct desktop *desktop, user_handle_t window ) +{ + /* if desktop has no foreground process, assume the receiving window is */ + if (desktop->foreground_input) return get_window_thread( desktop->foreground_input->active ); + if (window) return get_window_thread( get_user_full_handle( window ) ); + return NULL; +} + +struct rawinput_message +{ + struct thread *foreground; + struct hw_msg_source source; + unsigned int time; + struct hardware_msg_data data; +}; + +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; + + if (raw_msg->data.rawinput.type == RIM_TYPEMOUSE) + device = process->rawinput_mouse; + else if (raw_msg->data.rawinput.type == RIM_TYPEKEYBOARD) + device = process->rawinput_kbd; + if (!device) goto done; + + if (device->target) target_thread = get_window_thread( device->target ); + else target_thread = (struct thread *)grab_object( raw_msg->foreground ); + + if (!target_thread || target_thread->process != process) goto done; + if (!(target_desktop = get_thread_desktop( target_thread, 0 ))) goto done; + + if (!(msg = alloc_hardware_message( raw_msg->data.info, raw_msg->source, raw_msg->time ))) + goto done; + + msg->win = device->target; + msg->msg = WM_INPUT; + msg->wparam = RIM_INPUT; + msg->lparam = 0; + memcpy( msg->data, &raw_msg->data, sizeof(raw_msg->data) ); + + queue_hardware_message( target_desktop, msg, 0 ); + +done: + if (target_thread) release_object( target_thread ); + if (target_desktop) release_object( target_desktop ); + return 0; +} + /* queue a hardware message for a mouse event */ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input, unsigned int origin, struct msg_queue *sender ) { - const struct rawinput_device *device; struct hardware_msg_data *msg_data; + struct rawinput_message raw_msg; struct message *msg; + struct thread *foreground; unsigned int i, time, flags; struct hw_msg_source source = { IMDT_MOUSE, origin }; int wait = 0, x, y; @@ -1651,23 +1706,22 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons y = desktop->cursor.y; }
- if ((device = current->process->rawinput_mouse)) + if ((foreground = get_foreground_thread( desktop, win ))) { - if (!(msg = alloc_hardware_message( input->mouse.info, source, time ))) return 0; - msg_data = msg->data; - - msg->win = device->target; - msg->msg = WM_INPUT; - msg->wparam = RIM_INPUT; - msg->lparam = 0; + raw_msg.foreground = foreground; + raw_msg.source = source; + raw_msg.time = time;
+ msg_data = &raw_msg.data; + msg_data->info = input->mouse.info; msg_data->flags = flags; msg_data->rawinput.type = RIM_TYPEMOUSE; msg_data->rawinput.mouse.x = x - desktop->cursor.x; msg_data->rawinput.mouse.y = y - desktop->cursor.y; msg_data->rawinput.mouse.data = input->mouse.data;
- queue_hardware_message( desktop, msg, 0 ); + queue_rawinput_message( foreground->process, &raw_msg ); + release_object( foreground ); }
for (i = 0; i < ARRAY_SIZE( messages ); i++) @@ -1704,9 +1758,10 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c unsigned int origin, struct msg_queue *sender ) { struct hw_msg_source source = { IMDT_KEYBOARD, origin }; - const struct rawinput_device *device; struct hardware_msg_data *msg_data; + struct rawinput_message raw_msg; struct message *msg; + struct thread *foreground; unsigned char vkey = input->kbd.vkey; unsigned int message_code, time; int wait; @@ -1777,22 +1832,22 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c break; }
- if ((device = current->process->rawinput_kbd)) + if ((foreground = get_foreground_thread( desktop, win ))) { - if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0; - msg_data = msg->data; - - msg->win = device->target; - msg->msg = WM_INPUT; - msg->wparam = RIM_INPUT; + raw_msg.foreground = foreground; + raw_msg.source = source; + raw_msg.time = time;
+ msg_data = &raw_msg.data; + msg_data->info = input->kbd.info; msg_data->flags = input->kbd.flags; msg_data->rawinput.type = RIM_TYPEKEYBOARD; msg_data->rawinput.kbd.message = message_code; msg_data->rawinput.kbd.vkey = vkey; msg_data->rawinput.kbd.scan = input->kbd.scan;
- queue_hardware_message( desktop, msg, 0 ); + queue_rawinput_message( foreground->process, &raw_msg ); + release_object( foreground ); }
if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0;