[PATCH 3/7] d3d9/tests: Test messages on focus loss (v3).

Stefan Dösinger stefan at codeweavers.com
Mon Oct 6 06:42:58 CDT 2014


v3: Ignore a wparam in test_reset_fullscreen that randomly misbehaves on
the testbot.

v2: Don't test wparam of WM_ACTIVATE during creation.

Windows reliably sends a WM_ACTIVATE message that indicates that the
minimized device window received focus, as if d3d9 used
SW_SHOWMINIMIZED instead of SW_MINIMIZE. Yet after the
SetForegroundWindow call the focus is NULL. I suspect this is because
windows handles nested activation calls differently than we do. I
decided to ignore the issue because none of the games I have seems to
care about the difference.
---
 dlls/d3d9/tests/device.c | 106 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 94 insertions(+), 12 deletions(-)

diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index f3771d9..0efa55f 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -3058,6 +3058,8 @@ struct message
 {
     UINT message;
     enum message_window window;
+    BOOL check_wparam;
+    WPARAM expect_wparam;
 };
 
 static const struct message *expect_messages;
@@ -3098,7 +3100,16 @@ static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM
                 break;
         };
 
-        if (hwnd == w && expect_messages->message == message) ++expect_messages;
+
+        if (hwnd == w && expect_messages->message == message)
+        {
+            if (expect_messages->check_wparam)
+                ok(wparam == expect_messages->expect_wparam,
+                        "Got unexpected wparam %lx for message %x, expected %lx.\n",
+                        wparam, message, expect_messages->expect_wparam);
+
+            ++expect_messages;
+        }
     }
 
     return DefWindowProcA(hwnd, message, wparam, lparam);
@@ -3147,13 +3158,41 @@ static void test_wndproc(void)
     ULONG ref;
     DWORD res, tid;
     HWND tmp;
+    D3DPRESENT_PARAMETERS present_parameters = {0};
+    DEVMODEW mode;
+    BOOL ret;
+    HRESULT hr;
 
-    static const struct message messages[] =
+    static const struct message create_messages[] =
     {
-        {WM_WINDOWPOSCHANGING,  FOCUS_WINDOW},
-        {WM_ACTIVATE,           FOCUS_WINDOW},
-        {WM_SETFOCUS,           FOCUS_WINDOW},
-        {0,                     0},
+        {WM_WINDOWPOSCHANGING,  FOCUS_WINDOW,   FALSE,  0},
+        /* Do not test wparam here. If device creation succeeds,
+         * wparam is WA_ACTIVE. If device creation fails (testbot)
+         * wparam is set to WA_INACTIVE on some Windows versions. */
+        {WM_ACTIVATE,           FOCUS_WINDOW,   FALSE,  0},
+        {WM_SETFOCUS,           FOCUS_WINDOW,   FALSE,  0},
+        {0,                     0,              FALSE,  0},
+    };
+    static const struct message focus_loss_messages[] =
+    {
+        {WM_ACTIVATE,           FOCUS_WINDOW,   TRUE,   WA_INACTIVE},
+        {WM_DISPLAYCHANGE,      DEVICE_WINDOW,  FALSE,  0},
+        /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
+         * not deterministic. */
+        {WM_WINDOWPOSCHANGING,  DEVICE_WINDOW,  FALSE,  0},
+        /* Windows sends WM_ACTIVATE to the device window, indicating that
+         * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
+         * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
+         * leaves the device window active, breaking re-activation in the
+         * lost device test.
+         * {WM_ACTIVATE,           DEVICE_WINDOW,  TRUE,   0x200000 | WA_ACTIVE}, */
+        {WM_WINDOWPOSCHANGED,   DEVICE_WINDOW,  FALSE,  0},
+        {WM_SIZE,               DEVICE_WINDOW,  TRUE,   SIZE_MINIMIZED},
+        {WM_ACTIVATEAPP,        FOCUS_WINDOW,   TRUE,   FALSE},
+        /* WM_ACTIVATEAPP is sent to the device window too, but the order is
+         * not deterministic. It may be sent after the focus window handling
+         * or before. */
+        {0,                     0,              FALSE,  0},
     };
 
     d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
@@ -3201,10 +3240,16 @@ static void test_wndproc(void)
 
     flush_events();
 
-    expect_messages = messages;
+    expect_messages = create_messages;
 
-    device = create_device(d3d9, device_window, focus_window, FALSE);
-    if (!device)
+    present_parameters.Windowed = FALSE;
+    present_parameters.hDeviceWindow = device_window;
+    present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+    present_parameters.BackBufferWidth = 640;
+    present_parameters.BackBufferHeight = 480;
+    present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
+    if (FAILED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
+            D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device)))
     {
         skip("Failed to create a D3D device, skipping tests.\n");
         goto done;
@@ -3224,7 +3269,30 @@ static void test_wndproc(void)
     SetForegroundWindow(focus_window);
     flush_events();
 
-    filter_messages = focus_window;
+    proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
+    ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
+            (LONG_PTR)test_proc, proc);
+
+    proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
+    ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
+            (LONG_PTR)test_proc, proc);
+
+    filter_messages = NULL;
+    expect_messages = focus_loss_messages;
+    SetForegroundWindow(GetDesktopWindow());
+    ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
+            expect_messages->message, expect_messages->window);
+    expect_messages = NULL;
+    tmp = GetFocus();
+    ok(tmp != device_window, "The device window is active.\n");
+    ok(tmp != focus_window, "The focus window is active.\n");
+
+    memset(&mode, 0, sizeof(mode));
+    mode.dmSize = sizeof(mode);
+    ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &mode);
+    ok(ret, "Failed to get display mode.\n");
+    ok(mode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", mode.dmPelsWidth);
+    ok(mode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", mode.dmPelsHeight);
 
     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
@@ -3234,6 +3302,18 @@ static void test_wndproc(void)
     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
             (LONG_PTR)test_proc, proc);
 
+    /* For some reason I have to minimize and restore the focus window,
+     * otherwise native d3d9 fails device::reset. This may be related
+     * to the WM_ACTIVATE message during focus loss. */
+    ShowWindow(focus_window, SW_MINIMIZE);
+    ShowWindow(focus_window, SW_RESTORE);
+    SetForegroundWindow(focus_window);
+    flush_events();
+
+    filter_messages = focus_window;
+    hr = reset_device(device, device_window, FALSE);
+    ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
+
     ref = IDirect3DDevice9_Release(device);
     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
 
@@ -3489,8 +3569,10 @@ static void test_reset_fullscreen(void)
     ATOM atom;
     static const struct message messages[] =
     {
-        {WM_ACTIVATEAPP,    FOCUS_WINDOW},
-        {0,                     0},
+        /* Windows usually sends wparam = TRUE, except on the testbot,
+         * where it randomly sends FALSE. Ignore it. */
+        {WM_ACTIVATEAPP,    FOCUS_WINDOW,   FALSE,  0},
+        {0,                 0,              FALSE,  0},
     };
 
     d3d = Direct3DCreate9(D3D_SDK_VERSION);
-- 
2.0.4




More information about the wine-patches mailing list