From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/user32/tests/input.c | 18 ++++---- server/queue.c | 89 ++++++++++----------------------------- 2 files changed, 33 insertions(+), 74 deletions(-) diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index a5d82885b91..c8576672324 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -4679,6 +4679,7 @@ struct test_AttachThreadInput_params DWORD attach_count; BOOL activate; HWND active_hwnd; + BOOL active_todo; }; static DWORD WINAPI test_AttachThreadInput_thread(void *param) @@ -4711,8 +4712,8 @@ static DWORD WINAPI test_AttachThreadInput_thread(void *param) { SetFocus( args->active_hwnd ); SetActiveWindow( args->active_hwnd ); - ok_ptr( GetActiveWindow(), ==, args->active_hwnd ); - ok_ptr( GetFocus(), ==, args->active_hwnd ); + todo_wine_if( args->active_todo ) ok_ptr( GetActiveWindow(), ==, args->active_hwnd ); + todo_wine_if( args->active_todo ) ok_ptr( GetFocus(), ==, args->active_hwnd ); } SetEvent( args->start_event ); @@ -4974,6 +4975,7 @@ static void test_AttachThreadInput(void) args2.attach_from = GetCurrentThreadId(); args2.attach_count = 2; args2.active_hwnd = args1.hwnd; + args2.active_todo = TRUE; thread2 = CreateThread( NULL, 0, test_AttachThreadInput_thread, &args2, 0, &tid2 ); ok_ptr( thread2, !=, NULL ); ok_ret( 0, WaitForSingleObject( args2.start_event, 5000 ) ); @@ -5003,8 +5005,8 @@ static void test_AttachThreadInput(void) for (UINT i = 0; i < 2; i++) { ok_ret( 1, AttachThreadInput( tid1, GetCurrentThreadId(), TRUE ) ); - ok_ptr( GetActiveWindow(), ==, args1.hwnd ); - ok_ptr( GetFocus(), ==, args1.hwnd ); + todo_wine ok_ptr( GetActiveWindow(), ==, args1.hwnd ); + todo_wine ok_ptr( GetFocus(), ==, args1.hwnd ); } memset( &args2, 0, sizeof(args2) ); @@ -5080,8 +5082,8 @@ static void test_AttachThreadInput(void) /* all threads are attached */ SetFocus( args1.hwnd ); SetActiveWindow( args1.hwnd ); - ok_ptr( GetActiveWindow(), ==, args1.hwnd ); - ok_ptr( GetFocus(), ==, args1.hwnd ); + todo_wine ok_ptr( GetActiveWindow(), ==, args1.hwnd ); + todo_wine ok_ptr( GetFocus(), ==, args1.hwnd ); SetFocus( args2.hwnd ); SetActiveWindow( args2.hwnd ); @@ -5117,8 +5119,8 @@ static void test_AttachThreadInput(void) ok_ret( 0, WaitForSingleObject( thread1, 5000 ) ); ok_ret( 1, CloseHandle( thread1 ) ); - todo_wine ok_ptr( GetActiveWindow(), ==, NULL ); - todo_wine ok_ptr( GetFocus(), ==, NULL ); + ok_ptr( GetActiveWindow(), ==, NULL ); + ok_ptr( GetFocus(), ==, NULL ); ok_ret( 1, PostMessageA( args3.hwnd, WM_QUIT, 0, 0 ) ); ok_ret( 0, WaitForSingleObject( thread3, 5000 ) ); diff --git a/server/queue.c b/server/queue.c index bbefd31a08e..cfc6e376e8d 100644 --- a/server/queue.c +++ b/server/queue.c @@ -375,9 +375,22 @@ static void unlock_input_keystate( struct thread_input *input ) static void assign_thread_input( struct msg_queue *queue, struct thread_input *new_input ) { struct thread_input *old_input = queue->input; + user_handle_t new_focus = 0, new_active = 0; + struct thread *owner; if (old_input == new_input) return; + if (old_input->shared->focus && (owner = get_window_thread( old_input->shared->focus ))) + { + new_focus = owner->queue == queue ? old_input->shared->focus : 0; + release_object( owner ); + } + if (old_input->shared->active && (owner = get_window_thread( old_input->shared->active ))) + { + new_active = owner->queue == queue ? old_input->shared->active : 0; + release_object( owner ); + } + SHARED_WRITE_BEGIN( old_input->shared, input_shm_t ) { input_shm_t *old_shared = shared; @@ -386,6 +399,11 @@ static void assign_thread_input( struct msg_queue *queue, struct thread_input *n { input_shm_t *new_shared = shared; + if (!new_shared->focus) new_shared->focus = new_focus; + if (new_focus) old_shared->focus = 0; + if (!new_shared->active) new_shared->active = new_active; + if (new_active) old_shared->active = 0; + new_shared->cursor_count += queue->cursor_count; old_shared->cursor_count -= queue->cursor_count; @@ -1385,78 +1403,17 @@ int init_thread_queue( struct thread *thread ) /* attach two thread input data structures */ void attach_thread_input( struct msg_queue *queue_from, struct msg_queue *queue_to ) { - struct thread_input *input, *old_input; - input_shm_t *old_input_shm, *input_shm; - - input = (struct thread_input *)grab_object( queue_to->input ); - - old_input = queue_from->input; - old_input_shm = old_input->shared; - input_shm = input->shared; - - SHARED_WRITE_BEGIN( input_shm, input_shm_t ) - { - if (!shared->active) shared->active = old_input_shm->active; - if (!shared->focus) shared->focus = old_input_shm->focus; - } - SHARED_WRITE_END; - - assign_thread_input( queue_from, input ); - - release_object( input ); + assign_thread_input( queue_from, queue_to->input ); } /* detach two thread input data structures */ void detach_thread_input( struct msg_queue *queue_from, struct desktop *desktop ) { - struct thread *thread; - struct thread_input *input, *old_input = queue_from->input; - - if ((input = create_thread_input( desktop ))) - { - input_shm_t *old_input_shm, *input_shm; - old_input_shm = old_input->shared; - input_shm = input->shared; + struct thread_input *input; - if (old_input_shm->focus && (thread = get_window_thread( old_input_shm->focus ))) - { - if (thread->queue == queue_from) - { - SHARED_WRITE_BEGIN( old_input_shm, input_shm_t ) - { - input_shm_t *old_shared = shared; - SHARED_WRITE_BEGIN( input_shm, input_shm_t ) - { - shared->focus = old_shared->focus; - old_shared->focus = 0; - } - SHARED_WRITE_END; - } - SHARED_WRITE_END; - } - release_object( thread ); - } - if (old_input_shm->active && (thread = get_window_thread( old_input_shm->active ))) - { - if (thread->queue == queue_from) - { - SHARED_WRITE_BEGIN( old_input_shm, input_shm_t ) - { - input_shm_t *old_shared = shared; - SHARED_WRITE_BEGIN( input_shm, input_shm_t ) - { - shared->active = old_shared->active; - old_shared->active = 0; - } - SHARED_WRITE_END; - } - SHARED_WRITE_END; - } - release_object( thread ); - } - assign_thread_input( queue_from, input ); - release_object( input ); - } + if (!(input = create_thread_input( desktop ))) return; + assign_thread_input( queue_from, input ); + release_object( input ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11670