This delivers the rawinput messages to the correct process, regardless of where the input was received.
For now the RIDEV_INPUTSINK flag is not implemented, so the listening process has to be the foreground process, but iterating the process list will make it easier to implement later.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/tests/input.c | 2 +- server/queue.c | 118 +++++++++++++++++++++++++++----------- 2 files changed, 86 insertions(+), 34 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index ac6a2476785..7fa43f21fbb 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 }, };
static void rawinput_test_process(void) diff --git a/server/queue.c b/server/queue.c index 84ee0f9a4ea..94b9d555183 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1596,12 +1596,73 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa return 1; }
+struct rawinput_message +{ + struct desktop *desktop; + struct hw_msg_source source; + unsigned int time; + struct hardware_msg_data data; +}; + +static int queue_rawinput_message( struct process* process, void* user ) +{ + const struct rawinput_message* raw_msg = user; + const struct rawinput_device *device = NULL; + struct desktop *desktop = NULL; + struct thread *thread = NULL, *foreground = 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; + + /* skip if no device registered in process */ + if (!device) goto done; + + /* skip if event is from another desktop */ + if (!(desktop = get_desktop_obj( process, process->desktop, 0 )) || + (raw_msg->desktop && desktop != raw_msg->desktop)) + goto done; + + /* skip if there is no target window */ + if (!device->target && !desktop->foreground_input) + goto done; + + /* skip if target window is from a thread in another process */ + if (!(thread = get_window_thread( device->target ? device->target : desktop->foreground_input->active )) || + process != thread->process) + goto done; + + /* FIXME: Implement RIDEV_INPUTSINK */ + if (!desktop->foreground_input || !(foreground = get_window_thread( desktop->foreground_input->active )) || + thread->process != foreground->process) + 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( desktop, msg, 0 ); + +done: + if (foreground) release_object( foreground ); + if (thread) release_object( thread ); + if (desktop) release_object( 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; unsigned int i, time, flags; struct hw_msg_source source = { IMDT_MOUSE, origin }; @@ -1651,24 +1712,19 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons y = desktop->cursor.y; }
- if ((device = current->process->rawinput_mouse)) - { - 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.desktop = desktop; + raw_msg.source = source; + raw_msg.time = time;
- 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; + 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 ); - } + enum_processes( queue_rawinput_message, &raw_msg );
for (i = 0; i < ARRAY_SIZE( messages ); i++) { @@ -1704,8 +1760,8 @@ 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; unsigned char vkey = input->kbd.vkey; unsigned int message_code, time; @@ -1777,23 +1833,19 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c break; }
- if ((device = current->process->rawinput_kbd)) - { - 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.desktop = desktop; + raw_msg.source = source; + raw_msg.time = time;
- 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; + 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 ); - } + enum_processes( queue_rawinput_message, &raw_msg );
if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0; msg_data = msg->data;