[PATCH 3/3] winex11.drv: use the clipboard functions and formats to import drag and drop selections
Damjan Jovanovic
damjan.jov at gmail.com
Sun May 4 22:33:14 CDT 2014
Use the clipboard formats for importing drag and drop selections,
which de-duplicates a lot of code, allows the drag and drop code to
use INCR for large transfers, and supports dragging and dropping new
types into Wine, such as images.
Damjan Jovanovic
---
dlls/winex11.drv/clipboard.c | 19 +++
dlls/winex11.drv/x11drv.h | 1 +
dlls/winex11.drv/xdnd.c | 317 +++----------------------------------------
3 files changed, 38 insertions(+), 299 deletions(-)
diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c
index acb4e3f..e3508ca 100644
--- a/dlls/winex11.drv/clipboard.c
+++ b/dlls/winex11.drv/clipboard.c
@@ -1698,6 +1698,25 @@ static HANDLE
X11DRV_CLIPBOARD_ImportClipboardData(Display *display, Window w, A
/**************************************************************************
+ * X11DRV_CLIPBOARD_ImportSelection
+ *
+ * Import the X selection into the clipboard format registered for
the given X target.
+ */
+HANDLE X11DRV_CLIPBOARD_ImportSelection(Display *d, Atom target,
Window w, Atom prop, UINT *windowsFormat)
+{
+ WINE_CLIPFORMAT *clipFormat;
+
+ clipFormat = X11DRV_CLIPBOARD_LookupProperty(NULL, target);
+ if (clipFormat)
+ {
+ *windowsFormat = clipFormat->wFormatID;
+ return clipFormat->lpDrvImportFunc(d, w, prop);
+ }
+ return NULL;
+}
+
+
+/**************************************************************************
X11DRV_CLIPBOARD_ExportClipboardData
*
* Generic export clipboard data routine.
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 7a3374d..bcbfe14 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -238,6 +238,7 @@ 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 HANDLE X11DRV_CLIPBOARD_ImportSelection(Display *d, Atom
target, Window w, Atom prop, UINT *windowsFormat) DECLSPEC_HIDDEN;
/**************************************************************************
* X11 GDI driver
diff --git a/dlls/winex11.drv/xdnd.c b/dlls/winex11.drv/xdnd.c
index e894de0..4d19360 100644
--- a/dlls/winex11.drv/xdnd.c
+++ b/dlls/winex11.drv/xdnd.c
@@ -56,8 +56,7 @@ typedef struct tagXDNDDATA
{
int cf_win;
Atom cf_xdnd;
- void *data;
- unsigned int size;
+ HANDLE contents;
struct list entry;
} XDNDDATA, *LPXDNDDATA;
@@ -71,17 +70,11 @@ static HWND XDNDLastTargetWnd;
/* might be an ancestor of XDNDLastTargetWnd */
static HWND XDNDLastDropTargetWnd;
-static void X11DRV_XDND_InsertXDNDData(int property, int format,
void* data, unsigned int len);
-static int X11DRV_XDND_DeconstructTextURIList(int property, void*
data, int len);
-static int X11DRV_XDND_DeconstructTextPlain(int property, void* data, int len);
-static int X11DRV_XDND_DeconstructTextHTML(int property, void* data, int len);
-static int X11DRV_XDND_MapFormat(unsigned int property, unsigned char
*data, int len);
+static void X11DRV_XDND_InsertXDNDData(int property, int format,
HANDLE contents);
static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
Atom *types, unsigned long *count);
static void X11DRV_XDND_SendDropFiles(HWND hwnd);
static void X11DRV_XDND_FreeDragDropOp(void);
-static unsigned int X11DRV_XDND_UnixToDos(char** lpdest, char* lpsrc, int len);
-static WCHAR* X11DRV_XDND_URIToDOS(char *encodedURI);
static CRITICAL_SECTION xdnd_cs;
static CRITICAL_SECTION_DEBUG critsect_debug =
@@ -459,11 +452,6 @@ static void X11DRV_XDND_ResolveProperty(Display
*display, Window xwin, Time tm,
unsigned int i, j;
BOOL res;
XEvent xe;
- Atom acttype;
- int actfmt;
- unsigned long bytesret, icount;
- int entries = 0;
- unsigned char* data = NULL;
XDNDDATA *current, *next;
BOOL haveHDROP = FALSE;
@@ -473,6 +461,9 @@ static void X11DRV_XDND_ResolveProperty(Display
*display, Window xwin, Time tm,
for (i = 0; i < *count; i++)
{
+ HANDLE contents;
+ UINT windowsFormat;
+
TRACE("requesting atom %ld from xwin %ld\n", types[i], xwin);
if (types[i] == 0)
@@ -495,11 +486,9 @@ static void X11DRV_XDND_ResolveProperty(Display
*display, Window xwin, Time tm,
if (xe.xselection.property == None)
continue;
- XGetWindowProperty(display, xwin, x11drv_atom(XdndTarget), 0,
65535, FALSE,
- AnyPropertyType, &acttype, &actfmt, &icount, &bytesret, &data);
-
- entries += X11DRV_XDND_MapFormat(types[i], data,
get_property_size( actfmt, icount ));
- XFree(data);
+ contents = X11DRV_CLIPBOARD_ImportSelection(display,
types[i], xwin, x11drv_atom(XdndTarget), &windowsFormat);
+ if (contents)
+ X11DRV_XDND_InsertXDNDData(types[i], windowsFormat, contents);
}
/* On Windows when there is a CF_HDROP, there are no other CF_ formats.
@@ -520,14 +509,11 @@ static void X11DRV_XDND_ResolveProperty(Display
*display, Window xwin, Time tm,
if (current->cf_win != CF_HDROP && current->cf_win < CF_MAX)
{
list_remove(¤t->entry);
- HeapFree(GetProcessHeap(), 0, current->data);
+ GlobalFree(current->contents);
HeapFree(GetProcessHeap(), 0, current);
- --entries;
}
}
}
-
- *count = entries;
}
@@ -536,7 +522,7 @@ static void X11DRV_XDND_ResolveProperty(Display
*display, Window xwin, Time tm,
*
* Cache available XDND property
*/
-static void X11DRV_XDND_InsertXDNDData(int property, int format,
void* data, unsigned int len)
+static void X11DRV_XDND_InsertXDNDData(int property, int format,
HANDLE contents)
{
LPXDNDDATA current = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, sizeof(XDNDDATA));
@@ -545,8 +531,7 @@ static void X11DRV_XDND_InsertXDNDData(int
property, int format, void* data, uns
EnterCriticalSection(&xdnd_cs);
current->cf_xdnd = property;
current->cf_win = format;
- current->data = data;
- current->size = len;
+ current->contents = contents;
list_add_tail(&xdndData, ¤t->entry);
LeaveCriticalSection(&xdnd_cs);
}
@@ -554,158 +539,6 @@ static void X11DRV_XDND_InsertXDNDData(int
property, int format, void* data, uns
/**************************************************************************
- * X11DRV_XDND_MapFormat
- *
- * Map XDND MIME format to windows clipboard format.
- */
-static int X11DRV_XDND_MapFormat(unsigned int property, unsigned char
*data, int len)
-{
- void* xdata;
- int count = 0;
-
- TRACE("%d: %s\n", property, data);
-
- /* Always include the raw type */
- xdata = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
- memcpy(xdata, data, len);
- X11DRV_XDND_InsertXDNDData(property, property, xdata, len);
- count++;
-
- if (property == x11drv_atom(text_uri_list))
- count += X11DRV_XDND_DeconstructTextURIList(property, data, len);
- else if (property == x11drv_atom(text_plain))
- count += X11DRV_XDND_DeconstructTextPlain(property, data, len);
- else if (property == x11drv_atom(text_html))
- count += X11DRV_XDND_DeconstructTextHTML(property, data, len);
-
- return count;
-}
-
-
-/**************************************************************************
- * X11DRV_XDND_DeconstructTextURIList
- *
- * Interpret text/uri-list data and add records to <dndfmt> linked list
- */
-static int X11DRV_XDND_DeconstructTextURIList(int property, void*
data, int len)
-{
- char *uriList = data;
- char *uri;
- WCHAR *path;
-
- WCHAR *out = NULL;
- int size = 0;
- int capacity = 4096;
-
- int count = 0;
- int start = 0;
- int end = 0;
-
- out = HeapAlloc(GetProcessHeap(), 0, capacity * sizeof(WCHAR));
- if (out == NULL)
- return 0;
-
- while (end < len)
- {
- while (end < len && uriList[end] != '\r')
- ++end;
- if (end < (len - 1) && uriList[end+1] != '\n')
- {
- WARN("URI list line doesn't end in \\r\\n\n");
- break;
- }
-
- uri = HeapAlloc(GetProcessHeap(), 0, end - start + 1);
- if (uri == NULL)
- break;
- lstrcpynA(uri, &uriList[start], end - start + 1);
- path = X11DRV_XDND_URIToDOS(uri);
- TRACE("converted URI %s to DOS path %s\n", debugstr_a(uri),
debugstr_w(path));
- HeapFree(GetProcessHeap(), 0, uri);
-
- if (path)
- {
- int pathSize = strlenW(path) + 1;
- if (pathSize > capacity-size)
- {
- capacity = 2*capacity + pathSize;
- out = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
out, (capacity + 1)*sizeof(WCHAR));
- if (out == NULL)
- goto done;
- }
- memcpy(&out[size], path, pathSize * sizeof(WCHAR));
- size += pathSize;
- done:
- HeapFree(GetProcessHeap(), 0, path);
- if (out == NULL)
- break;
- }
-
- start = end + 2;
- end = start;
- }
- if (out && end >= len)
- {
- DROPFILES *dropFiles;
- dropFiles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(DROPFILES) + (size + 1)*sizeof(WCHAR));
- if (dropFiles)
- {
- dropFiles->pFiles = sizeof(DROPFILES);
- dropFiles->pt.x = XDNDxy.x;
- dropFiles->pt.y = XDNDxy.y;
- dropFiles->fNC = 0;
- dropFiles->fWide = TRUE;
- out[size] = '\0';
- memcpy(((char*)dropFiles) + dropFiles->pFiles, out, (size
+ 1)*sizeof(WCHAR));
- X11DRV_XDND_InsertXDNDData(property, CF_HDROP, dropFiles,
sizeof(DROPFILES) + (size + 1)*sizeof(WCHAR));
- count = 1;
- }
- }
- HeapFree(GetProcessHeap(), 0, out);
- return count;
-}
-
-
-/**************************************************************************
- * X11DRV_XDND_DeconstructTextPlain
- *
- * Interpret text/plain Data and add records to <dndfmt> linked list
- */
-static int X11DRV_XDND_DeconstructTextPlain(int property, void* data, int len)
-{
- char* dostext;
-
- /* Always supply plain text */
- X11DRV_XDND_UnixToDos(&dostext, data, len);
- X11DRV_XDND_InsertXDNDData(property, CF_TEXT, dostext, strlen(dostext));
-
- TRACE("CF_TEXT (%d): %s\n", CF_TEXT, dostext);
-
- return 1;
-}
-
-
-/**************************************************************************
- * X11DRV_XDND_DeconstructTextHTML
- *
- * Interpret text/html data and add records to <dndfmt> linked list
- */
-static int X11DRV_XDND_DeconstructTextHTML(int property, void* data, int len)
-{
- char* dostext;
-
- X11DRV_XDND_UnixToDos(&dostext, data, len);
-
- X11DRV_XDND_InsertXDNDData(property,
- RegisterClipboardFormatA("UniformResourceLocator"), dostext,
strlen(dostext));
-
- TRACE("UniformResourceLocator: %s\n", dostext);
-
- return 1;
-}
-
-
-/**************************************************************************
* X11DRV_XDND_SendDropFiles
*/
static void X11DRV_XDND_SendDropFiles(HWND hwnd)
@@ -727,14 +560,15 @@ static void X11DRV_XDND_SendDropFiles(HWND hwnd)
if (found)
{
- HGLOBAL dropHandle = GlobalAlloc(GMEM_FIXED, current->size);
+ HGLOBAL dropHandle = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
GlobalSize(current->contents));
if (dropHandle)
{
DROPFILES *lpDrop = GlobalLock(dropHandle);
lpDrop->pt.x = XDNDxy.x;
lpDrop->pt.y = XDNDxy.y;
- memcpy(lpDrop, current->data, current->size);
+ memcpy(lpDrop, GlobalLock(current->contents),
GlobalSize(current->contents));
+ GlobalUnlock(current->contents);
TRACE("Sending WM_DROPFILES: hWnd(0x%p) %p(%s)\n", hwnd,
((char*)lpDrop) + lpDrop->pFiles,
debugstr_w((WCHAR*)(((char*)lpDrop) + lpDrop->pFiles)));
GlobalUnlock(dropHandle);
@@ -764,7 +598,7 @@ static void X11DRV_XDND_FreeDragDropOp(void)
LIST_FOR_EACH_ENTRY_SAFE(current, next, &xdndData, XDNDDATA, entry)
{
list_remove(¤t->entry);
- HeapFree(GetProcessHeap(), 0, current->data);
+ GlobalFree(current->contents);
HeapFree(GetProcessHeap(), 0, current);
}
@@ -777,122 +611,6 @@ static void X11DRV_XDND_FreeDragDropOp(void)
}
-
-/**************************************************************************
- * X11DRV_XDND_UnixToDos
- */
-static unsigned int X11DRV_XDND_UnixToDos(char** lpdest, char* lpsrc, int len)
-{
- int i;
- unsigned int destlen, lines;
-
- for (i = 0, lines = 0; i <= len; i++)
- {
- if (lpsrc[i] == '\n')
- lines++;
- }
-
- destlen = len + lines + 1;
-
- if (lpdest)
- {
- char* lpstr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, destlen);
- for (i = 0, lines = 0; i <= len; i++)
- {
- if (lpsrc[i] == '\n')
- lpstr[++lines + i] = '\r';
- lpstr[lines + i] = lpsrc[i];
- }
-
- *lpdest = lpstr;
- }
-
- return lines;
-}
-
-
-/**************************************************************************
- * X11DRV_XDND_URIToDOS
- */
-static WCHAR* X11DRV_XDND_URIToDOS(char *encodedURI)
-{
- WCHAR *ret = NULL;
- int i;
- int j = 0;
- char *uri = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
strlen(encodedURI) + 1);
- if (uri == NULL)
- return NULL;
- for (i = 0; encodedURI[i]; ++i)
- {
- if (encodedURI[i] == '%')
- {
- if (encodedURI[i+1] && encodedURI[i+2])
- {
- char buffer[3];
- int number;
- buffer[0] = encodedURI[i+1];
- buffer[1] = encodedURI[i+2];
- buffer[2] = '\0';
- sscanf(buffer, "%x", &number);
- uri[j++] = number;
- i += 2;
- }
- else
- {
- WARN("invalid URI encoding in %s\n", debugstr_a(encodedURI));
- HeapFree(GetProcessHeap(), 0, uri);
- return NULL;
- }
- }
- else
- uri[j++] = encodedURI[i];
- }
-
- /* Read http://www.freedesktop.org/wiki/Draganddropwarts and cry... */
- if (strncmp(uri, "file:/", 6) == 0)
- {
- if (uri[6] == '/')
- {
- if (uri[7] == '/')
- {
- /* file:///path/to/file (nautilus, thunar) */
- ret = wine_get_dos_file_name(&uri[7]);
- }
- else if (uri[7])
- {
- /* file://hostname/path/to/file (X file drag spec) */
- char hostname[256];
- char *path = strchr(&uri[7], '/');
- if (path)
- {
- *path = '\0';
- if (strcmp(&uri[7], "localhost") == 0)
- {
- *path = '/';
- ret = wine_get_dos_file_name(path);
- }
- else if (gethostname(hostname, sizeof(hostname)) == 0)
- {
- if (strcmp(hostname, &uri[7]) == 0)
- {
- *path = '/';
- ret = wine_get_dos_file_name(path);
- }
- }
- }
- }
- }
- else if (uri[6])
- {
- /* file:/path/to/file (konqueror) */
- ret = wine_get_dos_file_name(&uri[5]);
- }
- }
- HeapFree(GetProcessHeap(), 0, uri);
- return ret;
-}
-
-
/**************************************************************************
* X11DRV_XDND_DescribeClipboardFormat
*/
@@ -985,10 +703,11 @@ static HRESULT WINAPI
XDNDDATAOBJECT_GetData(IDataObject *dataObject,
if (current->cf_win == formatEtc->cfFormat)
{
pMedium->tymed = TYMED_HGLOBAL;
- pMedium->u.hGlobal = HeapAlloc(GetProcessHeap(), 0,
current->size);
+ pMedium->u.hGlobal = GlobalAlloc(GMEM_FIXED |
GMEM_ZEROINIT, GlobalSize(current->contents));
if (pMedium->u.hGlobal == NULL)
return E_OUTOFMEMORY;
- memcpy(pMedium->u.hGlobal, current->data, current->size);
+ memcpy(pMedium->u.hGlobal,
GlobalLock(current->contents), GlobalSize(current->contents));
+ GlobalUnlock(current->contents);
pMedium->pUnkForRelease = 0;
return S_OK;
}
--
1.8.5.4
More information about the wine-patches
mailing list