From: Aric Stewart Subject: server: Do not replace focus and active windows with NULL on thread_attach_input Message-Id: <55353CA8.4010606@codeweavers.com> Date: Mon, 20 Apr 2015 12:51:36 -0500 --- dlls/user32/tests/input.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++ dlls/user32/tests/msg.c | 3 +- server/queue.c | 8 ++- 3 files changed, 142 insertions(+), 3 deletions(-) diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index faf9c8c..e7bf195 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -51,6 +51,7 @@ #include #include "windef.h" +#include "wingdi.h" #include "winbase.h" #include "winuser.h" @@ -2025,6 +2026,138 @@ static void test_Input_mouse(void) DestroyWindow(button_win); } + +static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + return DefWindowProcA(hwnd, message, wParam, lParam); +} + +struct wnd_event +{ + HWND hwnd; + HANDLE start_event; + BOOL setWindows; +}; + +static DWORD WINAPI thread_proc(void *param) +{ + MSG msg; + struct wnd_event *wnd_event = param; + + wnd_event->hwnd = CreateWindowExA(0, "TestWindowClass", "window caption text", WS_OVERLAPPEDWINDOW, + 100, 100, 200, 200, 0, 0, 0, NULL); + ok(wnd_event->hwnd != 0, "Failed to create overlapped window\n"); + + if (wnd_event->setWindows) + { + SetFocus(wnd_event->hwnd); + SetActiveWindow(wnd_event->hwnd); + } + + SetEvent(wnd_event->start_event); + + while (GetMessageA(&msg, 0, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessageA(&msg); + } + + return 0; +} + +static void test_attach_input(void) +{ + HANDLE hThread; + HWND ourWnd; + DWORD ret, tid; + struct wnd_event wnd_event; + WNDCLASSA cls; + + cls.style = 0; + cls.lpfnWndProc = MsgCheckProcA; + cls.cbClsExtra = 0; + cls.cbWndExtra = 0; + cls.hInstance = GetModuleHandleA(0); + cls.hIcon = 0; + cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); + cls.hbrBackground = GetStockObject(WHITE_BRUSH); + cls.lpszMenuName = NULL; + cls.lpszClassName = "TestWindowClass"; + if(!RegisterClassA(&cls)) return; + + wnd_event.start_event = CreateEventW(NULL, 0, 0, NULL); + wnd_event.setWindows = FALSE; + 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()); + + ok(WaitForSingleObject(wnd_event.start_event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); + CloseHandle(wnd_event.start_event); + + ourWnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, + 0, 0, 0, 0, 0, 0, 0, NULL); + ok(ourWnd!= 0, "failed to create ourWnd window\n"); + + SetFocus(ourWnd); + SetActiveWindow(ourWnd); + + 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()); + + ret = AttachThreadInput(GetCurrentThreadId(), tid, FALSE); + ok(ret, "AttachThreadInput error %d\n", GetLastError()); + + 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); + + 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()); + + 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); + + 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()); + + ret = AttachThreadInput(GetCurrentThreadId(), tid, FALSE); + ok(ret, "AttachThreadInput error %d\n", GetLastError()); + + 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); +} + START_TEST(input) { init_function_pointers(); @@ -2046,6 +2179,7 @@ START_TEST(input) test_get_async_key_state(); test_keyboard_layout_name(); test_key_names(); + test_attach_input(); if(pGetMouseMovePointsEx) test_GetMouseMovePointsEx(); diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index b014dd9..9b43aab 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -14238,10 +14238,9 @@ todo_wine ret = AttachThreadInput(GetCurrentThreadId(), tid, TRUE); ok(ret, "AttachThreadInput error %d\n", GetLastError()); -todo_wine { ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow()); ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus()); -} + flush_events(); flush_sequence(); diff --git a/server/queue.c b/server/queue.c index 3a321cd..c1f9fbd 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1048,7 +1048,7 @@ int init_thread_queue( struct thread *thread ) int attach_thread_input( struct thread *thread_from, struct thread *thread_to ) { struct desktop *desktop; - struct thread_input *input; + struct thread_input *input, *from_input; int ret; if (!thread_to->queue && !(thread_to->queue = create_msg_queue( thread_to, NULL ))) return 0; @@ -1063,6 +1063,12 @@ int attach_thread_input( struct thread *thread_from, struct thread *thread_to ) } release_object( desktop ); + from_input = (struct thread_input *)grab_object( thread_from->queue->input ); + if (!input->focus && from_input->focus) + input->focus = from_input->focus; + if (!input->active && from_input->active) + input->active = from_input->active; + ret = assign_thread_input( thread_from, input ); if (ret) memset( input->keystate, 0, sizeof(input->keystate) ); release_object( input );