From 3599f956e2bfe3dd76d7134ddd06b1e5cf5be4d5 Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Tue, 5 May 2015 09:14:25 -0500 Subject: [PATCH] server: Fixup input windows on thread_detach. --- dlls/user32/tests/input.c | 80 +++++++++++++++++++++++++++++++++++++++++------ server/queue.c | 21 ++++++++++++- 2 files changed, 90 insertions(+), 11 deletions(-) diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 78f4d8b7bd7..30b91a06559 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -2028,6 +2028,12 @@ static void test_Input_mouse(void) static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { + if (message == WM_USER+1) + { + HWND hwnd = (HWND)lParam; + ok(GetFocus() == hwnd, "thread expected focus %p, got %p\n", hwnd, GetFocus()); + ok(GetActiveWindow() == hwnd, "thread expected active %p, got %p\n", hwnd, GetActiveWindow()); + } return DefWindowProcA(hwnd, message, wParam, lParam); } @@ -2067,7 +2073,7 @@ static DWORD WINAPI thread_proc(void *param) static void test_attach_input(void) { HANDLE hThread; - HWND ourWnd; + HWND ourWnd, Wnd2; DWORD ret, tid; struct wnd_event wnd_event; WNDCLASSA cls; @@ -2102,6 +2108,10 @@ static void test_attach_input(void) 0, 0, 0, 0, 0, 0, 0, NULL); ok(ourWnd!= 0, "failed to create ourWnd window\n"); + Wnd2 = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, + 0, 0, 0, 0, 0, 0, 0, NULL); + ok(Wnd2!= 0, "failed to create Wnd2 window\n"); + SetFocus(ourWnd); SetActiveWindow(ourWnd); @@ -2111,8 +2121,35 @@ static void test_attach_input(void) ok(GetActiveWindow() == ourWnd, "expected active %p, got %p\n", ourWnd, GetActiveWindow()); ok(GetFocus() == ourWnd, "expected focus %p, got %p\n", ourWnd, GetFocus()); + SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)ourWnd); + ret = AttachThreadInput(GetCurrentThreadId(), tid, FALSE); ok(ret, "AttachThreadInput error %d\n", GetLastError()); + ok(GetActiveWindow() == ourWnd, "expected active %p, got %p\n", ourWnd, GetActiveWindow()); + ok(GetFocus() == ourWnd, "expected focus %p, got %p\n", ourWnd, GetFocus()); + + SendMessageA(wnd_event.hwnd, WM_USER+1, 0, 0); + + ret = AttachThreadInput(GetCurrentThreadId(), tid, TRUE); + ok(ret, "AttachThreadInput error %d\n", GetLastError()); + + ok(GetActiveWindow() == ourWnd, "expected active %p, got %p\n", ourWnd, GetActiveWindow()); + ok(GetFocus() == ourWnd, "expected focus %p, got %p\n", ourWnd, GetFocus()); + SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)ourWnd); + + SetActiveWindow(Wnd2); + SetFocus(Wnd2); + ok(GetActiveWindow() == Wnd2, "expected active %p, got %p\n", Wnd2, GetActiveWindow()); + ok(GetFocus() == Wnd2, "expected focus %p, got %p\n", Wnd2, GetFocus()); + + SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)Wnd2); + + ret = AttachThreadInput(GetCurrentThreadId(), tid, FALSE); + ok(ret, "AttachThreadInput error %d\n", GetLastError()); + ok(GetActiveWindow() == Wnd2, "expected active %p, got %p\n", Wnd2, GetActiveWindow()); + ok(GetFocus() == Wnd2, "expected focus %p, got %p\n", Wnd2, GetFocus()); + + SendMessageA(wnd_event.hwnd, WM_USER+1, 0, 0); ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0); ok(ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError()); @@ -2122,11 +2159,6 @@ static void test_attach_input(void) wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL); wnd_event.setWindows = TRUE; - if (!wnd_event.start_event) - { - win_skip("skipping interthread message test under win9x\n"); - return; - } hThread = CreateThread(NULL, 0, thread_proc, &wnd_event, 0, &tid); ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError()); @@ -2134,10 +2166,6 @@ static void test_attach_input(void) ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); CloseHandle(wnd_event.start_event); - ourWnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW, - 100, 100, 200, 200, 0, 0, 0, NULL); - ok(ourWnd!= 0, "failed to create ourWnd window\n"); - SetFocus(ourWnd); SetActiveWindow(ourWnd); @@ -2147,14 +2175,46 @@ static void test_attach_input(void) ok(GetActiveWindow() == wnd_event.hwnd, "expected active %p, got %p\n", wnd_event.hwnd, GetActiveWindow()); ok(GetFocus() == wnd_event.hwnd, "expected focus %p, got %p\n", wnd_event.hwnd, GetFocus()); + SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)wnd_event.hwnd); + + ret = AttachThreadInput(GetCurrentThreadId(), tid, FALSE); + ok(ret, "AttachThreadInput error %d\n", GetLastError()); + + ok(GetActiveWindow() == 0, "expected active 0, got %p\n", GetActiveWindow()); + ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); + + SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)wnd_event.hwnd); + + ret = AttachThreadInput(GetCurrentThreadId(), tid, TRUE); + ok(ret, "AttachThreadInput error %d\n", GetLastError()); + + ok(GetActiveWindow() == wnd_event.hwnd, "expected active %p, got %p\n", wnd_event.hwnd, GetActiveWindow()); + ok(GetFocus() == wnd_event.hwnd, "expected focus %p, got %p\n", wnd_event.hwnd, GetFocus()); + + SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)wnd_event.hwnd); + + SetFocus(Wnd2); + SetActiveWindow(Wnd2); + ok(GetActiveWindow() == Wnd2, "expected active %p, got %p\n", Wnd2, GetActiveWindow()); + ok(GetFocus() == Wnd2, "expected focus %p, got %p\n", Wnd2, GetFocus()); + + SendMessageA(wnd_event.hwnd, WM_USER+1, 0, (LPARAM)Wnd2); + ret = AttachThreadInput(GetCurrentThreadId(), tid, FALSE); ok(ret, "AttachThreadInput error %d\n", GetLastError()); + ok(GetActiveWindow() == Wnd2, "expected active %p, got %p\n", Wnd2, GetActiveWindow()); + ok(GetFocus() == Wnd2, "expected focus %p, got %p\n", Wnd2, GetFocus()); + + SendMessageA(wnd_event.hwnd, WM_USER+1, 0, 0); + ret = PostMessageA(wnd_event.hwnd, WM_QUIT, 0, 0); ok(ret, "PostMessageA(WM_QUIT) error %d\n", GetLastError()); ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); CloseHandle(hThread); + DestroyWindow(ourWnd); + DestroyWindow(Wnd2); } START_TEST(input) diff --git a/server/queue.c b/server/queue.c index 350d45acfe7..30869a0c1cd 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1095,10 +1095,29 @@ int attach_thread_input( struct thread *thread_from, struct thread *thread_to ) /* detach two thread input data structures */ void detach_thread_input( struct thread *thread_from ) { - struct thread_input *input; + struct thread *thread; + struct thread_input *input, *old_input = thread_from->queue->input; if ((input = create_thread_input( thread_from ))) { + if (old_input->focus && (thread = get_window_thread( old_input->focus ))) + { + if (thread == thread_from) + { + input->focus = old_input->focus; + old_input->focus = 0; + } + release_object( thread ); + } + if (old_input->active && (thread = get_window_thread( old_input->active ))) + { + if (thread == thread_from) + { + input->active = old_input->active; + old_input->active = 0; + } + release_object( thread ); + } assign_thread_input( thread_from, input ); release_object( input ); } -- 2.11.4.GIT