user32: Handle input injected through SendInput entirely in user32.

This commit is contained in:
Alexandre Julliard 2011-03-02 21:29:17 +01:00
parent c7efa293f0
commit f1a3480068
7 changed files with 77 additions and 48 deletions

View File

@ -80,7 +80,6 @@ static const USER_DRIVER *load_driver(void)
GET_USER_FUNC(GetKeyboardLayoutName); GET_USER_FUNC(GetKeyboardLayoutName);
GET_USER_FUNC(LoadKeyboardLayout); GET_USER_FUNC(LoadKeyboardLayout);
GET_USER_FUNC(MapVirtualKeyEx); GET_USER_FUNC(MapVirtualKeyEx);
GET_USER_FUNC(SendInput);
GET_USER_FUNC(ToUnicodeEx); GET_USER_FUNC(ToUnicodeEx);
GET_USER_FUNC(UnloadKeyboardLayout); GET_USER_FUNC(UnloadKeyboardLayout);
GET_USER_FUNC(VkKeyScanEx); GET_USER_FUNC(VkKeyScanEx);
@ -196,11 +195,6 @@ static UINT CDECL nulldrv_MapVirtualKeyEx( UINT code, UINT type, HKL layout )
return 0; return 0;
} }
static UINT CDECL nulldrv_SendInput( UINT count, LPINPUT inputs, int size )
{
return 0;
}
static INT CDECL nulldrv_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state, LPWSTR str, static INT CDECL nulldrv_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state, LPWSTR str,
int size, UINT flags, HKL layout ) int size, UINT flags, HKL layout )
{ {
@ -448,7 +442,6 @@ static USER_DRIVER null_driver =
nulldrv_GetKeyboardLayoutName, nulldrv_GetKeyboardLayoutName,
nulldrv_LoadKeyboardLayout, nulldrv_LoadKeyboardLayout,
nulldrv_MapVirtualKeyEx, nulldrv_MapVirtualKeyEx,
nulldrv_SendInput,
nulldrv_ToUnicodeEx, nulldrv_ToUnicodeEx,
nulldrv_UnloadKeyboardLayout, nulldrv_UnloadKeyboardLayout,
nulldrv_VkKeyScanEx, nulldrv_VkKeyScanEx,
@ -549,11 +542,6 @@ static UINT CDECL loaderdrv_MapVirtualKeyEx( UINT code, UINT type, HKL layout )
return load_driver()->pMapVirtualKeyEx( code, type, layout ); return load_driver()->pMapVirtualKeyEx( code, type, layout );
} }
static UINT CDECL loaderdrv_SendInput( UINT count, LPINPUT inputs, int size )
{
return load_driver()->pSendInput( count, inputs, size );
}
static INT CDECL loaderdrv_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state, LPWSTR str, static INT CDECL loaderdrv_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state, LPWSTR str,
int size, UINT flags, HKL layout ) int size, UINT flags, HKL layout )
{ {
@ -801,7 +789,6 @@ static USER_DRIVER lazy_load_driver =
loaderdrv_GetKeyboardLayoutName, loaderdrv_GetKeyboardLayoutName,
loaderdrv_LoadKeyboardLayout, loaderdrv_LoadKeyboardLayout,
loaderdrv_MapVirtualKeyEx, loaderdrv_MapVirtualKeyEx,
loaderdrv_SendInput,
loaderdrv_ToUnicodeEx, loaderdrv_ToUnicodeEx,
loaderdrv_UnloadKeyboardLayout, loaderdrv_UnloadKeyboardLayout,
loaderdrv_VkKeyScanEx, loaderdrv_VkKeyScanEx,

View File

@ -34,6 +34,8 @@
#define NONAMELESSUNION #define NONAMELESSUNION
#define NONAMELESSSTRUCT #define NONAMELESSSTRUCT
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "wingdi.h" #include "wingdi.h"
@ -50,6 +52,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(win); WINE_DEFAULT_DEBUG_CHANNEL(win);
WINE_DECLARE_DEBUG_CHANNEL(keyboard); WINE_DECLARE_DEBUG_CHANNEL(keyboard);
static DWORD last_mouse_event;
/*********************************************************************** /***********************************************************************
* get_key_state * get_key_state
@ -119,52 +122,92 @@ BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret )
* *
* Internal SendInput function to allow the graphics driver to inject real events. * Internal SendInput function to allow the graphics driver to inject real events.
*/ */
BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, BOOL injected ) BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input )
{ {
NTSTATUS status = send_hardware_message( hwnd, input, injected ? SEND_HWMSG_INJECTED : 0 ); NTSTATUS status = send_hardware_message( hwnd, input, 0 );
if (status) SetLastError( RtlNtStatusToDosError(status) ); if (status) SetLastError( RtlNtStatusToDosError(status) );
else if (input->type == INPUT_MOUSE) last_mouse_event = GetTickCount();
return !status; return !status;
} }
/***********************************************************************
* update_mouse_coords
*
* Helper for SendInput.
*/
static void update_mouse_coords( INPUT *input )
{
if (!(input->u.mi.dwFlags & MOUSEEVENTF_MOVE)) return;
if (input->u.mi.dwFlags & MOUSEEVENTF_ABSOLUTE)
{
input->u.mi.dx = (input->u.mi.dx * GetSystemMetrics( SM_CXSCREEN )) >> 16;
input->u.mi.dy = (input->u.mi.dy * GetSystemMetrics( SM_CYSCREEN )) >> 16;
}
else
{
int accel[3];
/* dx and dy can be negative numbers for relative movements */
SystemParametersInfoW(SPI_GETMOUSE, 0, accel, 0);
if (!accel[2]) return;
if (abs(input->u.mi.dx) > accel[0])
{
input->u.mi.dx *= 2;
if ((abs(input->u.mi.dx) > accel[1]) && (accel[2] == 2)) input->u.mi.dx *= 2;
}
if (abs(input->u.mi.dy) > accel[0])
{
input->u.mi.dy *= 2;
if ((abs(input->u.mi.dy) > accel[1]) && (accel[2] == 2)) input->u.mi.dy *= 2;
}
}
}
/*********************************************************************** /***********************************************************************
* SendInput (USER32.@) * SendInput (USER32.@)
*/ */
UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size ) UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size )
{
if (TRACE_ON(win))
{ {
UINT i; UINT i;
NTSTATUS status;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
switch(inputs[i].type) if (inputs[i].type == INPUT_MOUSE)
{ {
case INPUT_MOUSE: /* we need to update the coordinates to what the server expects */
TRACE("mouse: dx %d, dy %d, data %x, flags %x, time %u, info %lx\n", INPUT input = inputs[i];
inputs[i].u.mi.dx, inputs[i].u.mi.dy, inputs[i].u.mi.mouseData, update_mouse_coords( &input );
inputs[i].u.mi.dwFlags, inputs[i].u.mi.time, inputs[i].u.mi.dwExtraInfo); if (!(status = send_hardware_message( 0, &input, SEND_HWMSG_INJECTED )))
break; {
last_mouse_event = GetTickCount();
case INPUT_KEYBOARD: if ((input.u.mi.dwFlags & MOUSEEVENTF_MOVE) &&
TRACE("keyboard: vk %X, scan %x, flags %x, time %u, info %lx\n", ((input.u.mi.dwFlags & MOUSEEVENTF_ABSOLUTE) || input.u.mi.dx || input.u.mi.dy))
inputs[i].u.ki.wVk, inputs[i].u.ki.wScan, inputs[i].u.ki.dwFlags, {
inputs[i].u.ki.time, inputs[i].u.ki.dwExtraInfo); /* we have to actually move the cursor */
break; POINT pt;
GetCursorPos( &pt );
case INPUT_HARDWARE: if (!(input.u.mi.dwFlags & MOUSEEVENTF_ABSOLUTE) ||
TRACE("hardware: msg %d, wParamL %x, wParamH %x\n", pt.x != input.u.mi.dx || pt.y != input.u.mi.dy)
inputs[i].u.hi.uMsg, inputs[i].u.hi.wParamL, inputs[i].u.hi.wParamH); USER_Driver->pSetCursorPos( pt.x, pt.y );
break;
default:
FIXME("unknown input type %u\n", inputs[i].type);
break;
} }
} }
} }
else status = send_hardware_message( 0, &inputs[i], SEND_HWMSG_INJECTED );
return USER_Driver->pSendInput( count, inputs, size ); if (status)
{
SetLastError( RtlNtStatusToDosError(status) );
break;
}
}
return i;
} }
@ -210,11 +253,12 @@ void WINAPI mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
*/ */
BOOL WINAPI DECLSPEC_HOTPATCH GetCursorPos( POINT *pt ) BOOL WINAPI DECLSPEC_HOTPATCH GetCursorPos( POINT *pt )
{ {
BOOL ret; BOOL ret = FALSE;
if (!pt) return FALSE; if (!pt) return FALSE;
ret = USER_Driver->pGetCursorPos( pt ); /* query new position from graphics driver if we haven't updated recently */
if (GetTickCount() - last_mouse_event > 100) ret = USER_Driver->pGetCursorPos( pt );
SERVER_START_REQ( set_cursor ) SERVER_START_REQ( set_cursor )
{ {
@ -232,7 +276,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetCursorPos( POINT *pt )
} }
SERVER_END_REQ; SERVER_END_REQ;
return ret; return ret;
} }

View File

@ -779,7 +779,7 @@
# All functions must be prefixed with '__wine_' (for internal functions) # All functions must be prefixed with '__wine_' (for internal functions)
# or 'wine_' (for user-visible functions) to avoid namespace conflicts. # or 'wine_' (for user-visible functions) to avoid namespace conflicts.
# #
@ cdecl __wine_send_input(long ptr long) @ cdecl __wine_send_input(long ptr)
################################################################ ################################################################
# Wine dll separation hacks, these will go away, don't use them # Wine dll separation hacks, these will go away, don't use them

View File

@ -61,7 +61,6 @@ typedef struct tagUSER_DRIVER {
BOOL (CDECL *pGetKeyboardLayoutName)(LPWSTR); BOOL (CDECL *pGetKeyboardLayoutName)(LPWSTR);
HKL (CDECL *pLoadKeyboardLayout)(LPCWSTR, UINT); HKL (CDECL *pLoadKeyboardLayout)(LPCWSTR, UINT);
UINT (CDECL *pMapVirtualKeyEx)(UINT, UINT, HKL); UINT (CDECL *pMapVirtualKeyEx)(UINT, UINT, HKL);
UINT (CDECL *pSendInput)(UINT, LPINPUT, int);
INT (CDECL *pToUnicodeEx)(UINT, UINT, const BYTE *, LPWSTR, int, UINT, HKL); INT (CDECL *pToUnicodeEx)(UINT, UINT, const BYTE *, LPWSTR, int, UINT, HKL);
BOOL (CDECL *pUnloadKeyboardLayout)(HKL); BOOL (CDECL *pUnloadKeyboardLayout)(HKL);
SHORT (CDECL *pVkKeyScanEx)(WCHAR, HKL); SHORT (CDECL *pVkKeyScanEx)(WCHAR, HKL);

View File

@ -1251,7 +1251,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", TRACE_(key)("message=0x%04x wParam=0x%04x InputKeyState=0x%x\n",
message, wVk, key_state_table[wVk]); message, wVk, key_state_table[wVk]);
__wine_send_input( hwnd, &input, (injected_flags & LLKHF_INJECTED) != 0 ); __wine_send_input( hwnd, &input );
} }

View File

@ -349,7 +349,7 @@ void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y,
input.u.mi.time = time; input.u.mi.time = time;
input.u.mi.dwExtraInfo = extra_info; input.u.mi.dwExtraInfo = extra_info;
__wine_send_input( hwnd, &input, (injected_flags & LLMHF_INJECTED) != 0 ); __wine_send_input( hwnd, &input );
if (injected_flags & LLMHF_INJECTED) if (injected_flags & LLMHF_INJECTED)
{ {

View File

@ -5137,7 +5137,7 @@ WINUSERAPI INT WINAPI wvsprintfW(LPWSTR,LPCWSTR,__ms_va_list);
WORD WINAPI SYSTEM_KillSystemTimer( WORD ); WORD WINAPI SYSTEM_KillSystemTimer( WORD );
#ifdef __WINESRC__ #ifdef __WINESRC__
WINUSERAPI BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, BOOL injected ); WINUSERAPI BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input );
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus