Commit c7efa293 authored by Alexandre Julliard's avatar Alexandre Julliard

server: Invoke low-level hardware hooks directly from the server side.

parent ae895a1f
......@@ -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
......
......@@ -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 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment