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

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


v3: Handle focus setting failure. This should fix some problems on the
testbot. d3d9 and d3d9ex do not need this change, the new tests work
fine there if the process is not in foreground.
---
 dlls/d3d8/tests/device.c | 119 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 105 insertions(+), 14 deletions(-)

diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c
index e066b77..a7c1001 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -2098,6 +2098,8 @@ struct message
 {
     UINT message;
     enum message_window window;
+    BOOL check_wparam;
+    WPARAM expect_wparam;
 };
 
 static const struct message *expect_messages;
@@ -2138,7 +2140,15 @@ 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);
@@ -2187,17 +2197,45 @@ 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[] =
-    {
-        {WM_WINDOWPOSCHANGING,  FOCUS_WINDOW},
-        {WM_ACTIVATE,           FOCUS_WINDOW},
-        {WM_SETFOCUS,           FOCUS_WINDOW},
-        {WM_WINDOWPOSCHANGING,  DEVICE_WINDOW},
-        {WM_MOVE,               DEVICE_WINDOW},
-        {WM_SIZE,               DEVICE_WINDOW},
+    static const struct message create_messages[] =
+    {
+        {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},
+        {WM_WINDOWPOSCHANGING,  DEVICE_WINDOW,  FALSE,  0},
+        {WM_MOVE,               DEVICE_WINDOW,  FALSE,  0},
+        {WM_SIZE,               DEVICE_WINDOW,  FALSE,  0},
         {0,                     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},
+    };
 
     d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
     ok(!!d3d8, "Failed to create a D3D object.\n");
@@ -2240,14 +2278,24 @@ static void test_wndproc(void)
                 thread_params.dummy_window, tmp);
     }
     else
+    {
+        /* This happens when the tests are run from a process that does not
+         * have focus, e.g. the testbot scripts. */
         skip("Not running in foreground, skip foreground window test\n");
+    }
 
     flush_events();
 
-    expect_messages = messages;
+    expect_messages = create_messages;
 
-    device = create_device(d3d8, 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(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
+            D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device)))
     {
         skip("Failed to create a D3D device, skipping tests.\n");
         goto done;
@@ -2267,8 +2315,6 @@ 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);
@@ -2277,6 +2323,51 @@ static void test_wndproc(void)
     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;
+    if (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",
+                (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);
+
+        /* 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();
+    }
+    else
+    {
+        skip("SetForegroundWindow failed, skipping focus loss tests.\n");
+        expect_messages = NULL;
+    }
+
+
+    filter_messages = focus_window;
+    hr = reset_device(device, device_window, FALSE);
+    ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
+
     ref = IDirect3DDevice8_Release(device);
     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
 
-- 
2.0.4




More information about the wine-patches mailing list