Commit 8ba666f3 authored by Alexandre Julliard's avatar Alexandre Julliard

Store the keyboard state in the thread input structure on the server

side.
parent 3783e49d
......@@ -2298,3 +2298,69 @@ BOOL WINAPI GetGUIThreadInfo( DWORD id, GUITHREADINFO *info )
SERVER_END_REQ;
return ret;
}
/**********************************************************************
* GetKeyState (USER32.@)
*
* An application calls the GetKeyState function in response to a
* keyboard-input message. This function retrieves the state of the key
* at the time the input message was generated.
*/
SHORT WINAPI GetKeyState(INT vkey)
{
SHORT retval = 0;
SERVER_START_REQ( get_key_state )
{
req->tid = GetCurrentThreadId();
req->key = vkey;
if (!wine_server_call( req )) retval = (signed char)reply->state;
}
SERVER_END_REQ;
TRACE("key (0x%x) -> %x\n", vkey, retval);
return retval;
}
/**********************************************************************
* GetKeyboardState (USER32.@)
*/
BOOL WINAPI GetKeyboardState( LPBYTE state )
{
BOOL ret;
TRACE("(%p)\n", state);
memset( state, 0, 256 );
SERVER_START_REQ( get_key_state )
{
req->tid = GetCurrentThreadId();
req->key = -1;
wine_server_set_reply( req, state, 256 );
ret = !wine_server_call_err( req );
}
SERVER_END_REQ;
return ret;
}
/**********************************************************************
* SetKeyboardState (USER32.@)
*/
BOOL WINAPI SetKeyboardState( LPBYTE state )
{
BOOL ret;
TRACE("(%p)\n", state);
memset( state, 0, 256 );
SERVER_START_REQ( set_key_state )
{
req->tid = GetCurrentThreadId();
wine_server_add_data( req, state, 256 );
ret = !wine_server_call_err( req );
}
SERVER_END_REQ;
return ret;
}
......@@ -403,6 +403,33 @@ void WINAPI PostQuitMessage16( INT16 exitCode )
}
/**********************************************************************
* GetKeyState (USER.106)
*/
INT16 WINAPI GetKeyState16(INT16 vkey)
{
return GetKeyState(vkey);
}
/**********************************************************************
* GetKeyboardState (USER.222)
*/
BOOL WINAPI GetKeyboardState16( LPBYTE state )
{
return GetKeyboardState( state );
}
/**********************************************************************
* SetKeyboardState (USER.223)
*/
BOOL WINAPI SetKeyboardState16( LPBYTE state )
{
return SetKeyboardState( state );
}
/***********************************************************************
* SetMessageQueue (USER.266)
*/
......
......@@ -219,8 +219,8 @@
219 pascal16 CreateDialogIndirect(word ptr word segptr) CreateDialogIndirect16
220 pascal16 LoadMenuIndirect(ptr) LoadMenuIndirect16
221 pascal16 ScrollDC(word s_word s_word ptr ptr word ptr) ScrollDC16
222 pascal16 GetKeyboardState(ptr) GetKeyboardState
223 pascal16 SetKeyboardState(ptr) SetKeyboardState
222 pascal16 GetKeyboardState(ptr) GetKeyboardState16
223 pascal16 SetKeyboardState(ptr) SetKeyboardState16
224 pascal16 GetWindowTask(word) GetWindowTask16
225 pascal16 EnumTaskWindows(word segptr long) EnumTaskWindows16
226 stub LockInput # not in W2.0
......
......@@ -2778,6 +2778,32 @@ struct get_thread_input_reply
};
struct get_key_state_request
{
struct request_header __header;
thread_id_t tid;
int key;
};
struct get_key_state_reply
{
struct reply_header __header;
unsigned char state;
/* VARARG(keystate,bytes); */
};
struct set_key_state_request
{
struct request_header __header;
thread_id_t tid;
/* VARARG(keystate,bytes); */
};
struct set_key_state_reply
{
struct reply_header __header;
};
struct set_foreground_window_request
{
struct request_header __header;
......@@ -3112,6 +3138,8 @@ enum request
REQ_get_window_properties,
REQ_attach_thread_input,
REQ_get_thread_input,
REQ_get_key_state,
REQ_set_key_state,
REQ_set_foreground_window,
REQ_set_focus_window,
REQ_set_active_window,
......@@ -3289,6 +3317,8 @@ union generic_request
struct get_window_properties_request get_window_properties_request;
struct attach_thread_input_request attach_thread_input_request;
struct get_thread_input_request get_thread_input_request;
struct get_key_state_request get_key_state_request;
struct set_key_state_request set_key_state_request;
struct set_foreground_window_request set_foreground_window_request;
struct set_focus_window_request set_focus_window_request;
struct set_active_window_request set_active_window_request;
......@@ -3464,6 +3494,8 @@ union generic_reply
struct get_window_properties_reply get_window_properties_reply;
struct attach_thread_input_reply attach_thread_input_reply;
struct get_thread_input_reply get_thread_input_reply;
struct get_key_state_reply get_key_state_reply;
struct set_key_state_reply set_key_state_reply;
struct set_foreground_window_reply set_foreground_window_reply;
struct set_focus_window_reply set_focus_window_reply;
struct set_active_window_reply set_active_window_reply;
......@@ -3477,6 +3509,6 @@ union generic_reply
struct get_next_hook_reply get_next_hook_reply;
};
#define SERVER_PROTOCOL_VERSION 93
#define SERVER_PROTOCOL_VERSION 94
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -1941,6 +1941,21 @@ enum message_type
rectangle_t rect; /* caret rectangle */
@END
/* Retrieve queue keyboard state for a given thread */
@REQ(get_key_state)
thread_id_t tid; /* id of thread */
int key; /* optional key code or -1 */
@REPLY
unsigned char state; /* state of specified key */
VARARG(keystate,bytes); /* state array for all the keys */
@END
/* Set queue keyboard state for a given thread */
@REQ(set_key_state)
thread_id_t tid; /* id of thread */
VARARG(keystate,bytes); /* state array for all the keys */
@END
/* Set the system foreground window */
@REQ(set_foreground_window)
user_handle_t handle; /* handle to the foreground window */
......
......@@ -868,6 +868,68 @@ static struct timer *set_timer( struct msg_queue *queue, unsigned int rate )
return timer;
}
/* change the input key state for a given key */
static void set_input_key_state( struct thread_input *input, unsigned char key, int down )
{
if (down)
{
if (!(input->keystate[key] & 0x80)) input->keystate[key] ^= 0x01;
input->keystate[key] |= 0x80;
}
else input->keystate[key] &= ~0x80;
}
/* update the input key state for a keyboard message */
static void update_input_key_state( struct thread_input *input, const struct message *msg )
{
unsigned char key;
int down = 0, extended;
switch (msg->msg)
{
case WM_LBUTTONDOWN:
down = 1;
/* fall through */
case WM_LBUTTONUP:
set_input_key_state( input, VK_LBUTTON, down );
break;
case WM_MBUTTONDOWN:
down = 1;
/* fall through */
case WM_MBUTTONUP:
set_input_key_state( input, VK_MBUTTON, down );
break;
case WM_RBUTTONDOWN:
down = 1;
/* fall through */
case WM_RBUTTONUP:
set_input_key_state( input, VK_RBUTTON, down );
break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
down = 1;
/* fall through */
case WM_KEYUP:
case WM_SYSKEYUP:
key = (unsigned char)msg->wparam;
extended = ((msg->lparam >> 16) & KF_EXTENDED) != 0;
set_input_key_state( input, key, down );
switch(key)
{
case VK_SHIFT:
set_input_key_state( input, extended ? VK_RSHIFT : VK_LSHIFT, down );
break;
case VK_CONTROL:
set_input_key_state( input, extended ? VK_RCONTROL : VK_LCONTROL, down );
break;
case VK_MENU:
set_input_key_state( input, extended ? VK_RMENU : VK_LMENU, down );
break;
}
break;
}
}
/* release the hardware message currently being processed by the given thread */
static void release_hardware_message( struct thread *thread, int remove )
{
......@@ -879,6 +941,7 @@ static void release_hardware_message( struct thread *thread, int remove )
struct message *other;
int clr_bit;
update_input_key_state( input, input->msg );
unlink_message( &input->msg_list, input->msg );
clr_bit = get_hardware_msg_bit( input->msg );
for (other = input->msg_list.first; other; other = other->next)
......@@ -892,13 +955,19 @@ static void release_hardware_message( struct thread *thread, int remove )
}
/* find the window that should receive a given hardware message */
static user_handle_t find_hardware_message_window( struct thread_input *input, struct message *msg )
static user_handle_t find_hardware_message_window( struct thread_input *input, struct message *msg,
unsigned int *msg_code )
{
user_handle_t win = 0;
*msg_code = msg->msg;
if (is_keyboard_msg( msg ))
{
if (input && !(win = input->focus)) win = input->active;
if (input && !(win = input->focus))
{
win = input->active;
if (*msg_code < WM_SYSKEYDOWN) *msg_code += WM_SYSKEYDOWN - WM_KEYDOWN;
}
}
else /* mouse message */
{
......@@ -916,8 +985,9 @@ static void queue_hardware_message( struct msg_queue *queue, struct message *msg
user_handle_t win;
struct thread *thread;
struct thread_input *input;
unsigned int msg_code;
win = find_hardware_message_window( queue ? queue->input : foreground_input, msg );
win = find_hardware_message_window( queue ? queue->input : foreground_input, msg, &msg_code );
if (!win || !(thread = get_window_thread(win)))
{
free( msg );
......@@ -943,6 +1013,7 @@ static int get_hardware_message( struct thread *thread, struct message *first,
struct message *msg;
user_handle_t win;
int clear_bits, got_one = 0;
unsigned int msg_code;
if (input->msg_thread && input->msg_thread != thread)
return 0; /* locked by another thread */
......@@ -960,11 +1031,12 @@ static int get_hardware_message( struct thread *thread, struct message *first,
while (msg)
{
win = find_hardware_message_window( input, msg );
win = find_hardware_message_window( input, msg, &msg_code );
if (!win || !(win_thread = get_window_thread( win )))
{
/* no window at all, remove it */
struct message *next = msg->next;
update_input_key_state( input, msg );
unlink_message( &input->msg_list, msg );
free_message( msg );
msg = next;
......@@ -998,7 +1070,7 @@ static int get_hardware_message( struct thread *thread, struct message *first,
reply->type = MSG_HARDWARE;
reply->win = win;
reply->msg = msg->msg;
reply->msg = msg_code;
reply->wparam = msg->wparam;
reply->lparam = msg->lparam;
reply->x = msg->x;
......@@ -1458,6 +1530,40 @@ DECL_HANDLER(get_thread_input)
}
/* retrieve queue keyboard state for a given thread */
DECL_HANDLER(get_key_state)
{
struct thread *thread;
struct thread_input *input;
if (!(thread = get_thread_from_id( req->tid ))) return;
input = thread->queue ? thread->queue->input : NULL;
if (input)
{
if (req->key >= 0) reply->state = input->keystate[req->key & 0xff];
set_reply_data( input->keystate, min( get_reply_max_size(), sizeof(input->keystate) ));
}
release_object( thread );
}
/* set queue keyboard state for a given thread */
DECL_HANDLER(set_key_state)
{
struct thread *thread = NULL;
struct thread_input *input;
if (!(thread = get_thread_from_id( req->tid ))) return;
input = thread->queue ? thread->queue->input : NULL;
if (input)
{
size_t size = min( sizeof(input->keystate), get_req_data_size() );
if (size) memcpy( input->keystate, get_req_data(), size );
}
release_object( thread );
}
/* set the system foreground window */
DECL_HANDLER(set_foreground_window)
{
......
......@@ -262,6 +262,8 @@ DECL_HANDLER(get_window_property);
DECL_HANDLER(get_window_properties);
DECL_HANDLER(attach_thread_input);
DECL_HANDLER(get_thread_input);
DECL_HANDLER(get_key_state);
DECL_HANDLER(set_key_state);
DECL_HANDLER(set_foreground_window);
DECL_HANDLER(set_focus_window);
DECL_HANDLER(set_active_window);
......@@ -438,6 +440,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_get_window_properties,
(req_handler)req_attach_thread_input,
(req_handler)req_get_thread_input,
(req_handler)req_get_key_state,
(req_handler)req_set_key_state,
(req_handler)req_set_foreground_window,
(req_handler)req_set_focus_window,
(req_handler)req_set_active_window,
......
......@@ -2211,6 +2211,26 @@ static void dump_get_thread_input_reply( const struct get_thread_input_reply *re
dump_rectangle( &req->rect );
}
static void dump_get_key_state_request( const struct get_key_state_request *req )
{
fprintf( stderr, " tid=%08x,", req->tid );
fprintf( stderr, " key=%d", req->key );
}
static void dump_get_key_state_reply( const struct get_key_state_reply *req )
{
fprintf( stderr, " state=%02x,", req->state );
fprintf( stderr, " keystate=" );
dump_varargs_bytes( cur_size );
}
static void dump_set_key_state_request( const struct set_key_state_request *req )
{
fprintf( stderr, " tid=%08x,", req->tid );
fprintf( stderr, " keystate=" );
dump_varargs_bytes( cur_size );
}
static void dump_set_foreground_window_request( const struct set_foreground_window_request *req )
{
fprintf( stderr, " handle=%p", req->handle );
......@@ -2509,6 +2529,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_window_properties_request,
(dump_func)dump_attach_thread_input_request,
(dump_func)dump_get_thread_input_request,
(dump_func)dump_get_key_state_request,
(dump_func)dump_set_key_state_request,
(dump_func)dump_set_foreground_window_request,
(dump_func)dump_set_focus_window_request,
(dump_func)dump_set_active_window_request,
......@@ -2682,6 +2704,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_window_properties_reply,
(dump_func)0,
(dump_func)dump_get_thread_input_reply,
(dump_func)dump_get_key_state_reply,
(dump_func)0,
(dump_func)dump_set_foreground_window_reply,
(dump_func)dump_set_focus_window_reply,
(dump_func)dump_set_active_window_reply,
......@@ -2855,6 +2879,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"get_window_properties",
"attach_thread_input",
"get_thread_input",
"get_key_state",
"set_key_state",
"set_foreground_window",
"set_focus_window",
"set_active_window",
......
......@@ -51,8 +51,6 @@ WINE_DECLARE_DEBUG_CHANNEL(key);
#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
#define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
static BYTE QueueKeyStateTable[256];
/***********************************************************************
* is_keyboard_message
......@@ -131,80 +129,6 @@ static void queue_hardware_message( MSG *msg, ULONG_PTR extra_info )
/***********************************************************************
* update_queue_key_state
*/
static void update_queue_key_state( UINT msg, WPARAM wp, LPARAM lp )
{
BOOL down = FALSE, iskey = FALSE;
WPARAM dualkey = 0;
switch (msg)
{
case WM_LBUTTONDOWN:
down = TRUE;
/* fall through */
case WM_LBUTTONUP:
wp = VK_LBUTTON;
break;
case WM_MBUTTONDOWN:
down = TRUE;
/* fall through */
case WM_MBUTTONUP:
wp = VK_MBUTTON;
break;
case WM_RBUTTONDOWN:
down = TRUE;
/* fall through */
case WM_RBUTTONUP:
wp = VK_RBUTTON;
break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
down = TRUE;
/* fall through */
case WM_KEYUP:
case WM_SYSKEYUP:
wp = wp & 0xff;
iskey = TRUE;
break;
}
if (iskey)
{
switch(wp)
{
case VK_SHIFT:
dualkey = (HIWORD(lp) & KF_EXTENDED) ? VK_RSHIFT : VK_LSHIFT;
break;
case VK_CONTROL:
dualkey = (HIWORD(lp) & KF_EXTENDED) ? VK_RCONTROL : VK_LCONTROL;
break;
case VK_MENU:
dualkey = (HIWORD(lp) & KF_EXTENDED) ? VK_RMENU : VK_LMENU;
break;
}
}
if (down)
{
BYTE *p = &QueueKeyStateTable[wp];
if (!(*p & 0x80)) *p ^= 0x01;
*p |= 0x80;
}
else QueueKeyStateTable[wp] &= ~0x80;
if (dualkey)
{ /* also update the "dual" keys properly */
if (down)
{
BYTE *p = &QueueKeyStateTable[dualkey];
if (!(*p & 0x80)) *p ^= 0x01;
*p |= 0x80;
}
else QueueKeyStateTable[dualkey] &= ~0x80;
}
}
/***********************************************************************
* MSG_SendParentNotify
*
* Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
......@@ -330,18 +254,10 @@ void MSG_JournalPlayBackMsg(void)
*
* returns TRUE if the contents of 'msg' should be passed to the application
*/
static BOOL process_raw_keyboard_message( MSG *msg, ULONG_PTR extra_info )
static void process_raw_keyboard_message( MSG *msg )
{
EVENTMSG event;
if (!(msg->hwnd = GetFocus()))
{
/* Send the message to the active window instead, */
/* translating messages to their WM_SYS equivalent */
msg->hwnd = GetActiveWindow();
if (msg->message < WM_SYSKEYDOWN) msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
}
event.message = msg->message;
event.hwnd = msg->hwnd;
event.time = msg->time;
......@@ -349,11 +265,6 @@ static BOOL process_raw_keyboard_message( MSG *msg, ULONG_PTR extra_info )
event.paramH = msg->lParam & 0x7FFF;
if (HIWORD(msg->lParam) & 0x0100) event.paramH |= 0x8000; /* special_key - bit */
HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&event, TRUE );
/* if we are going to throw away the message, update the queue state now */
if (!msg->hwnd) update_queue_key_state( msg->message, msg->wParam, msg->lParam );
return (msg->hwnd != 0);
}
......@@ -366,8 +277,6 @@ static BOOL process_cooked_keyboard_message( MSG *msg, BOOL remove )
{
if (remove)
{
update_queue_key_state( msg->message, msg->wParam, msg->lParam );
/* Handle F1 key by sending out WM_HELP message */
if ((msg->message == WM_KEYUP) &&
(msg->wParam == VK_F1) &&
......@@ -398,10 +307,8 @@ static BOOL process_cooked_keyboard_message( MSG *msg, BOOL remove )
/***********************************************************************
* process_raw_mouse_message
*
* returns TRUE if the contents of 'msg' should be passed to the application
*/
static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info, BOOL remove )
static void process_raw_mouse_message( MSG *msg, BOOL remove )
{
static MSG clk_msg;
......@@ -478,7 +385,6 @@ static BOOL process_raw_mouse_message( MSG *msg, ULONG_PTR extra_info, BOOL remo
if (!(info.flags & GUI_INMENUMODE)) ScreenToClient( msg->hwnd, &pt );
}
msg->lParam = MAKELONG( pt.x, pt.y );
return TRUE;
}
......@@ -506,8 +412,6 @@ static BOOL process_cooked_mouse_message( MSG *msg, ULONG_PTR extra_info, BOOL r
raw_message += WM_LBUTTONDOWN - WM_LBUTTONDBLCLK;
}
if (remove) update_queue_key_state( raw_message, 0, 0 );
hook.pt = msg->pt;
hook.hwnd = msg->hwnd;
hook.wHitTestCode = hittest;
......@@ -602,11 +506,11 @@ BOOL MSG_process_raw_hardware_message( MSG *msg, ULONG_PTR extra_info, HWND hwnd
{
if (is_keyboard_message( msg->message ))
{
if (!process_raw_keyboard_message( msg, extra_info )) return FALSE;
process_raw_keyboard_message( msg );
}
else if (is_mouse_message( msg->message ))
{
if (!process_raw_mouse_message( msg, extra_info, remove )) return FALSE;
process_raw_mouse_message( msg, remove );
}
else
{
......@@ -635,63 +539,6 @@ BOOL MSG_process_cooked_hardware_message( MSG *msg, ULONG_PTR extra_info, BOOL r
}
/**********************************************************************
* GetKeyState (USER.106)
*/
INT16 WINAPI GetKeyState16(INT16 vkey)
{
return GetKeyState(vkey);
}
/**********************************************************************
* GetKeyState (USER32.@)
*
* An application calls the GetKeyState function in response to a
* keyboard-input message. This function retrieves the state of the key
* at the time the input message was generated. (SDK 3.1 Vol 2. p 390)
*/
SHORT WINAPI GetKeyState(INT vkey)
{
INT retval;
if (vkey >= 'a' && vkey <= 'z') vkey += 'A' - 'a';
retval = ((WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
(QueueKeyStateTable[vkey] & 0x80) |
(QueueKeyStateTable[vkey] & 0x01);
TRACE("key (0x%x) -> %x\n", vkey, retval);
return retval;
}
/**********************************************************************
* GetKeyboardState (USER.222)
* GetKeyboardState (USER32.@)
*
* An application calls the GetKeyboardState function in response to a
* keyboard input message. This function retrieves the state of the keyboard
* at the time the input message was generated. (SDK 3.1 Vol 2. p 387)
*/
BOOL WINAPI GetKeyboardState(LPBYTE lpKeyState)
{
TRACE_(key)("(%p)\n", lpKeyState);
if (lpKeyState) memcpy(lpKeyState, QueueKeyStateTable, 256);
return TRUE;
}
/**********************************************************************
* SetKeyboardState (USER.223)
* SetKeyboardState (USER32.@)
*/
BOOL WINAPI SetKeyboardState(LPBYTE lpKeyState)
{
TRACE_(key)("(%p)\n", lpKeyState);
if (lpKeyState) memcpy(QueueKeyStateTable, lpKeyState, 256);
return TRUE;
}
/***********************************************************************
* WaitMessage (USER.112) Suspend thread pending messages
* WaitMessage (USER32.@) Suspend thread pending messages
......@@ -974,6 +821,7 @@ BOOL WINAPI TranslateMessage( const MSG *msg )
UINT message;
WCHAR wp[2];
BOOL rc = FALSE;
BYTE state[256];
if (msg->message >= WM_KEYFIRST && msg->message <= WM_KEYLAST)
{
......@@ -989,8 +837,9 @@ BOOL WINAPI TranslateMessage( const MSG *msg )
TRACE_(key)("Translating key %s (%04x), scancode %02x\n",
SPY_GetVKeyName(msg->wParam), msg->wParam, LOBYTE(HIWORD(msg->lParam)));
GetKeyboardState( state );
/* FIXME : should handle ToUnicode yielding 2 */
switch (ToUnicode(msg->wParam, HIWORD(msg->lParam), QueueKeyStateTable, wp, 2, 0))
switch (ToUnicode(msg->wParam, HIWORD(msg->lParam), state, wp, 2, 0))
{
case 1:
message = (msg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
......
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