Commit 651c5988 authored by Ulrich Czekalla's avatar Ulrich Czekalla Committed by Alexandre Julliard

- Add a max wait time for selection notifies.

- Add new function to the x11drv to get clipboard format names of externally registered formats. - When a clipboard format is registered we should pass the global atom value as the format identifier. - Clipboard format name should be treated as case insensitive. - Serialize metafile bits when requested via a clipboard selection. - Return format ids for native formats when mapping from properties.
parent dba83c8b
......@@ -95,6 +95,7 @@ static BOOL load_driver(void)
GET_USER_FUNC(GetClipboardData);
GET_USER_FUNC(IsClipboardFormatAvailable);
GET_USER_FUNC(RegisterClipboardFormat);
GET_USER_FUNC(GetClipboardFormatName);
GET_USER_FUNC(IsSelectionOwner);
GET_USER_FUNC(ResetSelectionOwner);
GET_USER_FUNC(CreateWindow);
......
......@@ -68,6 +68,7 @@
# include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#include "ts_xlib.h"
#include "winreg.h"
......@@ -78,6 +79,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
/* Maximum wait time for slection notify */
#define MAXSELECTIONNOTIFYWAIT 5
/* Selection masks */
#define S_NOSELECTION 0
......@@ -187,21 +191,20 @@ Atom X11DRV_CLIPBOARD_MapFormatToProperty(UINT wFormat)
* Otherwise register a new atom.
*/
char str[256];
char *fmtName = CLIPBOARD_GetFormatName(wFormat);
int plen = strlen(FMT_PREFIX);
strcpy(str, FMT_PREFIX);
if (fmtName)
{
strncat(str, fmtName, sizeof(str) - strlen(FMT_PREFIX));
if (CLIPBOARD_GetFormatName(wFormat, str + plen, sizeof(str) - plen))
prop = TSXInternAtom(thread_display(), str, False);
}
break;
}
}
if (prop == None)
TRACE("\tNo mapping to X property for Windows clipboard format %d(%s)\n",
wFormat, CLIPBOARD_GetFormatName(wFormat));
wFormat, CLIPBOARD_GetFormatName(wFormat, NULL, 0));
return prop;
}
......@@ -377,6 +380,7 @@ int X11DRV_CLIPBOARD_CacheDataFormats( Atom SelectionName )
Atom* targetList=NULL;
Window w;
Window ownerSelection = 0;
time_t maxtm;
TRACE("enter\n");
/*
......@@ -410,7 +414,8 @@ int X11DRV_CLIPBOARD_CacheDataFormats( Atom SelectionName )
/*
* Wait until SelectionNotify is received
*/
while( TRUE )
maxtm = time(NULL) + MAXSELECTIONNOTIFYWAIT; /* Timeout after a maximum wait */
while( maxtm - time(NULL) > 0 )
{
if( XCheckTypedWindowEvent(display, w, SelectionNotify, &xe) )
if( xe.xselection.selection == selectionCacheSrc )
......@@ -624,9 +629,9 @@ static BOOL X11DRV_CLIPBOARD_ReadSelection(UINT wFormat, Window w, Atom prop, At
GlobalUnlock(hUnicodeText);
if (!SetClipboardData(CF_UNICODETEXT, hUnicodeText))
{
ERR("Not SET! Need to free our own block\n");
GlobalFree(hUnicodeText);
}
ERR("Not SET! Need to free our own block\n");
GlobalFree(hUnicodeText);
}
bRet = TRUE;
}
HeapFree(GetProcessHeap(), 0, lpstr);
......@@ -689,15 +694,22 @@ static BOOL X11DRV_CLIPBOARD_ReadSelection(UINT wFormat, Window w, Atom prop, At
if( cBytes )
{
/* Turn on the DDESHARE flag to enable shared 32 bit memory */
hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cBytes );
if( (lpClipData = GlobalLock(hClipData)) )
{
memcpy(lpClipData, val, cBytes);
GlobalUnlock(hClipData);
}
else
hClipData = 0;
if (wFormat == CF_METAFILEPICT || wFormat == CF_ENHMETAFILE)
{
hClipData = X11DRV_CLIPBOARD_SerializeMetafile(wFormat, (HANDLE)val, cBytes, FALSE);
}
else
{
/* Turn on the DDESHARE flag to enable shared 32 bit memory */
hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cBytes );
if( (lpClipData = GlobalLock(hClipData)) )
{
memcpy(lpClipData, val, cBytes);
GlobalUnlock(hClipData);
}
else
hClipData = 0;
}
}
if( hClipData )
......@@ -1022,9 +1034,9 @@ BOOL X11DRV_IsClipboardFormatAvailable(UINT wFormat)
* RegisterClipboardFormat (X11DRV.@)
*
* Registers a custom X clipboard format
* Returns: TRUE - success, FALSE - failure
* Returns: Format id or 0 on failure
*/
BOOL X11DRV_RegisterClipboardFormat( LPCSTR FormatName )
INT X11DRV_RegisterClipboardFormat( LPCSTR FormatName )
{
Display *display = thread_display();
Atom prop = None;
......@@ -1042,7 +1054,7 @@ BOOL X11DRV_RegisterClipboardFormat( LPCSTR FormatName )
prop = TSXInternAtom(display, str, False);
}
return (prop) ? TRUE : FALSE;
return prop;
}
/**************************************************************************
......@@ -1141,7 +1153,7 @@ BOOL X11DRV_GetClipboardData(UINT wFormat)
else
bRet = FALSE;
TRACE("\tpresent %s = %i\n", CLIPBOARD_GetFormatName(wFormat), bRet );
TRACE("\tpresent %s = %i\n", CLIPBOARD_GetFormatName(wFormat, NULL, 0), bRet );
}
TRACE("Returning %d\n", bRet);
......@@ -1313,3 +1325,89 @@ void X11DRV_CLIPBOARD_FreeResources( Atom property )
else prop = &(*prop)->next;
}
}
/**************************************************************************
* X11DRV_GetClipboardFormatName
*/
BOOL X11DRV_GetClipboardFormatName( UINT wFormat, LPSTR retStr, UINT maxlen )
{
BOOL bRet = FALSE;
char *itemFmtName = TSXGetAtomName(thread_display(), wFormat);
INT prefixlen = strlen(FMT_PREFIX);
if ( 0 == strncmp(itemFmtName, FMT_PREFIX, prefixlen ) )
{
strncpy(retStr, itemFmtName + prefixlen, maxlen);
bRet = TRUE;
}
TSXFree(itemFmtName);
return bRet;
}
/**************************************************************************
* CLIPBOARD_SerializeMetafile
*/
HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, INT cbytes, BOOL out)
{
HANDLE h = 0;
if (out) /* Serialize out, caller should free memory */
{
if (wformat == CF_METAFILEPICT)
{
LPMETAFILEPICT lpmfp = (LPMETAFILEPICT) GlobalLock(hdata);
int size = GetMetaFileBitsEx(lpmfp->hMF, 0, NULL);
h = GlobalAlloc(0, size + sizeof(METAFILEPICT));
if (h)
{
LPVOID pdata = GlobalLock(h);
memcpy(pdata, lpmfp, sizeof(METAFILEPICT));
GetMetaFileBitsEx(lpmfp->hMF, size, pdata + sizeof(METAFILEPICT));
GlobalUnlock(h);
}
GlobalUnlock(hdata);
}
else if (wformat == CF_ENHMETAFILE)
{
int size = GetEnhMetaFileBits(hdata, 0, NULL);
h = GlobalAlloc(0, size);
if (h)
{
LPVOID pdata = GlobalLock(h);
GetEnhMetaFileBits(hdata, size, pdata);
GlobalUnlock(h);
}
}
}
else
{
if (wformat == CF_METAFILEPICT)
{
h = GlobalAlloc(0, sizeof(METAFILEPICT));
if (h)
{
LPMETAFILEPICT pmfp = (LPMETAFILEPICT) GlobalLock(h);
memcpy(pmfp, (LPVOID)hdata, sizeof(METAFILEPICT));
pmfp->hMF = SetMetaFileBitsEx(cbytes - sizeof(METAFILEPICT),
(LPVOID)hdata + sizeof(METAFILEPICT));
GlobalUnlock(h);
}
}
else if (wformat == CF_ENHMETAFILE)
{
h = SetEnhMetaFileBits(cbytes, (LPVOID)hdata);
}
}
return h;
}
......@@ -584,7 +584,7 @@ static Atom EVENT_SelectionRequest_STRING( Display *display, Window requestor,
*/
itemFmtName = TSXGetAtomName(display, target);
TRACE("Request for %s (wFormat=%x %s)\n",
itemFmtName, CF_UNICODETEXT, CLIPBOARD_GetFormatName(CF_UNICODETEXT));
itemFmtName, CF_UNICODETEXT, CLIPBOARD_GetFormatName(CF_UNICODETEXT, NULL, 0));
TSXFree(itemFmtName);
hUnicodeText = GetClipboardData(CF_UNICODETEXT);
......@@ -650,7 +650,7 @@ static Atom EVENT_SelectionRequest_PIXMAP( Display *display, Window requestor,
itemFmtName = TSXGetAtomName(display, target);
wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
TRACE("Request for %s (wFormat=%x %s)\n",
itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat));
itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat, NULL, 0 ));
TSXFree(itemFmtName);
hClipData = GetClipboardData(wFormat);
......@@ -683,7 +683,7 @@ static Atom EVENT_SelectionRequest_PIXMAP( Display *display, Window requestor,
else
{
FIXME("%s to PIXMAP conversion not yet implemented!\n",
CLIPBOARD_GetFormatName(wFormat));
CLIPBOARD_GetFormatName(wFormat, NULL, 0));
rprop = None;
goto END;
}
......@@ -739,6 +739,7 @@ static Atom EVENT_SelectionRequest_WCF( Display *display, Window requestor,
char * itemFmtName;
int cBytes;
int xRc;
int bemf;
/*
* Map the requested X selection property type atom name to a
......@@ -747,11 +748,15 @@ static Atom EVENT_SelectionRequest_WCF( Display *display, Window requestor,
itemFmtName = TSXGetAtomName(display, target);
wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
TRACE("Request for %s (wFormat=%x %s)\n",
itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat));
itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat, NULL, 0));
TSXFree(itemFmtName);
hClipData = GetClipboardData(wFormat);
bemf = wFormat == CF_METAFILEPICT || wFormat == CF_ENHMETAFILE;
if (bemf)
hClipData = X11DRV_CLIPBOARD_SerializeMetafile(wFormat, hClipData, sizeof(hClipData), TRUE);
if( hClipData && (lpClipData = GlobalLock(hClipData)) )
{
cBytes = GlobalSize(hClipData);
......@@ -772,6 +777,9 @@ static Atom EVENT_SelectionRequest_WCF( Display *display, Window requestor,
rprop = None; /* Fail the request */
}
if (bemf) /* We must free serialized metafile data */
GlobalFree(hClipData);
return rprop;
}
......
......@@ -96,5 +96,6 @@ init X11DRV_Init
@ cdecl GetClipboardData(long) X11DRV_GetClipboardData
@ cdecl IsClipboardFormatAvailable(long) X11DRV_IsClipboardFormatAvailable
@ cdecl RegisterClipboardFormat(str) X11DRV_RegisterClipboardFormat
@ cdecl GetClipboardFormatName(long str long) X11DRV_GetClipboardFormatName
@ cdecl IsSelectionOwner() X11DRV_IsSelectionOwner
@ cdecl ResetSelectionOwner(ptr long) X11DRV_ResetSelectionOwner
......@@ -44,7 +44,7 @@ extern BOOL CLIPBOARD_IsCacheRendered();
extern void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange);
extern void CLIPBOARD_EmptyCache( BOOL bChange );
extern BOOL CLIPBOARD_IsPresent(WORD wFormat);
extern char * CLIPBOARD_GetFormatName(UINT wFormat);
extern char * CLIPBOARD_GetFormatName(UINT wFormat, LPSTR buf, INT size);
extern void CLIPBOARD_ReleaseOwner();
#endif /* __WINE_CLIPBOARD_H */
......@@ -86,7 +86,8 @@ typedef struct tagUSER_DRIVER {
void (*pSetClipboardData)(UINT); /* Set specified selection data */
BOOL (*pGetClipboardData)(UINT); /* Get specified selection data */
BOOL (*pIsClipboardFormatAvailable)(UINT); /* Check if specified format is available */
BOOL (*pRegisterClipboardFormat)(LPCSTR); /* Register a clipboard format */
INT (*pRegisterClipboardFormat)(LPCSTR); /* Register a clipboard format */
BOOL (*pGetClipboardFormatName)(UINT, LPSTR, UINT); /* Get a clipboard format name */
BOOL (*pIsSelectionOwner)(void); /* Check if we own the selection */
void (*pResetSelectionOwner)(HWND, BOOL);
......
......@@ -366,6 +366,7 @@ extern Atom X11DRV_CLIPBOARD_MapFormatToProperty(UINT id);
extern void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd);
extern BOOL X11DRV_IsSelectionOwner(void);
extern BOOL X11DRV_GetClipboardData(UINT wFormat);
extern HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, INT cbytes, BOOL out);
/* X11 event driver */
......
......@@ -66,8 +66,6 @@ static HWND hWndClipOwner; /* current clipboard owner */
static HANDLE16 hTaskClipOwner; /* clipboard owner's task */
static HWND hWndViewer; /* start of viewers chain */
static WORD LastRegFormat = CF_REGFORMATBASE;
/* Clipboard cache initial data.
* WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
* declared in clipboard.h
......@@ -90,7 +88,8 @@ WINE_CLIPFORMAT ClipFormats[] = {
{ CF_DSPTEXT, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats[13], &ClipFormats[15]},
{ CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats[14], &ClipFormats[16]},
{ CF_DSPBITMAP, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats[15], &ClipFormats[17]},
{ CF_HDROP, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats[16], NULL}
{ CF_HDROP, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats[16], &ClipFormats[18]},
{ CF_ENHMETAFILE, 1, 0, "Enhmetafile", 0, 0, 0, 0, &ClipFormats[17], NULL}
};
......@@ -391,10 +390,22 @@ HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
* CLIPBOARD_GetFormatName
* Gets the format name associated with an ID
*/
char * CLIPBOARD_GetFormatName(UINT wFormat)
char * CLIPBOARD_GetFormatName(UINT wFormat, LPSTR buf, INT size)
{
LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
return (lpFormat) ? lpFormat->Name : NULL;
if (lpFormat)
{
if (buf)
{
strncpy(buf, lpFormat->Name, size);
CharLowerA(buf);
}
return lpFormat->Name;
}
else
return NULL;
}
......@@ -1126,7 +1137,7 @@ INT WINAPI CountClipboardFormats(void)
&& USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) ) )
{
TRACE("\tdata found for format 0x%04x(%s)\n",
lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID));
lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID, NULL, 0));
FormatCount++;
}
}
......@@ -1185,7 +1196,7 @@ UINT WINAPI RegisterClipboardFormatA( LPCSTR FormatName )
while(TRUE)
{
if ( !strcmp(lpFormat->Name,FormatName) )
if ( !strcasecmp(lpFormat->Name,FormatName) )
{
lpFormat->wRefCount++;
return lpFormat->wFormatID;
......@@ -1204,7 +1215,6 @@ UINT WINAPI RegisterClipboardFormatA( LPCSTR FormatName )
return 0;
}
lpFormat->NextFormat = lpNewFormat;
lpNewFormat->wFormatID = LastRegFormat;
lpNewFormat->wRefCount = 1;
if (!(lpNewFormat->Name = HeapAlloc(GetProcessHeap(), 0, strlen(FormatName)+1 )))
......@@ -1214,6 +1224,7 @@ UINT WINAPI RegisterClipboardFormatA( LPCSTR FormatName )
return 0;
}
strcpy( lpNewFormat->Name, FormatName );
CharLowerA(lpNewFormat->Name);
lpNewFormat->wDataPresent = 0;
lpNewFormat->hData16 = 0;
......@@ -1224,9 +1235,10 @@ UINT WINAPI RegisterClipboardFormatA( LPCSTR FormatName )
lpNewFormat->NextFormat = NULL;
/* Pass on the registration request to the driver */
USER_Driver.pRegisterClipboardFormat( FormatName );
lpNewFormat->wFormatID = USER_Driver.pRegisterClipboardFormat(lpNewFormat->Name);
return LastRegFormat++;
TRACE("Registering format(%d): %s\n", lpNewFormat->wFormatID, FormatName);
return lpNewFormat->wFormatID;
}
......@@ -1269,8 +1281,20 @@ INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
if (lpFormat == NULL || lpFormat->Name == NULL ||
lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
if (lpFormat == NULL || lpFormat->Name == NULL)
{
/* Check if another wine process already registered the format */
if (wFormat && !USER_Driver.pGetClipboardFormatName(wFormat, retStr, maxlen))
{
RegisterClipboardFormatA(retStr); /* Make a cache entry */
return strlen(retStr);
}
else
{
TRACE("wFormat=%d not found\n", wFormat);
return 0;
}
}
TRACE("Name='%s' !\n", lpFormat->Name);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment