From: Stefan Dösinger Subject: [PATCH 2/5] wined3d: Set the device window size on focus window activation. Message-Id: <1416424433-1467-2-git-send-email-stefan@codeweavers.com> Date: Wed, 19 Nov 2014 20:13:50 +0100 D3d9ex in principle has the same behavior, but it is unreliable. Sometimes the WM_WINDOWPOSCHANGING message is missing, sometimes WM_SIZE is not generated from the arriving WINDOWPOSCHANGED message, and sometimes it works like in d3d8/9. --- dlls/d3d8/tests/device.c | 14 +++++++++++++- dlls/d3d9/tests/d3d9ex.c | 6 ++++++ dlls/d3d9/tests/device.c | 28 ++++++++++++++++++++++++---- dlls/wined3d/swapchain.c | 14 ++++++++++++++ 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c index 6244254..6ee4f89 100644 --- a/dlls/d3d8/tests/device.c +++ b/dlls/d3d8/tests/device.c @@ -2282,6 +2282,14 @@ static void test_wndproc(void) * or before. */ {0, 0, FALSE, 0}, }; + static const struct message reactivate_messages[] = + { + {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0}, + {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0}, + {WM_MOVE, DEVICE_WINDOW, FALSE, 0}, + {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE}, + {0, 0, FALSE, 0}, + }; d3d8 = Direct3DCreate8(D3D_SDK_VERSION); ok(!!d3d8, "Failed to create a D3D object.\n"); @@ -2469,13 +2477,17 @@ static void test_wndproc(void) /* 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. */ + expect_messages = reactivate_messages; 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(); + flush_events(); /* WM_WINDOWPOSCHANGING etc arrive after SetForegroundWindow returns. */ + 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; hr = IDirect3DDevice8_TestCooperativeLevel(device); ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr); diff --git a/dlls/d3d9/tests/d3d9ex.c b/dlls/d3d9/tests/d3d9ex.c index 5f54d5b..9f8c163 100644 --- a/dlls/d3d9/tests/d3d9ex.c +++ b/dlls/d3d9/tests/d3d9ex.c @@ -2052,6 +2052,12 @@ static void test_wndproc(void) * independent of D3DCREATE_NOWINDOWCHANGES. */ ShowWindow(device_window, SW_MINIMIZE); ShowWindow(device_window, SW_RESTORE); + + /* Reactivation messages like in d3d8/9 are random in native d3d9ex. + * Sometimes they are sent, sometimes they are not (tested on Vista + * and Windows 7). The minimizing and restoring of the device window + * may have something to do with this, but if the messages are sent, + * they are generated by the 3 calls below. */ ShowWindow(focus_window, SW_MINIMIZE); ShowWindow(focus_window, SW_RESTORE); /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */ diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index 3fd25d1..3e91267 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -3244,15 +3244,30 @@ static void test_wndproc(void) {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE}, {0, 0, FALSE, 0}, }; + static const struct message reactivate_messages[] = + { + {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0}, + {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0}, + {WM_MOVE, DEVICE_WINDOW, FALSE, 0}, + {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE}, + {0, 0, FALSE, 0}, + }; + static const struct message reactivate_messages_nowc[] = + { + /* We're activating the device window before activating the + * focus window, so no ACTIVATEAPP message is sent. */ + {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_ACTIVE}, + {0, 0, FALSE, 0}, + }; static const struct { DWORD create_flags; - const struct message *focus_loss_messages; + const struct message *focus_loss_messages, *reactivate_messages; } tests[] = { - {0, focus_loss_messages}, - {CREATE_DEVICE_NOWINDOWCHANGES, focus_loss_messages_nowc}, + {0, focus_loss_messages, reactivate_messages}, + {CREATE_DEVICE_NOWINDOWCHANGES, focus_loss_messages_nowc, reactivate_messages_nowc}, }; d3d9 = Direct3DCreate9(D3D_SDK_VERSION); @@ -3441,17 +3456,22 @@ static void test_wndproc(void) ShowWindow(device_window, SW_MINIMIZE); ShowWindow(device_window, SW_RESTORE); } + flush_events(); /* 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. */ + expect_messages = tests[i].reactivate_messages; 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(); + flush_events(); /* WM_WINDOWPOSCHANGING etc arrive after SetForegroundWindow returns. */ + 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; hr = IDirect3DDevice9_TestCooperativeLevel(device); ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr); diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 20731ef..d1b6d0b 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -1178,6 +1178,20 @@ void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activa { if (activate) { + if (!(swapchain->device->create_parms.flags & WINED3DCREATE_NOWINDOWCHANGES)) + { + /* The d3d versions do not agree on the exact messages here. D3d8 restores + * the window but leaves the size untouched, d3d9 sets the size on an + * invisible window, generates messages but doesn't change the window + * properties. The implementation follows d3d9. + * + * Guild Wars 1 wants a WINDOWPOSCHANGED message on the device window to + * resume drawing after a focus loss. */ + SetWindowPos(swapchain->device_window, NULL, 0, 0, + swapchain->desc.backbuffer_width, swapchain->desc.backbuffer_height, + SWP_NOACTIVATE | SWP_NOZORDER); + } + if (swapchain->device->wined3d->flags & WINED3D_RESTORE_MODE_ON_ACTIVATE) { if (FAILED(wined3d_set_adapter_display_mode(swapchain->device->wined3d, -- 2.0.4