From 262df397efd272d375fd93be8ee29240faf9ed80 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Tue, 30 Jun 2020 19:15:34 -0500 Subject: [PATCH] server-Key_State: Rebase and restore mistakenly deleted patch. --- ...-a-helper-function-to-update-the-thr.patch | 120 +++++++++++++ ...-locking-and-synchronization-of-keys.patch | 162 ++++++++++++++++++ patches/server-Key_State/definition | 5 + 3 files changed, 287 insertions(+) create mode 100644 patches/server-Key_State/0001-server-Introduce-a-helper-function-to-update-the-thr.patch create mode 100644 patches/server-Key_State/0002-server-Implement-locking-and-synchronization-of-keys.patch create mode 100644 patches/server-Key_State/definition diff --git a/patches/server-Key_State/0001-server-Introduce-a-helper-function-to-update-the-thr.patch b/patches/server-Key_State/0001-server-Introduce-a-helper-function-to-update-the-thr.patch new file mode 100644 index 00000000..2f57b1f8 --- /dev/null +++ b/patches/server-Key_State/0001-server-Introduce-a-helper-function-to-update-the-thr.patch @@ -0,0 +1,120 @@ +From 0fefda7a02d52d1c8813d7caaf2ca3cc6e352a29 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Thu, 12 Mar 2015 00:44:25 +0100 +Subject: [PATCH] server: Introduce a helper function to update the + thread_input key state. + +--- + server/queue.c | 40 +++++++++++++++++++++++----------------- + 1 file changed, 23 insertions(+), 17 deletions(-) + +diff --git a/server/queue.c b/server/queue.c +index 432885f9e4c..0a20bd3639d 100644 +--- a/server/queue.c ++++ b/server/queue.c +@@ -1295,9 +1295,9 @@ static void set_input_key_state( unsigned char *keystate, unsigned char key, int + else keystate[key] &= ~0x80; + } + +-/* update the input key state for a keyboard message */ +-static void update_input_key_state( struct desktop *desktop, unsigned char *keystate, +- unsigned int msg, lparam_t wparam ) ++/* update the key state for a keyboard message */ ++static void update_key_state( struct desktop *desktop, unsigned char *keystate, ++ unsigned int msg, lparam_t wparam ) + { + unsigned char key; + int down = 0; +@@ -1366,21 +1366,27 @@ static void update_desktop_mouse_state( struct desktop *desktop, unsigned int fl + if (flags & MOUSEEVENTF_MOVE) + update_desktop_cursor_pos( desktop, x, y ); + if (flags & MOUSEEVENTF_LEFTDOWN) +- update_input_key_state( desktop, desktop->keystate, WM_LBUTTONDOWN, wparam ); ++ update_key_state( desktop, desktop->keystate, WM_LBUTTONDOWN, wparam ); + if (flags & MOUSEEVENTF_LEFTUP) +- update_input_key_state( desktop, desktop->keystate, WM_LBUTTONUP, wparam ); ++ update_key_state( desktop, desktop->keystate, WM_LBUTTONUP, wparam ); + if (flags & MOUSEEVENTF_RIGHTDOWN) +- update_input_key_state( desktop, desktop->keystate, WM_RBUTTONDOWN, wparam ); ++ update_key_state( desktop, desktop->keystate, WM_RBUTTONDOWN, wparam ); + if (flags & MOUSEEVENTF_RIGHTUP) +- update_input_key_state( desktop, desktop->keystate, WM_RBUTTONUP, wparam ); ++ update_key_state( desktop, desktop->keystate, WM_RBUTTONUP, wparam ); + if (flags & MOUSEEVENTF_MIDDLEDOWN) +- update_input_key_state( desktop, desktop->keystate, WM_MBUTTONDOWN, wparam ); ++ update_key_state( desktop, desktop->keystate, WM_MBUTTONDOWN, wparam ); + if (flags & MOUSEEVENTF_MIDDLEUP) +- update_input_key_state( desktop, desktop->keystate, WM_MBUTTONUP, wparam ); ++ update_key_state( desktop, desktop->keystate, WM_MBUTTONUP, wparam ); + if (flags & MOUSEEVENTF_XDOWN) +- update_input_key_state( desktop, desktop->keystate, WM_XBUTTONDOWN, wparam ); ++ update_key_state( desktop, desktop->keystate, WM_XBUTTONDOWN, wparam ); + if (flags & MOUSEEVENTF_XUP) +- update_input_key_state( desktop, desktop->keystate, WM_XBUTTONUP, wparam ); ++ update_key_state( desktop, desktop->keystate, WM_XBUTTONUP, wparam ); ++} ++ ++/* update the thread input key state for a keyboard message */ ++static void update_input_key_state( struct thread_input *input, unsigned int msg, lparam_t wparam ) ++{ ++ update_key_state( input->desktop, input->keystate, msg, wparam ); + } + + /* release the hardware message currently being processed by the given thread */ +@@ -1413,7 +1419,7 @@ static void release_hardware_message( struct msg_queue *queue, unsigned int hw_i + } + if (clr_bit) clear_queue_bits( queue, clr_bit ); + +- update_input_key_state( input->desktop, input->keystate, msg->msg, msg->wparam ); ++ update_input_key_state( input, msg->msg, msg->wparam ); + list_remove( &msg->entry ); + free_message( msg ); + } +@@ -1532,7 +1538,7 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg + struct thread_input *input; + unsigned int msg_code; + +- update_input_key_state( desktop, desktop->keystate, msg->msg, msg->wparam ); ++ update_key_state( desktop, desktop->keystate, msg->msg, msg->wparam ); + last_input_time = get_tick_count(); + if (msg->msg != WM_MOUSEMOVE) always_queue = 1; + +@@ -1567,7 +1573,7 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg + win = find_hardware_message_window( desktop, input, msg, &msg_code, &thread ); + if (!win || !thread) + { +- if (input) update_input_key_state( input->desktop, input->keystate, msg->msg, msg->wparam ); ++ if (input) update_input_key_state( input, msg->msg, msg->wparam ); + free_message( msg ); + return; + } +@@ -1905,7 +1911,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c + + if ((device = current->process->rawinput_kbd) && (device->flags & RIDEV_NOLEGACY)) + { +- update_input_key_state( desktop, desktop->keystate, message_code, vkey ); ++ update_key_state( desktop, desktop->keystate, message_code, vkey ); + return 0; + } + +@@ -2034,7 +2040,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user + if (!win || !win_thread) + { + /* no window at all, remove it */ +- update_input_key_state( input->desktop, input->keystate, msg->msg, msg->wparam ); ++ update_input_key_state( input, msg->msg, msg->wparam ); + list_remove( &msg->entry ); + free_message( msg ); + continue; +@@ -2050,7 +2056,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user + else + { + /* for another thread input, drop it */ +- update_input_key_state( input->desktop, input->keystate, msg->msg, msg->wparam ); ++ update_input_key_state( input, msg->msg, msg->wparam ); + list_remove( &msg->entry ); + free_message( msg ); + } +-- +2.27.0 + diff --git a/patches/server-Key_State/0002-server-Implement-locking-and-synchronization-of-keys.patch b/patches/server-Key_State/0002-server-Implement-locking-and-synchronization-of-keys.patch new file mode 100644 index 00000000..7154d093 --- /dev/null +++ b/patches/server-Key_State/0002-server-Implement-locking-and-synchronization-of-keys.patch @@ -0,0 +1,162 @@ +From 8df095ad7919b8eb1f6317ffa90e0242bc51f243 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Fri, 10 Jul 2015 16:13:53 +0200 +Subject: [PATCH] server: Implement locking and synchronization of keystate + buffer. (rev 3) + +--- + server/queue.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 57 insertions(+), 2 deletions(-) + +diff --git a/server/queue.c b/server/queue.c +index e8df9775022..8d421195f63 100644 +--- a/server/queue.c ++++ b/server/queue.c +@@ -113,7 +113,9 @@ struct thread_input + user_handle_t cursor; /* current cursor */ + int cursor_count; /* cursor show count */ + struct list msg_list; /* list of hardware messages */ ++ int lock_count; /* lock counter for keystate */ + unsigned char keystate[256]; /* state of each key */ ++ unsigned char shadow_keystate[256]; /* shadow copy of keystate */ + }; + + struct msg_queue +@@ -124,6 +126,7 @@ struct msg_queue + unsigned int wake_mask; /* wakeup mask */ + unsigned int changed_bits; /* changed wakeup bits */ + unsigned int changed_mask; /* changed wakeup mask */ ++ int keystate_locked; /* keystate is locked */ + int paint_count; /* pending paint messages count */ + int hotkey_count; /* pending hotkey messages count */ + int quit_message; /* is there a pending quit message? */ +@@ -257,9 +260,11 @@ static struct thread_input *create_thread_input( struct thread *thread ) + input->move_size = 0; + input->cursor = 0; + input->cursor_count = 0; ++ input->lock_count = 0; + list_init( &input->msg_list ); + set_caret_window( input, 0 ); + memset( input->keystate, 0, sizeof(input->keystate) ); ++ memset( input->shadow_keystate, 0, sizeof(input->shadow_keystate) ); + + if (!(input->desktop = get_thread_desktop( thread, 0 /* FIXME: access rights */ ))) + { +@@ -290,6 +295,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ + queue->wake_mask = 0; + queue->changed_bits = 0; + queue->changed_mask = 0; ++ queue->keystate_locked = 0; + queue->paint_count = 0; + queue->hotkey_count = 0; + queue->quit_message = 0; +@@ -333,8 +339,10 @@ static int assign_thread_input( struct thread *thread, struct thread_input *new_ + } + if (queue->input) + { ++ if (queue->keystate_locked) queue->input->lock_count--; + queue->input->cursor_count -= queue->cursor_count; + release_object( queue->input ); ++ queue->keystate_locked = 0; + } + queue->input = (struct thread_input *)grab_object( new_input ); + new_input->cursor_count += queue->cursor_count; +@@ -1025,6 +1033,7 @@ static void msg_queue_destroy( struct object *obj ) + free( timer ); + } + if (queue->timeout) remove_timeout_user( queue->timeout ); ++ if (queue->keystate_locked) queue->input->lock_count--; + queue->input->cursor_count -= queue->cursor_count; + release_object( queue->input ); + if (queue->hooks) release_object( queue->hooks ); +@@ -1125,7 +1134,11 @@ int attach_thread_input( struct thread *thread_from, struct thread *thread_to ) + } + + ret = assign_thread_input( thread_from, input ); +- if (ret) memset( input->keystate, 0, sizeof(input->keystate) ); ++ if (ret) ++ { ++ memset( input->keystate, 0, sizeof(input->keystate) ); ++ memset( input->shadow_keystate, 0, sizeof(input->shadow_keystate) ); ++ } + release_object( input ); + return ret; + } +@@ -1383,9 +1396,30 @@ static void update_desktop_mouse_state( struct desktop *desktop, unsigned int fl + update_input_key_state( desktop, desktop->keystate, WM_XBUTTONUP, wparam ); + } + ++/* synchronizes the thread input key state with the desktop */ ++static void synchronize_input_key_state( struct thread_input *input ) ++{ ++ if (!input->lock_count) ++ { ++ unsigned char *shadow_keystate = input->shadow_keystate; ++ unsigned char *keystate = input->keystate; ++ unsigned int i; ++ ++ for (i = 0; i < 256; i++) ++ { ++ if (input->desktop->keystate[i] != shadow_keystate[i]) ++ { ++ keystate[i] = input->desktop->keystate[i] & ~0x40; ++ shadow_keystate[i] = input->desktop->keystate[i]; ++ } ++ } ++ } ++} ++ + /* update the thread input key state for a keyboard message */ + static void update_input_key_state( struct thread_input *input, unsigned int msg, lparam_t wparam ) + { ++ synchronize_input_key_state( input ); + update_key_state( input->desktop, input->keystate, msg, wparam ); + } + +@@ -1586,6 +1620,15 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg + else + { + msg->unique_id = 0; /* will be set once we return it to the app */ ++ ++ /* lock the keystate on the first hardware message */ ++ if (!thread->queue->keystate_locked) ++ { ++ synchronize_input_key_state( input ); ++ input->lock_count++; ++ thread->queue->keystate_locked = 1; ++ } ++ + list_add_tail( &input->msg_list, &msg->entry ); + set_queue_bits( thread->queue, get_hardware_msg_bit(msg) ); + } +@@ -2524,6 +2567,13 @@ DECL_HANDLER(get_message) + queue->last_get_msg = current_time; + if (!filter) filter = QS_ALLINPUT; + ++ /* no longer lock the keystate if we have processed all input */ ++ if (queue->keystate_locked && !(queue->wake_bits & QS_ALLINPUT)) ++ { ++ queue->input->lock_count--; ++ queue->keystate_locked = 0; ++ } ++ + /* first check for sent messages */ + if ((ptr = list_head( &queue->msg_list[SEND_MESSAGE] ))) + { +@@ -2980,7 +3030,12 @@ DECL_HANDLER(get_key_state) + if (!(thread = get_thread_from_id( req->tid ))) return; + if (thread->queue) + { +- if (req->key >= 0) reply->state = thread->queue->input->keystate[req->key & 0xff]; ++ if (req->key >= 0) ++ { ++ /* synchronize with desktop keystate, but _only_ if req->key is given */ ++ synchronize_input_key_state( thread->queue->input ); ++ reply->state = thread->queue->input->keystate[req->key & 0xff]; ++ } + set_reply_data( thread->queue->input->keystate, size ); + release_object( thread ); + return; +-- +2.27.0 + diff --git a/patches/server-Key_State/definition b/patches/server-Key_State/definition new file mode 100644 index 00000000..a9ebdedd --- /dev/null +++ b/patches/server-Key_State/definition @@ -0,0 +1,5 @@ +# Fixes: [27238] Fallback to global key state for threads without a queue +Fixes: [31899] Implement locking and synchronization of key states +Fixes: [35907] Fix caps lock state issues with multiple processes +# Please review this for correctness; rebasing against 8cf7fe3b7c2 may have +# broken it.