Signed-off-by: Stefan Dösinger stefan@codeweavers.com
---
The only new bit of information here is the WM_KILLFOCUS message. The rest is already covered by the focus loss test, but it is (a) helpful to make the two window changes explicit and (b) it will serve as a place to check the state of the DirectDraw object during the focus loss sequence. --- dlls/ddraw/tests/ddraw1.c | 6 +++++- dlls/ddraw/tests/ddraw2.c | 6 +++++- dlls/ddraw/tests/ddraw4.c | 6 +++++- dlls/ddraw/tests/ddraw7.c | 6 +++++- 4 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c index ee4fa5bfaab..aad7bbff1f4 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c @@ -2447,8 +2447,12 @@ static void test_coop_level_mode_set(void) static const struct message exclusive_focus_loss_messages[] = { {WM_ACTIVATE, TRUE, WA_INACTIVE}, + {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window resize due to mode change. */ + {WM_WINDOWPOSCHANGED, FALSE, 0}, + {WM_SIZE, TRUE, SIZE_RESTORED}, /* Generated by DefWindowProc. */ {WM_DISPLAYCHANGE, FALSE, 0}, - {WM_WINDOWPOSCHANGING, FALSE, 0}, + {WM_KILLFOCUS, FALSE, 0}, + {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window minimized. */ /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of * SW_MINIMIZED, causing a recursive window activation that does not * produce the same result in Wine yet. Ignore the difference for now. diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index 9394705330a..29c3c845cb1 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -2572,8 +2572,12 @@ static void test_coop_level_mode_set(void) static const struct message exclusive_focus_loss_messages[] = { {WM_ACTIVATE, TRUE, WA_INACTIVE}, + {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window resize due to mode change. */ + {WM_WINDOWPOSCHANGED, FALSE, 0}, + {WM_SIZE, TRUE, SIZE_RESTORED}, /* Generated by DefWindowProc. */ {WM_DISPLAYCHANGE, FALSE, 0}, - {WM_WINDOWPOSCHANGING, FALSE, 0}, + {WM_KILLFOCUS, FALSE, 0}, + {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window minimized. */ /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of * SW_MINIMIZED, causing a recursive window activation that does not * produce the same result in Wine yet. Ignore the difference for now. diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index 6a3630a2c0e..7cf61cea911 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -2713,8 +2713,12 @@ static void test_coop_level_mode_set(void) static const struct message exclusive_focus_loss_messages[] = { {WM_ACTIVATE, TRUE, WA_INACTIVE}, + {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window resize due to mode change. */ + {WM_WINDOWPOSCHANGED, FALSE, 0}, + {WM_SIZE, TRUE, SIZE_RESTORED}, /* Generated by DefWindowProc. */ {WM_DISPLAYCHANGE, FALSE, 0}, - {WM_WINDOWPOSCHANGING, FALSE, 0}, + {WM_KILLFOCUS, FALSE, 0}, + {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window minimized. */ /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of * SW_MINIMIZED, causing a recursive window activation that does not * produce the same result in Wine yet. Ignore the difference for now. diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 5bb2951cee7..6ae4207b34b 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -2442,8 +2442,12 @@ static void test_coop_level_mode_set(void) static const struct message exclusive_focus_loss_messages[] = { {WM_ACTIVATE, TRUE, WA_INACTIVE}, + {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window resize due to mode change. */ + {WM_WINDOWPOSCHANGED, FALSE, 0}, + {WM_SIZE, TRUE, SIZE_RESTORED}, /* Generated by DefWindowProc. */ {WM_DISPLAYCHANGE, FALSE, 0}, - {WM_WINDOWPOSCHANGING, FALSE, 0}, + {WM_KILLFOCUS, FALSE, 0}, + {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window minimized. */ /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of * SW_MINIMIZED, causing a recursive window activation that does not * produce the same result in Wine yet. Ignore the difference for now.
This fixes tabbing out of Deus Ex Game of the Year edition.
Signed-off-by: Stefan Dösinger stefan@codeweavers.com
---
This patch ignores that d3d9 has different behavior than ddraw. D3d9's behavior matches what we currently have (the device state during focus loss is D3DERR_DEVICENOTRESET, and only the final WM_ACTIVATEAPP message has D3DERR_DEVICELOST). This could be handled via a create flag. I am not doing it for now because I think it is less likely for a d3d9 app to depend on it (you can't destroy the device until the very end, but still can't do anything due to D3DERR_DEVICENOTRESET). --- dlls/wined3d/device.c | 2 -- dlls/wined3d/swapchain.c | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index abb2a893637..70d43e07e39 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -5319,8 +5319,6 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL
for (i = 0; i < device->swapchain_count; i++) wined3d_swapchain_activate(device->swapchains[i], wparam); - - device->device_parent->ops->activate(device->device_parent, wparam); } else if (message == WM_SYSCOMMAND) { diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index b068cf164cd..9c48de2193c 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -1162,6 +1162,9 @@ void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activa device->adapter->ordinal, &swapchain->d3d_mode))) ERR("Failed to set display mode.\n"); } + + if (swapchain == device->swapchains[0]) + device->device_parent->ops->activate(device->device_parent, TRUE); } else { @@ -1171,6 +1174,17 @@ void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activa
swapchain->reapply_mode = TRUE;
+ /* Some DDraw apps (Deus Ex: GOTY, and presumably all UT 1 based games) destroy the device + * during window minimization. Do our housekeeping now, as the device may not exist after + * the ShowWindow call. + * + * In d3d9, the device is marked lost after the window is minimized. If we find an app + * that needs this behavior (e.g. because it calls TestCooperativeLevel in the window proc) + * we'll have to control this via a create flag. Note that the device and swapchain are not + * safe to access after the ShowWindow call. */ + if (swapchain == device->swapchains[0]) + device->device_parent->ops->activate(device->device_parent, FALSE); + if (!(device->create_parms.flags & WINED3DCREATE_NOWINDOWCHANGES) && IsWindowVisible(swapchain->device_window)) ShowWindow(swapchain->device_window, SW_MINIMIZE);
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Stefan Dösinger stefan@codeweavers.com --- dlls/wined3d/swapchain.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 9c48de2193c..5cca4be9775 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -1132,13 +1132,15 @@ void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activa { struct wined3d_device *device = swapchain->device; BOOL filter_messages = device->filter_messages; + BOOL focus_messages = device->wined3d->flags & WINED3D_FOCUS_MESSAGES;
/* This code is not protected by the wined3d mutex, so it may run while * wined3d_device_reset is active. Testing on Windows shows that changing * focus during resets and resetting during focus change events causes * the application to crash with an invalid memory access. */
- device->filter_messages = !(device->wined3d->flags & WINED3D_FOCUS_MESSAGES); + if (!focus_messages) + device->filter_messages = 1;
if (activate) { @@ -1190,7 +1192,8 @@ void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activa ShowWindow(swapchain->device_window, SW_MINIMIZE); }
- device->filter_messages = filter_messages; + if (!focus_messages) + device->filter_messages = filter_messages; }
HRESULT CDECL wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapchain, unsigned int buffer_count,
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Stefan Dösinger stefan@codeweavers.com
---
During focus restore the state differs between Windows versions.
The primary surface is lost before the first WM_DISPLAYCHANGED message is delivered. I am not testing this here because we change the display mode before we drop focus, to test if ddraw restores the mode. I would have to add another mode switch cycle to document the surface loss behavior, which I prefer not to do until we have an application that is picky about it.
On a sidenode, it seems that DDERR_SURFACELOST is picked up without any messages. If I hide all messages from ddraw by replacing the WNDPROC the primary still gets lost. The focus loss needs the WM_ACTIVATEAPP message though. If I hide that message, weird things happen. --- dlls/ddraw/tests/ddraw4.c | 38 ++++++++++++++++++++++++++------------ dlls/ddraw/tests/ddraw7.c | 38 ++++++++++++++++++++++++++------------ 2 files changed, 52 insertions(+), 24 deletions(-)
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index 7cf61cea911..3aae42554f2 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -532,12 +532,16 @@ struct message UINT message; BOOL check_wparam; WPARAM expect_wparam; + HRESULT ddraw_state; };
static const struct message *expect_messages; +static IDirectDraw4 *focus_test_ddraw;
static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { + HRESULT hr; + if (expect_messages && message == expect_messages->message) { if (expect_messages->check_wparam) @@ -545,6 +549,13 @@ static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM "Got unexpected wparam %lx for message %x, expected %lx.\n", wparam, message, expect_messages->expect_wparam);
+ if (focus_test_ddraw) + { + hr = IDirectDraw4_TestCooperativeLevel(focus_test_ddraw); + ok(hr == expect_messages->ddraw_state, "Got ddraw state %#x on message %#x, expected %#x.\n", + hr, message, expect_messages->ddraw_state); + } + ++expect_messages; }
@@ -2712,22 +2723,22 @@ static void test_coop_level_mode_set(void) }; static const struct message exclusive_focus_loss_messages[] = { - {WM_ACTIVATE, TRUE, WA_INACTIVE}, - {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window resize due to mode change. */ - {WM_WINDOWPOSCHANGED, FALSE, 0}, - {WM_SIZE, TRUE, SIZE_RESTORED}, /* Generated by DefWindowProc. */ - {WM_DISPLAYCHANGE, FALSE, 0}, - {WM_KILLFOCUS, FALSE, 0}, - {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window minimized. */ + {WM_ACTIVATE, TRUE, WA_INACTIVE, DD_OK}, + {WM_WINDOWPOSCHANGING, FALSE, 0, DD_OK}, /* Window resize due to mode change. */ + {WM_WINDOWPOSCHANGED, FALSE, 0, DD_OK}, + {WM_SIZE, TRUE, SIZE_RESTORED, DD_OK}, /* Generated by DefWindowProc. */ + {WM_DISPLAYCHANGE, FALSE, 0, DD_OK}, + {WM_KILLFOCUS, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, + {WM_WINDOWPOSCHANGING, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, /* Window minimized. */ /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of * SW_MINIMIZED, causing a recursive window activation that does not * produce the same result in Wine yet. Ignore the difference for now. * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */ - {WM_WINDOWPOSCHANGED, FALSE, 0}, - {WM_MOVE, FALSE, 0}, - {WM_SIZE, TRUE, SIZE_MINIMIZED}, - {WM_ACTIVATEAPP, TRUE, FALSE}, - {0, FALSE, 0}, + {WM_WINDOWPOSCHANGED, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, + {WM_MOVE, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, + {WM_SIZE, TRUE, SIZE_MINIMIZED, DDERR_NOEXCLUSIVEMODE}, + {WM_ACTIVATEAPP, TRUE, FALSE, DDERR_NOEXCLUSIVEMODE}, + {0, FALSE, 0, 0}, }; static const struct message exclusive_focus_restore_messages[] = { @@ -2912,9 +2923,12 @@ static void test_coop_level_mode_set(void) wine_dbgstr_rect(&r));
expect_messages = exclusive_focus_loss_messages; + focus_test_ddraw = ddraw; ret = SetForegroundWindow(GetDesktopWindow()); ok(ret, "Failed to set foreground window.\n"); ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message); + focus_test_ddraw = NULL; + memset(&devmode, 0, sizeof(devmode)); devmode.dmSize = sizeof(devmode); ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode); diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 6ae4207b34b..4691135186b 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -448,12 +448,16 @@ struct message UINT message; BOOL check_wparam; WPARAM expect_wparam; + HRESULT ddraw_state; };
static const struct message *expect_messages; +static IDirectDraw7 *focus_test_ddraw;
static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { + HRESULT hr; + if (expect_messages && message == expect_messages->message) { if (expect_messages->check_wparam) @@ -461,6 +465,13 @@ static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM "Got unexpected wparam %lx for message %x, expected %lx.\n", wparam, message, expect_messages->expect_wparam);
+ if (focus_test_ddraw) + { + hr = IDirectDraw7_TestCooperativeLevel(focus_test_ddraw); + ok(hr == expect_messages->ddraw_state, "Got ddraw state %#x on message %#x, expected %#x.\n", + hr, message, expect_messages->ddraw_state); + } + ++expect_messages; }
@@ -2441,22 +2452,22 @@ static void test_coop_level_mode_set(void) }; static const struct message exclusive_focus_loss_messages[] = { - {WM_ACTIVATE, TRUE, WA_INACTIVE}, - {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window resize due to mode change. */ - {WM_WINDOWPOSCHANGED, FALSE, 0}, - {WM_SIZE, TRUE, SIZE_RESTORED}, /* Generated by DefWindowProc. */ - {WM_DISPLAYCHANGE, FALSE, 0}, - {WM_KILLFOCUS, FALSE, 0}, - {WM_WINDOWPOSCHANGING, FALSE, 0}, /* Window minimized. */ + {WM_ACTIVATE, TRUE, WA_INACTIVE, DD_OK}, + {WM_WINDOWPOSCHANGING, FALSE, 0, DD_OK}, /* Window resize due to mode change. */ + {WM_WINDOWPOSCHANGED, FALSE, 0, DD_OK}, + {WM_SIZE, TRUE, SIZE_RESTORED, DD_OK}, /* Generated by DefWindowProc. */ + {WM_DISPLAYCHANGE, FALSE, 0, DD_OK}, + {WM_KILLFOCUS, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, + {WM_WINDOWPOSCHANGING, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, /* Window minimized. */ /* Like d3d8 and d3d9 ddraw seems to use SW_SHOWMINIMIZED instead of * SW_MINIMIZED, causing a recursive window activation that does not * produce the same result in Wine yet. Ignore the difference for now. * {WM_ACTIVATE, TRUE, 0x200000 | WA_ACTIVE}, */ - {WM_WINDOWPOSCHANGED, FALSE, 0}, - {WM_MOVE, FALSE, 0}, - {WM_SIZE, TRUE, SIZE_MINIMIZED}, - {WM_ACTIVATEAPP, TRUE, FALSE}, - {0, FALSE, 0}, + {WM_WINDOWPOSCHANGED, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, + {WM_MOVE, FALSE, 0, DDERR_NOEXCLUSIVEMODE}, + {WM_SIZE, TRUE, SIZE_MINIMIZED, DDERR_NOEXCLUSIVEMODE}, + {WM_ACTIVATEAPP, TRUE, FALSE, DDERR_NOEXCLUSIVEMODE}, + {0, FALSE, 0, 0}, }; static const struct message exclusive_focus_restore_messages[] = { @@ -2641,9 +2652,12 @@ static void test_coop_level_mode_set(void) wine_dbgstr_rect(&r));
expect_messages = exclusive_focus_loss_messages; + focus_test_ddraw = ddraw; ret = SetForegroundWindow(GetDesktopWindow()); ok(ret, "Failed to set foreground window.\n"); ok(!expect_messages->message, "Expected message %#x, but didn't receive it.\n", expect_messages->message); + focus_test_ddraw = NULL; + memset(&devmode, 0, sizeof(devmode)); devmode.dmSize = sizeof(devmode); ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=43112
Your paranoid android.
=== wvistau64_he (32 bit Windows report) ===
ddraw: ddraw4.c:2990: Test failed: Expected message 0x46, but didn't receive it. ddraw4.c:2992: Test failed: Expected screen size 1024x768, got 0x0. ddraw4.c:2998: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3028: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3035: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3061: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3084: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3106: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3132: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3152: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3188: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3198: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3224: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3247: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3269: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3295: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3315: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw4.c:3352: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746).
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Stefan Dösinger stefan@codeweavers.com --- dlls/d3d8/tests/device.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c index 6bae783644a..5c4e5b96659 100644 --- a/dlls/d3d8/tests/device.c +++ b/dlls/d3d8/tests/device.c @@ -2435,12 +2435,14 @@ struct message enum message_window window; BOOL check_wparam; WPARAM expect_wparam; + HRESULT device_state; WINDOWPOS *store_wp; };
static const struct message *expect_messages; static HWND device_window, focus_window; static LONG windowposchanged_received, syscommand_received; +static IDirect3DDevice8 *focus_test_device;
struct wndproc_thread_param { @@ -2452,6 +2454,8 @@ struct wndproc_thread_param
static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { + HRESULT hr; + if (filter_messages && filter_messages == hwnd) { if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY) @@ -2487,6 +2491,18 @@ static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM if (expect_messages->store_wp) *expect_messages->store_wp = *(WINDOWPOS *)lparam;
+ if (focus_test_device) + { + hr = IDirect3DDevice8_TestCooperativeLevel(focus_test_device); + /* Wined3d marks the device lost earlier than Windows (it follows ddraw + * behavior. See test_wndproc before the focus_loss_messages sequence + * about the D3DERR_DEVICENOTRESET behavior, */ + todo_wine_if(message != WM_ACTIVATEAPP || hr == D3D_OK) + ok(hr == expect_messages->device_state, + "Got device state %#x on message %#x, expected %#x.\n", + hr, message, expect_messages->device_state); + } + ++expect_messages; } } @@ -2576,23 +2592,24 @@ static void test_wndproc(void) * 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_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0}, + {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET}, /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is * not deterministic. */ - {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0}, + {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET}, /* 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_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET}, + {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED, + D3DERR_DEVICENOTRESET}, + {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE, D3DERR_DEVICELOST}, /* 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}, + {0, 0, FALSE, 0, 0}, }; static const struct message reactivate_messages[] = { @@ -2673,7 +2690,7 @@ static void test_wndproc(void) {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0}, {WM_SIZE, DEVICE_WINDOW, FALSE, 0}, {WM_SHOWWINDOW, DEVICE_WINDOW, FALSE, 0}, - {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, &windowpos}, + {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, ~0U, &windowpos}, {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0}, /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is * differs between Wine and Windows. */ @@ -2832,6 +2849,7 @@ static void test_wndproc(void) ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
expect_messages = focus_loss_messages; + focus_test_device = device; /* 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 @@ -2844,6 +2862,7 @@ static void test_wndproc(void) tmp = GetFocus(); ok(tmp != device_window, "The device window is active.\n"); ok(tmp != focus_window, "The focus window is active.\n"); + focus_test_device = NULL;
/* The Present call is necessary to make native realize the device is lost. */ hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=43113
Your paranoid android.
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Stefan Dösinger stefan@codeweavers.com --- dlls/d3d9/tests/d3d9ex.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-)
diff --git a/dlls/d3d9/tests/d3d9ex.c b/dlls/d3d9/tests/d3d9ex.c index 63b7c5a46d9..bd2687f8fd8 100644 --- a/dlls/d3d9/tests/d3d9ex.c +++ b/dlls/d3d9/tests/d3d9ex.c @@ -2470,12 +2470,14 @@ struct message enum message_window window; BOOL check_wparam; WPARAM expect_wparam; + HRESULT device_state; WINDOWPOS *store_wp; };
static const struct message *expect_messages; static HWND device_window, focus_window; static LONG windowposchanged_received, syscommand_received; +static IDirect3DDevice9Ex *focus_test_device;
struct wndproc_thread_param { @@ -2487,6 +2489,8 @@ struct wndproc_thread_param
static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { + HRESULT hr; + if (filter_messages && filter_messages == hwnd) { if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY) @@ -2522,6 +2526,15 @@ static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM if (expect_messages->store_wp) *expect_messages->store_wp = *(WINDOWPOS *)lparam;
+ if (focus_test_device) + { + hr = IDirect3DDevice9Ex_CheckDeviceState(focus_test_device, device_window); + todo_wine_if(message != WM_ACTIVATEAPP && message != WM_DISPLAYCHANGE) + ok(hr == expect_messages->device_state, + "Got device state %#x on message %#x, expected %#x.\n", + hr, message, expect_messages->device_state); + } + ++expect_messages; } } @@ -2610,23 +2623,31 @@ static void test_wndproc(void) * 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_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0}, + + /* The S_PRESENT_MODE_CHANGED state is only there because we change the mode + * before dropping focus. From the base d3d9 tests one might expect d3d9ex to + * pick up the mode change by the time we receive WM_DISPLAYCHANGE, but as + * the tests below show, a present call is needed for that to happen. I don't + * want to call present in a focus loss message handler until we have an app + * that does that. Without the previous change (+present) the state would be + * D3D_OK all the way until the WM_ACTIVATEAPP message. */ + {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0, S_PRESENT_MODE_CHANGED}, /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is * not deterministic. */ - {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0}, + {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, S_PRESENT_MODE_CHANGED}, /* 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_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0, S_PRESENT_MODE_CHANGED}, + {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED, S_PRESENT_MODE_CHANGED}, + {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE, S_PRESENT_OCCLUDED}, /* 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}, + {0, 0, FALSE, 0, 0}, }; static const struct message focus_loss_messages_nowc[] = { @@ -2704,7 +2725,7 @@ static void test_wndproc(void) {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0}, {WM_SIZE, DEVICE_WINDOW, FALSE, 0}, {WM_SHOWWINDOW, DEVICE_WINDOW, FALSE, 0}, - {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, &windowpos}, + {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, ~0U, &windowpos}, {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0}, /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is * differs between Wine and Windows. */
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=43114
Your paranoid android.
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Stefan Dösinger stefan@codeweavers.com --- dlls/d3d9/tests/device.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-)
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index 66bf5b00c50..ffa144a0fd3 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -3427,12 +3427,14 @@ struct message enum message_window window; BOOL check_wparam; WPARAM expect_wparam; + HRESULT device_state; WINDOWPOS *store_wp; };
static const struct message *expect_messages; static HWND device_window, focus_window; static LONG windowposchanged_received, syscommand_received, wm_size_received; +static IDirect3DDevice9 *focus_test_device;
struct wndproc_thread_param { @@ -3444,6 +3446,8 @@ struct wndproc_thread_param
static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { + HRESULT hr; + if (filter_messages && filter_messages == hwnd) { if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY) @@ -3479,6 +3483,18 @@ static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM if (expect_messages->store_wp) *expect_messages->store_wp = *(WINDOWPOS *)lparam;
+ if (focus_test_device) + { + hr = IDirect3DDevice9_TestCooperativeLevel(focus_test_device); + /* Wined3d marks the device lost earlier than Windows (it follows ddraw + * behavior. See test_wndproc before the focus_loss_messages sequence + * about the D3DERR_DEVICENOTRESET behavior, */ + todo_wine_if(message != WM_ACTIVATEAPP || hr == D3D_OK) + ok(hr == expect_messages->device_state, + "Got device state %#x on message %#x, expected %#x.\n", + hr, message, expect_messages->device_state); + } + ++expect_messages; } } @@ -3567,23 +3583,24 @@ static void test_wndproc(void) * 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_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0}, + {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET}, /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is * not deterministic. */ - {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0}, + {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET}, /* 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_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET}, + {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED, + D3DERR_DEVICENOTRESET}, + {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE, D3DERR_DEVICELOST}, /* 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}, + {0, 0, FALSE, 0, 0}, }; static const struct message focus_loss_messages_nowc[] = { @@ -3591,9 +3608,9 @@ static void test_wndproc(void) * 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_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0}, - {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE}, - {0, 0, FALSE, 0}, + {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET}, + {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE, D3DERR_DEVICELOST}, + {0, 0, FALSE, 0, 0}, }; static const struct message reactivate_messages[] = { @@ -3681,7 +3698,7 @@ static void test_wndproc(void) {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0}, {WM_SIZE, DEVICE_WINDOW, FALSE, 0}, {WM_SHOWWINDOW, DEVICE_WINDOW, FALSE, 0}, - {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, &windowpos}, + {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, ~0U, &windowpos}, {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0}, /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is * differs between Wine and Windows. */ @@ -3871,6 +3888,7 @@ static void test_wndproc(void) todo_wine_if (hr != D3DERR_DEVICENOTRESET) ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
+ focus_test_device = device; 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 @@ -3884,6 +3902,7 @@ static void test_wndproc(void) 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); + focus_test_device = NULL;
hr = IDirect3DDevice9_TestCooperativeLevel(device); ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=43115
Your paranoid android.
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Stefan Dösinger stefan@codeweavers.com
---
The ddraw object is actually freed and not kept alive by some hidden refcount. I checked this by HeapAlloc'ing memory and zeroing it until the address space is full. The memory killfocus_ddraw points to is overwritten by this. --- dlls/ddraw/tests/ddraw1.c | 54 +++++++++++++++++++++++++++++++++++++++ dlls/ddraw/tests/ddraw2.c | 54 +++++++++++++++++++++++++++++++++++++++ dlls/ddraw/tests/ddraw4.c | 54 +++++++++++++++++++++++++++++++++++++++ dlls/ddraw/tests/ddraw7.c | 54 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 216 insertions(+)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c index aad7bbff1f4..1f93a97329e 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c @@ -11875,6 +11875,59 @@ static void test_find_device(void) IDirectDraw_Release(ddraw); }
+static IDirectDraw *killfocus_ddraw; +static IDirectDrawSurface *killfocus_surface; + +static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) +{ + ULONG ref; + + if (message == WM_KILLFOCUS) + { + ref = IDirectDrawSurface_Release(killfocus_surface); + ok(!ref, "Unexpected surface refcount %u.\n", ref); + ref = IDirectDraw_Release(killfocus_ddraw); + ok(!ref, "Unexpected ddraw refcount %u.\n", ref); + killfocus_ddraw = NULL; + } + + return DefWindowProcA(window, message, wparam, lparam); +} + +static void test_killfocus(void) +{ + DDSURFACEDESC surface_desc; + HRESULT hr; + HWND window; + WNDCLASSA wc = {0}; + + wc.lpfnWndProc = killfocus_proc; + wc.lpszClassName = "ddraw_killfocus_wndproc_wc"; + ok(RegisterClassA(&wc), "Failed to register window class.\n"); + + window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + + killfocus_ddraw = create_ddraw(); + ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n"); + + hr = IDirectDraw_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE); + ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS; + surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + hr = IDirectDraw_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + + SetForegroundWindow(GetDesktopWindow()); + ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n"); + + DestroyWindow(window); + UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL)); +} + START_TEST(ddraw1) { DDDEVICEIDENTIFIER identifier; @@ -11980,4 +12033,5 @@ START_TEST(ddraw1) test_execute_data(); test_viewport(); test_find_device(); + test_killfocus(); } diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index 29c3c845cb1..95cdf8bd82d 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -13157,6 +13157,59 @@ static void test_find_device(void) IDirectDraw2_Release(ddraw); }
+static IDirectDraw2 *killfocus_ddraw; +static IDirectDrawSurface *killfocus_surface; + +static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) +{ + ULONG ref; + + if (message == WM_KILLFOCUS) + { + ref = IDirectDrawSurface_Release(killfocus_surface); + ok(!ref, "Unexpected surface refcount %u.\n", ref); + ref = IDirectDraw2_Release(killfocus_ddraw); + ok(!ref, "Unexpected ddraw refcount %u.\n", ref); + killfocus_ddraw = NULL; + } + + return DefWindowProcA(window, message, wparam, lparam); +} + +static void test_killfocus(void) +{ + DDSURFACEDESC surface_desc; + HRESULT hr; + HWND window; + WNDCLASSA wc = {0}; + + wc.lpfnWndProc = killfocus_proc; + wc.lpszClassName = "ddraw_killfocus_wndproc_wc"; + ok(RegisterClassA(&wc), "Failed to register window class.\n"); + + window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + + killfocus_ddraw = create_ddraw(); + ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n"); + + hr = IDirectDraw2_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE); + ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS; + surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + hr = IDirectDraw_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + + SetForegroundWindow(GetDesktopWindow()); + ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n"); + + DestroyWindow(window); + UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL)); +} + START_TEST(ddraw2) { DDDEVICEIDENTIFIER identifier; @@ -13270,4 +13323,5 @@ START_TEST(ddraw2) test_enum_surfaces(); test_viewport(); test_find_device(); + test_killfocus(); } diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index 3aae42554f2..a62aaf0f30e 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -15265,6 +15265,59 @@ static void test_find_device(void) IDirectDraw4_Release(ddraw); }
+static IDirectDraw4 *killfocus_ddraw; +static IDirectDrawSurface4 *killfocus_surface; + +static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) +{ + ULONG ref; + + if (message == WM_KILLFOCUS) + { + ref = IDirectDrawSurface4_Release(killfocus_surface); + ok(!ref, "Unexpected surface refcount %u.\n", ref); + ref = IDirectDraw4_Release(killfocus_ddraw); + ok(!ref, "Unexpected ddraw refcount %u.\n", ref); + killfocus_ddraw = NULL; + } + + return DefWindowProcA(window, message, wparam, lparam); +} + +static void test_killfocus(void) +{ + DDSURFACEDESC2 surface_desc; + HRESULT hr; + HWND window; + WNDCLASSA wc = {0}; + + wc.lpfnWndProc = killfocus_proc; + wc.lpszClassName = "ddraw_killfocus_wndproc_wc"; + ok(RegisterClassA(&wc), "Failed to register window class.\n"); + + window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + + killfocus_ddraw = create_ddraw(); + ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n"); + + hr = IDirectDraw4_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE); + ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS; + surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + hr = IDirectDraw7_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + + SetForegroundWindow(GetDesktopWindow()); + ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n"); + + DestroyWindow(window); + UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL)); +} + START_TEST(ddraw4) { DDDEVICEIDENTIFIER identifier; @@ -15392,4 +15445,5 @@ START_TEST(ddraw4) test_enum_surfaces(); test_viewport(); test_find_device(); + test_killfocus(); } diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 4691135186b..05151b06510 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -15035,6 +15035,59 @@ static void test_color_vertex(void) DestroyWindow(window); }
+static IDirectDraw7 *killfocus_ddraw; +static IDirectDrawSurface7 *killfocus_surface; + +static LRESULT CALLBACK killfocus_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) +{ + ULONG ref; + + if (message == WM_KILLFOCUS) + { + ref = IDirectDrawSurface7_Release(killfocus_surface); + ok(!ref, "Unexpected surface refcount %u.\n", ref); + ref = IDirectDraw7_Release(killfocus_ddraw); + ok(!ref, "Unexpected ddraw refcount %u.\n", ref); + killfocus_ddraw = NULL; + } + + return DefWindowProcA(window, message, wparam, lparam); +} + +static void test_killfocus(void) +{ + DDSURFACEDESC2 surface_desc; + HRESULT hr; + HWND window; + WNDCLASSA wc = {0}; + + wc.lpfnWndProc = killfocus_proc; + wc.lpszClassName = "ddraw_killfocus_wndproc_wc"; + ok(RegisterClassA(&wc), "Failed to register window class.\n"); + + window = CreateWindowA("ddraw_killfocus_wndproc_wc", "d3d7_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + + killfocus_ddraw = create_ddraw(); + ok(!!killfocus_ddraw, "Failed to create a ddraw object.\n"); + + hr = IDirectDraw7_SetCooperativeLevel(killfocus_ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE); + ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS; + surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + hr = IDirectDraw7_CreateSurface(killfocus_ddraw, &surface_desc, &killfocus_surface, NULL); + ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); + + SetForegroundWindow(GetDesktopWindow()); + ok(!killfocus_ddraw, "WM_KILLFOCUS was not received.\n"); + + DestroyWindow(window); + UnregisterClassA("ddraw_killfocus_wndproc_wc", GetModuleHandleA(NULL)); +} + START_TEST(ddraw7) { DDDEVICEIDENTIFIER2 identifier; @@ -15173,4 +15226,5 @@ START_TEST(ddraw7) test_viewport(); test_device_load(); test_color_vertex(); + test_killfocus(); }
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=43116
Your paranoid android.
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=43109
Your paranoid android.
=== wvistau64 (32 bit Windows report) ===
ddraw: ddraw1.c:2705: Test failed: Expected message 0x46, but didn't receive it. ddraw1.c:2707: Test failed: Expected screen size 1024x768, got 0x0. ddraw1.c:2713: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2743: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2750: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2776: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2799: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2828: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2854: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2874: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2910: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2920: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2946: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2969: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2991: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:3017: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:3037: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:3074: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746).
=== wvistau64_he (32 bit Windows report) ===
ddraw: ddraw1.c:2705: Test failed: Expected message 0x46, but didn't receive it. ddraw1.c:2707: Test failed: Expected screen size 1024x768, got 0x0. ddraw1.c:2713: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2743: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2750: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2776: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2799: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2828: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2854: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2874: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2910: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2920: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2946: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2969: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:2991: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:3017: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:3037: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746). ddraw1.c:3074: Test failed: Expected (0,0)-(1024,768), got (-8,-8)-(1032,746).
=== w864 (32 bit Windows report) ===
ddraw: ddraw1.c:1739: Test failed: Got unexpected color 0x000000ff.
=== w1064 (32 bit Windows report) ===
ddraw: ddraw1.c:10488: Test failed: Got unexpected color 0x00ffffff.
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)