[PATCH v2 1/4] dxgi: Implement dxgi_factory_MakeWindowAssociation().

Zhiyi Zhang zzhang at codeweavers.com
Wed Apr 24 09:19:13 CDT 2019


Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
v2: Add tests to show that window association doesn't modify WNDPROC.

 dlls/dxgi/dxgi_private.h |  1 +
 dlls/dxgi/factory.c      | 74 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 72 insertions(+), 3 deletions(-)

diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h
index b6999c729a..7fb28287ad 100644
--- a/dlls/dxgi/dxgi_private.h
+++ b/dlls/dxgi/dxgi_private.h
@@ -115,6 +115,7 @@ struct dxgi_factory
     struct wined3d *wined3d;
     BOOL extended;
     HWND device_window;
+    struct list associated_windows;
 };
 
 HRESULT dxgi_factory_create(REFIID riid, void **factory, BOOL extended) DECLSPEC_HIDDEN;
diff --git a/dlls/dxgi/factory.c b/dlls/dxgi/factory.c
index 52c145bc6a..5aadef62e4 100644
--- a/dlls/dxgi/factory.c
+++ b/dlls/dxgi/factory.c
@@ -24,6 +24,17 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dxgi);
 
+const WCHAR wine_dxgi_associated_factory_propW[] =
+    {'W','i','n','e','D','X','G','I','A','s','s','o','c','i','a','t','e','d','F','a','c','t','o','r','y',0};
+const WCHAR wine_dxgi_associated_flags_propW[] =
+    {'W','i','n','e','D','X','G','I','A','s','s','o','c','i','a','t','e','d','F','l','a','g','s',0};
+
+struct dxgi_associated_window
+{
+    HWND hwnd;
+    struct list entry;
+};
+
 static inline struct dxgi_factory *impl_from_IWineDXGIFactory(IWineDXGIFactory *iface)
 {
     return CONTAINING_RECORD(iface, struct dxgi_factory, IWineDXGIFactory_iface);
@@ -70,11 +81,20 @@ static ULONG STDMETHODCALLTYPE dxgi_factory_Release(IWineDXGIFactory *iface)
 {
     struct dxgi_factory *factory = impl_from_IWineDXGIFactory(iface);
     ULONG refcount = InterlockedDecrement(&factory->refcount);
+    struct dxgi_associated_window *window, *window2;
 
     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
 
     if (!refcount)
     {
+        LIST_FOR_EACH_ENTRY_SAFE(window, window2, &factory->associated_windows, struct dxgi_associated_window, entry)
+        {
+            RemovePropW(window->hwnd, wine_dxgi_associated_factory_propW);
+            RemovePropW(window->hwnd, wine_dxgi_associated_flags_propW);
+            list_remove(&window->entry);
+            heap_free(window);
+        }
+
         if (factory->device_window)
             DestroyWindow(factory->device_window);
 
@@ -172,11 +192,58 @@ static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumAdapters(IWineDXGIFactory *ifa
 }
 
 static HRESULT STDMETHODCALLTYPE dxgi_factory_MakeWindowAssociation(IWineDXGIFactory *iface,
-        HWND window, UINT flags)
+        HWND hwnd, UINT flags)
 {
-    FIXME("iface %p, window %p, flags %#x stub!\n", iface, window, flags);
+    struct dxgi_factory *factory = impl_from_IWineDXGIFactory(iface);
+    struct dxgi_associated_window *window, *window2;
+    HANDLE handle;
+    HRESULT hr = S_OK;
 
-    return S_OK;
+    TRACE("iface %p, window %p, flags %#x.\n", iface, hwnd, flags);
+
+    if (flags > DXGI_MWA_VALID)
+        return DXGI_ERROR_INVALID_CALL;
+
+    wined3d_mutex_lock();
+
+    /* Delete all associated windows from this factory */
+    if (!hwnd)
+    {
+        LIST_FOR_EACH_ENTRY_SAFE(window, window2, &factory->associated_windows, struct dxgi_associated_window, entry)
+        {
+            RemovePropW(window->hwnd, wine_dxgi_associated_factory_propW);
+            RemovePropW(window->hwnd, wine_dxgi_associated_flags_propW);
+            list_remove(&window->entry);
+            heap_free(window);
+        }
+    }
+    /* Add a new window association */
+    else
+    {
+        handle = GetPropW(hwnd, wine_dxgi_associated_factory_propW);
+        if (!handle)
+        {
+            window = heap_alloc_zero(sizeof(struct dxgi_associated_window));
+            if (!window)
+            {
+                hr = E_OUTOFMEMORY;
+                goto done;
+            }
+
+            SetPropW(hwnd, wine_dxgi_associated_factory_propW, iface);
+            SetPropW(hwnd, wine_dxgi_associated_flags_propW, (HANDLE)(UINT_PTR)flags);
+            window->hwnd = hwnd;
+            list_add_head(&factory->associated_windows, &window->entry);
+        }
+        else if (handle == iface)
+            SetPropW(hwnd, wine_dxgi_associated_flags_propW, (HANDLE)(UINT_PTR)flags);
+        else
+            WARN("Window is already associated to another factory.\n");
+    }
+
+done:
+    wined3d_mutex_unlock();
+    return hr;
 }
 
 static HRESULT STDMETHODCALLTYPE dxgi_factory_GetWindowAssociation(IWineDXGIFactory *iface, HWND *window)
@@ -501,6 +568,7 @@ static HRESULT dxgi_factory_init(struct dxgi_factory *factory, BOOL extended)
     }
 
     factory->extended = extended;
+    list_init(&factory->associated_windows);
 
     return S_OK;
 }
-- 
2.20.1





More information about the wine-devel mailing list