server-Key_State: Replace with new patches from Rémi Bernon.

This also serves as a rebase against 2fcc1d0ecdebc55a5f515b1390ce715303f6a6ad.
This commit is contained in:
Zebediah Figura 2021-04-02 20:15:01 -05:00
parent 545073aafa
commit 733a420dd7
11 changed files with 614 additions and 354 deletions

View File

@ -1,4 +1,4 @@
From 1aac9111b536d35eec696e20141b6c5d6d92579b Mon Sep 17 00:00:00 2001
From 2da453ad472ce69926e158bd4e933facd985d1cd Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 16:01:56 -0500
Subject: [PATCH] server: Create eventfd file descriptors for message queues.
@ -8,7 +8,7 @@ Subject: [PATCH] server: Create eventfd file descriptors for message queues.
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/server/queue.c b/server/queue.c
index 263bb46ea00..4d416a88d88 100644
index 1f1392387df..d34bc284d08 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -43,6 +43,7 @@
@ -19,15 +19,15 @@ index 263bb46ea00..4d416a88d88 100644
#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
#define WM_NCMOUSELAST (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST))
@@ -141,6 +142,7 @@ struct msg_queue
struct hook_table *hooks; /* hook table */
@@ -144,6 +145,7 @@ struct msg_queue
timeout_t last_get_msg; /* time of last get message call */
int keystate_lock; /* owns an input keystate lock */
unsigned int ignore_post_msg; /* ignore post messages newer than this unique id */
+ int esync_fd; /* esync file descriptor (signalled on message) */
};
struct hotkey
@@ -157,6 +159,7 @@ static void msg_queue_dump( struct object *obj, int verbose );
@@ -160,6 +162,7 @@ static void msg_queue_dump( struct object *obj, int verbose );
static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry );
static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry );
static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entry );
@ -35,7 +35,7 @@ index 263bb46ea00..4d416a88d88 100644
static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry );
static void msg_queue_destroy( struct object *obj );
static void msg_queue_poll_event( struct fd *fd, int event );
@@ -172,7 +175,7 @@ static const struct object_ops msg_queue_ops =
@@ -175,7 +178,7 @@ static const struct object_ops msg_queue_ops =
msg_queue_add_queue, /* add_queue */
msg_queue_remove_queue, /* remove_queue */
msg_queue_signaled, /* signaled */
@ -44,9 +44,9 @@ index 263bb46ea00..4d416a88d88 100644
msg_queue_satisfied, /* satisfied */
no_signal, /* signal */
no_get_fd, /* get_fd */
@@ -309,12 +312,16 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
queue->hooks = NULL;
@@ -315,12 +318,16 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
queue->last_get_msg = current_time;
queue->keystate_lock = 0;
queue->ignore_post_msg = 0;
+ queue->esync_fd = -1;
list_init( &queue->send_result );
@ -61,17 +61,17 @@ index 263bb46ea00..4d416a88d88 100644
thread->queue = queue;
}
if (new_input) release_object( new_input );
@@ -491,6 +498,9 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits
{
queue->wake_bits &= ~bits;
queue->changed_bits &= ~bits;
@@ -534,6 +541,9 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits
if (queue->keystate_lock) unlock_input_keystate( queue->input );
queue->keystate_lock = 0;
}
+
+ if (do_esync() && !is_signaled( queue ))
+ esync_clear( queue->esync_fd );
}
/* check whether msg is a keyboard message */
@@ -1004,6 +1014,13 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr
@@ -1047,6 +1057,13 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr
return ret || is_signaled( queue );
}
@ -85,7 +85,7 @@ index 263bb46ea00..4d416a88d88 100644
static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry )
{
struct msg_queue *queue = (struct msg_queue *)obj;
@@ -2381,6 +2398,9 @@ DECL_HANDLER(get_queue_status)
@@ -2425,6 +2442,9 @@ DECL_HANDLER(get_queue_status)
reply->wake_bits = queue->wake_bits;
reply->changed_bits = queue->changed_bits;
queue->changed_bits &= ~req->clear_bits;
@ -96,5 +96,5 @@ index 263bb46ea00..4d416a88d88 100644
else reply->wake_bits = reply->changed_bits = 0;
}
--
2.28.0
2.30.2

View File

@ -1,4 +1,4 @@
From df50f6973c1fa60db18b408001ac50c03fb2fa07 Mon Sep 17 00:00:00 2001
From e0a89702e35941e75ce06f795966c92b3f195ed8 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 16:11:23 -0500
Subject: [PATCH] server, ntdll: Implement message waits.
@ -105,10 +105,10 @@ index fcbe563bb5a..88490e08ef9 100644
{
struct stat st;
diff --git a/server/protocol.def b/server/protocol.def
index 9062a5020c2..789bc56e7f1 100644
index cf00ab99c63..ecbb78cc9bb 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3697,3 +3697,8 @@ enum esync_type
@@ -3734,3 +3734,8 @@ enum esync_type
int type;
unsigned int shm_idx;
@END
@ -118,26 +118,26 @@ index 9062a5020c2..789bc56e7f1 100644
+ int in_msgwait; /* are we in a message wait? */
+@END
diff --git a/server/queue.c b/server/queue.c
index 4d416a88d88..efaf8a0f7e7 100644
index d34bc284d08..f4edb299dc3 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -143,6 +143,7 @@ struct msg_queue
timeout_t last_get_msg; /* time of last get message call */
@@ -146,6 +146,7 @@ struct msg_queue
int keystate_lock; /* owns an input keystate lock */
unsigned int ignore_post_msg; /* ignore post messages newer than this unique id */
int esync_fd; /* esync file descriptor (signalled on message) */
+ int esync_in_msgwait; /* our thread is currently waiting on us */
};
struct hotkey
@@ -313,6 +314,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
queue->last_get_msg = current_time;
@@ -319,6 +320,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
queue->keystate_lock = 0;
queue->ignore_post_msg = 0;
queue->esync_fd = -1;
+ queue->esync_in_msgwait = 0;
list_init( &queue->send_result );
list_init( &queue->callback_result );
list_init( &queue->pending_timers );
@@ -959,6 +961,10 @@ static int is_queue_hung( struct msg_queue *queue )
@@ -1002,6 +1004,10 @@ static int is_queue_hung( struct msg_queue *queue )
if (get_wait_queue_thread(entry)->queue == queue)
return 0; /* thread is waiting on queue -> not hung */
}
@ -148,7 +148,7 @@ index 4d416a88d88..efaf8a0f7e7 100644
return 1;
}
@@ -3385,3 +3391,18 @@ DECL_HANDLER(get_rawinput_devices)
@@ -3416,3 +3422,18 @@ DECL_HANDLER(get_rawinput_devices)
devices[i++] = e->device;
}
}
@ -168,5 +168,5 @@ index 4d416a88d88..efaf8a0f7e7 100644
+ set_fd_events( queue->fd, req->in_msgwait ? POLLIN : 0 );
+}
--
2.28.0
2.30.2

View File

@ -51,7 +51,7 @@ usage()
# Get the upstream commit sha
upstream_commit()
{
echo "97b420224e767b24d89722ff5efeca38a8ecf1e2"
echo "2fcc1d0ecdebc55a5f515b1390ce715303f6a6ad"
}
# Show version information
@ -1449,6 +1449,13 @@ if test "$enable_eventfd_synchronization" -eq 1; then
enable_server_Signal_Thread=1
fi
if test "$enable_server_PeekMessage" -eq 1; then
if test "$enable_server_Key_State" -gt 1; then
abort "Patchset server-Key_State disabled, but server-PeekMessage depends on that."
fi
enable_server_Key_State=1
fi
if test "$enable_ntdll_Junction_Points" -eq 1; then
if test "$enable_ntdll_DOS_Attributes" -gt 1; then
abort "Patchset ntdll-DOS_Attributes disabled, but ntdll-Junction_Points depends on that."
@ -2303,8 +2310,30 @@ if test "$enable_ntdll_Junction_Points" -eq 1; then
patch_apply ntdll-Junction_Points/0038-server-Rewrite-absolute-reparse-point-targets-if-the.patch
fi
# Patchset server-Key_State
# |
# | This patchset fixes the following Wine bugs:
# | * [#26269] BioShock 2: Loss of keyboard input on loading screen
# | * [#31899] No keyboard input in La-Mulana remake (GetKeyState should behave similar to GetAsyncKeyState for specific
# | window messages / queue states)
# | * [#35907] Caps Lock state gets confused with multiple processes/threads
# | * [#45385] Wrong state of virtual keys after cycling windows. Usually VK_MENU, VK_SHIFT and VK_CONTROL, but every key can
# | be affected.
# |
# | Modified files:
# | * dlls/user32/tests/input.c, server/queue.c
# |
if test "$enable_server_Key_State" -eq 1; then
patch_apply server-Key_State/0001-server-Create-message-queue-and-thread-input-in-set_.patch
patch_apply server-Key_State/0002-server-Lock-thread-input-keystate-whenever-it-is-mod.patch
patch_apply server-Key_State/0003-server-Create-message-queue-and-thread-input-in-get_.patch
fi
# Patchset server-PeekMessage
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * server-Key_State
# |
# | This patchset fixes the following Wine bugs:
# | * [#28884] GetMessage should remove already seen messages with higher priority
# |
@ -2336,8 +2365,8 @@ fi
# Patchset eventfd_synchronization
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * ntdll-DOS_Attributes, ntdll-NtQueryEaFile, ntdll-Junction_Points, server-PeekMessage, server-Realtime_Priority, server-
# | Signal_Thread
# | * ntdll-DOS_Attributes, ntdll-NtQueryEaFile, ntdll-Junction_Points, server-Key_State, server-PeekMessage, server-
# | Realtime_Priority, server-Signal_Thread
# |
# | This patchset fixes the following Wine bugs:
# | * [#36692] Many multi-threaded applications have poor performance due to heavy use of synchronization primitives
@ -3324,20 +3353,6 @@ if test "$enable_server_File_Permissions" -eq 1; then
patch_apply server-File_Permissions/0008-server-Improve-mapping-of-DACL-to-file-permissions.patch
fi
# Patchset server-Key_State
# |
# | This patchset fixes the following Wine bugs:
# | * [#31899] Implement locking and synchronization of key states
# | * [#35907] Fix caps lock state issues with multiple processes
# |
# | Modified files:
# | * server/queue.c
# |
if test "$enable_server_Key_State" -eq 1; then
patch_apply server-Key_State/0001-server-Introduce-a-helper-function-to-update-the-thr.patch
patch_apply server-Key_State/0002-server-Implement-locking-and-synchronization-of-keys.patch
fi
# Patchset server-Stored_ACLs
# |
# | This patchset has the following (direct or indirect) dependencies:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -1,4 +1,4 @@
From c527f32596831ae31b055cd77cb3bc848f83a8a8 Mon Sep 17 00:00:00 2001
From 9875a6033aaa0043a7c29926a026ecafb56382e6 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 15 Mar 2015 01:05:48 +0100
Subject: [PATCH] server: Fix handling of GetMessage after previous PeekMessage
@ -15,10 +15,10 @@ Changes in v3:
2 files changed, 62 insertions(+), 17 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index f84525a0bf9..80cc0daa6c6 100644
index 7eaa2c67945..8f8b1b98933 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -12429,13 +12429,10 @@ static void test_PeekMessage3(void)
@@ -12648,13 +12648,10 @@ static void test_PeekMessage3(void)
ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
PostMessageA(hwnd, WM_USER, 0, 0);
ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE);
@ -32,7 +32,7 @@ index f84525a0bf9..80cc0daa6c6 100644
ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
ret = PeekMessageA(&msg, NULL, 0, 0, 0);
ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
@@ -12445,10 +12442,8 @@ static void test_PeekMessage3(void)
@@ -12664,10 +12661,8 @@ static void test_PeekMessage3(void)
ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
PostMessageA(hwnd, WM_USER, 0, 0);
ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE);
@ -43,7 +43,7 @@ index f84525a0bf9..80cc0daa6c6 100644
ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
ret = PeekMessageA(&msg, NULL, 0, 0, 0);
ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
@@ -12460,10 +12455,8 @@ static void test_PeekMessage3(void)
@@ -12679,10 +12674,8 @@ static void test_PeekMessage3(void)
ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
PostMessageA(hwnd, WM_USER, 0, 0);
ret = GetMessageA(&msg, NULL, 0, 0);
@ -54,7 +54,7 @@ index f84525a0bf9..80cc0daa6c6 100644
ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
ret = PeekMessageA(&msg, NULL, 0, 0, 0);
ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
@@ -12491,14 +12484,32 @@ static void test_PeekMessage3(void)
@@ -12710,14 +12703,32 @@ static void test_PeekMessage3(void)
ret = GetMessageA(&msg, NULL, 0, 0);
ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
ret = GetMessageA(&msg, NULL, 0, 0);
@ -90,26 +90,26 @@ index f84525a0bf9..80cc0daa6c6 100644
* because both messages are in the same queue. */
diff --git a/server/queue.c b/server/queue.c
index a65eab38bdc..bf315f5008c 100644
index fce65e360d4..451aaeca008 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -140,6 +140,7 @@ struct msg_queue
struct thread_input *input; /* thread input descriptor */
@@ -143,6 +143,7 @@ struct msg_queue
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 */
+ unsigned int ignore_post_msg; /* ignore post messages newer than this unique id */
};
struct hotkey
@@ -300,6 +301,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
queue->input = (struct thread_input *)grab_object( input );
@@ -311,6 +312,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
queue->hooks = NULL;
queue->last_get_msg = current_time;
queue->keystate_lock = 0;
+ queue->ignore_post_msg = 0;
list_init( &queue->send_result );
list_init( &queue->callback_result );
list_init( &queue->pending_timers );
@@ -529,13 +531,21 @@ static inline struct msg_queue *get_current_queue(void)
@@ -577,13 +579,21 @@ static inline struct msg_queue *get_current_queue(void)
}
/* get a (pseudo-)unique id to tag hardware messages */
@ -132,7 +132,7 @@ index a65eab38bdc..bf315f5008c 100644
/* try to merge a message with the last in the list; return 1 if successful */
static int merge_message( struct thread_input *input, const struct message *msg )
{
@@ -813,7 +823,7 @@ static int match_window( user_handle_t win, user_handle_t msg_win )
@@ -861,7 +871,7 @@ static int match_window( user_handle_t win, user_handle_t msg_win )
}
/* retrieve a posted message */
@ -141,7 +141,7 @@ index a65eab38bdc..bf315f5008c 100644
unsigned int first, unsigned int last, unsigned int flags,
struct get_message_reply *reply )
{
@@ -824,6 +834,7 @@ static int get_posted_message( struct msg_queue *queue, user_handle_t win,
@@ -872,6 +882,7 @@ static int get_posted_message( struct msg_queue *queue, user_handle_t win,
{
if (!match_window( win, msg->win )) continue;
if (!check_msg_filter( msg->msg, first, last )) continue;
@ -149,7 +149,7 @@ index a65eab38bdc..bf315f5008c 100644
goto found; /* found one */
}
return 0;
@@ -1439,6 +1450,7 @@ found:
@@ -1488,6 +1499,7 @@ found:
msg->msg = WM_HOTKEY;
msg->wparam = hotkey->id;
msg->lparam = ((hotkey->vkey & 0xffff) << 16) | modifiers;
@ -157,7 +157,7 @@ index a65eab38bdc..bf315f5008c 100644
free( msg->data );
msg->data = NULL;
@@ -2061,7 +2073,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user
@@ -2125,7 +2137,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user
continue;
}
/* now we can return it */
@ -166,7 +166,7 @@ index a65eab38bdc..bf315f5008c 100644
reply->type = MSG_HARDWARE;
reply->win = win;
reply->msg = msg_code;
@@ -2167,6 +2179,7 @@ void post_message( user_handle_t win, unsigned int message, lparam_t wparam, lpa
@@ -2231,6 +2243,7 @@ void post_message( user_handle_t win, unsigned int message, lparam_t wparam, lpa
msg->result = NULL;
msg->data = NULL;
msg->data_size = 0;
@ -174,7 +174,7 @@ index a65eab38bdc..bf315f5008c 100644
get_message_defaults( thread->queue, &msg->x, &msg->y, &msg->time );
@@ -2411,6 +2424,7 @@ DECL_HANDLER(send_message)
@@ -2475,6 +2488,7 @@ DECL_HANDLER(send_message)
set_queue_bits( recv_queue, QS_SENDMESSAGE );
break;
case MSG_POSTED:
@ -182,7 +182,7 @@ index a65eab38bdc..bf315f5008c 100644
list_add_tail( &recv_queue->msg_list[POST_MESSAGE], &msg->entry );
set_queue_bits( recv_queue, QS_POSTMESSAGE|QS_ALLPOSTMESSAGE );
if (msg->msg == WM_HOTKEY)
@@ -2531,12 +2545,12 @@ DECL_HANDLER(get_message)
@@ -2595,12 +2609,12 @@ DECL_HANDLER(get_message)
/* then check for posted messages */
if ((filter & QS_POSTMESSAGE) &&
@ -197,7 +197,7 @@ index a65eab38bdc..bf315f5008c 100644
return;
/* only check for quit messages if not posted messages pending */
@@ -2547,7 +2561,7 @@ DECL_HANDLER(get_message)
@@ -2611,7 +2625,7 @@ DECL_HANDLER(get_message)
if ((filter & QS_INPUT) &&
filter_contains_hw_range( req->get_first, req->get_last ) &&
get_hardware_message( current, req->hw_id, get_win, req->get_first, req->get_last, req->flags, reply ))
@ -206,7 +206,7 @@ index a65eab38bdc..bf315f5008c 100644
/* now check for WM_PAINT */
if ((filter & QS_PAINT) &&
@@ -2560,7 +2574,7 @@ DECL_HANDLER(get_message)
@@ -2624,7 +2638,7 @@ DECL_HANDLER(get_message)
reply->wparam = 0;
reply->lparam = 0;
get_message_defaults( queue, &reply->x, &reply->y, &reply->time );
@ -215,7 +215,7 @@ index a65eab38bdc..bf315f5008c 100644
}
/* now check for timer */
@@ -2576,13 +2590,30 @@ DECL_HANDLER(get_message)
@@ -2640,13 +2654,30 @@ DECL_HANDLER(get_message)
get_message_defaults( queue, &reply->x, &reply->y, &reply->time );
if (!(req->flags & PM_NOYIELD) && current->process->idle_event)
set_event( current->process->idle_event );
@ -247,7 +247,7 @@ index a65eab38bdc..bf315f5008c 100644
}
@@ -2600,7 +2631,10 @@ DECL_HANDLER(reply_message)
@@ -2664,7 +2695,10 @@ DECL_HANDLER(reply_message)
DECL_HANDLER(accept_hardware_message)
{
if (current->queue)
@ -259,5 +259,5 @@ index a65eab38bdc..bf315f5008c 100644
set_error( STATUS_ACCESS_DENIED );
}
--
2.27.0
2.30.2

View File

@ -1 +1,2 @@
Fixes: [28884] GetMessage should remove already seen messages with higher priority
Depends: server-Key_State