Store the keyboard state in the thread input structure on the server
side.
diff --git a/server/queue.c b/server/queue.c
index b913116..8eaba4d 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -868,6 +868,68 @@
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 @@
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 @@
}
/* 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 @@
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 @@
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 @@
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 @@
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 @@
}
+/* 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)
{