[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