From 02e30f5f77e0aea121137be19c8e5d5a36cd5bf8 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 1 Mar 2011 20:33:15 +0100 Subject: [PATCH] server: Pass the original hardware input data to the server and set the message parameters on the server side. --- dlls/winex11.drv/keyboard.c | 36 +++---- dlls/winex11.drv/mouse.c | 18 ++-- include/wine/server_protocol.h | 41 ++++++-- server/protocol.def | 39 ++++++-- server/queue.c | 165 ++++++++++++++++++++++++++++----- server/request.h | 11 +-- server/trace.c | 37 ++++++-- tools/make_requests | 1 + 8 files changed, 267 insertions(+), 81 deletions(-) diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 8a8f482da5a..190436b3aad 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1156,7 +1156,6 @@ void X11DRV_send_keyboard_input( HWND hwnd, WORD wVk, WORD wScan, DWORD event_fl UINT message; KBDLLHOOKSTRUCT hook; WORD flags, wVkStripped, wVkL, wVkR, vk_hook = wVk; - LPARAM lParam = 0; if (!time) time = GetTickCount(); @@ -1225,13 +1224,7 @@ void X11DRV_send_keyboard_input( HWND hwnd, WORD wVk, WORD wScan, DWORD event_fl if (!(event_flags & KEYEVENTF_UNICODE) && key_state_table[wVk] & 0x80) flags |= KF_REPEAT; } - if (event_flags & KEYEVENTF_UNICODE) - { - vk_hook = wVk = VK_PACKET; - lParam = MAKELPARAM(1 /* repeat count */, wScan); - TRACE_(key)("message=0x%04x wParam=0x%04X lParam=0x%08lx\n", - message, wVk, lParam); - } + if (event_flags & KEYEVENTF_UNICODE) vk_hook = wVk = VK_PACKET; /* Hook gets whatever key was sent. */ hook.vkCode = vk_hook; @@ -1254,25 +1247,22 @@ void X11DRV_send_keyboard_input( HWND hwnd, WORD wVk, WORD wScan, DWORD event_fl key_state_table[wVk] |= 0xc0; key_state_table[wVkStripped] = key_state_table[wVkL] | key_state_table[wVkR]; } - - if (key_state_table[VK_MENU] & 0x80) flags |= KF_ALTDOWN; - - if (wVkStripped == VK_SHIFT) flags &= ~KF_EXTENDED; - - lParam = MAKELPARAM(1 /* repeat count */, flags); - - TRACE_(key)(" message=0x%04x wParam=0x%04X, lParam=0x%08lx, InputKeyState=0x%x\n", - message, wVk, lParam, key_state_table[wVk]); } + TRACE_(key)("message=0x%04x wParam=0x%04x InputKeyState=0x%x\n", + message, wVk, key_state_table[wVk]); + SERVER_START_REQ( send_hardware_message ) { - req->win = wine_server_user_handle( hwnd ); - req->msg = message; - req->wparam = wVk; - req->lparam = lParam; - req->time = time; - req->info = dwExtraInfo; + req->win = wine_server_user_handle( hwnd ); + req->msg = message; + req->input.type = INPUT_KEYBOARD; + req->input.kbd.vkey = vk_hook; + req->input.kbd.scan = wScan; + req->input.kbd.flags = event_flags; + req->input.kbd.time = time; + req->input.kbd.info = dwExtraInfo; + if (injected_flags & LLKHF_INJECTED) req->flags = SEND_HWMSG_INJECTED; wine_server_call( req ); } SERVER_END_REQ; diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 811695a5da9..bbdccd7c090 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -306,14 +306,16 @@ static void queue_raw_mouse_message( UINT message, HWND hwnd, DWORD x, DWORD y, SERVER_START_REQ( send_hardware_message ) { - req->win = wine_server_user_handle( hwnd ); - req->msg = message; - req->wparam = MAKEWPARAM( 0, data ); - req->lparam = 0; - req->x = x; - req->y = y; - req->time = time; - req->info = extra_info; + req->win = wine_server_user_handle( hwnd ); + req->msg = message; + req->input.type = INPUT_MOUSE; + req->input.mouse.x = x; + req->input.mouse.y = y; + req->input.mouse.data = data; + req->input.mouse.flags = 0; /* FIXME */ + req->input.mouse.time = time; + req->input.mouse.info = extra_info; + if (injected_flags & LLMHF_INJECTED) req->flags = SEND_HWMSG_INJECTED; wine_server_call( req ); } SERVER_END_REQ; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 4a25433735a..327acc487cb 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -301,6 +301,36 @@ struct winevent_msg_data }; +typedef union +{ + int type; + struct + { + int type; + unsigned short vkey; + unsigned short scan; + unsigned int flags; + unsigned int time; + lparam_t info; + } kbd; + struct + { + int type; + int x; + int y; + unsigned int data; + unsigned int flags; + unsigned int time; + lparam_t info; + } mouse; + struct + { + int type; + unsigned int msg; + lparam_t lparam; + } hw; +} hw_input_t; + typedef union { unsigned char bytes[1]; @@ -2762,18 +2792,15 @@ struct send_hardware_message_request { struct request_header __header; user_handle_t win; + hw_input_t input; + unsigned int flags; unsigned int msg; - unsigned int time; - lparam_t wparam; - lparam_t lparam; - lparam_t info; - int x; - int y; }; struct send_hardware_message_reply { struct reply_header __header; }; +#define SEND_HWMSG_INJECTED 0x01 @@ -5529,6 +5556,6 @@ union generic_reply struct set_cursor_reply set_cursor_reply; }; -#define SERVER_PROTOCOL_VERSION 415 +#define SERVER_PROTOCOL_VERSION 416 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index c1e4fdbef43..593ce4ec119 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -317,6 +317,36 @@ struct winevent_msg_data /* followed by module name if any */ }; +typedef union +{ + int type; + struct + { + int type; /* INPUT_KEYBOARD */ + unsigned short vkey; /* virtual key code */ + unsigned short scan; /* scan code */ + unsigned int flags; /* event flags */ + unsigned int time; /* event time */ + lparam_t info; /* extra info */ + } kbd; + struct + { + int type; /* INPUT_MOUSE */ + int x; /* coordinates */ + int y; + unsigned int data; /* mouse data */ + unsigned int flags; /* event flags */ + unsigned int time; /* event time */ + lparam_t info; /* extra info */ + } mouse; + struct + { + int type; /* INPUT_HARDWARE */ + unsigned int msg; /* message code */ + lparam_t lparam; /* message param */ + } hw; +} hw_input_t; + typedef union { unsigned char bytes[1]; /* raw data for sent messages */ @@ -2002,14 +2032,11 @@ enum message_type /* Send a hardware message to a thread queue */ @REQ(send_hardware_message) user_handle_t win; /* window handle */ + hw_input_t input; /* input data */ + unsigned int flags; /* flags (see below) */ unsigned int msg; /* message code */ - unsigned int time; /* message time */ - lparam_t wparam; /* parameters */ - lparam_t lparam; /* parameters */ - lparam_t info; /* extra info */ - int x; /* x position */ - int y; /* y position */ @END +#define SEND_HWMSG_INJECTED 0x01 /* Get a message from the current queue */ diff --git a/server/queue.c b/server/queue.c index 58be426cbec..1353b00f10c 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1282,7 +1282,13 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg update_input_key_state( desktop, desktop->keystate, msg ); last_input_time = get_tick_count(); - if (!is_keyboard_msg( msg )) + if (is_keyboard_msg( msg )) + { + if (desktop->keystate[VK_MENU] & 0x80) msg->lparam |= KF_ALTDOWN << 16; + if (msg->wparam == VK_SHIFT || msg->wparam == VK_LSHIFT || msg->wparam == VK_RSHIFT) + msg->lparam &= ~(KF_EXTENDED << 16); + } + else { if (msg->msg == WM_MOUSEMOVE) set_cursor_pos( desktop, data->x, data->y ); if (desktop->keystate[VK_LBUTTON] & 0x80) msg->wparam |= MK_LBUTTON; @@ -1322,6 +1328,128 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg release_object( thread ); } +/* queue a hardware message for a mouse event */ +static void queue_mouse_message( struct desktop *desktop, user_handle_t win, unsigned int message, + const hw_input_t *input ) +{ + struct hardware_msg_data *msg_data; + struct message *msg; + + if (!(msg = mem_alloc( sizeof(*msg) ))) return; + if (!(msg_data = mem_alloc( sizeof(*msg_data) ))) + { + free( msg ); + return; + } + memset( msg_data, 0, sizeof(*msg_data) ); + + msg->type = MSG_HARDWARE; + msg->win = get_user_full_handle( win ); + msg->msg = message; + msg->wparam = input->mouse.data << 16; + msg->lparam = 0; + msg->time = input->mouse.time; + msg->result = NULL; + msg->data = msg_data; + msg->data_size = sizeof(*msg_data); + msg_data->x = input->mouse.x; + msg_data->y = input->mouse.y; + msg_data->info = input->mouse.info; + if (!msg->time) msg->time = get_tick_count(); + + queue_hardware_message( desktop, msg ); +} + +/* queue a hardware message for a keyboard event */ +static void queue_keyboard_message( struct desktop *desktop, user_handle_t win, unsigned int message, + const hw_input_t *input ) +{ + struct hardware_msg_data *msg_data; + struct message *msg; + unsigned char vkey = input->kbd.vkey; + + if (!(msg = mem_alloc( sizeof(*msg) ))) return; + if (!(msg_data = mem_alloc( sizeof(*msg_data) ))) + { + free( msg ); + return; + } + memset( msg_data, 0, sizeof(*msg_data) ); + + msg->type = MSG_HARDWARE; + msg->win = get_user_full_handle( win ); + msg->msg = message; + msg->lparam = (input->kbd.scan << 16) | 1; /* repeat count */ + msg->time = input->kbd.time; + msg->result = NULL; + msg->data = msg_data; + msg->data_size = sizeof(*msg_data); + msg_data->info = input->kbd.info; + if (!msg->time) msg->time = get_tick_count(); + + if (input->kbd.flags & KEYEVENTF_UNICODE) + { + msg->wparam = VK_PACKET; + } + else + { + switch (vkey) + { + case VK_MENU: + case VK_LMENU: + case VK_RMENU: + vkey = (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) ? VK_RMENU : VK_LMENU; + break; + case VK_CONTROL: + case VK_LCONTROL: + case VK_RCONTROL: + vkey = (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) ? VK_RCONTROL : VK_LCONTROL; + break; + case VK_SHIFT: + case VK_LSHIFT: + case VK_RSHIFT: + vkey = (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) ? VK_RSHIFT : VK_LSHIFT; + break; + } + if (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) msg->lparam |= KF_EXTENDED << 16; + /* FIXME: set KF_DLGMODE and KF_MENUMODE when needed */ + if (input->kbd.flags & KEYEVENTF_KEYUP) msg->lparam |= (KF_REPEAT | KF_UP) << 16; + else if (desktop->keystate[vkey] & 0x80) msg->lparam |= KF_REPEAT << 16; + + msg->wparam = vkey; + } + + queue_hardware_message( desktop, msg ); +} + +/* queue a hardware message for a custom type of event */ +static void queue_custom_hardware_message( struct desktop *desktop, user_handle_t win, + const hw_input_t *input ) +{ + struct hardware_msg_data *msg_data; + struct message *msg; + + if (!(msg = mem_alloc( sizeof(*msg) ))) return; + if (!(msg_data = mem_alloc( sizeof(*msg_data) ))) + { + free( msg ); + return; + } + memset( msg_data, 0, sizeof(*msg_data) ); + + msg->type = MSG_HARDWARE; + msg->win = get_user_full_handle( win ); + msg->msg = input->hw.msg; + msg->wparam = 0; + msg->lparam = input->hw.lparam; + msg->time = get_tick_count(); + msg->result = NULL; + msg->data = msg_data; + msg->data_size = sizeof(*msg_data); + + queue_hardware_message( desktop, msg ); +} + /* check message filter for a hardware message */ static int check_hw_message_filter( user_handle_t win, unsigned int msg_code, user_handle_t filter_win, unsigned int first, unsigned int last ) @@ -1735,10 +1863,8 @@ DECL_HANDLER(send_message) /* send a hardware message to a thread queue */ DECL_HANDLER(send_hardware_message) { - struct message *msg; struct thread *thread = NULL; struct desktop *desktop; - struct hardware_msg_data *data; if (req->win) { @@ -1747,29 +1873,20 @@ DECL_HANDLER(send_hardware_message) } else if (!(desktop = get_thread_desktop( current, 0 ))) return; - if (!(data = mem_alloc( sizeof(*data) ))) goto done; - - memset( data, 0, sizeof(*data) ); - data->x = req->x; - data->y = req->y; - data->info = req->info; - - if ((msg = mem_alloc( sizeof(*msg) ))) + switch (req->input.type) { - msg->type = MSG_HARDWARE; - msg->win = get_user_full_handle( req->win ); - msg->msg = req->msg; - msg->wparam = req->wparam; - msg->lparam = req->lparam; - msg->time = req->time; - msg->result = NULL; - msg->data = data; - msg->data_size = sizeof(*data); - queue_hardware_message( desktop, msg ); + case INPUT_MOUSE: + queue_mouse_message( desktop, req->win, req->msg, &req->input ); + break; + case INPUT_KEYBOARD: + queue_keyboard_message( desktop, req->win, req->msg, &req->input ); + break; + case INPUT_HARDWARE: + queue_custom_hardware_message( desktop, req->win, &req->input ); + break; + default: + set_error( STATUS_INVALID_PARAMETER ); } - else free( data ); - -done: if (thread) release_object( thread ); release_object( desktop ); } diff --git a/server/request.h b/server/request.h index d757987eee9..780c2ebef3b 100644 --- a/server/request.h +++ b/server/request.h @@ -617,6 +617,7 @@ C_ASSERT( sizeof(client_ptr_t) == 8 ); C_ASSERT( sizeof(cpu_type_t) == 4 ); C_ASSERT( sizeof(data_size_t) == 4 ); C_ASSERT( sizeof(file_pos_t) == 8 ); +C_ASSERT( sizeof(hw_input_t) == 32 ); C_ASSERT( sizeof(int) == 4 ); C_ASSERT( sizeof(ioctl_code_t) == 4 ); C_ASSERT( sizeof(lparam_t) == 8 ); @@ -1378,13 +1379,9 @@ C_ASSERT( sizeof(struct send_message_request) == 56 ); C_ASSERT( FIELD_OFFSET(struct post_quit_message_request, exit_code) == 12 ); C_ASSERT( sizeof(struct post_quit_message_request) == 16 ); C_ASSERT( FIELD_OFFSET(struct send_hardware_message_request, win) == 12 ); -C_ASSERT( FIELD_OFFSET(struct send_hardware_message_request, msg) == 16 ); -C_ASSERT( FIELD_OFFSET(struct send_hardware_message_request, time) == 20 ); -C_ASSERT( FIELD_OFFSET(struct send_hardware_message_request, wparam) == 24 ); -C_ASSERT( FIELD_OFFSET(struct send_hardware_message_request, lparam) == 32 ); -C_ASSERT( FIELD_OFFSET(struct send_hardware_message_request, info) == 40 ); -C_ASSERT( FIELD_OFFSET(struct send_hardware_message_request, x) == 48 ); -C_ASSERT( FIELD_OFFSET(struct send_hardware_message_request, y) == 52 ); +C_ASSERT( FIELD_OFFSET(struct send_hardware_message_request, input) == 16 ); +C_ASSERT( FIELD_OFFSET(struct send_hardware_message_request, flags) == 48 ); +C_ASSERT( FIELD_OFFSET(struct send_hardware_message_request, msg) == 52 ); C_ASSERT( sizeof(struct send_hardware_message_request) == 56 ); C_ASSERT( FIELD_OFFSET(struct get_message_request, flags) == 12 ); C_ASSERT( FIELD_OFFSET(struct get_message_request, get_win) == 16 ); diff --git a/server/trace.c b/server/trace.c index 0539fccd191..e39780e8c11 100644 --- a/server/trace.c +++ b/server/trace.c @@ -36,6 +36,7 @@ #include "winbase.h" #include "wincon.h" #include "winternl.h" +#include "winuser.h" #include "winioctl.h" #include "file.h" #include "request.h" @@ -293,6 +294,34 @@ static void dump_async_data( const char *prefix, const async_data_t *data ) fputc( '}', stderr ); } +static void dump_hw_input( const char *prefix, const hw_input_t *input ) +{ + switch (input->type) + { + case INPUT_MOUSE: + fprintf( stderr, "%s{type=MOUSE,x=%d,y=%d,data=%08x,flags=%08x,time=%u", + prefix, input->mouse.x, input->mouse.y, input->mouse.data, input->mouse.flags, + input->mouse.time ); + dump_uint64( ",info=", &input->mouse.info ); + fputc( '}', stderr ); + break; + case INPUT_KEYBOARD: + fprintf( stderr, "%s{type=KEYBOARD,vkey=%04hx,scan=%04hx,flags=%08x,time=%u", + prefix, input->kbd.vkey, input->kbd.scan, input->kbd.flags, input->kbd.time ); + dump_uint64( ",info=", &input->kbd.info ); + fputc( '}', stderr ); + break; + case INPUT_HARDWARE: + fprintf( stderr, "%s{type=HARDWARE,msg=%04x", prefix, input->hw.msg ); + dump_uint64( ",lparam=", &input->hw.lparam ); + fputc( '}', stderr ); + break; + default: + fprintf( stderr, "%s{type=%04x}", prefix, input->type ); + break; + } +} + static void dump_luid( const char *prefix, const luid_t *luid ) { fprintf( stderr, "%s%d.%u", prefix, luid->high_part, luid->low_part ); @@ -2465,13 +2494,9 @@ static void dump_post_quit_message_request( const struct post_quit_message_reque static void dump_send_hardware_message_request( const struct send_hardware_message_request *req ) { fprintf( stderr, " win=%08x", req->win ); + dump_hw_input( ", input=", &req->input ); + fprintf( stderr, ", flags=%08x", req->flags ); fprintf( stderr, ", msg=%08x", req->msg ); - fprintf( stderr, ", time=%08x", req->time ); - dump_uint64( ", wparam=", &req->wparam ); - dump_uint64( ", lparam=", &req->lparam ); - dump_uint64( ", info=", &req->info ); - fprintf( stderr, ", x=%d", req->x ); - fprintf( stderr, ", y=%d", req->y ); } static void dump_get_message_request( const struct get_message_request *req ) diff --git a/tools/make_requests b/tools/make_requests index 22be2f72cc2..445ad067d76 100755 --- a/tools/make_requests +++ b/tools/make_requests @@ -51,6 +51,7 @@ my %formats = "luid_t" => [ 8, 4, "&dump_luid" ], "ioctl_code_t" => [ 4, 4, "&dump_ioctl_code" ], "cpu_type_t" => [ 4, 4, "&dump_cpu_type" ], + "hw_input_t" => [ 32, 8, "&dump_hw_input" ], ); my @requests = ();