From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/winstation.c | 12 ++++++++++-- server/protocol.def | 1 + server/queue.c | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index 41a4d63b54c..5ed08433b27 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -56,6 +56,7 @@ struct session_thread_data const shared_object_t *shared_desktop; /* thread desktop shared session cached object */ const shared_object_t *shared_queue; /* thread message queue shared session cached object */ struct shared_input_cache shared_input; /* current thread input shared session cached object */ + struct shared_input_cache shared_foreground; /* foreground thread input shared session cached object */ };
struct session_block @@ -286,7 +287,11 @@ static NTSTATUS try_get_shared_input( UINT tid, struct object_lock *lock, const }
/* check object validity by comparing ids, within the object seqlock */ - valid = cache->id == object->id; + if ((valid = cache->id == object->id) && !tid) + { + /* check that a previously locked foreground thread input is still foreground */ + valid = !!object->shm.input.foreground; + }
if (!lock->id || !shared_object_release_seqlock( object, lock->seq )) { @@ -309,6 +314,7 @@ NTSTATUS get_shared_input( UINT tid, struct object_lock *lock, const input_shm_t TRACE( "tid %u, lock %p, input_shm %p\n", tid, lock, input_shm );
if (tid == GetCurrentThreadId()) cache = &data->shared_input; + else if (!tid) cache = &data->shared_foreground; else return STATUS_INVALID_HANDLE;
do { status = try_get_shared_input( tid, lock, input_shm, cache ); } @@ -543,7 +549,9 @@ BOOL WINAPI NtUserSetThreadDesktop( HDESK handle ) if (ret) /* reset the desktop windows */ { struct user_thread_info *thread_info = get_user_thread_info(); - get_session_thread_data()->shared_desktop = find_shared_session_object( locator ); + struct session_thread_data *data = get_session_thread_data(); + data->shared_desktop = find_shared_session_object( locator ); + memset( &data->shared_foreground, 0, sizeof(data->shared_foreground) ); thread_info->client_info.top_window = 0; thread_info->client_info.msg_window = 0; if (was_virtual_desktop != is_virtual_desktop()) update_display_cache( FALSE ); diff --git a/server/protocol.def b/server/protocol.def index 5a1b30d4049..8002f3482ea 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -925,6 +925,7 @@ typedef volatile struct
typedef volatile struct { + int foreground; /* is desktop foreground thread input */ user_handle_t active; /* handle to the active window */ user_handle_t focus; /* handle to the focus window */ user_handle_t capture; /* handle to the capture window */ diff --git a/server/queue.c b/server/queue.c index ea3afc7cacf..a6908f0f384 100644 --- a/server/queue.c +++ b/server/queue.c @@ -275,6 +275,7 @@ static struct thread_input *create_thread_input( struct thread *thread )
SHARED_WRITE_BEGIN( input->shared, input_shm_t ) { + shared->foreground = 0; shared->active = 0; shared->focus = 0; shared->capture = 0; @@ -609,9 +610,26 @@ void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, unsig /* change the foreground input and reset the cursor clip rect */ static void set_foreground_input( struct desktop *desktop, struct thread_input *input ) { + const input_shm_t *input_shm, *old_input_shm, dummy_shm = {0}; + if (desktop->foreground_input == input) return; + input_shm = input ? input->shared : &dummy_shm; + old_input_shm = desktop->foreground_input ? desktop->foreground_input->shared : &dummy_shm; + set_clip_rectangle( desktop, NULL, SET_CURSOR_NOCLIP, 1 ); desktop->foreground_input = input; + + SHARED_WRITE_BEGIN( old_input_shm, input_shm_t ) + { + input_shm_t *old_shared = shared; + SHARED_WRITE_BEGIN( input_shm, input_shm_t ) + { + old_shared->foreground = 0; + shared->foreground = 1; + } + SHARED_WRITE_END; + } + SHARED_WRITE_END; }
/* get the hook table for a given thread */