[PATCH 1/6] d3d9/tests: Test messages on focus loss (v2).
Stefan Dösinger
stefan at codeweavers.com
Mon Nov 17 14:17:20 CST 2014
Version 2: Fix test failures on focus-follows-mouse WMs. The particular
changes I made to do so:
*) Don't expect a WM_ACTIVATE message on the focus window. It's not
really related to the ShowWindow(SW_MINIMIZE) call d3d performs.
*) When restoring focus set it twice. This is needed to make KDE and
FVWM happy.
Resolution changing behavior will be tested in a separate patch.
---
dlls/d3d9/tests/d3d9ex.c | 286 +++++++++++++++++++++++++++++---------------
dlls/d3d9/tests/device.c | 302 ++++++++++++++++++++++++++++++++---------------
2 files changed, 393 insertions(+), 195 deletions(-)
diff --git a/dlls/d3d9/tests/d3d9ex.c b/dlls/d3d9/tests/d3d9ex.c
index bbb95b0..a43baa4 100644
--- a/dlls/d3d9/tests/d3d9ex.c
+++ b/dlls/d3d9/tests/d3d9ex.c
@@ -1702,6 +1702,8 @@ struct message
{
UINT message;
enum message_window window;
+ BOOL check_wparam;
+ WPARAM expect_wparam;
};
static const struct message *expect_messages;
@@ -1743,7 +1745,14 @@ static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM
};
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);
@@ -1795,13 +1804,58 @@ static void test_wndproc(void)
ULONG ref;
DWORD res, tid;
HWND tmp;
+ unsigned int i;
+ HRESULT hr;
- static const struct message messages[] =
+ 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},
+ {0, 0, FALSE, 0},
+ };
+ static const struct message focus_loss_messages[] =
+ {
+ /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
+ * not reliable on X11 WMs. When the window focus follows the
+ * mouse pointer the message is not sent.
+ * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
+ {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},
+ };
+ static const struct message focus_loss_messages_nowc[] =
+ {
+ /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
+ * not reliable on X11 WMs. When the window focus follows the
+ * mouse pointer the message is not sent.
+ * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
+ {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
+ {0, 0, FALSE, 0},
+ };
+ static const struct
+ {
+ DWORD create_flags;
+ const struct message *focus_loss_messages;
+ }
+ tests[] =
{
- {WM_WINDOWPOSCHANGING, FOCUS_WINDOW},
- {WM_ACTIVATE, FOCUS_WINDOW},
- {WM_SETFOCUS, FOCUS_WINDOW},
- {0, 0},
+ {0, focus_loss_messages},
+ {CREATE_DEVICE_NOWINDOWCHANGES, focus_loss_messages_nowc},
};
wc.lpfnWndProc = test_proc;
@@ -1813,121 +1867,159 @@ static void test_wndproc(void)
thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
- focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
- WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
- registry_mode.dmPelsHeight, 0, 0, 0, 0);
- device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
- WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
- registry_mode.dmPelsHeight, 0, 0, 0, 0);
- thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
- ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
-
- res = WaitForSingleObject(thread_params.window_created, INFINITE);
- ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
-
- 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);
-
- trace("device_window %p, focus_window %p, dummy_window %p.\n",
- device_window, focus_window, thread_params.dummy_window);
-
- tmp = GetFocus();
- ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
- if (thread_params.running_in_foreground)
+ for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
{
- tmp = GetForegroundWindow();
- ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
- thread_params.dummy_window, tmp);
- }
- else
- skip("Not running in foreground, skip foreground window test\n");
+ focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
+ WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
+ registry_mode.dmPelsHeight, 0, 0, 0, 0);
+ device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
+ WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
+ registry_mode.dmPelsHeight, 0, 0, 0, 0);
+ thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
+ ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
- flush_events();
+ res = WaitForSingleObject(thread_params.window_created, INFINITE);
+ ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
- expect_messages = messages;
+ 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);
- device_desc.device_window = device_window;
- device_desc.width = registry_mode.dmPelsWidth;
- device_desc.height = registry_mode.dmPelsHeight;
- device_desc.flags = CREATE_DEVICE_FULLSCREEN;
- if (!(device = create_device(focus_window, &device_desc)))
- {
- skip("Failed to create a D3D device, skipping tests.\n");
- goto done;
- }
-
- 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;
+ trace("device_window %p, focus_window %p, dummy_window %p.\n",
+ device_window, focus_window, thread_params.dummy_window);
- if (0) /* Disabled until we can make this work in a reliable way on Wine. */
- {
tmp = GetFocus();
- ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
- tmp = GetForegroundWindow();
- ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
- }
- SetForegroundWindow(focus_window);
- flush_events();
+ ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
+ if (thread_params.running_in_foreground)
+ {
+ tmp = GetForegroundWindow();
+ ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
+ thread_params.dummy_window, tmp);
+ }
+ else
+ skip("Not running in foreground, skip foreground window test\n");
- filter_messages = focus_window;
+ flush_events();
- proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
- ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
- (LONG_PTR)test_proc, proc);
+ expect_messages = create_messages;
- proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
- ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
+ device_desc.device_window = device_window;
+ device_desc.width = registry_mode.dmPelsWidth;
+ device_desc.height = registry_mode.dmPelsHeight;
+ device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].create_flags;
+ if (!(device = create_device(focus_window, &device_desc)))
+ {
+ skip("Failed to create a D3D device, skipping tests.\n");
+ goto done;
+ }
- ref = IDirect3DDevice9Ex_Release(device);
- ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
+ 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);
+ expect_messages = NULL;
- proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
- ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
- (LONG_PTR)test_proc, proc);
+ if (0) /* Disabled until we can make this work in a reliable way on Wine. */
+ {
+ tmp = GetFocus();
+ ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
+ tmp = GetForegroundWindow();
+ ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
+ }
+ SetForegroundWindow(focus_window);
+ flush_events();
+
+ 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.\n",
+ (LONG_PTR)test_proc);
+
+ expect_messages = tests[i].focus_loss_messages;
+ /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
+ * manually changing the focus. It generates the same messages, but the task
+ * bar still shows the previous foreground window as active, and the window has
+ * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
+ * the device is difficult, see below. */
+ 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);
+ expect_messages = NULL;
+ tmp = GetFocus();
+ ok(tmp != device_window, "The device window is active, i=%u.\n", i);
+ ok(tmp != focus_window, "The focus window is active, i=%u.\n", i);
+
+ hr = IDirect3DDevice9Ex_CheckDeviceState(device, device_window);
+ ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x, i=%u.\n", hr, i);
+
+ /* In d3d9ex the device and focus windows have to be minimized and restored,
+ * otherwise native does not notice that focus has been restored. This is
+ * independent of D3DCREATE_NOWINDOWCHANGES. */
+ ShowWindow(device_window, SW_MINIMIZE);
+ ShowWindow(device_window, SW_RESTORE);
+ ShowWindow(focus_window, SW_MINIMIZE);
+ ShowWindow(focus_window, SW_RESTORE);
+ /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
+ SetForegroundWindow(focus_window);
+ flush_events();
+ SetForegroundWindow(focus_window);
+ flush_events();
+
+ /* Calling Reset is not necessary in d3d9ex. */
+ hr = IDirect3DDevice9Ex_CheckDeviceState(device, device_window);
+ ok(hr == S_OK, "Got unexpected hr %#x, i=%u.\n", hr, i);
+
+ filter_messages = focus_window;
+ ref = IDirect3DDevice9Ex_Release(device);
+ ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
- 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;
- }
+ proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
+ ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
+ (LONG_PTR)test_proc, proc, i);
- ref = IDirect3DDevice9Ex_Release(device);
- ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
+ 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;
+ }
- device_desc.device_window = device_window;
- if (!(device = create_device(focus_window, &device_desc)))
- {
- skip("Failed to create a D3D device, skipping tests.\n");
- goto done;
- }
+ ref = IDirect3DDevice9Ex_Release(device);
+ ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
- proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
- ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
+ device_desc.device_window = device_window;
+ if (!(device = create_device(focus_window, &device_desc)))
+ {
+ skip("Failed to create a D3D device, skipping tests.\n");
+ goto done;
+ }
- ref = IDirect3DDevice9Ex_Release(device);
- ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
+ proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
+ ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n",
+ (LONG_PTR)test_proc);
- proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
- ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
- (LONG_PTR)DefWindowProcA, proc);
+ ref = IDirect3DDevice9Ex_Release(device);
+ ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
+
+ proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
+ ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
+ (LONG_PTR)DefWindowProcA, proc);
done:
- filter_messages = NULL;
+ filter_messages = NULL;
+ DestroyWindow(device_window);
+ DestroyWindow(focus_window);
+ SetEvent(thread_params.test_finished);
+ WaitForSingleObject(thread, INFINITE);
+ CloseHandle(thread);
+ }
- SetEvent(thread_params.test_finished);
- WaitForSingleObject(thread, INFINITE);
CloseHandle(thread_params.test_finished);
CloseHandle(thread_params.window_created);
- CloseHandle(thread);
- DestroyWindow(device_window);
- DestroyWindow(focus_window);
UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
}
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index 1a5008a..5ffcfdc 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -3091,6 +3091,8 @@ struct message
{
UINT message;
enum message_window window;
+ BOOL check_wparam;
+ WPARAM expect_wparam;
};
static const struct message *expect_messages;
@@ -3131,7 +3133,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);
@@ -3182,13 +3192,58 @@ static void test_wndproc(void)
ULONG ref;
DWORD res, tid;
HWND tmp;
+ unsigned int i;
+ 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 (wparam = WA_INACTIVE) is sent on Windows. It is
+ * not reliable on X11 WMs. When the window focus follows the
+ * mouse pointer the message is not sent.
+ * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
+ {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},
+ };
+ static const struct message focus_loss_messages_nowc[] =
+ {
+ /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
+ * not reliable on X11 WMs. When the window focus follows the
+ * mouse pointer the message is not sent.
+ * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
+ {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
+ {0, 0, FALSE, 0},
+ };
+ static const struct
+ {
+ DWORD create_flags;
+ const struct message *focus_loss_messages;
+ }
+ tests[] =
+ {
+ {0, focus_loss_messages},
+ {CREATE_DEVICE_NOWINDOWCHANGES, focus_loss_messages_nowc},
};
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
@@ -3203,122 +3258,171 @@ static void test_wndproc(void)
thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
- focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
- WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
- registry_mode.dmPelsHeight, 0, 0, 0, 0);
- device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
- WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
- registry_mode.dmPelsHeight, 0, 0, 0, 0);
- thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
- ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
+ for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
+ {
+ focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
+ WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
+ registry_mode.dmPelsHeight, 0, 0, 0, 0);
+ device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
+ WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
+ registry_mode.dmPelsHeight, 0, 0, 0, 0);
+ thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
+ ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
- res = WaitForSingleObject(thread_params.window_created, INFINITE);
- ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
+ res = WaitForSingleObject(thread_params.window_created, INFINITE);
+ ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
- 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);
+ 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);
- trace("device_window %p, focus_window %p, dummy_window %p.\n",
- device_window, focus_window, thread_params.dummy_window);
+ trace("device_window %p, focus_window %p, dummy_window %p.\n",
+ device_window, focus_window, thread_params.dummy_window);
- tmp = GetFocus();
- ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
- if (thread_params.running_in_foreground)
- {
- tmp = GetForegroundWindow();
- ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
- thread_params.dummy_window, tmp);
- }
- else
- skip("Not running in foreground, skip foreground window test\n");
+ tmp = GetFocus();
+ ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
+ if (thread_params.running_in_foreground)
+ {
+ tmp = GetForegroundWindow();
+ ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
+ thread_params.dummy_window, tmp);
+ }
+ else
+ skip("Not running in foreground, skip foreground window test\n");
- flush_events();
+ flush_events();
- expect_messages = messages;
+ expect_messages = create_messages;
- device_desc.device_window = device_window;
- device_desc.width = registry_mode.dmPelsWidth;
- device_desc.height = registry_mode.dmPelsHeight;
- device_desc.flags = CREATE_DEVICE_FULLSCREEN;
- if (!(device = create_device(d3d9, focus_window, &device_desc)))
- {
- skip("Failed to create a D3D device, skipping tests.\n");
- goto done;
- }
+ device_desc.device_window = device_window;
+ device_desc.width = registry_mode.dmPelsWidth;
+ device_desc.height = registry_mode.dmPelsHeight;
+ device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].create_flags;
+ if (!(device = create_device(d3d9, focus_window, &device_desc)))
+ {
+ skip("Failed to create a D3D device, skipping tests.\n");
+ goto done;
+ }
- 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;
+ 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);
+ expect_messages = NULL;
- if (0) /* Disabled until we can make this work in a reliable way on Wine. */
- {
+ if (0) /* Disabled until we can make this work in a reliable way on Wine. */
+ {
+ tmp = GetFocus();
+ ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
+ tmp = GetForegroundWindow();
+ ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
+ }
+ SetForegroundWindow(focus_window);
+ flush_events();
+
+ proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
+ ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
+ (LONG_PTR)test_proc, proc, i);
+
+ proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
+ ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
+ (LONG_PTR)test_proc, i);
+
+ expect_messages = tests[i].focus_loss_messages;
+ /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
+ * manually changing the focus. It generates the same messages, but the task
+ * bar still shows the previous foreground window as active, and the window has
+ * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
+ * the device is difficult, see below. */
+ 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);
+ expect_messages = NULL;
tmp = GetFocus();
- ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
- tmp = GetForegroundWindow();
- ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
- }
- SetForegroundWindow(focus_window);
- flush_events();
+ ok(tmp != device_window, "The device window is active, i=%u.\n", i);
+ ok(tmp != focus_window, "The focus window is active, i=%u.\n", i);
- filter_messages = focus_window;
+ hr = IDirect3DDevice9_TestCooperativeLevel(device);
+ ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
- proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
- ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
- (LONG_PTR)test_proc, proc);
+ /* This is needed on native with D3DCREATE_NOWINDOWCHANGES, and it needs to be
+ * done before the focus window is restored. This makes sense to some extent
+ * because minimizing the window on focus loss is the application's job if this
+ * flag is set. */
+ if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
+ {
+ ShowWindow(device_window, SW_MINIMIZE);
+ ShowWindow(device_window, SW_RESTORE);
+ }
- proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
- ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
+ /* I have to minimize and restore the focus window, otherwise native d3d9 fails
+ * device::reset with D3DERR_DEVICELOST. This does not happen when the window
+ * restore is triggered by the user. */
+ ShowWindow(focus_window, SW_MINIMIZE);
+ ShowWindow(focus_window, SW_RESTORE);
+ /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
+ SetForegroundWindow(focus_window);
+ flush_events();
+ SetForegroundWindow(focus_window);
+ flush_events();
+
+ hr = IDirect3DDevice9_TestCooperativeLevel(device);
+ ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
+
+ /* Releasing a device in lost state breaks follow-up tests on native. */
+ hr = reset_device(device, &device_desc);
+ ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, i=%u.\n", hr, i);
- ref = IDirect3DDevice9_Release(device);
- ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
+ filter_messages = focus_window;
- proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
- ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
- (LONG_PTR)test_proc, proc);
+ ref = IDirect3DDevice9_Release(device);
+ ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
- device_desc.device_window = focus_window;
- if (!(device = create_device(d3d9, focus_window, &device_desc)))
- {
- skip("Failed to create a D3D device, skipping tests.\n");
- goto done;
- }
+ proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
+ ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
+ (LONG_PTR)test_proc, proc, i);
- ref = IDirect3DDevice9_Release(device);
- ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
+ device_desc.device_window = focus_window;
+ if (!(device = create_device(d3d9, focus_window, &device_desc)))
+ {
+ skip("Failed to create a D3D device, skipping tests.\n");
+ goto done;
+ }
- device_desc.device_window = device_window;
- if (!(device = create_device(d3d9, focus_window, &device_desc)))
- {
- skip("Failed to create a D3D device, skipping tests.\n");
- goto done;
- }
+ ref = IDirect3DDevice9_Release(device);
+ ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
- proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
- ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
+ device_desc.device_window = device_window;
+ if (!(device = create_device(d3d9, focus_window, &device_desc)))
+ {
+ skip("Failed to create a D3D device, skipping tests.\n");
+ goto done;
+ }
- ref = IDirect3DDevice9_Release(device);
- ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
+ proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
+ ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
+ (LONG_PTR)test_proc, i);
- proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
- ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
- (LONG_PTR)DefWindowProcA, proc);
+ ref = IDirect3DDevice9_Release(device);
+ ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
+
+ proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
+ ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx, i=%u.\n",
+ (LONG_PTR)DefWindowProcA, proc, i);
done:
- filter_messages = NULL;
- IDirect3D9_Release(d3d9);
+ filter_messages = NULL;
+ DestroyWindow(device_window);
+ DestroyWindow(focus_window);
+ SetEvent(thread_params.test_finished);
+ WaitForSingleObject(thread, INFINITE);
+ CloseHandle(thread);
+ }
- SetEvent(thread_params.test_finished);
- WaitForSingleObject(thread, INFINITE);
+ IDirect3D9_Release(d3d9);
CloseHandle(thread_params.test_finished);
CloseHandle(thread_params.window_created);
- CloseHandle(thread);
-
- DestroyWindow(device_window);
- DestroyWindow(focus_window);
UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
}
@@ -3540,8 +3644,10 @@ static void test_reset_fullscreen(void)
struct device_desc device_desc;
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
More information about the wine-patches
mailing list