Commit 0e85ac17 authored by Henry Goffin's avatar Henry Goffin Committed by Alexandre Julliard

win32u: Invalidate all cached keys after input.

This patch addresses an issue in Second Life and potentially other multi-threaded applications which process WM_KEYDOWN in one thread and then verify that the key is "still down" with GetAsyncKeyState from another thread. Wine uses a per-thread key cache, resulting in inconsistent views of key status. Caches are now invalidated when an input event is injected by the driver or via SendInput.
parent 7c3941ce
......@@ -2585,13 +2585,11 @@ LRESULT send_internal_message_timeout( DWORD dest_pid, DWORD dest_tid,
*/
NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput, UINT flags )
{
struct user_key_state_info *key_state_info = get_user_thread_info()->key_state;
struct send_message_info info;
int prev_x, prev_y, new_x, new_y;
INT counter = global_key_state_counter;
USAGE hid_usage_page, hid_usage;
NTSTATUS ret;
BOOL wait;
BOOL wait, affects_key_state = FALSE;
info.type = MSG_HARDWARE;
info.dest_tid = 0;
......@@ -2629,6 +2627,10 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r
req->input.mouse.flags = input->mi.dwFlags;
req->input.mouse.time = input->mi.time;
req->input.mouse.info = input->mi.dwExtraInfo;
affects_key_state = !!(input->mi.dwFlags & (MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP |
MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP |
MOUSEEVENTF_MIDDLEDOWN | MOUSEEVENTF_MIDDLEUP |
MOUSEEVENTF_XDOWN | MOUSEEVENTF_XUP));
break;
case INPUT_KEYBOARD:
req->input.kbd.vkey = input->ki.wVk;
......@@ -2636,6 +2638,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r
req->input.kbd.flags = input->ki.dwFlags;
req->input.kbd.time = input->ki.time;
req->input.kbd.info = input->ki.dwExtraInfo;
affects_key_state = TRUE;
break;
case INPUT_HARDWARE:
req->input.hw.msg = input->hi.uMsg;
......@@ -2664,8 +2667,6 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r
}
break;
}
if (key_state_info) wine_server_set_reply( req, key_state_info->state,
sizeof(key_state_info->state) );
ret = wine_server_call( req );
wait = reply->wait;
prev_x = reply->prev_x;
......@@ -2677,11 +2678,8 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r
if (!ret)
{
if (key_state_info)
{
key_state_info->time = NtGetTickCount();
key_state_info->counter = counter;
}
if (affects_key_state)
InterlockedIncrement( &global_key_state_counter ); /* force refreshing the key state cache */
if ((flags & SEND_HWMSG_INJECTED) && (prev_x != new_x || prev_y != new_y))
user_driver->pSetCursorPos( new_x, new_y );
}
......
......@@ -2768,7 +2768,6 @@ struct send_hardware_message_reply
int prev_y;
int new_x;
int new_y;
/* VARARG(keystate,bytes); */
char __pad_28[4];
};
#define SEND_HWMSG_INJECTED 0x01
......@@ -6356,7 +6355,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 760
#define SERVER_PROTOCOL_VERSION 761
/* ### protocol_version end ### */
......
......@@ -2078,7 +2078,6 @@ enum message_type
int prev_y;
int new_x; /* new cursor position */
int new_y;
VARARG(keystate,bytes); /* global state array for all the keys */
@END
#define SEND_HWMSG_INJECTED 0x01
......
......@@ -2551,7 +2551,6 @@ DECL_HANDLER(send_hardware_message)
struct desktop *desktop;
unsigned int origin = (req->flags & SEND_HWMSG_INJECTED ? IMO_INJECTED : IMO_HARDWARE);
struct msg_queue *sender = get_current_queue();
data_size_t size = min( 256, get_reply_max_size() );
if (!(desktop = get_thread_desktop( current, 0 ))) return;
......@@ -2587,7 +2586,6 @@ DECL_HANDLER(send_hardware_message)
reply->new_x = desktop->cursor.x;
reply->new_y = desktop->cursor.y;
set_reply_data( desktop->keystate, size );
release_object( desktop );
}
......
......@@ -2662,7 +2662,6 @@ static void dump_send_hardware_message_reply( const struct send_hardware_message
fprintf( stderr, ", prev_y=%d", req->prev_y );
fprintf( stderr, ", new_x=%d", req->new_x );
fprintf( stderr, ", new_y=%d", req->new_y );
dump_varargs_bytes( ", keystate=", cur_size );
}
static void dump_get_message_request( const struct get_message_request *req )
......
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