Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
For some reason I had to use AttachThreadInput, otherwise I couldn't set the window to foreground on Windows, even from the thread itself, it always failed... I don't know why but apparently this is a common "trick" to get around it.
Also, for some reason GetForegroundWindow on wine returns NULL (when it's set to the other thread's window, even if set from the other thread), regardless of AttachThreadInput or not, so I had to mark it as todo_wine. :-/
dlls/d3d8/tests/device.c | 283 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 283 insertions(+)
diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c index fc94dca..d503241 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,255 @@ 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); + + AttachThreadInput(tid, GetCurrentThreadId(), TRUE); + ret = SetForegroundWindow(thread_params.hwnd); + ok(ret, "Failed to set foreground window.\n"); + AttachThreadInput(tid, GetCurrentThreadId(), FALSE); + SendMessageTimeoutW(thread_params.hwnd, WM_NULL, 0, 0, 0, 2000, &result); + + SetActiveWindow(NULL); + todo_wine 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);