From: Stefan Dösinger Subject: [PATCH 3/7] d3d9/tests: Test messages on focus loss (v3). Message-Id: <1412595782-19231-3-git-send-email-stefan@codeweavers.com> Date: Mon, 6 Oct 2014 13:42:58 +0200 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