From: "Gabriel Ivăncescu" Subject: [PATCH v7 4/6] d3d8/tests: Test for window changes when it's not foreground. Message-Id: <0d1d7cfa0a45aacb02bf32ee5da6d27a93ac9c71.1642524328.git.gabrielopcode@gmail.com> Date: Tue, 18 Jan 2022 18:50:28 +0200 In-Reply-To: <05381e8c5ffc4392318a3ba1c3664ac47def7e38.1642524328.git.gabrielopcode@gmail.com> References: <05381e8c5ffc4392318a3ba1c3664ac47def7e38.1642524328.git.gabrielopcode@gmail.com> Signed-off-by: Gabriel Ivăncescu --- Minimizing/restoring and setting foreground twice + waiting for thread msgs seems to work in all cases for testing, both on native and wine. dlls/d3d8/tests/device.c | 289 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 289 insertions(+) diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c index fc94dca..b565bc4 100644 --- a/dlls/d3d8/tests/device.c +++ b/dlls/d3d8/tests/device.c @@ -3935,16 +3935,50 @@ cleanup: DestroyWindow(hwnd); } +struct create_window_thread_params +{ + HANDLE event; + HWND hwnd; +}; + +static DWORD WINAPI create_window_thread(void *data) +{ + struct create_window_thread_params *params = data; + HWND hwnd; + MSG msg; + + hwnd = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 10, 20, 30, 40, 0, 0, 0, 0); + ok(!!hwnd, "Failed to create window.\n"); + flush_events(); + params->hwnd = hwnd; + SetEvent(params->event); + while (GetMessageA(&msg, 0, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessageA(&msg); + if (!params->hwnd) + break; + } + DestroyWindow(hwnd); + return 0; +} + static void test_window_style(void) { + struct create_window_thread_params thread_params; RECT focus_rect, fullscreen_rect, r; LONG device_style, device_exstyle; LONG focus_style, focus_exstyle; struct device_desc device_desc; LONG style, expected_style; IDirect3DDevice8 *device; + HWND active_window; IDirect3D8 *d3d8; + DWORD_PTR result; + HANDLE thread; HRESULT hr; + DWORD tid; ULONG ref; BOOL ret; @@ -4055,6 +4089,261 @@ static void test_window_style(void) ref = IDirect3DDevice8_Release(device); ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref); + DestroyWindow(device_window); + DestroyWindow(focus_window); + + /* Window changes are done only if the current process has the foreground window at creation */ + focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0); + device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0); + active_window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 10, 20, 30, 40, 0, 0, 0, 0); + + device_style = GetWindowLongA(device_window, GWL_STYLE); + device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE); + focus_style = GetWindowLongA(focus_window, GWL_STYLE); + focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE); + + ret = SetForegroundWindow(active_window); + ok(ret, "Failed to set foreground window.\n"); + ok(GetActiveWindow() == active_window, "Unexpected active window.\n"); + + device_desc.device_window = device_window; + device_desc.flags = CREATE_DEVICE_FULLSCREEN; + device = create_device(d3d8, focus_window, &device_desc); + ok(!!device, "Failed to create a D3D device.\n"); + + style = GetWindowLongA(device_window, GWL_STYLE); + todo_wine ok(style == device_style || broken(style == (device_style & ~WS_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window style %#x, got %#x.\n", device_style, style); + style = GetWindowLongA(device_window, GWL_EXSTYLE); + expected_style = device_exstyle | WS_EX_TOPMOST; + todo_wine ok(style == expected_style || broken(style == (expected_style & ~WS_EX_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window extended style %#x, got %#x.\n", expected_style, style); + + style = GetWindowLongA(focus_window, GWL_STYLE); + ok(style == focus_style, "Expected focus window style %#x, got %#x.\n", focus_style, style); + style = GetWindowLongA(focus_window, GWL_EXSTYLE); + ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n", focus_exstyle, style); + + device_desc.flags = 0; + hr = reset_device(device, &device_desc); + ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr); + + ret = SetForegroundWindow(GetDesktopWindow()); + ok(ret, "Failed to set foreground window.\n"); + device_desc.flags = CREATE_DEVICE_FULLSCREEN; + hr = reset_device(device, &device_desc); + ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr); + ShowWindow(device_window, SW_SHOWNOACTIVATE); + + style = GetWindowLongA(device_window, GWL_STYLE); + todo_wine ok(style == device_style || broken(style == (device_style & ~WS_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window style %#x, got %#x.\n", device_style, style); + style = GetWindowLongA(device_window, GWL_EXSTYLE); + expected_style = device_exstyle | WS_EX_TOPMOST; + todo_wine ok(style == expected_style || broken(style == (expected_style & ~WS_EX_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window extended style %#x, got %#x.\n", expected_style, style); + GetWindowRect(device_window, &r); + ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r)); + + ref = IDirect3DDevice8_Release(device); + ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref); + DestroyWindow(active_window); + DestroyWindow(device_window); + DestroyWindow(focus_window); + + focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0); + device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0); + + device_style = GetWindowLongA(device_window, GWL_STYLE); + device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE); + focus_style = GetWindowLongA(focus_window, GWL_STYLE); + focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE); + + thread_params.hwnd = NULL; + thread_params.event = CreateEventW(NULL, 0, 0, NULL); + ok(!!thread_params.event, "Failed to create event.\n"); + thread = CreateThread(NULL, 0, create_window_thread, &thread_params, 0, &tid); + ok(!!thread, "Failed to create thread.\n"); + ok(WaitForSingleObject(thread_params.event, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed.\n"); + ok(!!thread_params.hwnd, "Failed to create window in another thread.\n"); + CloseHandle(thread_params.event); + + /* Minimize and restore the other thread's window, otherwise native fails to + set the foreground window to it, even if it's done from the thread itself. */ + ShowWindow(thread_params.hwnd, SW_MINIMIZE); + ShowWindow(thread_params.hwnd, SW_RESTORE); + /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */ + SetForegroundWindow(thread_params.hwnd); + flush_events(); + SetForegroundWindow(thread_params.hwnd); + flush_events(); + /* Wait for thread to process all related messages */ + SendMessageTimeoutW(thread_params.hwnd, WM_NULL, 0, 0, 0, 2000, &result); + + SetActiveWindow(NULL); + ok(GetForegroundWindow() == thread_params.hwnd, "Unexpected foreground window.\n"); + + device_desc.device_window = device_window; + device_desc.flags = CREATE_DEVICE_FULLSCREEN; + device = create_device(d3d8, focus_window, &device_desc); + ok(!!device, "Failed to create a D3D device.\n"); + + style = GetWindowLongA(device_window, GWL_STYLE); + todo_wine ok(style == device_style || broken(style == (device_style & ~WS_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window style %#x, got %#x.\n", device_style, style); + style = GetWindowLongA(device_window, GWL_EXSTYLE); + expected_style = device_exstyle | WS_EX_TOPMOST; + todo_wine ok(style == expected_style || broken(style == (expected_style & ~WS_EX_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window extended style %#x, got %#x.\n", expected_style, style); + + style = GetWindowLongA(focus_window, GWL_STYLE); + ok(style == focus_style, "Expected focus window style %#x, got %#x.\n", focus_style, style); + style = GetWindowLongA(focus_window, GWL_EXSTYLE); + ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n", focus_exstyle, style); + + ref = IDirect3DDevice8_Release(device); + ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref); + thread_params.hwnd = NULL; + PostThreadMessageW(tid, WM_NULL, 0, 0); + DestroyWindow(device_window); + DestroyWindow(focus_window); + ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed.\n"); + CloseHandle(thread); + + focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0); + device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0); + + device_style = GetWindowLongA(device_window, GWL_STYLE); + device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE); + focus_style = GetWindowLongA(focus_window, GWL_STYLE); + focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE); + + ret = SetForegroundWindow(GetDesktopWindow()); + ok(ret, "Failed to set foreground window.\n"); + SetActiveWindow(focus_window); + ok(GetActiveWindow() == focus_window, "Unexpected active window.\n"); + + device_desc.device_window = device_window; + device_desc.flags = CREATE_DEVICE_FULLSCREEN; + device = create_device(d3d8, focus_window, &device_desc); + ok(!!device, "Failed to create a D3D device.\n"); + ShowWindow(device_window, SW_SHOWNOACTIVATE); + + /* Windows 8 and some versions of Windows 10 have some pretty + inconsistent behavior but topmost is set even when inactive. */ + style = GetWindowLongA(device_window, GWL_EXSTYLE); + if (broken(style & WS_EX_TOPMOST)) + { + win_skip("topmost set when inactive due to inconsistent behavior, skipping related tests...\n"); + goto skip_inactive; + } + todo_wine ok(style == device_exstyle || broken(style == (device_exstyle & ~WS_EX_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window extended style %#x, got %#x.\n", device_exstyle, style); + style = GetWindowLongA(device_window, GWL_STYLE); + todo_wine ok(style == device_style || broken(style == (device_style & ~WS_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window style %#x, got %#x.\n", device_style, style); + + style = GetWindowLongA(focus_window, GWL_STYLE); + ok(style == focus_style, "Expected focus window style %#x, got %#x.\n", focus_style, style); + style = GetWindowLongA(focus_window, GWL_EXSTYLE); + ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n", focus_exstyle, style); + + device_desc.flags = 0; + hr = reset_device(device, &device_desc); + ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr); + + ret = SetForegroundWindow(GetDesktopWindow()); + ok(ret, "Failed to set foreground window.\n"); + SetActiveWindow(focus_window); + ok(GetActiveWindow() == focus_window, "Unexpected active window."); + device_desc.flags = CREATE_DEVICE_FULLSCREEN; + hr = reset_device(device, &device_desc); + ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr); + + style = GetWindowLongA(device_window, GWL_STYLE); + todo_wine ok(style == device_style || broken(style == (device_style & ~WS_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window style %#x, got %#x.\n", device_style, style); + style = GetWindowLongA(device_window, GWL_EXSTYLE); + todo_wine ok(style == device_exstyle || broken(style == (device_exstyle & ~WS_EX_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window extended style %#x, got %#x.\n", device_exstyle, style); + GetWindowRect(device_window, &r); + ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r)); + + SetForegroundWindow(focus_window); + ok(ret, "Failed to set foreground window.\n"); + hr = reset_device(device, &device_desc); + ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr); + + style = GetWindowLongA(device_window, GWL_STYLE); + todo_wine ok(style == device_style || broken(style == (device_style & ~WS_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window style %#x, got %#x.\n", device_style, style); + style = GetWindowLongA(device_window, GWL_EXSTYLE); + todo_wine ok(style == device_exstyle || broken(style == (device_exstyle & ~WS_EX_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window extended style %#x, got %#x.\n", device_exstyle, style); + + device_desc.flags = 0; + hr = reset_device(device, &device_desc); + ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr); + + device_desc.flags = CREATE_DEVICE_FULLSCREEN; + hr = reset_device(device, &device_desc); + ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr); + + style = GetWindowLongA(device_window, GWL_STYLE); + todo_wine ok(style == device_style || broken(style == (device_style & ~WS_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window style %#x, got %#x.\n", device_style, style); + style = GetWindowLongA(device_window, GWL_EXSTYLE); + todo_wine ok(style == device_exstyle || broken(style == (device_exstyle & ~WS_EX_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window extended style %#x, got %#x.\n", device_exstyle, style); + + ref = IDirect3DDevice8_Release(device); + ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref); + DestroyWindow(device_window); + DestroyWindow(focus_window); + + focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0); + device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0); + + device_style = GetWindowLongA(device_window, GWL_STYLE); + device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE); + focus_style = GetWindowLongA(focus_window, GWL_STYLE); + focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE); + + ret = SetForegroundWindow(GetDesktopWindow()); + ok(ret, "Failed to set foreground window.\n"); + SetActiveWindow(device_window); + ok(GetActiveWindow() == device_window, "Unexpected active window.\n"); + + device_desc.device_window = device_window; + device_desc.flags = CREATE_DEVICE_FULLSCREEN; + device = create_device(d3d8, focus_window, &device_desc); + ok(!!device, "Failed to create a D3D device.\n"); + ShowWindow(device_window, SW_SHOWNOACTIVATE); + + style = GetWindowLongA(device_window, GWL_STYLE); + todo_wine ok(style == device_style || broken(style == (device_style & ~WS_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window style %#x, got %#x.\n", device_style, style); + style = GetWindowLongA(device_window, GWL_EXSTYLE); + todo_wine ok(style == device_exstyle || broken(style == (device_exstyle & ~WS_EX_OVERLAPPEDWINDOW)) /* w1064v1809 */, + "Expected device window extended style %#x, got %#x.\n", device_exstyle, style); + + style = GetWindowLongA(focus_window, GWL_STYLE); + ok(style == focus_style, "Expected focus window style %#x, got %#x.\n", focus_style, style); + style = GetWindowLongA(focus_window, GWL_EXSTYLE); + ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n", focus_exstyle, style); + +skip_inactive: + ref = IDirect3DDevice8_Release(device); + ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref); done: IDirect3D8_Release(d3d8); -- 2.34.1