From ae895a1f100682fdee679bad1b5cadda8e00ddef Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 2 Mar 2011 19:43:53 +0100 Subject: [PATCH] user32: Export a Wine-specific function to send hardware input from the graphics driver. --- dlls/user32/input.c | 13 +++++++++++ dlls/user32/message.c | 43 +++++++++++++++++++++++++++++++++++++ dlls/user32/user32.spec | 8 +++++++ dlls/user32/user_private.h | 1 + dlls/winex11.drv/keyboard.c | 23 ++++++++------------ dlls/winex11.drv/mouse.c | 24 +++++++++------------ include/winuser.h | 4 ++++ 7 files changed, 88 insertions(+), 28 deletions(-) diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 455e55a98f..c30a195768 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -114,6 +114,19 @@ BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) } +/*********************************************************************** + * __wine_send_input (USER32.@) + * + * Internal SendInput function to allow the graphics driver to inject real events. + */ +BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, BOOL injected ) +{ + NTSTATUS status = send_hardware_message( hwnd, input, injected ? SEND_HWMSG_INJECTED : 0 ); + if (status) SetLastError( RtlNtStatusToDosError(status) ); + return !status; +} + + /*********************************************************************** * SendInput (USER32.@) */ diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 93a90ea837..0095af39bb 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -25,6 +25,8 @@ #include #include +#define NONAMELESSUNION +#define NONAMELESSSTRUCT #include "ntstatus.h" #define WIN32_NO_STATUS #include "windef.h" @@ -3065,6 +3067,47 @@ static BOOL send_message( struct send_message_info *info, DWORD_PTR *res_ptr, BO } +/*********************************************************************** + * send_hardware_message + */ +NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags ) +{ + NTSTATUS ret; + + SERVER_START_REQ( send_hardware_message ) + { + req->win = wine_server_user_handle( hwnd ); + req->flags = flags; + req->input.type = input->type; + switch (input->type) + { + case INPUT_MOUSE: + req->input.mouse.x = input->u.mi.dx; + req->input.mouse.y = input->u.mi.dy; + req->input.mouse.data = input->u.mi.mouseData; + req->input.mouse.flags = input->u.mi.dwFlags; + req->input.mouse.time = input->u.mi.time; + req->input.mouse.info = input->u.mi.dwExtraInfo; + break; + case INPUT_KEYBOARD: + req->input.kbd.vkey = input->u.ki.wVk; + req->input.kbd.scan = input->u.ki.wScan; + req->input.kbd.flags = input->u.ki.dwFlags; + req->input.kbd.time = input->u.ki.time; + req->input.kbd.info = input->u.ki.dwExtraInfo; + break; + case INPUT_HARDWARE: + req->input.hw.msg = input->u.hi.uMsg; + req->input.hw.lparam = MAKELONG( input->u.hi.wParamL, input->u.hi.wParamH ); + break; + } + ret = wine_server_call( req ); + } + SERVER_END_REQ; + return ret; +} + + /*********************************************************************** * MSG_SendInternalMessageTimeout * diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index 5eb7154239..63aff08e32 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -773,6 +773,14 @@ @ stdcall wvsprintfA(ptr str ptr) @ stdcall wvsprintfW(ptr wstr ptr) +################################################################ +# Wine internal extensions +# +# All functions must be prefixed with '__wine_' (for internal functions) +# or 'wine_' (for user-visible functions) to avoid namespace conflicts. +# +@ cdecl __wine_send_input(long ptr long) + ################################################################ # Wine dll separation hacks, these will go away, don't use them # diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 23b4269ed5..afd948ba6f 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -213,6 +213,7 @@ extern void erase_now( HWND hwnd, UINT rdw_flags ) DECLSPEC_HIDDEN; extern void *get_hook_proc( void *proc, const WCHAR *module ); extern LRESULT call_current_hook( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN; extern BOOL map_wparam_AtoW( UINT message, WPARAM *wparam, enum wm_char_mapping mapping ) DECLSPEC_HIDDEN; +extern NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags ) DECLSPEC_HIDDEN; extern LRESULT MSG_SendInternalMessageTimeout( DWORD dest_pid, DWORD dest_tid, UINT msg, WPARAM wparam, LPARAM lparam, UINT flags, UINT timeout, PDWORD_PTR res_ptr ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 04d737102c..6fc7bb0651 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1154,6 +1154,7 @@ void X11DRV_send_keyboard_input( HWND hwnd, WORD wVk, WORD wScan, DWORD event_fl DWORD dwExtraInfo, UINT injected_flags ) { UINT message; + INPUT input; KBDLLHOOKSTRUCT hook; WORD flags, wVkStripped, wVkL, wVkR, vk_hook = wVk; @@ -1234,6 +1235,13 @@ void X11DRV_send_keyboard_input( HWND hwnd, WORD wVk, WORD wScan, DWORD event_fl 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; + input.u.ki.dwFlags = event_flags; + input.u.ki.time = time; + input.u.ki.dwExtraInfo = dwExtraInfo; + if (!(event_flags & KEYEVENTF_UNICODE)) { if (event_flags & KEYEVENTF_KEYUP) @@ -1252,20 +1260,7 @@ void X11DRV_send_keyboard_input( HWND hwnd, WORD wVk, WORD wScan, DWORD event_fl 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->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; + __wine_send_input( hwnd, &input, (injected_flags & LLKHF_INJECTED) != 0 ); } diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 236ba75a9f..2d71be51fa 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -292,6 +292,7 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y, DWORD data, DWORD time, DWORD extra_info, UINT injected_flags ) { POINT pt; + INPUT input; MSLLHOOKSTRUCT hook; if (!time) time = GetTickCount(); @@ -414,20 +415,15 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y, if (HOOK_CallHooks( WH_MOUSE_LL, HC_ACTION, WM_XBUTTONUP, (LPARAM)&hook, TRUE )) return; } - SERVER_START_REQ( send_hardware_message ) - { - req->win = wine_server_user_handle( hwnd ); - req->input.type = INPUT_MOUSE; - req->input.mouse.x = pt.x; - req->input.mouse.y = pt.y; - req->input.mouse.data = data; - req->input.mouse.flags = flags | MOUSEEVENTF_ABSOLUTE; - 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; + input.type = INPUT_MOUSE; + input.u.mi.dx = pt.x; + input.u.mi.dy = pt.y; + input.u.mi.mouseData = data; + input.u.mi.dwFlags = flags | MOUSEEVENTF_ABSOLUTE; + input.u.mi.time = time; + input.u.mi.dwExtraInfo = extra_info; + + __wine_send_input( hwnd, &input, (injected_flags & LLMHF_INJECTED) != 0 ); } #ifdef SONAME_LIBXCURSOR diff --git a/include/winuser.h b/include/winuser.h index d95bfeafe3..bd35803441 100644 --- a/include/winuser.h +++ b/include/winuser.h @@ -5136,6 +5136,10 @@ WINUSERAPI INT WINAPI wvsprintfW(LPWSTR,LPCWSTR,__ms_va_list); /* NOTE: This is SYSTEM.3, not USER.182, which is also named KillSystemTimer */ WORD WINAPI SYSTEM_KillSystemTimer( WORD ); +#ifdef __WINESRC__ +WINUSERAPI BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, BOOL injected ); +#endif + #ifdef __cplusplus } #endif -- 2.32.0.93.g670b81a890