diff --git a/dlls/d3d9/tests/d3d9ex.c b/dlls/d3d9/tests/d3d9ex.c index 0ac9db712a9..e20740569de 100644 --- a/dlls/d3d9/tests/d3d9ex.c +++ b/dlls/d3d9/tests/d3d9ex.c @@ -1723,8 +1723,9 @@ struct message WPARAM expect_wparam; }; -static const struct message *expect_messages, *unexpected_messages; +static const struct message *expect_messages; static HWND device_window, focus_window; +static BOOL windowposchanged_received; struct wndproc_thread_param { @@ -1772,12 +1773,12 @@ static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM } } - if (unexpected_messages) - { - const struct message *i; - for (i = unexpected_messages; i->message; i++) - ok(i->message != message, "Got unexpected message %x on window %p.\n", message, hwnd); - } + /* KDE randomly does something with the hidden window during the + * mode change that sometimes generates a WM_WINDOWPOSCHANGING + * message. A WM_WINDOWPOSCHANGED message is not generated, so + * just flag WM_WINDOWPOSCHANGED as bad. */ + if (message == WM_WINDOWPOSCHANGED) + windowposchanged_received = TRUE; return DefWindowProcA(hwnd, message, wparam, lparam); } @@ -1887,24 +1888,26 @@ static void test_wndproc(void) {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE}, {0, 0, FALSE, 0}, }; - static const struct message focus_loss_messages_hidden_unexpected[] = + static const struct message focus_loss_messages_filtered[] = { - /* KDE randomly does something with the hidden window during the - * mode change that sometimes generates a WM_WINDOWPOSCHANGING - * message. A WM_WINDOWPOSCHANGED message is not generated, so - * just flag WM_WINDOWPOSCHANGED as bad. */ - {WM_WINDOWPOSCHANGED, 0, FALSE, 0}, + /* WM_ACTIVATE is delivered to the window proc because it is + * generated by SetForegroundWindow before the d3d routine + * starts it work. Don't check for it due to focus-follows-mouse + * WMs though. */ + {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0}, + {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE}, {0, 0, FALSE, 0}, }; static const struct { DWORD create_flags; const struct message *focus_loss_messages; + BOOL iconic; } tests[] = { - {0, focus_loss_messages}, - {CREATE_DEVICE_NOWINDOWCHANGES, focus_loss_messages_nowc}, + {0, focus_loss_messages, TRUE}, + {CREATE_DEVICE_NOWINDOWCHANGES, focus_loss_messages_nowc, FALSE}, }; hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex); @@ -2122,12 +2125,12 @@ static void test_wndproc(void) flush_events(); expect_messages = focus_loss_messages_hidden; - unexpected_messages = focus_loss_messages_hidden_unexpected; + windowposchanged_received = FALSE; SetForegroundWindow(GetDesktopWindow()); ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n", expect_messages->message, expect_messages->window, i); + ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i); expect_messages = NULL; - unexpected_messages = NULL; ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode); ok(ret, "Failed to get display mode.\n"); @@ -2152,13 +2155,47 @@ static void test_wndproc(void) ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n", (LONG_PTR)test_proc, proc, i); + /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent + * on native in the test below. It isn't needed anyways. Creating the third + * device will show it again. */ + filter_messages = NULL; + ShowWindow(device_window, SW_HIDE); + filter_messages = focus_window; + device_desc.device_window = focus_window; if (!(device = create_device(focus_window, &device_desc))) { skip("Failed to create a D3D device, skipping tests.\n"); goto done; } + filter_messages = NULL; + SetForegroundWindow(focus_window); /* For KDE. */ + flush_events(); + expect_messages = focus_loss_messages_filtered; + windowposchanged_received = FALSE; + SetForegroundWindow(GetDesktopWindow()); + ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n", + expect_messages->message, expect_messages->window, i); + if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES) + ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i); + else + todo_wine ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i); + expect_messages = NULL; + + /* The window is iconic even though no message was sent. */ + ok(!IsIconic(focus_window) == !tests[i].iconic, + "Expected IsIconic %u, got %u, i=%u.\n", tests[i].iconic, IsIconic(focus_window), i); + + /* This test can't activate, drop focus and restore focus like in plain d3d9 because d3d9ex + * immediately restores the device on activation. There are plenty of WM_WINDOWPOSCHANGED + * messages that are generated by ShowWindow, so testing for their absence is pointless. */ + ShowWindow(focus_window, SW_MINIMIZE); + ShowWindow(focus_window, SW_RESTORE); + SetForegroundWindow(focus_window); + flush_events(); + + filter_messages = focus_window; ref = IDirect3DDevice9Ex_Release(device); ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);