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(LoadKeyboardLayout);
GET_USER_FUNC(MapVirtualKeyEx);
GET_USER_FUNC(SendInput);
GET_USER_FUNC(ToUnicodeEx);
GET_USER_FUNC(UnloadKeyboardLayout);
GET_USER_FUNC(VkKeyScanEx);
@ -196,11 +195,6 @@ static UINT CDECL nulldrv_MapVirtualKeyEx( UINT code, UINT type, HKL layout )
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,
int size, UINT flags, HKL layout )
{
@ -448,7 +442,6 @@ static USER_DRIVER null_driver =
nulldrv_GetKeyboardLayoutName,
nulldrv_LoadKeyboardLayout,
nulldrv_MapVirtualKeyEx,
nulldrv_SendInput,
nulldrv_ToUnicodeEx,
nulldrv_UnloadKeyboardLayout,
nulldrv_VkKeyScanEx,
@ -549,11 +542,6 @@ static UINT CDECL loaderdrv_MapVirtualKeyEx( UINT code, UINT type, HKL 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,
int size, UINT flags, HKL layout )
{
@ -801,7 +789,6 @@ static USER_DRIVER lazy_load_driver =
loaderdrv_GetKeyboardLayoutName,
loaderdrv_LoadKeyboardLayout,
loaderdrv_MapVirtualKeyEx,
loaderdrv_SendInput,
loaderdrv_ToUnicodeEx,
loaderdrv_UnloadKeyboardLayout,
loaderdrv_VkKeyScanEx,

View File

@ -34,6 +34,8 @@
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
@ -50,6 +52,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(win);
WINE_DECLARE_DEBUG_CHANNEL(keyboard);
static DWORD last_mouse_event;
/***********************************************************************
* 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.
*/
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) );
else if (input->type == INPUT_MOUSE) last_mouse_event = GetTickCount();
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.@)
*/
UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size )
{
if (TRACE_ON(win))
{
UINT i;
NTSTATUS status;
for (i = 0; i < count; i++)
{
switch(inputs[i].type)
if (inputs[i].type == INPUT_MOUSE)
{
case INPUT_MOUSE:
TRACE("mouse: dx %d, dy %d, data %x, flags %x, time %u, info %lx\n",
inputs[i].u.mi.dx, inputs[i].u.mi.dy, inputs[i].u.mi.mouseData,
inputs[i].u.mi.dwFlags, inputs[i].u.mi.time, inputs[i].u.mi.dwExtraInfo);
break;
/* we need to update the coordinates to what the server expects */
INPUT input = inputs[i];
update_mouse_coords( &input );
if (!(status = send_hardware_message( 0, &input, SEND_HWMSG_INJECTED )))
{
last_mouse_event = GetTickCount();
case INPUT_KEYBOARD:
TRACE("keyboard: vk %X, scan %x, flags %x, time %u, info %lx\n",
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);
break;
case INPUT_HARDWARE:
TRACE("hardware: msg %d, wParamL %x, wParamH %x\n",
inputs[i].u.hi.uMsg, inputs[i].u.hi.wParamL, inputs[i].u.hi.wParamH);
break;
default:
FIXME("unknown input type %u\n", inputs[i].type);
break;
if ((input.u.mi.dwFlags & MOUSEEVENTF_MOVE) &&
((input.u.mi.dwFlags & MOUSEEVENTF_ABSOLUTE) || input.u.mi.dx || input.u.mi.dy))
{
/* we have to actually move the cursor */
POINT pt;
GetCursorPos( &pt );
if (!(input.u.mi.dwFlags & MOUSEEVENTF_ABSOLUTE) ||
pt.x != input.u.mi.dx || pt.y != input.u.mi.dy)
USER_Driver->pSetCursorPos( pt.x, pt.y );
}
}
}
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 ret;
BOOL ret = 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 )
{
@ -232,7 +276,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetCursorPos( POINT *pt )
}
SERVER_END_REQ;
return ret;
}

View File

@ -779,7 +779,7 @@
# 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)
@ cdecl __wine_send_input(long ptr)
################################################################
# 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);
HKL (CDECL *pLoadKeyboardLayout)(LPCWSTR, UINT);
UINT (CDECL *pMapVirtualKeyEx)(UINT, UINT, HKL);
UINT (CDECL *pSendInput)(UINT, LPINPUT, int);
INT (CDECL *pToUnicodeEx)(UINT, UINT, const BYTE *, LPWSTR, int, UINT, HKL);
BOOL (CDECL *pUnloadKeyboardLayout)(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",
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.dwExtraInfo = extra_info;
__wine_send_input( hwnd, &input, (injected_flags & LLMHF_INJECTED) != 0 );
__wine_send_input( hwnd, &input );
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 );
#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
#ifdef __cplusplus