mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Added patch to implement proper locking of keystate and synchronization with desktop thread.
This commit is contained in:
parent
513ca1f4ba
commit
8c17307f95
@ -38,9 +38,11 @@ Wine. All those differences are also documented on the
|
||||
Included bug fixes and improvements
|
||||
===================================
|
||||
|
||||
**Bugfixes and features included in the next upcoming release [1]:**
|
||||
**Bugfixes and features included in the next upcoming release [3]:**
|
||||
|
||||
* Fix caps lock state issues with multiple processes ([Wine Bug #35907](https://bugs.winehq.org/show_bug.cgi?id=35907))
|
||||
* Fix multithreading issues with fullscreen clipping ([Wine Bug #38087](https://bugs.winehq.org/show_bug.cgi?id=38087))
|
||||
* Implement locking and synchronization of key states ([Wine Bug #31899](https://bugs.winehq.org/show_bug.cgi?id=31899))
|
||||
|
||||
|
||||
**Bugs fixed in Wine Staging 1.7.38 [190]:**
|
||||
|
1
debian/changelog
vendored
1
debian/changelog
vendored
@ -2,6 +2,7 @@ wine-staging (1.7.39) UNRELEASED; urgency=low
|
||||
* Added patch for tests of RtlIpv6StringToAddress, RtlIpv{4,6}StringToAddressEx (by Mark Jansen).
|
||||
* Added patch to fix multithreading issues with fullscreen clipping.
|
||||
* Added patch with tests for VerQueryValueA (by Mark Jansen).
|
||||
* Added patch to implement proper locking of keystate and synchronization with desktop thread.
|
||||
* Removed patch to avoid hardcoded values for sizeof(GUID) (accepted upstream).
|
||||
-- Sebastian Lackner <sebastian@fds-team.de> Mon, 09 Mar 2015 16:52:35 +0100
|
||||
|
||||
|
@ -3537,14 +3537,18 @@ fi
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#27238] Fallback to global key state for threads without a queue
|
||||
# | * [#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-Fall-back-to-global-key-state-when-thread-doe.patch
|
||||
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
|
||||
(
|
||||
echo '+ { "Sebastian Lackner", "server: Fall back to global key state when thread doesn'\''t have a queue.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "server: Introduce a helper function to update the thread_input key state.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "server: Implement locking and synchronization of keystate buffer.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
|
@ -1,58 +0,0 @@
|
||||
From c908afaed01d4ca53ef66a7fb649402f9ae1a3d8 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Thu, 26 Feb 2015 04:23:28 +0100
|
||||
Subject: server: Fall back to global key state when thread doesn't have a
|
||||
queue.
|
||||
|
||||
---
|
||||
server/queue.c | 25 +++++++++++++------------
|
||||
1 file changed, 13 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/server/queue.c b/server/queue.c
|
||||
index 3a321cd..6cbf8e1 100644
|
||||
--- a/server/queue.c
|
||||
+++ b/server/queue.c
|
||||
@@ -2783,27 +2783,28 @@ DECL_HANDLER(get_key_state)
|
||||
struct desktop *desktop;
|
||||
data_size_t size = min( 256, get_reply_max_size() );
|
||||
|
||||
- if (!req->tid) /* get global async key state */
|
||||
- {
|
||||
- if (!(desktop = get_thread_desktop( current, 0 ))) return;
|
||||
- if (req->key >= 0)
|
||||
- {
|
||||
- reply->state = desktop->keystate[req->key & 0xff];
|
||||
- desktop->keystate[req->key & 0xff] &= ~0x40;
|
||||
- }
|
||||
- set_reply_data( desktop->keystate, size );
|
||||
- release_object( desktop );
|
||||
- }
|
||||
- else
|
||||
+ if (req->tid)
|
||||
{
|
||||
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];
|
||||
set_reply_data( thread->queue->input->keystate, size );
|
||||
+ release_object( thread );
|
||||
+ return;
|
||||
}
|
||||
release_object( thread );
|
||||
}
|
||||
+
|
||||
+ /* get global async key state */
|
||||
+ if (!(desktop = get_thread_desktop( current, 0 ))) return;
|
||||
+ if (req->key >= 0)
|
||||
+ {
|
||||
+ reply->state = desktop->keystate[req->key & 0xff];
|
||||
+ desktop->keystate[req->key & 0xff] &= ~0x40;
|
||||
+ }
|
||||
+ set_reply_data( desktop->keystate, size );
|
||||
+ release_object( desktop );
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
2.3.0
|
||||
|
@ -0,0 +1,88 @@
|
||||
From b575a8659eb9daa7af14c15f9f564a19e4b5dbd5 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Thu, 12 Mar 2015 00:44:25 +0100
|
||||
Subject: server: Introduce a helper function to update the thread_input key
|
||||
state.
|
||||
|
||||
---
|
||||
server/queue.c | 22 ++++++++++++++--------
|
||||
1 file changed, 14 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/server/queue.c b/server/queue.c
|
||||
index 3a321cd..85c0786 100644
|
||||
--- a/server/queue.c
|
||||
+++ b/server/queue.c
|
||||
@@ -1215,9 +1215,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,
|
||||
- const struct message *msg )
|
||||
+/* update the key state for a keyboard message */
|
||||
+static void update_key_state( struct desktop *desktop, unsigned char *keystate,
|
||||
+ const struct message *msg )
|
||||
{
|
||||
unsigned char key;
|
||||
int down = 0;
|
||||
@@ -1279,6 +1279,12 @@ static void update_input_key_state( struct desktop *desktop, unsigned char *keys
|
||||
}
|
||||
}
|
||||
|
||||
+/* update the thread input key state for a keyboard message */
|
||||
+static void update_input_key_state( struct thread_input *input, const struct message *msg )
|
||||
+{
|
||||
+ update_key_state( input->desktop, input->keystate, msg );
|
||||
+}
|
||||
+
|
||||
/* release the hardware message currently being processed by the given thread */
|
||||
static void release_hardware_message( struct msg_queue *queue, unsigned int hw_id,
|
||||
int remove )
|
||||
@@ -1309,7 +1315,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 );
|
||||
+ update_input_key_state( input, msg );
|
||||
list_remove( &msg->entry );
|
||||
free_message( msg );
|
||||
}
|
||||
@@ -1430,7 +1436,7 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg
|
||||
unsigned int msg_code;
|
||||
struct hardware_msg_data *data = msg->data;
|
||||
|
||||
- update_input_key_state( desktop, desktop->keystate, msg );
|
||||
+ update_key_state( desktop, desktop->keystate, msg );
|
||||
last_input_time = get_tick_count();
|
||||
if (msg->msg != WM_MOUSEMOVE) always_queue = 1;
|
||||
|
||||
@@ -1473,7 +1479,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 );
|
||||
+ if (input) update_input_key_state( input, msg );
|
||||
free_message( msg );
|
||||
return;
|
||||
}
|
||||
@@ -1911,7 +1917,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 );
|
||||
+ update_input_key_state( input, msg );
|
||||
list_remove( &msg->entry );
|
||||
free_message( msg );
|
||||
continue;
|
||||
@@ -1927,7 +1933,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 );
|
||||
+ update_input_key_state( input, msg );
|
||||
list_remove( &msg->entry );
|
||||
free_message( msg );
|
||||
}
|
||||
--
|
||||
2.3.1
|
||||
|
@ -0,0 +1,144 @@
|
||||
From 230ab0ec85f3f175396876907fed42ef285d0f64 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Thu, 12 Mar 2015 02:56:21 +0100
|
||||
Subject: server: Implement locking and synchronization of keystate buffer.
|
||||
|
||||
---
|
||||
server/queue.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 55 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/server/queue.c b/server/queue.c
|
||||
index 85c0786..426f626 100644
|
||||
--- a/server/queue.c
|
||||
+++ b/server/queue.c
|
||||
@@ -111,6 +111,7 @@ 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 */
|
||||
};
|
||||
|
||||
@@ -122,6 +123,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? */
|
||||
@@ -250,6 +252,7 @@ static struct thread_input *create_thread_input( struct thread *thread )
|
||||
input->cursor = 0;
|
||||
input->cursor_count = 0;
|
||||
list_init( &input->msg_list );
|
||||
+ input->lock_count = 0;
|
||||
set_caret_window( input, 0 );
|
||||
memset( input->keystate, 0, sizeof(input->keystate) );
|
||||
|
||||
@@ -282,6 +285,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;
|
||||
@@ -970,6 +974,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 );
|
||||
@@ -1279,9 +1284,22 @@ static void update_key_state( struct desktop *desktop, unsigned char *keystate,
|
||||
}
|
||||
}
|
||||
|
||||
+/* 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 *keystate = input->keystate;
|
||||
+ unsigned int i;
|
||||
+ for (i = 0; i < 256; i++)
|
||||
+ keystate[i] = input->desktop->keystate[i] & ~0x40;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* update the thread input key state for a keyboard message */
|
||||
static void update_input_key_state( struct thread_input *input, const struct message *msg )
|
||||
{
|
||||
+ synchronize_input_key_state( input );
|
||||
update_key_state( input->desktop, input->keystate, msg );
|
||||
}
|
||||
|
||||
@@ -1492,6 +1510,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) );
|
||||
}
|
||||
@@ -2363,6 +2390,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] )))
|
||||
{
|
||||
@@ -2802,13 +2836,33 @@ DECL_HANDLER(get_key_state)
|
||||
}
|
||||
else
|
||||
{
|
||||
+ unsigned char *keystate;
|
||||
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;
|
||||
}
|
||||
release_object( thread );
|
||||
+
|
||||
+ /* 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 );
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.3.1
|
||||
|
@ -1 +1,3 @@
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user