[PATCH 2/5] wined3d: Set the device window size on focus window activation.

Stefan Dösinger stefan at codeweavers.com
Wed Nov 19 13:13:50 CST 2014


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




More information about the wine-patches mailing list