[PATCH v2 4/6] winex11: Return selection data as a single buffer from import_xdnd_selection.

Huw Davies huw at codeweavers.com
Wed Apr 27 08:01:15 CDT 2022


From: Jacek Caban <jacek at codeweavers.com>

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/winex11.drv/clipboard.c | 29 +++++++++++++++++------------
 dlls/winex11.drv/x11drv.h    | 14 +++++++++++---
 dlls/winex11.drv/xdnd.c      | 26 ++++++++++++++++++++++++--
 3 files changed, 52 insertions(+), 17 deletions(-)

diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c
index ec69778fc3c..92284d436dd 100644
--- a/dlls/winex11.drv/clipboard.c
+++ b/dlls/winex11.drv/clipboard.c
@@ -1096,21 +1096,21 @@ static void *import_selection( Display *display, Window win, Atom selection,
 
 
 /**************************************************************************
- *      X11DRV_CLIPBOARD_ImportSelection
+ *      import_xdnd_selection
  *
  *  Import the X selection into the clipboard format registered for the given X target.
  */
-void X11DRV_CLIPBOARD_ImportSelection( Display *display, Window win, Atom selection,
-                                       Atom *targets, UINT count,
-                                       void (*callback)( UINT, HANDLE ))
+struct format_entry *import_xdnd_selection( Display *display, Window win, Atom selection,
+                                            Atom *targets, UINT count, size_t *ret_size )
 {
+    size_t size, buf_size = 0, entry_size;
     UINT i;
-    HANDLE handle;
     void *data;
-    size_t size;
     struct clipboard_format *format;
+    struct format_entry *ret = NULL, *entry;
 
     register_x11_formats( targets, count );
+    *ret_size = 0;
 
     for (i = 0; i < count; i++)
     {
@@ -1118,16 +1118,21 @@ void X11DRV_CLIPBOARD_ImportSelection( Display *display, Window win, Atom select
         if (!format->id) continue;
         if (!(data = import_selection( display, win, selection, format, &size ))) continue;
 
-        if ((handle = GlobalAlloc( GMEM_FIXED, size )))
+        entry_size = (FIELD_OFFSET( struct format_entry, data[size] ) + 7) & ~7;
+        if (buf_size < size + entry_size)
         {
-            void *ptr;
-            ptr = GlobalLock( handle );
-            memcpy( ptr, data, size );
-            GlobalUnlock( handle );
-            callback( format->id, handle );
+            if (!(ret = realloc( ret, *ret_size + entry_size + 1024 ))) continue;
+            buf_size = *ret_size + entry_size + 1024; /* extra space for following entries */
         }
+        entry = (struct format_entry *)((char *)ret + *ret_size);
+        entry->format = format->id;
+        entry->size = size;
+        if (size) memcpy( entry->data, data, size );
+        *ret_size += entry_size;
         free( data );
     }
+
+    return ret;
 }
 
 
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index a8d2f78aa6b..f6d28122fc3 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -297,9 +297,17 @@ extern void X11DRV_XDND_EnterEvent( HWND hWnd, XClientMessageEvent *event ) DECL
 extern void X11DRV_XDND_PositionEvent( HWND hWnd, XClientMessageEvent *event ) DECLSPEC_HIDDEN;
 extern void X11DRV_XDND_DropEvent( HWND hWnd, XClientMessageEvent *event ) DECLSPEC_HIDDEN;
 extern void X11DRV_XDND_LeaveEvent( HWND hWnd, XClientMessageEvent *event ) DECLSPEC_HIDDEN;
-extern void X11DRV_CLIPBOARD_ImportSelection( Display *display, Window win, Atom selection,
-                                              Atom *targets, UINT count,
-                                              void (*callback)( UINT, HANDLE )) DECLSPEC_HIDDEN;
+
+struct format_entry
+{
+    UINT format;
+    UINT size;
+    char data[1];
+};
+
+extern struct format_entry *import_xdnd_selection( Display *display, Window win, Atom selection,
+                                                   Atom *targets, UINT count,
+                                                   size_t *size ) DECLSPEC_HIDDEN;
 
 /**************************************************************************
  * X11 GDI driver
diff --git a/dlls/winex11.drv/xdnd.c b/dlls/winex11.drv/xdnd.c
index b9bba1ff872..aa46467f6f7 100644
--- a/dlls/winex11.drv/xdnd.c
+++ b/dlls/winex11.drv/xdnd.c
@@ -79,6 +79,12 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
 static CRITICAL_SECTION xdnd_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
 
 
+static struct format_entry *next_format( struct format_entry *entry )
+{
+    return (struct format_entry *)&entry->data[(entry->size + 7) & ~7];
+}
+
+
 /* Based on functions in dlls/ole32/ole2.c */
 static HANDLE get_droptarget_local_handle(HWND hwnd)
 {
@@ -523,15 +529,31 @@ void X11DRV_XDND_LeaveEvent( HWND hWnd, XClientMessageEvent *event )
 static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
                                         Atom *types, unsigned long count)
 {
+    struct format_entry *formats, *formats_end, *iter;
     XDNDDATA *current, *next;
     BOOL haveHDROP = FALSE;
+    size_t size;
 
     TRACE("count(%ld)\n", count);
 
     X11DRV_XDND_FreeDragDropOp(); /* Clear previously cached data */
 
-    X11DRV_CLIPBOARD_ImportSelection( display, xwin, x11drv_atom(XdndSelection),
-                                      types, count, X11DRV_XDND_InsertXDNDData );
+    formats = import_xdnd_selection( display, xwin, x11drv_atom(XdndSelection), types, count, &size );
+    if (formats)
+    {
+        formats_end = (struct format_entry *)((char *)formats + size);
+        for (iter = formats; iter < formats_end; iter = next_format( iter ))
+        {
+            HANDLE handle;
+            if ((handle = GlobalAlloc( GMEM_FIXED, iter->size )))
+            {
+                void *ptr = GlobalLock( handle );
+                memcpy( ptr, iter->data, iter->size );
+                GlobalUnlock( handle );
+                X11DRV_XDND_InsertXDNDData( iter->format, handle );
+            }
+        }
+    }
 
     /* On Windows when there is a CF_HDROP, there are no other CF_ formats.
      * foobar2000 relies on this (spaces -> %20's without it).
-- 
2.25.1




More information about the wine-devel mailing list