[1/3] user32/tests: Add a test for calling SetWindowPos for other thread window. Resend.
Dmitry Timoshkov
dmitry at baikal.ru
Thu Apr 30 05:03:54 CDT 2015
This test shows that SetWindowPos is supposed to send all its messages from
the caller's thread causing every SendMessage perfom an inter-thread message
processing.
Testbot failures are not related to this patch.
---
dlls/user32/tests/msg.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 123 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index 5ef3840..f2ba805 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -14679,7 +14679,6 @@ static void test_SendMessage_other_thread(int thread_n)
hthread = CreateThread(NULL, 0, thread_n == 1 ? SendMessage_thread_1 : SendMessage_thread_2, &wnd_event, 0, &tid);
ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
- CloseHandle(hthread);
flush_events();
flush_sequence();
@@ -14747,6 +14746,125 @@ else
trace("main: call DestroyWindow\n");
DestroyWindow(msg.hwnd);
+ WaitForSingleObject(hthread, INFINITE);
+ CloseHandle(hthread);
+
+ flush_events();
+ flush_sequence();
+}
+
+static const struct message swp_1[] = {
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOACTIVATE },
+ { 0 }
+};
+static const struct message swp_2[] = {
+ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCLIENTSIZE },
+ { WM_MOVE, sent|defwinproc|wparam, 0 },
+ { WM_GETTEXT, sent|optional },
+ { WM_NCCALCSIZE, sent|optional },
+ { 0 }
+};
+
+static DWORD WINAPI SetWindowPos_thread(void *param)
+{
+ struct wnd_event *wnd_event = param;
+
+ trace("thread: starting\n");
+ WaitForSingleObject(wnd_event->start_event, INFINITE);
+
+ trace("thread: call SetWindowPos\n");
+ /* just move to avoid too complex message sequence, what matters is
+ * WM_WINDOWPOSCHANGING + WM_WINDOWPOSCHANGED sent from other thread.
+ */
+ SetWindowPos(wnd_event->hwnd, 0, -100, -100, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+ trace("thread: ret SetWindowPos\n");
+
+ return 0;
+}
+
+static void test_SetWindowPos_other_thread(void)
+{
+ DWORD qs_all_input = QS_ALLINPUT & ~QS_RAWINPUT;
+ HANDLE hthread;
+ struct wnd_event wnd_event;
+ DWORD tid, ret, timeout;
+ MSG msg;
+
+ wnd_event.start_event = CreateEventA(NULL, 0, 0, NULL);
+
+ wnd_event.hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
+ 100, 100, 200, 200, 0, 0, 0, NULL);
+ ok(wnd_event.hwnd != 0, "CreateWindowEx failed\n");
+
+ hthread = CreateThread(NULL, 0, SetWindowPos_thread, &wnd_event, 0, &tid);
+ ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
+
+ flush_events();
+ flush_sequence();
+
+ ret = GetQueueStatus(QS_SENDMESSAGE);
+ ok(ret == 0, "wrong status %08x\n", ret);
+
+ SetEvent(wnd_event.start_event);
+
+ /* wait for other thread's SendMessage */
+ timeout = 0;
+ for (;;)
+ {
+ ret = GetQueueStatus(QS_SENDMESSAGE);
+ if (ret == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE)) break;
+ Sleep(50);
+ timeout += 50;
+ if (timeout > 500)
+ {
+ ok(0, "time out waiting for SendMessage from other thread\n");
+ break;
+ }
+ }
+
+ ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE);
+ ok(ret == MAKELONG(0, QS_SENDMESSAGE), "wrong status %08x\n", ret);
+
+ trace("main: call PeekMessage\n");
+ ok(!PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should fail\n");
+ ok_sequence(swp_1, "SetWindowPos from other thread 1", TRUE);
+
+ /* wait for other thread's SendMessage */
+ timeout = 0;
+ for (;;)
+ {
+ ret = GetQueueStatus(QS_SENDMESSAGE);
+ if (ret == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE)) break;
+ Sleep(50);
+ timeout += 50;
+ if (timeout > 500)
+ {
+todo_wine
+ ok(0, "time out waiting for SendMessage from other thread\n");
+ break;
+ }
+ }
+
+ ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE);
+todo_wine
+ ok(ret == MAKELONG(0, QS_SENDMESSAGE), "wrong status %08x\n", ret);
+
+ trace("main: call PeekMessage\n");
+ ok(!PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should fail\n");
+ ok_sequence(swp_2, "SetWindowPos from other thread 2", TRUE);
+
+ /* intentionally yield */
+ MsgWaitForMultipleObjects(0, NULL, FALSE, 100, qs_all_input);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE);
+ ok(ret == 0, "wrong status %08x\n", ret);
+
+ trace("main: call DestroyWindow\n");
+ DestroyWindow(msg.hwnd);
+
+ WaitForSingleObject(hthread, INFINITE);
+ CloseHandle(hthread);
+
flush_events();
flush_sequence();
}
@@ -14890,6 +15008,10 @@ START_TEST(msg)
* which rely on active/foreground windows being correct.
*/
test_SetForegroundWindow();
+ /* calling SetWindowPos from other thread breaks window activation
+ * under Wine, so keep it here.
+ */
+ test_SetWindowPos_other_thread();
UnhookWindowsHookEx(hCBT_hook);
if (pUnhookWinEvent && hEvent_hook)
--
2.3.7
More information about the wine-patches
mailing list