winex11: Use format_entry to store cached XDND formats data.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2022-04-27 14:01:17 +01:00 committed by Alexandre Julliard
parent f7ac2c7833
commit d25c8c5770
1 changed files with 33 additions and 76 deletions

View File

@ -45,14 +45,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(xdnd); WINE_DEFAULT_DEBUG_CHANNEL(xdnd);
typedef struct tagXDNDDATA static struct format_entry *xdnd_formats, *xdnd_formats_end;
{
int cf_win;
HANDLE contents;
struct list entry;
} XDNDDATA, *LPXDNDDATA;
static struct list xdndData = LIST_INIT(xdndData);
static POINT XDNDxy = { 0, 0 }; static POINT XDNDxy = { 0, 0 };
static IDataObject XDNDDataObject; static IDataObject XDNDDataObject;
static BOOL XDNDAccepted = FALSE; static BOOL XDNDAccepted = FALSE;
@ -62,7 +55,6 @@ static HWND XDNDLastTargetWnd;
/* might be an ancestor of XDNDLastTargetWnd */ /* might be an ancestor of XDNDLastTargetWnd */
static HWND XDNDLastDropTargetWnd; static HWND XDNDLastDropTargetWnd;
static void X11DRV_XDND_InsertXDNDData( UINT format, HANDLE contents );
static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm, static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
Atom *types, unsigned long count); Atom *types, unsigned long count);
static BOOL X11DRV_XDND_HasHDROP(void); static BOOL X11DRV_XDND_HasHDROP(void);
@ -529,7 +521,7 @@ void X11DRV_XDND_LeaveEvent( HWND hWnd, XClientMessageEvent *event )
static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm, static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
Atom *types, unsigned long count) Atom *types, unsigned long count)
{ {
struct format_entry *formats, *formats_end, *iter; struct format_entry *formats;
size_t size; size_t size;
TRACE("count(%ld)\n", count); TRACE("count(%ld)\n", count);
@ -537,41 +529,14 @@ static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
X11DRV_XDND_FreeDragDropOp(); /* Clear previously cached data */ X11DRV_XDND_FreeDragDropOp(); /* Clear previously cached data */
formats = import_xdnd_selection( display, xwin, x11drv_atom(XdndSelection), types, count, &size ); formats = import_xdnd_selection( display, xwin, x11drv_atom(XdndSelection), types, count, &size );
if (formats) if (!formats) return;
{
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 );
}
}
}
}
if ((xdnd_formats = HeapAlloc( GetProcessHeap(), 0, size )))
/**************************************************************************
* X11DRV_XDND_InsertXDNDData
*
* Cache available XDND property
*/
static void X11DRV_XDND_InsertXDNDData( UINT format, HANDLE contents )
{
LPXDNDDATA current = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(XDNDDATA));
if (current)
{ {
EnterCriticalSection(&xdnd_cs); memcpy( xdnd_formats, formats, size );
current->cf_win = format; xdnd_formats_end = (struct format_entry *)((char *)xdnd_formats + size);
current->contents = contents;
list_add_tail(&xdndData, &current->entry);
LeaveCriticalSection(&xdnd_cs);
} }
free( formats );
} }
@ -580,15 +545,15 @@ static void X11DRV_XDND_InsertXDNDData( UINT format, HANDLE contents )
*/ */
static BOOL X11DRV_XDND_HasHDROP(void) static BOOL X11DRV_XDND_HasHDROP(void)
{ {
LPXDNDDATA current = NULL; struct format_entry *iter;
BOOL found = FALSE; BOOL found = FALSE;
EnterCriticalSection(&xdnd_cs); EnterCriticalSection(&xdnd_cs);
/* Find CF_HDROP type if any */ /* Find CF_HDROP type if any */
LIST_FOR_EACH_ENTRY(current, &xdndData, XDNDDATA, entry) for (iter = xdnd_formats; iter < xdnd_formats_end; iter = next_format( iter ))
{ {
if (current->cf_win == CF_HDROP) if (iter->format == CF_HDROP)
{ {
found = TRUE; found = TRUE;
break; break;
@ -605,15 +570,15 @@ static BOOL X11DRV_XDND_HasHDROP(void)
*/ */
static HRESULT X11DRV_XDND_SendDropFiles(HWND hwnd) static HRESULT X11DRV_XDND_SendDropFiles(HWND hwnd)
{ {
struct format_entry *iter;
HRESULT hr; HRESULT hr;
LPXDNDDATA current = NULL;
BOOL found = FALSE; BOOL found = FALSE;
EnterCriticalSection(&xdnd_cs); EnterCriticalSection(&xdnd_cs);
LIST_FOR_EACH_ENTRY(current, &xdndData, XDNDDATA, entry) for (iter = xdnd_formats; iter < xdnd_formats_end; iter = next_format( iter ))
{ {
if (current->cf_win == CF_HDROP) if (iter->format == CF_HDROP)
{ {
found = TRUE; found = TRUE;
break; break;
@ -621,13 +586,12 @@ static HRESULT X11DRV_XDND_SendDropFiles(HWND hwnd)
} }
if (found) if (found)
{ {
HGLOBAL dropHandle = GlobalAlloc(GMEM_FIXED, GlobalSize(current->contents)); HGLOBAL dropHandle = GlobalAlloc(GMEM_FIXED, iter->size);
if (dropHandle) if (dropHandle)
{ {
RECT rect; RECT rect;
DROPFILES *lpDrop = GlobalLock(dropHandle); DROPFILES *lpDrop = GlobalLock(dropHandle);
memcpy(lpDrop, GlobalLock(current->contents), GlobalSize(current->contents)); memcpy(lpDrop, iter->data, iter->size);
GlobalUnlock(current->contents);
lpDrop->pt.x = XDNDxy.x; lpDrop->pt.x = XDNDxy.x;
lpDrop->pt.y = XDNDxy.y; lpDrop->pt.y = XDNDxy.y;
lpDrop->fNC = !(ScreenToClient(hwnd, &lpDrop->pt) && lpDrop->fNC = !(ScreenToClient(hwnd, &lpDrop->pt) &&
@ -662,20 +626,12 @@ static HRESULT X11DRV_XDND_SendDropFiles(HWND hwnd)
*/ */
static void X11DRV_XDND_FreeDragDropOp(void) static void X11DRV_XDND_FreeDragDropOp(void)
{ {
LPXDNDDATA next;
LPXDNDDATA current;
TRACE("\n"); TRACE("\n");
EnterCriticalSection(&xdnd_cs); EnterCriticalSection(&xdnd_cs);
/** Free data cache */ HeapFree( GetProcessHeap(), 0, xdnd_formats );
LIST_FOR_EACH_ENTRY_SAFE(current, next, &xdndData, XDNDDATA, entry) xdnd_formats = xdnd_formats_end = NULL;
{
list_remove(&current->entry);
GlobalFree(current->contents);
HeapFree(GetProcessHeap(), 0, current);
}
XDNDxy.x = XDNDxy.y = 0; XDNDxy.x = XDNDxy.y = 0;
XDNDLastTargetWnd = NULL; XDNDLastTargetWnd = NULL;
@ -772,18 +728,18 @@ static HRESULT WINAPI XDNDDATAOBJECT_GetData(IDataObject *dataObject,
hr = IDataObject_QueryGetData(dataObject, formatEtc); hr = IDataObject_QueryGetData(dataObject, formatEtc);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
XDNDDATA *current; struct format_entry *iter;
LIST_FOR_EACH_ENTRY(current, &xdndData, XDNDDATA, entry)
for (iter = xdnd_formats; iter < xdnd_formats_end; iter = next_format( iter ))
{ {
if (current->cf_win == formatEtc->cfFormat) if (iter->format == formatEtc->cfFormat)
{ {
pMedium->tymed = TYMED_HGLOBAL; pMedium->tymed = TYMED_HGLOBAL;
pMedium->u.hGlobal = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, GlobalSize(current->contents)); pMedium->u.hGlobal = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, iter->size);
if (pMedium->u.hGlobal == NULL) if (pMedium->u.hGlobal == NULL)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
memcpy(GlobalLock(pMedium->u.hGlobal), GlobalLock(current->contents), GlobalSize(current->contents)); memcpy(GlobalLock(pMedium->u.hGlobal), iter->data, iter->size);
GlobalUnlock(pMedium->u.hGlobal); GlobalUnlock(pMedium->u.hGlobal);
GlobalUnlock(current->contents);
pMedium->pUnkForRelease = 0; pMedium->pUnkForRelease = 0;
return S_OK; return S_OK;
} }
@ -803,8 +759,8 @@ static HRESULT WINAPI XDNDDATAOBJECT_GetDataHere(IDataObject *dataObject,
static HRESULT WINAPI XDNDDATAOBJECT_QueryGetData(IDataObject *dataObject, static HRESULT WINAPI XDNDDATAOBJECT_QueryGetData(IDataObject *dataObject,
FORMATETC *formatEtc) FORMATETC *formatEtc)
{ {
struct format_entry *iter;
char formatDesc[1024]; char formatDesc[1024];
XDNDDATA *current;
TRACE("(%p, %p={.tymed=0x%x, .dwAspect=%d, .cfFormat=%d}\n", TRACE("(%p, %p={.tymed=0x%x, .dwAspect=%d, .cfFormat=%d}\n",
dataObject, formatEtc, formatEtc->tymed, formatEtc->dwAspect, formatEtc->cfFormat); dataObject, formatEtc, formatEtc->tymed, formatEtc->dwAspect, formatEtc->cfFormat);
@ -819,9 +775,9 @@ static HRESULT WINAPI XDNDDATAOBJECT_QueryGetData(IDataObject *dataObject,
* and we have no way to implement them on XDnD anyway, so ignore them too. * and we have no way to implement them on XDnD anyway, so ignore them too.
*/ */
LIST_FOR_EACH_ENTRY(current, &xdndData, XDNDDATA, entry) for (iter = xdnd_formats; iter < xdnd_formats_end; iter = next_format( iter ))
{ {
if (current->cf_win == formatEtc->cfFormat) if (iter->format == formatEtc->cfFormat)
{ {
TRACE("application found %s\n", formatDesc); TRACE("application found %s\n", formatDesc);
return S_OK; return S_OK;
@ -853,7 +809,8 @@ static HRESULT WINAPI XDNDDATAOBJECT_EnumFormatEtc(IDataObject *dataObject,
DWORD dwDirection, DWORD dwDirection,
IEnumFORMATETC **ppEnumFormatEtc) IEnumFORMATETC **ppEnumFormatEtc)
{ {
DWORD count; struct format_entry *iter;
DWORD count = 0;
FORMATETC *formats; FORMATETC *formats;
TRACE("(%p, %u, %p)\n", dataObject, dwDirection, ppEnumFormatEtc); TRACE("(%p, %u, %p)\n", dataObject, dwDirection, ppEnumFormatEtc);
@ -864,16 +821,16 @@ static HRESULT WINAPI XDNDDATAOBJECT_EnumFormatEtc(IDataObject *dataObject,
return E_NOTIMPL; return E_NOTIMPL;
} }
count = list_count(&xdndData); for (iter = xdnd_formats; iter < xdnd_formats_end; iter = next_format( iter )) count++;
formats = HeapAlloc(GetProcessHeap(), 0, count * sizeof(FORMATETC)); formats = HeapAlloc(GetProcessHeap(), 0, count * sizeof(FORMATETC));
if (formats) if (formats)
{ {
XDNDDATA *current;
DWORD i = 0; DWORD i = 0;
HRESULT hr; HRESULT hr;
LIST_FOR_EACH_ENTRY(current, &xdndData, XDNDDATA, entry) for (iter = xdnd_formats; iter < xdnd_formats_end; iter = next_format( iter ))
{ {
formats[i].cfFormat = current->cf_win; formats[i].cfFormat = iter->format;
formats[i].ptd = NULL; formats[i].ptd = NULL;
formats[i].dwAspect = DVASPECT_CONTENT; formats[i].dwAspect = DVASPECT_CONTENT;
formats[i].lindex = -1; formats[i].lindex = -1;