[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