server: Pass the original hardware input data to the server and set the message parameters on the server side.
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index 8a8f482..190436b 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -1156,7 +1156,6 @@
UINT message;
KBDLLHOOKSTRUCT hook;
WORD flags, wVkStripped, wVkL, wVkR, vk_hook = wVk;
- LPARAM lParam = 0;
if (!time) time = GetTickCount();
@@ -1225,13 +1224,7 @@
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 @@
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 811695a..bbdccd7 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -306,14 +306,16 @@
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 4a25433..327acc4 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -303,6 +303,36 @@
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];
struct hardware_msg_data hardware;
struct callback_msg_data callback;
@@ -2762,18 +2792,15 @@
{
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 @@
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 c1e4fdb..593ce4e 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -319,6 +319,36 @@
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 */
struct hardware_msg_data hardware;
struct callback_msg_data callback;
@@ -2002,14 +2032,11 @@
/* 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 58be426..1353b00 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1282,7 +1282,13 @@
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 @@
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 @@
/* 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 @@
}
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 d757987..780c2eb 100644
--- a/server/request.h
+++ b/server/request.h
@@ -617,6 +617,7 @@
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( 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 0539fcc..e39780e 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 @@
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_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 22be2f7..445ad06 100755
--- a/tools/make_requests
+++ b/tools/make_requests
@@ -51,6 +51,7 @@
"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 = ();