- 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.
This commit is contained in:
parent
dba83c8bfc
commit
651c5988aa
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue