server: Invoke low-level hardware hooks directly from the server side.
This commit is contained in:
parent
ae895a1f10
commit
c7efa293f0
|
@ -2709,6 +2709,38 @@ static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags
|
|||
info.msg.lParam, msg_data->winevent.tid, info.msg.time);
|
||||
}
|
||||
continue;
|
||||
case MSG_HOOK_LL:
|
||||
info.flags = ISMEX_SEND;
|
||||
result = 0;
|
||||
if (info.msg.message == WH_KEYBOARD_LL && size >= sizeof(msg_data->hardware))
|
||||
{
|
||||
KBDLLHOOKSTRUCT hook;
|
||||
|
||||
hook.vkCode = LOWORD( info.msg.lParam );
|
||||
hook.scanCode = HIWORD( info.msg.lParam );
|
||||
hook.flags = msg_data->hardware.flags;
|
||||
hook.time = info.msg.time;
|
||||
hook.dwExtraInfo = msg_data->hardware.info;
|
||||
TRACE( "calling keyboard LL hook vk %x scan %x flags %x time %u info %lx\n",
|
||||
hook.vkCode, hook.scanCode, hook.flags, hook.time, hook.dwExtraInfo );
|
||||
result = HOOK_CallHooks( WH_KEYBOARD_LL, HC_ACTION, info.msg.wParam, (LPARAM)&hook, TRUE );
|
||||
}
|
||||
else if (info.msg.message == WH_MOUSE_LL && size >= sizeof(msg_data->hardware))
|
||||
{
|
||||
MSLLHOOKSTRUCT hook;
|
||||
|
||||
hook.pt.x = msg_data->hardware.x;
|
||||
hook.pt.y = msg_data->hardware.y;
|
||||
hook.mouseData = info.msg.lParam;
|
||||
hook.flags = msg_data->hardware.flags;
|
||||
hook.time = info.msg.time;
|
||||
hook.dwExtraInfo = msg_data->hardware.info;
|
||||
TRACE( "calling mouse LL hook pos %d,%d data %x flags %x time %u info %lx\n",
|
||||
hook.pt.x, hook.pt.y, hook.mouseData, hook.flags, hook.time, hook.dwExtraInfo );
|
||||
result = HOOK_CallHooks( WH_MOUSE_LL, HC_ACTION, info.msg.wParam, (LPARAM)&hook, TRUE );
|
||||
}
|
||||
reply_message( &info, result, TRUE );
|
||||
continue;
|
||||
case MSG_OTHER_PROCESS:
|
||||
info.flags = ISMEX_SEND;
|
||||
if (!unpack_message( info.msg.hwnd, info.msg.message, &info.msg.wParam,
|
||||
|
@ -3072,7 +3104,15 @@ static BOOL send_message( struct send_message_info *info, DWORD_PTR *res_ptr, BO
|
|||
*/
|
||||
NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags )
|
||||
{
|
||||
struct send_message_info info;
|
||||
NTSTATUS ret;
|
||||
BOOL wait;
|
||||
|
||||
info.type = MSG_HARDWARE;
|
||||
info.dest_tid = 0;
|
||||
info.hwnd = hwnd;
|
||||
info.flags = 0;
|
||||
info.timeout = 0;
|
||||
|
||||
SERVER_START_REQ( send_hardware_message )
|
||||
{
|
||||
|
@ -3102,8 +3142,16 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags )
|
|||
break;
|
||||
}
|
||||
ret = wine_server_call( req );
|
||||
wait = reply->wait;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (wait)
|
||||
{
|
||||
LRESULT ignored;
|
||||
wait_message_reply( 0 );
|
||||
retrieve_reply( &info, 0, &ignored );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1155,7 +1155,6 @@ void X11DRV_send_keyboard_input( HWND hwnd, WORD wVk, WORD wScan, DWORD event_fl
|
|||
{
|
||||
UINT message;
|
||||
INPUT input;
|
||||
KBDLLHOOKSTRUCT hook;
|
||||
WORD flags, wVkStripped, wVkL, wVkR, vk_hook = wVk;
|
||||
|
||||
if (!time) time = GetTickCount();
|
||||
|
@ -1227,14 +1226,6 @@ void X11DRV_send_keyboard_input( HWND hwnd, WORD wVk, WORD wScan, DWORD event_fl
|
|||
|
||||
if (event_flags & KEYEVENTF_UNICODE) vk_hook = wVk = VK_PACKET;
|
||||
|
||||
/* Hook gets whatever key was sent. */
|
||||
hook.vkCode = vk_hook;
|
||||
hook.scanCode = wScan;
|
||||
hook.flags = (flags >> 8) | injected_flags;
|
||||
hook.time = time;
|
||||
hook.dwExtraInfo = dwExtraInfo;
|
||||
if (HOOK_CallHooks( WH_KEYBOARD_LL, HC_ACTION, message, (LPARAM)&hook, TRUE )) return;
|
||||
|
||||
input.type = INPUT_KEYBOARD;
|
||||
input.u.ki.wVk = vk_hook;
|
||||
input.u.ki.wScan = wScan;
|
||||
|
|
|
@ -293,7 +293,6 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y,
|
|||
{
|
||||
POINT pt;
|
||||
INPUT input;
|
||||
MSLLHOOKSTRUCT hook;
|
||||
|
||||
if (!time) time = GetTickCount();
|
||||
|
||||
|
@ -308,34 +307,29 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y,
|
|||
{
|
||||
pt.x = x;
|
||||
pt.y = y;
|
||||
wine_tsx11_lock();
|
||||
if (cursor_pos.x == x && cursor_pos.y == y &&
|
||||
(flags & ~(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE)))
|
||||
flags &= ~MOUSEEVENTF_MOVE;
|
||||
wine_tsx11_unlock();
|
||||
}
|
||||
}
|
||||
else if (flags & MOUSEEVENTF_MOVE)
|
||||
{
|
||||
int accel[3], xMult = 1, yMult = 1;
|
||||
int accel[3];
|
||||
|
||||
/* dx and dy can be negative numbers for relative movements */
|
||||
SystemParametersInfoW(SPI_GETMOUSE, 0, accel, 0);
|
||||
|
||||
if (abs(x) > accel[0] && accel[2] != 0)
|
||||
{
|
||||
xMult = 2;
|
||||
if ((abs(x) > accel[1]) && (accel[2] == 2)) xMult = 4;
|
||||
x = (int)x * 2;
|
||||
if ((abs(x) > accel[1]) && (accel[2] == 2)) x = (int)x * 2;
|
||||
}
|
||||
if (abs(y) > accel[0] && accel[2] != 0)
|
||||
{
|
||||
yMult = 2;
|
||||
if ((abs(y) > accel[1]) && (accel[2] == 2)) yMult = 4;
|
||||
y = (int)y * 2;
|
||||
if ((abs(y) > accel[1]) && (accel[2] == 2)) y = (int)y * 2;
|
||||
}
|
||||
|
||||
wine_tsx11_lock();
|
||||
pt.x = cursor_pos.x + (long)x * xMult;
|
||||
pt.y = cursor_pos.y + (long)y * yMult;
|
||||
pt.x = cursor_pos.x + x;
|
||||
pt.y = cursor_pos.y + y;
|
||||
wine_tsx11_unlock();
|
||||
}
|
||||
else
|
||||
|
@ -345,85 +339,28 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y,
|
|||
wine_tsx11_unlock();
|
||||
}
|
||||
|
||||
hook.pt.x = pt.x;
|
||||
hook.pt.y = pt.y;
|
||||
hook.mouseData = MAKELONG( 0, data );
|
||||
hook.flags = injected_flags;
|
||||
hook.time = time;
|
||||
hook.dwExtraInfo = extra_info;
|
||||
last_time_modified = GetTickCount();
|
||||
|
||||
if (flags & MOUSEEVENTF_MOVE)
|
||||
{
|
||||
if (HOOK_CallHooks( WH_MOUSE_LL, HC_ACTION, WM_MOUSEMOVE, (LPARAM)&hook, TRUE )) return;
|
||||
if ((injected_flags & LLMHF_INJECTED) &&
|
||||
((flags & MOUSEEVENTF_ABSOLUTE) || x || y)) /* we have to actually move the cursor */
|
||||
{
|
||||
clip_point_to_rect( &cursor_clip, &pt );
|
||||
X11DRV_SetCursorPos( pt.x, pt.y );
|
||||
}
|
||||
else
|
||||
{
|
||||
wine_tsx11_lock();
|
||||
clip_point_to_rect( &cursor_clip, &pt);
|
||||
cursor_pos = pt;
|
||||
wine_tsx11_unlock();
|
||||
}
|
||||
}
|
||||
if (flags & MOUSEEVENTF_LEFTDOWN)
|
||||
{
|
||||
if (HOOK_CallHooks( WH_MOUSE_LL, HC_ACTION,
|
||||
GetSystemMetrics(SM_SWAPBUTTON) ? WM_RBUTTONDOWN : WM_LBUTTONDOWN,
|
||||
(LPARAM)&hook, TRUE )) return;
|
||||
}
|
||||
if (flags & MOUSEEVENTF_LEFTUP)
|
||||
{
|
||||
if (HOOK_CallHooks( WH_MOUSE_LL, HC_ACTION,
|
||||
GetSystemMetrics(SM_SWAPBUTTON) ? WM_RBUTTONUP : WM_LBUTTONUP,
|
||||
(LPARAM)&hook, TRUE )) return;
|
||||
}
|
||||
if (flags & MOUSEEVENTF_RIGHTDOWN)
|
||||
{
|
||||
if (HOOK_CallHooks( WH_MOUSE_LL, HC_ACTION,
|
||||
GetSystemMetrics(SM_SWAPBUTTON) ? WM_LBUTTONDOWN : WM_RBUTTONDOWN,
|
||||
(LPARAM)&hook, TRUE )) return;
|
||||
}
|
||||
if (flags & MOUSEEVENTF_RIGHTUP)
|
||||
{
|
||||
if (HOOK_CallHooks( WH_MOUSE_LL, HC_ACTION,
|
||||
GetSystemMetrics(SM_SWAPBUTTON) ? WM_LBUTTONUP : WM_RBUTTONUP,
|
||||
(LPARAM)&hook, TRUE )) return;
|
||||
}
|
||||
if (flags & MOUSEEVENTF_MIDDLEDOWN)
|
||||
{
|
||||
if (HOOK_CallHooks( WH_MOUSE_LL, HC_ACTION, WM_MBUTTONDOWN, (LPARAM)&hook, TRUE )) return;
|
||||
}
|
||||
if (flags & MOUSEEVENTF_MIDDLEUP)
|
||||
{
|
||||
if (HOOK_CallHooks( WH_MOUSE_LL, HC_ACTION, WM_MBUTTONUP, (LPARAM)&hook, TRUE )) return;
|
||||
}
|
||||
if (flags & MOUSEEVENTF_WHEEL)
|
||||
{
|
||||
if (HOOK_CallHooks( WH_MOUSE_LL, HC_ACTION, WM_MOUSEWHEEL, (LPARAM)&hook, TRUE )) return;
|
||||
}
|
||||
if (flags & MOUSEEVENTF_XDOWN)
|
||||
{
|
||||
if (HOOK_CallHooks( WH_MOUSE_LL, HC_ACTION, WM_XBUTTONDOWN, (LPARAM)&hook, TRUE )) return;
|
||||
}
|
||||
if (flags & MOUSEEVENTF_XUP)
|
||||
{
|
||||
if (HOOK_CallHooks( WH_MOUSE_LL, HC_ACTION, WM_XBUTTONUP, (LPARAM)&hook, TRUE )) return;
|
||||
}
|
||||
|
||||
input.type = INPUT_MOUSE;
|
||||
input.u.mi.dx = pt.x;
|
||||
input.u.mi.dy = pt.y;
|
||||
input.u.mi.dx = x;
|
||||
input.u.mi.dy = y;
|
||||
input.u.mi.mouseData = data;
|
||||
input.u.mi.dwFlags = flags | MOUSEEVENTF_ABSOLUTE;
|
||||
input.u.mi.dwFlags = flags;
|
||||
input.u.mi.time = time;
|
||||
input.u.mi.dwExtraInfo = extra_info;
|
||||
|
||||
__wine_send_input( hwnd, &input, (injected_flags & LLMHF_INJECTED) != 0 );
|
||||
|
||||
if (injected_flags & LLMHF_INJECTED)
|
||||
{
|
||||
if ((flags & MOUSEEVENTF_MOVE) &&
|
||||
((flags & MOUSEEVENTF_ABSOLUTE) || x || y)) /* we have to actually move the cursor */
|
||||
{
|
||||
GetCursorPos( &pt );
|
||||
if (!(flags & MOUSEEVENTF_ABSOLUTE) || pt.x != x || pt.y != y)
|
||||
X11DRV_SetCursorPos( pt.x, pt.y );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SONAME_LIBXCURSOR
|
||||
|
|
|
@ -283,7 +283,7 @@ struct hardware_msg_data
|
|||
int x;
|
||||
int y;
|
||||
unsigned int hw_id;
|
||||
int __pad;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct callback_msg_data
|
||||
|
@ -2782,7 +2782,8 @@ enum message_type
|
|||
MSG_OTHER_PROCESS,
|
||||
MSG_POSTED,
|
||||
MSG_HARDWARE,
|
||||
MSG_WINEVENT
|
||||
MSG_WINEVENT,
|
||||
MSG_HOOK_LL
|
||||
};
|
||||
#define SEND_MSG_ABORT_IF_HUNG 0x01
|
||||
|
||||
|
@ -2794,11 +2795,13 @@ struct send_hardware_message_request
|
|||
user_handle_t win;
|
||||
hw_input_t input;
|
||||
unsigned int flags;
|
||||
unsigned int msg;
|
||||
char __pad_52[4];
|
||||
};
|
||||
struct send_hardware_message_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
int wait;
|
||||
char __pad_12[4];
|
||||
};
|
||||
#define SEND_HWMSG_INJECTED 0x01
|
||||
|
||||
|
@ -5556,6 +5559,6 @@ union generic_reply
|
|||
struct set_cursor_reply set_cursor_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 416
|
||||
#define SERVER_PROTOCOL_VERSION 417
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -369,6 +369,17 @@ unsigned int get_active_hooks(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* return the thread that owns the first global hook */
|
||||
struct thread *get_first_global_hook( int id )
|
||||
{
|
||||
struct hook *hook;
|
||||
struct hook_table *global_hooks = get_global_hooks( current );
|
||||
|
||||
if (!global_hooks) return NULL;
|
||||
if (!(hook = get_first_valid_hook( global_hooks, id - WH_MINHOOK, EVENT_MIN, 0, 0, 0 ))) return NULL;
|
||||
return hook->owner;
|
||||
}
|
||||
|
||||
/* set a window hook */
|
||||
DECL_HANDLER(set_hook)
|
||||
{
|
||||
|
|
|
@ -299,7 +299,7 @@ struct hardware_msg_data
|
|||
int x; /* x position */
|
||||
int y; /* y position */
|
||||
unsigned int hw_id; /* unique id */
|
||||
int __pad;
|
||||
unsigned int flags; /* hook flags */
|
||||
};
|
||||
|
||||
struct callback_msg_data
|
||||
|
@ -2024,7 +2024,8 @@ enum message_type
|
|||
MSG_OTHER_PROCESS, /* sent from other process, may include vararg data, always Unicode */
|
||||
MSG_POSTED, /* posted message (from PostMessageW), always Unicode */
|
||||
MSG_HARDWARE, /* hardware message */
|
||||
MSG_WINEVENT /* winevent message */
|
||||
MSG_WINEVENT, /* winevent message */
|
||||
MSG_HOOK_LL /* low-level hardware hook */
|
||||
};
|
||||
#define SEND_MSG_ABORT_IF_HUNG 0x01
|
||||
|
||||
|
@ -2034,7 +2035,8 @@ enum message_type
|
|||
user_handle_t win; /* window handle */
|
||||
hw_input_t input; /* input data */
|
||||
unsigned int flags; /* flags (see below) */
|
||||
unsigned int msg; /* message code */
|
||||
@REPLY
|
||||
int wait; /* do we need to wait for a reply? */
|
||||
@END
|
||||
#define SEND_HWMSG_INJECTED 0x01
|
||||
|
||||
|
|
150
server/queue.c
150
server/queue.c
|
@ -58,6 +58,8 @@ struct message_result
|
|||
int replied; /* has it been replied to? */
|
||||
unsigned int error; /* error code to pass back to sender */
|
||||
lparam_t result; /* reply result */
|
||||
struct message *hardware_msg; /* hardware message if low-level hook result */
|
||||
struct desktop *desktop; /* desktop for hardware message */
|
||||
struct message *callback_msg; /* message to queue for callback */
|
||||
void *data; /* message reply data */
|
||||
unsigned int data_size; /* size of message reply data */
|
||||
|
@ -201,6 +203,7 @@ static const struct object_ops thread_input_ops =
|
|||
/* pointer to input structure of foreground thread */
|
||||
static unsigned int last_input_time;
|
||||
|
||||
static void queue_hardware_message( struct desktop *desktop, struct message *msg );
|
||||
static void free_message( struct message *msg );
|
||||
|
||||
/* set the caret window in a given thread input */
|
||||
|
@ -436,6 +439,8 @@ static void free_result( struct message_result *result )
|
|||
if (result->timeout) remove_timeout_user( result->timeout );
|
||||
free( result->data );
|
||||
if (result->callback_msg) free_message( result->callback_msg );
|
||||
if (result->hardware_msg) free_message( result->hardware_msg );
|
||||
if (result->desktop) release_object( result->desktop );
|
||||
free( result );
|
||||
}
|
||||
|
||||
|
@ -460,6 +465,17 @@ static void store_message_result( struct message_result *res, lparam_t result, u
|
|||
remove_timeout_user( res->timeout );
|
||||
res->timeout = NULL;
|
||||
}
|
||||
|
||||
if (res->hardware_msg)
|
||||
{
|
||||
if (!error && result) /* rejected by the hook */
|
||||
free_message( res->hardware_msg );
|
||||
else
|
||||
queue_hardware_message( res->desktop, res->hardware_msg );
|
||||
|
||||
res->hardware_msg = NULL;
|
||||
}
|
||||
|
||||
if (res->sender)
|
||||
{
|
||||
if (res->callback_msg)
|
||||
|
@ -479,7 +495,7 @@ static void store_message_result( struct message_result *res, lparam_t result, u
|
|||
set_queue_bits( res->sender, QS_SMRESULT );
|
||||
}
|
||||
}
|
||||
|
||||
else if (!res->receiver) free_result( res );
|
||||
}
|
||||
|
||||
/* free a message when deleting a queue or window */
|
||||
|
@ -489,12 +505,8 @@ static void free_message( struct message *msg )
|
|||
if (result)
|
||||
{
|
||||
result->msg = NULL;
|
||||
if (result->sender)
|
||||
{
|
||||
result->receiver = NULL;
|
||||
store_message_result( result, 0, STATUS_ACCESS_DENIED /*FIXME*/ );
|
||||
}
|
||||
else free_result( result );
|
||||
result->receiver = NULL;
|
||||
store_message_result( result, 0, STATUS_ACCESS_DENIED /*FIXME*/ );
|
||||
}
|
||||
free( msg->data );
|
||||
free( msg );
|
||||
|
@ -535,13 +547,7 @@ static void result_timeout( void *private )
|
|||
msg->result = NULL;
|
||||
remove_queue_message( result->receiver, msg, SEND_MESSAGE );
|
||||
result->receiver = NULL;
|
||||
if (!result->sender)
|
||||
{
|
||||
free_result( result );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
store_message_result( result, 0, STATUS_TIMEOUT );
|
||||
}
|
||||
|
||||
|
@ -553,13 +559,16 @@ static struct message_result *alloc_message_result( struct msg_queue *send_queue
|
|||
struct message_result *result = mem_alloc( sizeof(*result) );
|
||||
if (result)
|
||||
{
|
||||
result->msg = msg;
|
||||
result->sender = send_queue;
|
||||
result->receiver = recv_queue;
|
||||
result->replied = 0;
|
||||
result->data = NULL;
|
||||
result->data_size = 0;
|
||||
result->timeout = NULL;
|
||||
result->msg = msg;
|
||||
result->sender = send_queue;
|
||||
result->receiver = recv_queue;
|
||||
result->replied = 0;
|
||||
result->data = NULL;
|
||||
result->data_size = 0;
|
||||
result->timeout = NULL;
|
||||
result->hardware_msg = NULL;
|
||||
result->desktop = NULL;
|
||||
result->callback_msg = NULL;
|
||||
|
||||
if (msg->type == MSG_CALLBACK)
|
||||
{
|
||||
|
@ -586,11 +595,7 @@ static struct message_result *alloc_message_result( struct msg_queue *send_queue
|
|||
result->callback_msg = callback_msg;
|
||||
list_add_head( &send_queue->callback_result, &result->sender_entry );
|
||||
}
|
||||
else
|
||||
{
|
||||
result->callback_msg = NULL;
|
||||
list_add_head( &send_queue->send_result, &result->sender_entry );
|
||||
}
|
||||
else if (send_queue) list_add_head( &send_queue->send_result, &result->sender_entry );
|
||||
|
||||
if (timeout != TIMEOUT_INFINITE)
|
||||
result->timeout = add_timeout_user( timeout, result_timeout, result );
|
||||
|
@ -641,7 +646,7 @@ static void reply_message( struct msg_queue *queue, lparam_t result,
|
|||
{
|
||||
queue->recv_result = res->recv_next;
|
||||
res->receiver = NULL;
|
||||
if (!res->sender) /* no one waiting for it */
|
||||
if (!res->sender && !res->hardware_msg) /* no one waiting for it */
|
||||
{
|
||||
free_result( res );
|
||||
return;
|
||||
|
@ -1328,13 +1333,58 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg
|
|||
release_object( thread );
|
||||
}
|
||||
|
||||
/* send the low-level hook message for a given hardware message */
|
||||
static int send_hook_ll_message( struct desktop *desktop, struct message *hardware_msg,
|
||||
const hw_input_t *input, struct msg_queue *sender )
|
||||
{
|
||||
struct thread *hook_thread;
|
||||
struct msg_queue *queue;
|
||||
struct message *msg;
|
||||
timeout_t timeout = 2000 * -10000; /* FIXME: load from registry */
|
||||
int id = (input->type == INPUT_MOUSE) ? WH_MOUSE_LL : WH_KEYBOARD_LL;
|
||||
|
||||
if (!(hook_thread = get_first_global_hook( id ))) return 0;
|
||||
if (!(queue = hook_thread->queue)) return 0;
|
||||
|
||||
if (!(msg = mem_alloc( sizeof(*msg) ))) return 0;
|
||||
|
||||
msg->type = MSG_HOOK_LL;
|
||||
msg->win = 0;
|
||||
msg->msg = id;
|
||||
msg->wparam = hardware_msg->msg;
|
||||
msg->time = hardware_msg->time;
|
||||
msg->data_size = hardware_msg->data_size;
|
||||
msg->result = NULL;
|
||||
|
||||
if (input->type == INPUT_KEYBOARD)
|
||||
{
|
||||
unsigned short vkey = input->kbd.vkey;
|
||||
if (input->kbd.flags & KEYEVENTF_UNICODE) vkey = VK_PACKET;
|
||||
msg->lparam = (input->kbd.scan << 16) | vkey;
|
||||
}
|
||||
else msg->lparam = input->mouse.data;
|
||||
|
||||
if (!(msg->data = memdup( hardware_msg->data, hardware_msg->data_size )) ||
|
||||
!(msg->result = alloc_message_result( sender, queue, msg, timeout )))
|
||||
{
|
||||
free_message( msg );
|
||||
return 0;
|
||||
}
|
||||
msg->result->hardware_msg = hardware_msg;
|
||||
msg->result->desktop = (struct desktop *)grab_object( desktop );
|
||||
list_add_tail( &queue->msg_list[SEND_MESSAGE], &msg->entry );
|
||||
set_queue_bits( queue, QS_SENDMESSAGE );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* queue a hardware message for a mouse event */
|
||||
static void queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input )
|
||||
static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input,
|
||||
unsigned int hook_flags, struct msg_queue *sender )
|
||||
{
|
||||
struct hardware_msg_data *msg_data;
|
||||
struct message *msg;
|
||||
unsigned int i, time, flags;
|
||||
int x, y;
|
||||
int wait = 0, x, y;
|
||||
|
||||
static const unsigned int messages[] =
|
||||
{
|
||||
|
@ -1383,12 +1433,13 @@ static void queue_mouse_message( struct desktop *desktop, user_handle_t win, con
|
|||
{
|
||||
if (!messages[i]) continue;
|
||||
if (!(flags & (1 << i))) continue;
|
||||
flags &= ~(1 << i);
|
||||
|
||||
if (!(msg = mem_alloc( sizeof(*msg) ))) return;
|
||||
if (!(msg = mem_alloc( sizeof(*msg) ))) return 0;
|
||||
if (!(msg_data = mem_alloc( sizeof(*msg_data) )))
|
||||
{
|
||||
free( msg );
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
memset( msg_data, 0, sizeof(*msg_data) );
|
||||
|
||||
|
@ -1404,23 +1455,34 @@ static void queue_mouse_message( struct desktop *desktop, user_handle_t win, con
|
|||
msg_data->x = x;
|
||||
msg_data->y = y;
|
||||
msg_data->info = input->mouse.info;
|
||||
if (hook_flags & SEND_HWMSG_INJECTED) msg_data->flags = LLMHF_INJECTED;
|
||||
|
||||
queue_hardware_message( desktop, msg );
|
||||
/* specify a sender only when sending the last message */
|
||||
if (!(flags & ((1 << sizeof(messages)/sizeof(messages[0])) - 1)))
|
||||
{
|
||||
if (!(wait = send_hook_ll_message( desktop, msg, input, sender )))
|
||||
queue_hardware_message( desktop, msg );
|
||||
}
|
||||
else if (!send_hook_ll_message( desktop, msg, input, NULL ))
|
||||
queue_hardware_message( desktop, msg );
|
||||
}
|
||||
return wait;
|
||||
}
|
||||
|
||||
/* queue a hardware message for a keyboard event */
|
||||
static void queue_keyboard_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input )
|
||||
static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input,
|
||||
unsigned int hook_flags, struct msg_queue *sender )
|
||||
{
|
||||
struct hardware_msg_data *msg_data;
|
||||
struct message *msg;
|
||||
unsigned char vkey = input->kbd.vkey;
|
||||
int wait;
|
||||
|
||||
if (!(msg = mem_alloc( sizeof(*msg) ))) return;
|
||||
if (!(msg = mem_alloc( sizeof(*msg) ))) return 0;
|
||||
if (!(msg_data = mem_alloc( sizeof(*msg_data) )))
|
||||
{
|
||||
free( msg );
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
memset( msg_data, 0, sizeof(*msg_data) );
|
||||
|
||||
|
@ -1433,6 +1495,7 @@ static void queue_keyboard_message( struct desktop *desktop, user_handle_t win,
|
|||
msg->data_size = sizeof(*msg_data);
|
||||
msg_data->info = input->kbd.info;
|
||||
if (!msg->time) msg->time = get_tick_count();
|
||||
if (hook_flags & SEND_HWMSG_INJECTED) msg_data->flags = LLKHF_INJECTED;
|
||||
|
||||
if (input->kbd.flags & KEYEVENTF_UNICODE)
|
||||
{
|
||||
|
@ -1440,6 +1503,7 @@ static void queue_keyboard_message( struct desktop *desktop, user_handle_t win,
|
|||
}
|
||||
else
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
switch (vkey)
|
||||
{
|
||||
case VK_MENU:
|
||||
|
@ -1458,12 +1522,14 @@ static void queue_keyboard_message( struct desktop *desktop, user_handle_t win,
|
|||
vkey = (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) ? VK_RSHIFT : VK_LSHIFT;
|
||||
break;
|
||||
}
|
||||
if (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) msg->lparam |= KF_EXTENDED << 16;
|
||||
if (input->kbd.flags & KEYEVENTF_EXTENDEDKEY) flags |= KF_EXTENDED;
|
||||
/* 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;
|
||||
if (input->kbd.flags & KEYEVENTF_KEYUP) flags |= KF_REPEAT | KF_UP;
|
||||
else if (desktop->keystate[vkey] & 0x80) flags |= KF_REPEAT;
|
||||
|
||||
msg->wparam = vkey;
|
||||
msg->lparam |= flags << 16;
|
||||
msg_data->flags |= (flags & (KF_EXTENDED | KF_ALTDOWN | KF_UP)) >> 8;
|
||||
}
|
||||
|
||||
msg->msg = (input->kbd.flags & KEYEVENTF_KEYUP) ? WM_KEYUP : WM_KEYDOWN;
|
||||
|
@ -1508,8 +1574,10 @@ static void queue_keyboard_message( struct desktop *desktop, user_handle_t win,
|
|||
desktop->keystate[VK_MENU] &= ~0x02;
|
||||
break;
|
||||
}
|
||||
if (!(wait = send_hook_ll_message( desktop, msg, input, sender )))
|
||||
queue_hardware_message( desktop, msg );
|
||||
|
||||
queue_hardware_message( desktop, msg );
|
||||
return wait;
|
||||
}
|
||||
|
||||
/* queue a hardware message for a custom type of event */
|
||||
|
@ -1941,6 +2009,7 @@ DECL_HANDLER(send_message)
|
|||
break;
|
||||
case MSG_HARDWARE: /* should use send_hardware_message instead */
|
||||
case MSG_CALLBACK_RESULT: /* cannot send this one */
|
||||
case MSG_HOOK_LL: /* generated internally */
|
||||
default:
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
free( msg );
|
||||
|
@ -1955,6 +2024,7 @@ DECL_HANDLER(send_hardware_message)
|
|||
{
|
||||
struct thread *thread = NULL;
|
||||
struct desktop *desktop;
|
||||
struct msg_queue *sender = get_current_queue();
|
||||
|
||||
if (req->win)
|
||||
{
|
||||
|
@ -1966,10 +2036,10 @@ DECL_HANDLER(send_hardware_message)
|
|||
switch (req->input.type)
|
||||
{
|
||||
case INPUT_MOUSE:
|
||||
queue_mouse_message( desktop, req->win, &req->input );
|
||||
reply->wait = queue_mouse_message( desktop, req->win, &req->input, req->flags, sender );
|
||||
break;
|
||||
case INPUT_KEYBOARD:
|
||||
queue_keyboard_message( desktop, req->win, &req->input );
|
||||
reply->wait = queue_keyboard_message( desktop, req->win, &req->input, req->flags, sender );
|
||||
break;
|
||||
case INPUT_HARDWARE:
|
||||
queue_custom_hardware_message( desktop, req->win, &req->input );
|
||||
|
|
|
@ -1381,8 +1381,9 @@ 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, 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 send_hardware_message_reply, wait) == 8 );
|
||||
C_ASSERT( sizeof(struct send_hardware_message_reply) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_message_request, flags) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_message_request, get_win) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_message_request, get_first) == 20 );
|
||||
|
|
|
@ -2496,7 +2496,11 @@ static void dump_send_hardware_message_request( const struct send_hardware_messa
|
|||
fprintf( stderr, " win=%08x", req->win );
|
||||
dump_hw_input( ", input=", &req->input );
|
||||
fprintf( stderr, ", flags=%08x", req->flags );
|
||||
fprintf( stderr, ", msg=%08x", req->msg );
|
||||
}
|
||||
|
||||
static void dump_send_hardware_message_reply( const struct send_hardware_message_reply *req )
|
||||
{
|
||||
fprintf( stderr, " wait=%d", req->wait );
|
||||
}
|
||||
|
||||
static void dump_get_message_request( const struct get_message_request *req )
|
||||
|
@ -4275,7 +4279,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_get_process_idle_event_reply,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(dump_func)dump_send_hardware_message_reply,
|
||||
(dump_func)dump_get_message_reply,
|
||||
NULL,
|
||||
NULL,
|
||||
|
|
|
@ -87,6 +87,7 @@ extern void cleanup_clipboard_thread( struct thread *thread );
|
|||
|
||||
extern void remove_thread_hooks( struct thread *thread );
|
||||
extern unsigned int get_active_hooks(void);
|
||||
extern struct thread *get_first_global_hook( int id );
|
||||
|
||||
/* queue functions */
|
||||
|
||||
|
|
Loading…
Reference in New Issue