You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-09-12 18:50:20 -07:00
server-Key_State: Replace with new patches from Rémi Bernon.
This also serves as a rebase against 2fcc1d0ecdebc55a5f515b1390ce715303f6a6ad.
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
From 4778b1c3d59bd87b067b6266e38ddd9a5d8bae86 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
|
||||
Date: Thu, 1 Apr 2021 23:19:18 +0200
|
||||
Subject: [PATCH] server: Create message queue and thread input in
|
||||
set_key_state.
|
||||
|
||||
This marks one test case as todo, but it was an outlier, and the 'X' key
|
||||
state is now wrong in all cases. Overall this makes the tests results
|
||||
more coherent.
|
||||
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=26269
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=27238
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=31899
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=35907
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45385
|
||||
---
|
||||
dlls/user32/tests/input.c | 52 +++++++++++++++++++--------------------
|
||||
server/queue.c | 3 ++-
|
||||
2 files changed, 28 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
|
||||
index 63163b7ed01..c146e4b5cd9 100644
|
||||
--- a/dlls/user32/tests/input.c
|
||||
+++ b/dlls/user32/tests/input.c
|
||||
@@ -3761,8 +3761,8 @@ struct get_key_state_thread_params
|
||||
int index;
|
||||
};
|
||||
|
||||
-#define check_get_keyboard_state(i, j, c, x, todo_c, todo_x) check_get_keyboard_state_(i, j, c, x, todo_c, todo_x, __LINE__)
|
||||
-static void check_get_keyboard_state_(int i, int j, int c, int x, int todo_c, int todo_x, int line)
|
||||
+#define check_get_keyboard_state(i, j, c, x, todo_x) check_get_keyboard_state_(i, j, c, x, todo_x, __LINE__)
|
||||
+static void check_get_keyboard_state_(int i, int j, int c, int x, int todo_x, int line)
|
||||
{
|
||||
unsigned char keystate[256];
|
||||
BOOL ret;
|
||||
@@ -3771,18 +3771,18 @@ static void check_get_keyboard_state_(int i, int j, int c, int x, int todo_c, in
|
||||
ret = GetKeyboardState(keystate);
|
||||
ok_(__FILE__, line)(ret, "GetKeyboardState failed, %u\n", GetLastError());
|
||||
todo_wine_if(todo_x) ok_(__FILE__, line)(!(keystate['X'] & 0x80) == !x, "%d:%d: expected that X keystate is %s\n", i, j, x ? "set" : "unset");
|
||||
- todo_wine_if(todo_c) ok_(__FILE__, line)(!(keystate['C'] & 0x80) == !c, "%d:%d: expected that C keystate is %s\n", i, j, c ? "set" : "unset");
|
||||
+ ok_(__FILE__, line)(!(keystate['C'] & 0x80) == !c, "%d:%d: expected that C keystate is %s\n", i, j, c ? "set" : "unset");
|
||||
|
||||
/* calling it twice shouldn't change */
|
||||
memset(keystate, 0, sizeof(keystate));
|
||||
ret = GetKeyboardState(keystate);
|
||||
ok_(__FILE__, line)(ret, "GetKeyboardState failed, %u\n", GetLastError());
|
||||
todo_wine_if(todo_x) ok_(__FILE__, line)(!(keystate['X'] & 0x80) == !x, "%d:%d: expected that X keystate is %s\n", i, j, x ? "set" : "unset");
|
||||
- todo_wine_if(todo_c) ok_(__FILE__, line)(!(keystate['C'] & 0x80) == !c, "%d:%d: expected that C keystate is %s\n", i, j, c ? "set" : "unset");
|
||||
+ ok_(__FILE__, line)(!(keystate['C'] & 0x80) == !c, "%d:%d: expected that C keystate is %s\n", i, j, c ? "set" : "unset");
|
||||
}
|
||||
|
||||
-#define check_get_key_state(i, j, c, x, todo_c, todo_x) check_get_key_state_(i, j, c, x, todo_c, todo_x, __LINE__)
|
||||
-static void check_get_key_state_(int i, int j, int c, int x, int todo_c, int todo_x, int line)
|
||||
+#define check_get_key_state(i, j, c, x, todo_x) check_get_key_state_(i, j, c, x, todo_x, __LINE__)
|
||||
+static void check_get_key_state_(int i, int j, int c, int x, int todo_x, int line)
|
||||
{
|
||||
SHORT state;
|
||||
|
||||
@@ -3791,7 +3791,7 @@ static void check_get_key_state_(int i, int j, int c, int x, int todo_c, int tod
|
||||
ok_(__FILE__, line)(!(state & 0x007e), "%d:%d: expected that X undefined bits are unset, got %#x\n", i, j, state);
|
||||
|
||||
state = GetKeyState('C');
|
||||
- todo_wine_if(todo_c) ok_(__FILE__, line)(!(state & 0x8000) == !c, "%d:%d: expected that C highest bit is %s, got %#x\n", i, j, c ? "set" : "unset", state);
|
||||
+ ok_(__FILE__, line)(!(state & 0x8000) == !c, "%d:%d: expected that C highest bit is %s, got %#x\n", i, j, c ? "set" : "unset", state);
|
||||
ok_(__FILE__, line)(!(state & 0x007e), "%d:%d: expected that C undefined bits are unset, got %#x\n", i, j, state);
|
||||
}
|
||||
|
||||
@@ -3808,7 +3808,7 @@ static DWORD WINAPI get_key_state_thread(void *arg)
|
||||
int i = params->index, j;
|
||||
|
||||
test = get_key_state_tests + i;
|
||||
- has_queue = test->peek_message;
|
||||
+ has_queue = test->peek_message || test->set_keyboard_state;
|
||||
|
||||
if (test->peek_message)
|
||||
{
|
||||
@@ -3841,18 +3841,18 @@ static DWORD WINAPI get_key_state_thread(void *arg)
|
||||
if (test->set_keyboard_state) expect_c = TRUE;
|
||||
else expect_c = FALSE;
|
||||
|
||||
- check_get_keyboard_state(i, j, expect_c, FALSE, /* todo */ i == 6, !has_queue);
|
||||
- check_get_key_state(i, j, expect_c, expect_x, /* todo */ i == 6, i != 6 && (has_queue || j == 0));
|
||||
- check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ i == 6, i != 6 && (has_queue || j == 0));
|
||||
+ check_get_keyboard_state(i, j, expect_c, FALSE, /* todo */ !has_queue);
|
||||
+ check_get_key_state(i, j, expect_c, expect_x, /* todo */ has_queue || j == 0);
|
||||
+ check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ has_queue || j == 0);
|
||||
|
||||
/* key released */
|
||||
ReleaseSemaphore(semaphores[0], 1, NULL);
|
||||
result = WaitForSingleObject(semaphores[1], 1000);
|
||||
ok(result == WAIT_OBJECT_0, "%d: WaitForSingleObject returned %u\n", i, result);
|
||||
|
||||
- check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ i == 6, has_queue || i == 6 || j > 0);
|
||||
- check_get_key_state(i, j, expect_c, FALSE, /* todo */ i == 6, FALSE);
|
||||
- check_get_keyboard_state(i, j, expect_c, FALSE, /* todo */ i == 6, FALSE);
|
||||
+ check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ has_queue || j > 0);
|
||||
+ check_get_key_state(i, j, expect_c, FALSE, /* todo */ FALSE);
|
||||
+ check_get_keyboard_state(i, j, expect_c, FALSE, /* todo */ FALSE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -3920,18 +3920,18 @@ static void test_GetKeyState(void)
|
||||
}
|
||||
else expect_c = FALSE;
|
||||
|
||||
- check_get_keyboard_state(i, j, expect_c, FALSE, /* todo */ FALSE, FALSE);
|
||||
- check_get_key_state(i, j, expect_c, FALSE, /* todo */ FALSE, FALSE);
|
||||
- check_get_keyboard_state(i, j, expect_c, FALSE, /* todo */ FALSE, FALSE);
|
||||
+ check_get_keyboard_state(i, j, expect_c, FALSE, /* todo */ FALSE);
|
||||
+ check_get_key_state(i, j, expect_c, FALSE, /* todo */ FALSE);
|
||||
+ check_get_keyboard_state(i, j, expect_c, FALSE, /* todo */ FALSE);
|
||||
|
||||
if (test->peek_message_main) while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
|
||||
if (test->peek_message_main) expect_x = TRUE;
|
||||
else expect_x = FALSE;
|
||||
|
||||
- check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ FALSE, FALSE);
|
||||
- check_get_key_state(i, j, expect_c, expect_x, /* todo */ FALSE, FALSE);
|
||||
- check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ FALSE, FALSE);
|
||||
+ check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ FALSE);
|
||||
+ check_get_key_state(i, j, expect_c, expect_x, /* todo */ FALSE);
|
||||
+ check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ FALSE);
|
||||
|
||||
ReleaseSemaphore(params.semaphores[1], 1, NULL);
|
||||
|
||||
@@ -3947,15 +3947,15 @@ static void test_GetKeyState(void)
|
||||
SetKeyboardState(keystate);
|
||||
}
|
||||
|
||||
- check_get_keyboard_state(i, j, FALSE, expect_x, /* todo */ FALSE, FALSE);
|
||||
- check_get_key_state(i, j, FALSE, expect_x, /* todo */ FALSE, FALSE);
|
||||
- check_get_keyboard_state(i, j, FALSE, expect_x, /* todo */ FALSE, FALSE);
|
||||
+ check_get_keyboard_state(i, j, FALSE, expect_x, /* todo */ FALSE);
|
||||
+ check_get_key_state(i, j, FALSE, expect_x, /* todo */ FALSE);
|
||||
+ check_get_keyboard_state(i, j, FALSE, expect_x, /* todo */ FALSE);
|
||||
|
||||
if (test->peek_message_main) while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
|
||||
- check_get_keyboard_state(i, j, FALSE, FALSE, /* todo */ FALSE, FALSE);
|
||||
- check_get_key_state(i, j, FALSE, FALSE, /* todo */ FALSE, FALSE);
|
||||
- check_get_keyboard_state(i, j, FALSE, FALSE, /* todo */ FALSE, FALSE);
|
||||
+ check_get_keyboard_state(i, j, FALSE, FALSE, /* todo */ FALSE);
|
||||
+ check_get_key_state(i, j, FALSE, FALSE, /* todo */ FALSE);
|
||||
+ check_get_keyboard_state(i, j, FALSE, FALSE, /* todo */ FALSE);
|
||||
|
||||
ReleaseSemaphore(params.semaphores[1], 1, NULL);
|
||||
}
|
||||
diff --git a/server/queue.c b/server/queue.c
|
||||
index b026c03e13d..5c9f91a13c5 100644
|
||||
--- a/server/queue.c
|
||||
+++ b/server/queue.c
|
||||
@@ -3007,9 +3007,10 @@ DECL_HANDLER(get_key_state)
|
||||
DECL_HANDLER(set_key_state)
|
||||
{
|
||||
struct desktop *desktop;
|
||||
+ struct msg_queue *queue = get_current_queue();
|
||||
data_size_t size = min( 256, get_req_data_size() );
|
||||
|
||||
- if (current->queue) memcpy( current->queue->input->keystate, get_req_data(), size );
|
||||
+ memcpy( queue->input->keystate, get_req_data(), size );
|
||||
if (req->async && (desktop = get_thread_desktop( current, 0 )))
|
||||
{
|
||||
memcpy( desktop->keystate, get_req_data(), size );
|
||||
--
|
||||
2.30.2
|
||||
|
@@ -1,120 +0,0 @@
|
||||
From be8f547f53a1f8d35d9680a8cb2f0cfa808568b8 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
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 7e7e6fbdf29..344e4298a56 100644
|
||||
--- a/server/queue.c
|
||||
+++ b/server/queue.c
|
||||
@@ -1300,9 +1300,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;
|
||||
@@ -1371,21 +1371,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 );
|
||||
}
|
||||
@@ -1542,7 +1548,7 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg
|
||||
struct hardware_msg_data *msg_data = msg->data;
|
||||
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;
|
||||
|
||||
@@ -1581,7 +1587,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;
|
||||
}
|
||||
@@ -1919,7 +1925,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;
|
||||
}
|
||||
|
||||
@@ -2048,7 +2054,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;
|
||||
@@ -2064,7 +2070,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.28.0
|
||||
|
@@ -1,162 +0,0 @@
|
||||
From b4259641f65faa6272c882019d773989b1f1d3d4 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
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 cd84684d4a0..77496da03ca 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? */
|
||||
@@ -259,9 +262,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 */ )))
|
||||
{
|
||||
@@ -292,6 +297,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;
|
||||
@@ -335,8 +341,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;
|
||||
@@ -1027,6 +1035,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 );
|
||||
@@ -1127,7 +1136,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;
|
||||
}
|
||||
@@ -1385,9 +1398,30 @@ static void update_desktop_mouse_state( struct desktop *desktop, unsigned int fl
|
||||
update_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 );
|
||||
}
|
||||
|
||||
@@ -1588,6 +1622,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) );
|
||||
}
|
||||
@@ -2526,6 +2569,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] )))
|
||||
{
|
||||
@@ -2982,7 +3032,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
|
||||
|
@@ -0,0 +1,187 @@
|
||||
From a6f4d1c57d31c0a8f50afd5af9d50b7e587c84f5 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
|
||||
Date: Thu, 1 Apr 2021 23:30:46 +0200
|
||||
Subject: [PATCH] server: Lock thread input keystate whenever it is modified.
|
||||
|
||||
And synchronize it with desktop async keystate, on GetKeyState calls,
|
||||
if it is not locked yet.
|
||||
|
||||
Based on a patch from Sebastian Lackner <sebastian@fds-team.de>.
|
||||
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=26269
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=27238
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=31899
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=35907
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45385
|
||||
---
|
||||
dlls/user32/tests/input.c | 6 ++---
|
||||
server/queue.c | 51 ++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 53 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
|
||||
index c146e4b5cd9..246569961be 100644
|
||||
--- a/dlls/user32/tests/input.c
|
||||
+++ b/dlls/user32/tests/input.c
|
||||
@@ -3842,15 +3842,15 @@ static DWORD WINAPI get_key_state_thread(void *arg)
|
||||
else expect_c = FALSE;
|
||||
|
||||
check_get_keyboard_state(i, j, expect_c, FALSE, /* todo */ !has_queue);
|
||||
- check_get_key_state(i, j, expect_c, expect_x, /* todo */ has_queue || j == 0);
|
||||
- check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ has_queue || j == 0);
|
||||
+ check_get_key_state(i, j, expect_c, expect_x, /* todo */ !has_queue && j == 0);
|
||||
+ check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ !has_queue && j == 0);
|
||||
|
||||
/* key released */
|
||||
ReleaseSemaphore(semaphores[0], 1, NULL);
|
||||
result = WaitForSingleObject(semaphores[1], 1000);
|
||||
ok(result == WAIT_OBJECT_0, "%d: WaitForSingleObject returned %u\n", i, result);
|
||||
|
||||
- check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ has_queue || j > 0);
|
||||
+ check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ !has_queue && j > 0);
|
||||
check_get_key_state(i, j, expect_c, FALSE, /* todo */ FALSE);
|
||||
check_get_keyboard_state(i, j, expect_c, FALSE, /* todo */ FALSE);
|
||||
}
|
||||
diff --git a/server/queue.c b/server/queue.c
|
||||
index 5c9f91a13c5..0782c526327 100644
|
||||
--- a/server/queue.c
|
||||
+++ b/server/queue.c
|
||||
@@ -114,6 +114,8 @@ struct thread_input
|
||||
int cursor_count; /* cursor show count */
|
||||
struct list msg_list; /* list of hardware messages */
|
||||
unsigned char keystate[256]; /* state of each key */
|
||||
+ unsigned char desktop_keystate[256]; /* desktop keystate when keystate was synced */
|
||||
+ int keystate_lock; /* keystate is locked */
|
||||
};
|
||||
|
||||
struct msg_queue
|
||||
@@ -140,6 +142,7 @@ struct msg_queue
|
||||
struct thread_input *input; /* thread input descriptor */
|
||||
struct hook_table *hooks; /* hook table */
|
||||
timeout_t last_get_msg; /* time of last get message call */
|
||||
+ int keystate_lock; /* owns an input keystate lock */
|
||||
};
|
||||
|
||||
struct hotkey
|
||||
@@ -265,12 +268,14 @@ static struct thread_input *create_thread_input( struct thread *thread )
|
||||
list_init( &input->msg_list );
|
||||
set_caret_window( input, 0 );
|
||||
memset( input->keystate, 0, sizeof(input->keystate) );
|
||||
+ input->keystate_lock = 0;
|
||||
|
||||
if (!(input->desktop = get_thread_desktop( thread, 0 /* FIXME: access rights */ )))
|
||||
{
|
||||
release_object( input );
|
||||
return NULL;
|
||||
}
|
||||
+ memcpy( input->desktop_keystate, input->desktop->keystate, sizeof(input->desktop_keystate) );
|
||||
}
|
||||
return input;
|
||||
}
|
||||
@@ -305,6 +310,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
|
||||
queue->input = (struct thread_input *)grab_object( input );
|
||||
queue->hooks = NULL;
|
||||
queue->last_get_msg = current_time;
|
||||
+ queue->keystate_lock = 0;
|
||||
list_init( &queue->send_result );
|
||||
list_init( &queue->callback_result );
|
||||
list_init( &queue->pending_timers );
|
||||
@@ -326,6 +332,31 @@ void free_msg_queue( struct thread *thread )
|
||||
thread->queue = NULL;
|
||||
}
|
||||
|
||||
+/* synchronize thread input keystate with the desktop */
|
||||
+static void sync_input_keystate( struct thread_input *input )
|
||||
+{
|
||||
+ int i;
|
||||
+ if (!input->desktop || input->keystate_lock) return;
|
||||
+ for (i = 0; i < sizeof(input->keystate); ++i)
|
||||
+ {
|
||||
+ if (input->desktop_keystate[i] == input->desktop->keystate[i]) continue;
|
||||
+ input->keystate[i] = input->desktop_keystate[i] = input->desktop->keystate[i];
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* locks thread input keystate to prevent synchronization */
|
||||
+static void lock_input_keystate( struct thread_input *input )
|
||||
+{
|
||||
+ input->keystate_lock++;
|
||||
+}
|
||||
+
|
||||
+/* unlock the thread input keystate and synchronize it again */
|
||||
+static void unlock_input_keystate( struct thread_input *input )
|
||||
+{
|
||||
+ input->keystate_lock--;
|
||||
+ if (!input->keystate_lock) sync_input_keystate( input );
|
||||
+}
|
||||
+
|
||||
/* change the thread input data of a given thread */
|
||||
static int assign_thread_input( struct thread *thread, struct thread_input *new_input )
|
||||
{
|
||||
@@ -339,9 +370,11 @@ static int assign_thread_input( struct thread *thread, struct thread_input *new_
|
||||
if (queue->input)
|
||||
{
|
||||
queue->input->cursor_count -= queue->cursor_count;
|
||||
+ if (queue->keystate_lock) unlock_input_keystate( queue->input );
|
||||
release_object( queue->input );
|
||||
}
|
||||
queue->input = (struct thread_input *)grab_object( new_input );
|
||||
+ if (queue->keystate_lock) lock_input_keystate( queue->input );
|
||||
new_input->cursor_count += queue->cursor_count;
|
||||
return 1;
|
||||
}
|
||||
@@ -477,6 +510,11 @@ static inline int is_signaled( struct msg_queue *queue )
|
||||
/* set some queue bits */
|
||||
static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits )
|
||||
{
|
||||
+ if (bits & (QS_KEY | QS_MOUSEBUTTON))
|
||||
+ {
|
||||
+ if (!queue->keystate_lock) lock_input_keystate( queue->input );
|
||||
+ queue->keystate_lock = 1;
|
||||
+ }
|
||||
queue->wake_bits |= bits;
|
||||
queue->changed_bits |= bits;
|
||||
if (is_signaled( queue )) wake_up( &queue->obj, 0 );
|
||||
@@ -487,6 +525,11 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits
|
||||
{
|
||||
queue->wake_bits &= ~bits;
|
||||
queue->changed_bits &= ~bits;
|
||||
+ if (!(queue->wake_bits & (QS_KEY | QS_MOUSEBUTTON)))
|
||||
+ {
|
||||
+ if (queue->keystate_lock) unlock_input_keystate( queue->input );
|
||||
+ queue->keystate_lock = 0;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* check whether msg is a keyboard message */
|
||||
@@ -1031,6 +1074,7 @@ static void msg_queue_destroy( struct object *obj )
|
||||
}
|
||||
if (queue->timeout) remove_timeout_user( queue->timeout );
|
||||
queue->input->cursor_count -= queue->cursor_count;
|
||||
+ if (queue->keystate_lock) unlock_input_keystate( queue->input );
|
||||
release_object( queue->input );
|
||||
if (queue->hooks) release_object( queue->hooks );
|
||||
if (queue->fd) release_object( queue->fd );
|
||||
@@ -2997,7 +3041,11 @@ DECL_HANDLER(get_key_state)
|
||||
else
|
||||
{
|
||||
unsigned char *keystate = current->queue->input->keystate;
|
||||
- if (req->key >= 0) reply->state = keystate[req->key & 0xff];
|
||||
+ if (req->key >= 0)
|
||||
+ {
|
||||
+ if (current->queue) sync_input_keystate( current->queue->input );
|
||||
+ reply->state = keystate[req->key & 0xff];
|
||||
+ }
|
||||
set_reply_data( keystate, size );
|
||||
}
|
||||
}
|
||||
@@ -3011,6 +3059,7 @@ DECL_HANDLER(set_key_state)
|
||||
data_size_t size = min( 256, get_req_data_size() );
|
||||
|
||||
memcpy( queue->input->keystate, get_req_data(), size );
|
||||
+ memcpy( queue->input->desktop_keystate, queue->input->desktop->keystate, 256 );
|
||||
if (req->async && (desktop = get_thread_desktop( current, 0 )))
|
||||
{
|
||||
memcpy( desktop->keystate, get_req_data(), size );
|
||||
--
|
||||
2.30.2
|
||||
|
@@ -0,0 +1,172 @@
|
||||
From a6a449881f6643183316ad867b49bd99f53fa4a4 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
|
||||
Date: Thu, 1 Apr 2021 23:41:31 +0200
|
||||
Subject: [PATCH] server: Create message queue and thread input in
|
||||
get_key_state.
|
||||
|
||||
This removes the fallback to desktop async keystate and uses instead the
|
||||
keystate synchronization logic in all cases.
|
||||
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=26269
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=27238
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=31899
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=35907
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45385
|
||||
---
|
||||
dlls/user32/tests/input.c | 50 +++++++++++++++++++--------------------
|
||||
server/queue.c | 18 +++-----------
|
||||
2 files changed, 28 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
|
||||
index 246569961be..561f932b18b 100644
|
||||
--- a/dlls/user32/tests/input.c
|
||||
+++ b/dlls/user32/tests/input.c
|
||||
@@ -3761,8 +3761,8 @@ struct get_key_state_thread_params
|
||||
int index;
|
||||
};
|
||||
|
||||
-#define check_get_keyboard_state(i, j, c, x, todo_x) check_get_keyboard_state_(i, j, c, x, todo_x, __LINE__)
|
||||
-static void check_get_keyboard_state_(int i, int j, int c, int x, int todo_x, int line)
|
||||
+#define check_get_keyboard_state(i, j, c, x) check_get_keyboard_state_(i, j, c, x, __LINE__)
|
||||
+static void check_get_keyboard_state_(int i, int j, int c, int x, int line)
|
||||
{
|
||||
unsigned char keystate[256];
|
||||
BOOL ret;
|
||||
@@ -3770,24 +3770,24 @@ static void check_get_keyboard_state_(int i, int j, int c, int x, int todo_x, in
|
||||
memset(keystate, 0, sizeof(keystate));
|
||||
ret = GetKeyboardState(keystate);
|
||||
ok_(__FILE__, line)(ret, "GetKeyboardState failed, %u\n", GetLastError());
|
||||
- todo_wine_if(todo_x) ok_(__FILE__, line)(!(keystate['X'] & 0x80) == !x, "%d:%d: expected that X keystate is %s\n", i, j, x ? "set" : "unset");
|
||||
+ ok_(__FILE__, line)(!(keystate['X'] & 0x80) == !x, "%d:%d: expected that X keystate is %s\n", i, j, x ? "set" : "unset");
|
||||
ok_(__FILE__, line)(!(keystate['C'] & 0x80) == !c, "%d:%d: expected that C keystate is %s\n", i, j, c ? "set" : "unset");
|
||||
|
||||
/* calling it twice shouldn't change */
|
||||
memset(keystate, 0, sizeof(keystate));
|
||||
ret = GetKeyboardState(keystate);
|
||||
ok_(__FILE__, line)(ret, "GetKeyboardState failed, %u\n", GetLastError());
|
||||
- todo_wine_if(todo_x) ok_(__FILE__, line)(!(keystate['X'] & 0x80) == !x, "%d:%d: expected that X keystate is %s\n", i, j, x ? "set" : "unset");
|
||||
+ ok_(__FILE__, line)(!(keystate['X'] & 0x80) == !x, "%d:%d: expected that X keystate is %s\n", i, j, x ? "set" : "unset");
|
||||
ok_(__FILE__, line)(!(keystate['C'] & 0x80) == !c, "%d:%d: expected that C keystate is %s\n", i, j, c ? "set" : "unset");
|
||||
}
|
||||
|
||||
-#define check_get_key_state(i, j, c, x, todo_x) check_get_key_state_(i, j, c, x, todo_x, __LINE__)
|
||||
-static void check_get_key_state_(int i, int j, int c, int x, int todo_x, int line)
|
||||
+#define check_get_key_state(i, j, c, x) check_get_key_state_(i, j, c, x, __LINE__)
|
||||
+static void check_get_key_state_(int i, int j, int c, int x, int line)
|
||||
{
|
||||
SHORT state;
|
||||
|
||||
state = GetKeyState('X');
|
||||
- todo_wine_if(todo_x) ok_(__FILE__, line)(!(state & 0x8000) == !x, "%d:%d: expected that X highest bit is %s, got %#x\n", i, j, x ? "set" : "unset", state);
|
||||
+ ok_(__FILE__, line)(!(state & 0x8000) == !x, "%d:%d: expected that X highest bit is %s, got %#x\n", i, j, x ? "set" : "unset", state);
|
||||
ok_(__FILE__, line)(!(state & 0x007e), "%d:%d: expected that X undefined bits are unset, got %#x\n", i, j, state);
|
||||
|
||||
state = GetKeyState('C');
|
||||
@@ -3841,18 +3841,18 @@ static DWORD WINAPI get_key_state_thread(void *arg)
|
||||
if (test->set_keyboard_state) expect_c = TRUE;
|
||||
else expect_c = FALSE;
|
||||
|
||||
- check_get_keyboard_state(i, j, expect_c, FALSE, /* todo */ !has_queue);
|
||||
- check_get_key_state(i, j, expect_c, expect_x, /* todo */ !has_queue && j == 0);
|
||||
- check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ !has_queue && j == 0);
|
||||
+ check_get_keyboard_state(i, j, expect_c, FALSE);
|
||||
+ check_get_key_state(i, j, expect_c, expect_x);
|
||||
+ check_get_keyboard_state(i, j, expect_c, expect_x);
|
||||
|
||||
/* key released */
|
||||
ReleaseSemaphore(semaphores[0], 1, NULL);
|
||||
result = WaitForSingleObject(semaphores[1], 1000);
|
||||
ok(result == WAIT_OBJECT_0, "%d: WaitForSingleObject returned %u\n", i, result);
|
||||
|
||||
- check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ !has_queue && j > 0);
|
||||
- check_get_key_state(i, j, expect_c, FALSE, /* todo */ FALSE);
|
||||
- check_get_keyboard_state(i, j, expect_c, FALSE, /* todo */ FALSE);
|
||||
+ check_get_keyboard_state(i, j, expect_c, expect_x);
|
||||
+ check_get_key_state(i, j, expect_c, FALSE);
|
||||
+ check_get_keyboard_state(i, j, expect_c, FALSE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -3920,18 +3920,18 @@ static void test_GetKeyState(void)
|
||||
}
|
||||
else expect_c = FALSE;
|
||||
|
||||
- check_get_keyboard_state(i, j, expect_c, FALSE, /* todo */ FALSE);
|
||||
- check_get_key_state(i, j, expect_c, FALSE, /* todo */ FALSE);
|
||||
- check_get_keyboard_state(i, j, expect_c, FALSE, /* todo */ FALSE);
|
||||
+ check_get_keyboard_state(i, j, expect_c, FALSE);
|
||||
+ check_get_key_state(i, j, expect_c, FALSE);
|
||||
+ check_get_keyboard_state(i, j, expect_c, FALSE);
|
||||
|
||||
if (test->peek_message_main) while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
|
||||
if (test->peek_message_main) expect_x = TRUE;
|
||||
else expect_x = FALSE;
|
||||
|
||||
- check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ FALSE);
|
||||
- check_get_key_state(i, j, expect_c, expect_x, /* todo */ FALSE);
|
||||
- check_get_keyboard_state(i, j, expect_c, expect_x, /* todo */ FALSE);
|
||||
+ check_get_keyboard_state(i, j, expect_c, expect_x);
|
||||
+ check_get_key_state(i, j, expect_c, expect_x);
|
||||
+ check_get_keyboard_state(i, j, expect_c, expect_x);
|
||||
|
||||
ReleaseSemaphore(params.semaphores[1], 1, NULL);
|
||||
|
||||
@@ -3947,15 +3947,15 @@ static void test_GetKeyState(void)
|
||||
SetKeyboardState(keystate);
|
||||
}
|
||||
|
||||
- check_get_keyboard_state(i, j, FALSE, expect_x, /* todo */ FALSE);
|
||||
- check_get_key_state(i, j, FALSE, expect_x, /* todo */ FALSE);
|
||||
- check_get_keyboard_state(i, j, FALSE, expect_x, /* todo */ FALSE);
|
||||
+ check_get_keyboard_state(i, j, FALSE, expect_x);
|
||||
+ check_get_key_state(i, j, FALSE, expect_x);
|
||||
+ check_get_keyboard_state(i, j, FALSE, expect_x);
|
||||
|
||||
if (test->peek_message_main) while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
|
||||
- check_get_keyboard_state(i, j, FALSE, FALSE, /* todo */ FALSE);
|
||||
- check_get_key_state(i, j, FALSE, FALSE, /* todo */ FALSE);
|
||||
- check_get_keyboard_state(i, j, FALSE, FALSE, /* todo */ FALSE);
|
||||
+ check_get_keyboard_state(i, j, FALSE, FALSE);
|
||||
+ check_get_key_state(i, j, FALSE, FALSE);
|
||||
+ check_get_keyboard_state(i, j, FALSE, FALSE);
|
||||
|
||||
ReleaseSemaphore(params.semaphores[1], 1, NULL);
|
||||
}
|
||||
diff --git a/server/queue.c b/server/queue.c
|
||||
index 0782c526327..fce65e360d4 100644
|
||||
--- a/server/queue.c
|
||||
+++ b/server/queue.c
|
||||
@@ -3025,25 +3025,13 @@ DECL_HANDLER(get_key_state)
|
||||
set_reply_data( desktop->keystate, size );
|
||||
release_object( desktop );
|
||||
}
|
||||
- else if (!current->queue)
|
||||
- {
|
||||
- unsigned char *keystate;
|
||||
- /* fallback to desktop keystate */
|
||||
- if (!(desktop = get_thread_desktop( current, 0 ))) return;
|
||||
- if (req->key >= 0) reply->state = desktop->keystate[req->key & 0xff] & ~0x40;
|
||||
- if ((keystate = set_reply_data_size( size )))
|
||||
- {
|
||||
- unsigned int i;
|
||||
- for (i = 0; i < size; i++) keystate[i] = desktop->keystate[i] & ~0x40;
|
||||
- }
|
||||
- release_object( desktop );
|
||||
- }
|
||||
else
|
||||
{
|
||||
- unsigned char *keystate = current->queue->input->keystate;
|
||||
+ struct msg_queue *queue = get_current_queue();
|
||||
+ unsigned char *keystate = queue->input->keystate;
|
||||
if (req->key >= 0)
|
||||
{
|
||||
- if (current->queue) sync_input_keystate( current->queue->input );
|
||||
+ sync_input_keystate( queue->input );
|
||||
reply->state = keystate[req->key & 0xff];
|
||||
}
|
||||
set_reply_data( keystate, size );
|
||||
--
|
||||
2.30.2
|
||||
|
@@ -1,5 +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.
|
||||
Fixes: [26269] BioShock 2: Loss of keyboard input on loading screen
|
||||
# Fixes: [27238] Tesla: The Weather Man demo: movement keys not working (GetKeyState should fallback to GetAsyncKeyState for threads without message queue)
|
||||
Fixes: [31899] No keyboard input in La-Mulana remake (GetKeyState should behave similar to GetAsyncKeyState for specific window messages / queue states)
|
||||
Fixes: [35907] Caps Lock state gets confused with multiple processes/threads
|
||||
Fixes: [45385] Wrong state of virtual keys after cycling windows. Usually VK_MENU, VK_SHIFT and VK_CONTROL, but every key can be affected.
|
||||
|
Reference in New Issue
Block a user