hw/xwin: Implement INCR protocol for X clipboard -> Windows clipboard
Also, relax the timeout mechanism so it allows 1 second between events, rather than 1 second for the entire transfer, as transfers of large pastes can take more than 1 second. Also, prefer UTF8_STRING encoding to COMPOUND_TEXT encoding
This commit is contained in:
parent
4f95d87d66
commit
56a91f2067
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
*Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
|
||||
*
|
||||
|
@ -38,7 +37,7 @@
|
|||
/* Windows headers */
|
||||
#include <X11/Xwindows.h>
|
||||
|
||||
#define WIN_XEVENTS_SUCCESS 0
|
||||
#define WIN_XEVENTS_SUCCESS 0 // more like 'CONTINUE'
|
||||
#define WIN_XEVENTS_FAILED 1
|
||||
#define WIN_XEVENTS_NOTIFY_DATA 3
|
||||
#define WIN_XEVENTS_NOTIFY_TARGETS 4
|
||||
|
@ -77,6 +76,7 @@ typedef struct
|
|||
Atom atomUTF8String;
|
||||
Atom atomCompoundText;
|
||||
Atom atomTargets;
|
||||
Atom atomIncr;
|
||||
} ClipboardAtoms;
|
||||
|
||||
/* Modern clipboard API functions */
|
||||
|
@ -111,6 +111,8 @@ typedef struct
|
|||
{
|
||||
Bool fUseUnicode;
|
||||
Atom *targetList;
|
||||
unsigned char *incr;
|
||||
unsigned long int incrsize;
|
||||
} ClipboardConversionData;
|
||||
|
||||
int
|
||||
|
|
|
@ -199,6 +199,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
|
|||
atoms.atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False);
|
||||
atoms.atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False);
|
||||
atoms.atomTargets = XInternAtom (pDisplay, "TARGETS", False);
|
||||
atoms.atomIncr = XInternAtom (pDisplay, "INCR", False);
|
||||
|
||||
/* Create a messaging window */
|
||||
iWindow = XCreateSimpleWindow(pDisplay,
|
||||
|
@ -265,6 +266,8 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
|
|||
}
|
||||
|
||||
data.fUseUnicode = fUseUnicode;
|
||||
data.incr = NULL;
|
||||
data.incrsize = 0;
|
||||
|
||||
/* Loop for events */
|
||||
while (1) {
|
||||
|
|
|
@ -73,9 +73,8 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay,
|
|||
int iConnNumber;
|
||||
struct timeval tv;
|
||||
int iReturn;
|
||||
DWORD dwStopTime = GetTickCount() + iTimeoutSec * 1000;
|
||||
|
||||
winDebug("winProcessXEventsTimeout () - pumping X events for %d seconds\n",
|
||||
winDebug("winProcessXEventsTimeout () - pumping X events, timeout %d seconds\n",
|
||||
iTimeoutSec);
|
||||
|
||||
/* Get our connection number */
|
||||
|
@ -104,11 +103,9 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay,
|
|||
FD_SET(iConnNumber, &fdsRead);
|
||||
|
||||
/* Adjust timeout */
|
||||
remainingTime = dwStopTime - GetTickCount();
|
||||
remainingTime = iTimeoutSec * 1000;
|
||||
tv.tv_sec = remainingTime / 1000;
|
||||
tv.tv_usec = (remainingTime % 1000) * 1000;
|
||||
winDebug("winProcessXEventsTimeout () - %ld milliseconds left\n",
|
||||
remainingTime);
|
||||
|
||||
/* Break out if no time left */
|
||||
if (remainingTime <= 0)
|
||||
|
@ -494,6 +491,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
/* Process X events */
|
||||
data.fUseUnicode = fConvertToUnicode;
|
||||
data.incr = NULL;
|
||||
data.incrsize = 0;
|
||||
|
||||
iReturn = winProcessXEventsTimeout(hwnd,
|
||||
iWindow,
|
||||
pDisplay,
|
||||
|
@ -517,10 +517,10 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
struct target_priority target_priority_table[] =
|
||||
{
|
||||
{ atoms->atomCompoundText, 0 },
|
||||
#ifdef X_HAVE_UTF8_STRING
|
||||
{ atoms->atomUTF8String, 1 },
|
||||
{ atoms->atomUTF8String, 0 },
|
||||
#endif
|
||||
{ atoms->atomCompoundText, 1 },
|
||||
{ XA_STRING, 2 },
|
||||
};
|
||||
|
||||
|
|
|
@ -184,6 +184,271 @@ winClipboardSelectionNotifyTargets(HWND hwnd, Window iWindow, Display *pDisplay,
|
|||
return WIN_XEVENTS_NOTIFY_TARGETS;
|
||||
}
|
||||
|
||||
static int
|
||||
winClipboardSelectionNotifyData(HWND hwnd, Window iWindow, Display *pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms)
|
||||
{
|
||||
Atom encoding;
|
||||
int format;
|
||||
unsigned long int nitems;
|
||||
unsigned long int after;
|
||||
unsigned char *value;
|
||||
XTextProperty xtpText = { 0 };
|
||||
Bool fSetClipboardData = TRUE;
|
||||
int iReturn;
|
||||
char **ppszTextList = NULL;
|
||||
int iCount;
|
||||
char *pszReturnData = NULL;
|
||||
wchar_t *pwszUnicodeStr = NULL;
|
||||
HGLOBAL hGlobal = NULL;
|
||||
char *pszConvertData = NULL;
|
||||
char *pszGlobalData = NULL;
|
||||
|
||||
/* Retrieve the selection data and delete the property */
|
||||
iReturn = XGetWindowProperty(pDisplay,
|
||||
iWindow,
|
||||
atoms->atomLocalProperty,
|
||||
0,
|
||||
INT_MAX,
|
||||
True,
|
||||
AnyPropertyType,
|
||||
&encoding,
|
||||
&format,
|
||||
&nitems,
|
||||
&after,
|
||||
&value);
|
||||
if (iReturn != Success) {
|
||||
ErrorF("winClipboardFlushXEvents - SelectionNotify - "
|
||||
"XGetWindowProperty () failed, aborting: %d\n", iReturn);
|
||||
goto winClipboardFlushXEvents_SelectionNotify_Done;
|
||||
}
|
||||
|
||||
{
|
||||
char *pszAtomName = NULL;
|
||||
|
||||
winDebug("SelectionNotify - returned data %lu left %lu\n", nitems, after);
|
||||
pszAtomName = XGetAtomName(pDisplay, encoding);
|
||||
winDebug("Notify atom name %s\n", pszAtomName);
|
||||
XFree(pszAtomName);
|
||||
pszAtomName = NULL;
|
||||
}
|
||||
|
||||
/* INCR reply indicates the start of a incremental transfer */
|
||||
if (encoding == atoms->atomIncr) {
|
||||
winDebug("winClipboardSelectionNotifyData: starting INCR, anticipated size %d\n", *(int *)value);
|
||||
data->incrsize = 0;
|
||||
data->incr = malloc(*(int *)value);
|
||||
// XXX: if malloc failed, we have an error
|
||||
return WIN_XEVENTS_SUCCESS;
|
||||
}
|
||||
else if (data->incr) {
|
||||
/* If an INCR transfer is in progress ... */
|
||||
if (nitems == 0) {
|
||||
winDebug("winClipboardSelectionNotifyData: ending INCR, actual size %ld\n", data->incrsize);
|
||||
/* a zero-length property indicates the end of the data */
|
||||
xtpText.value = data->incr;
|
||||
xtpText.encoding = encoding;
|
||||
xtpText.format = format; // XXX: The type of the converted selection is the type of the first partial property. The remaining partial properties must have the same type.
|
||||
xtpText.nitems = data->incrsize;
|
||||
}
|
||||
else {
|
||||
/* Otherwise, continue appending the INCR data */
|
||||
winDebug("winClipboardSelectionNotifyData: INCR, %ld bytes\n", nitems);
|
||||
data->incr = realloc(data->incr, data->incrsize + nitems);
|
||||
memcpy(data->incr + data->incrsize, value, nitems);
|
||||
data->incrsize = data->incrsize + nitems;
|
||||
return WIN_XEVENTS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Otherwise, the data is just contained in the property */
|
||||
winDebug("winClipboardSelectionNotifyData: non-INCR, %ld bytes\n", nitems);
|
||||
xtpText.value = value;
|
||||
xtpText.encoding = encoding;
|
||||
xtpText.format = format;
|
||||
xtpText.nitems = nitems;
|
||||
}
|
||||
|
||||
if (data->fUseUnicode) {
|
||||
#ifdef X_HAVE_UTF8_STRING
|
||||
/* Convert the text property to a text list */
|
||||
iReturn = Xutf8TextPropertyToTextList(pDisplay,
|
||||
&xtpText,
|
||||
&ppszTextList, &iCount);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
iReturn = XmbTextPropertyToTextList(pDisplay,
|
||||
&xtpText,
|
||||
&ppszTextList, &iCount);
|
||||
}
|
||||
if (iReturn == Success || iReturn > 0) {
|
||||
/* Conversion succeeded or some unconvertible characters */
|
||||
if (ppszTextList != NULL) {
|
||||
int i;
|
||||
int iReturnDataLen = 0;
|
||||
for (i = 0; i < iCount; i++) {
|
||||
iReturnDataLen += strlen(ppszTextList[i]);
|
||||
}
|
||||
pszReturnData = malloc(iReturnDataLen + 1);
|
||||
pszReturnData[0] = '\0';
|
||||
for (i = 0; i < iCount; i++) {
|
||||
strcat(pszReturnData, ppszTextList[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ErrorF("winClipboardFlushXEvents - SelectionNotify - "
|
||||
"X*TextPropertyToTextList list_return is NULL.\n");
|
||||
pszReturnData = malloc(1);
|
||||
pszReturnData[0] = '\0';
|
||||
}
|
||||
}
|
||||
else {
|
||||
ErrorF("winClipboardFlushXEvents - SelectionNotify - "
|
||||
"X*TextPropertyToTextList returned: ");
|
||||
switch (iReturn) {
|
||||
case XNoMemory:
|
||||
ErrorF("XNoMemory\n");
|
||||
break;
|
||||
case XLocaleNotSupported:
|
||||
ErrorF("XLocaleNotSupported\n");
|
||||
break;
|
||||
case XConverterNotFound:
|
||||
ErrorF("XConverterNotFound\n");
|
||||
break;
|
||||
default:
|
||||
ErrorF("%d\n", iReturn);
|
||||
break;
|
||||
}
|
||||
pszReturnData = malloc(1);
|
||||
pszReturnData[0] = '\0';
|
||||
}
|
||||
|
||||
|
||||
if (ppszTextList)
|
||||
XFreeStringList(ppszTextList);
|
||||
ppszTextList = NULL;
|
||||
|
||||
/* Free the data returned from XGetWindowProperty */
|
||||
XFree(value);
|
||||
value = NULL;
|
||||
nitems = 0;
|
||||
|
||||
/* Free any INCR data */
|
||||
if (data->incr) {
|
||||
free(data->incr);
|
||||
data->incr = NULL;
|
||||
data->incrsize = 0;
|
||||
}
|
||||
|
||||
/* Convert the X clipboard string to DOS format */
|
||||
winClipboardUNIXtoDOS(&pszReturnData, strlen(pszReturnData));
|
||||
|
||||
if (data->fUseUnicode) {
|
||||
/* Find out how much space needed to convert MBCS to Unicode */
|
||||
int iUnicodeLen = MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
pszReturnData, -1, NULL, 0);
|
||||
|
||||
/* NOTE: iUnicodeLen includes space for null terminator */
|
||||
pwszUnicodeStr = malloc(sizeof(wchar_t) * iUnicodeLen);
|
||||
if (!pwszUnicodeStr) {
|
||||
ErrorF("winClipboardFlushXEvents - SelectionNotify "
|
||||
"malloc failed for pwszUnicodeStr, aborting.\n");
|
||||
|
||||
/* Abort */
|
||||
goto winClipboardFlushXEvents_SelectionNotify_Done;
|
||||
}
|
||||
|
||||
/* Do the actual conversion */
|
||||
MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
pszReturnData,
|
||||
-1, pwszUnicodeStr, iUnicodeLen);
|
||||
|
||||
/* Allocate global memory for the X clipboard data */
|
||||
hGlobal = GlobalAlloc(GMEM_MOVEABLE,
|
||||
sizeof(wchar_t) * iUnicodeLen);
|
||||
}
|
||||
else {
|
||||
int iConvertDataLen = 0;
|
||||
pszConvertData = strdup(pszReturnData);
|
||||
iConvertDataLen = strlen(pszConvertData) + 1;
|
||||
|
||||
/* Allocate global memory for the X clipboard data */
|
||||
hGlobal = GlobalAlloc(GMEM_MOVEABLE, iConvertDataLen);
|
||||
}
|
||||
|
||||
free(pszReturnData);
|
||||
|
||||
/* Check that global memory was allocated */
|
||||
if (!hGlobal) {
|
||||
ErrorF("winClipboardFlushXEvents - SelectionNotify "
|
||||
"GlobalAlloc failed, aborting: %08x\n", (unsigned int)GetLastError());
|
||||
|
||||
/* Abort */
|
||||
goto winClipboardFlushXEvents_SelectionNotify_Done;
|
||||
}
|
||||
|
||||
/* Obtain a pointer to the global memory */
|
||||
pszGlobalData = GlobalLock(hGlobal);
|
||||
if (pszGlobalData == NULL) {
|
||||
ErrorF("winClipboardFlushXEvents - Could not lock global "
|
||||
"memory for clipboard transfer\n");
|
||||
|
||||
/* Abort */
|
||||
goto winClipboardFlushXEvents_SelectionNotify_Done;
|
||||
}
|
||||
|
||||
/* Copy the returned string into the global memory */
|
||||
if (data->fUseUnicode) {
|
||||
wcscpy((wchar_t *)pszGlobalData, pwszUnicodeStr);
|
||||
free(pwszUnicodeStr);
|
||||
pwszUnicodeStr = NULL;
|
||||
}
|
||||
else {
|
||||
strcpy(pszGlobalData, pszConvertData);
|
||||
free(pszConvertData);
|
||||
pszConvertData = NULL;
|
||||
}
|
||||
|
||||
/* Release the pointer to the global memory */
|
||||
GlobalUnlock(hGlobal);
|
||||
pszGlobalData = NULL;
|
||||
|
||||
/* Push the selection data to the Windows clipboard */
|
||||
if (data->fUseUnicode)
|
||||
SetClipboardData(CF_UNICODETEXT, hGlobal);
|
||||
else
|
||||
SetClipboardData(CF_TEXT, hGlobal);
|
||||
|
||||
/* Flag that SetClipboardData has been called */
|
||||
fSetClipboardData = FALSE;
|
||||
|
||||
/*
|
||||
* NOTE: Do not try to free pszGlobalData, it is owned by
|
||||
* Windows after the call to SetClipboardData ().
|
||||
*/
|
||||
|
||||
winClipboardFlushXEvents_SelectionNotify_Done:
|
||||
/* Free allocated resources */
|
||||
if (ppszTextList)
|
||||
XFreeStringList(ppszTextList);
|
||||
if (value) {
|
||||
XFree(value);
|
||||
value = NULL;
|
||||
nitems = 0;
|
||||
}
|
||||
free(pszConvertData);
|
||||
free(pwszUnicodeStr);
|
||||
if (hGlobal && pszGlobalData)
|
||||
GlobalUnlock(hGlobal);
|
||||
if (fSetClipboardData) {
|
||||
SetClipboardData(CF_UNICODETEXT, NULL);
|
||||
SetClipboardData(CF_TEXT, NULL);
|
||||
}
|
||||
return WIN_XEVENTS_NOTIFY_DATA;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process any pending X events
|
||||
*/
|
||||
|
@ -193,7 +458,6 @@ winClipboardFlushXEvents(HWND hwnd,
|
|||
Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms)
|
||||
{
|
||||
Atom atomClipboard = atoms->atomClipboard;
|
||||
Atom atomLocalProperty = atoms->atomLocalProperty;
|
||||
Atom atomUTF8String = atoms->atomUTF8String;
|
||||
Atom atomCompoundText = atoms->atomCompoundText;
|
||||
Atom atomTargets = atoms->atomTargets;
|
||||
|
@ -203,20 +467,14 @@ winClipboardFlushXEvents(HWND hwnd,
|
|||
XTextProperty xtpText = { 0 };
|
||||
XEvent event;
|
||||
XSelectionEvent eventSelection;
|
||||
unsigned long ulReturnBytesLeft;
|
||||
char *pszReturnData = NULL;
|
||||
char *pszGlobalData = NULL;
|
||||
int iReturn;
|
||||
HGLOBAL hGlobal = NULL;
|
||||
XICCEncodingStyle xiccesStyle;
|
||||
char *pszConvertData = NULL;
|
||||
char *pszTextList[2] = { NULL };
|
||||
int iCount;
|
||||
char **ppszTextList = NULL;
|
||||
wchar_t *pwszUnicodeStr = NULL;
|
||||
Bool fAbort = FALSE;
|
||||
Bool fCloseClipboard = FALSE;
|
||||
Bool fSetClipboardData = TRUE;
|
||||
|
||||
/* Get the next event - will not block because one is ready */
|
||||
XNextEvent(pDisplay, &event);
|
||||
|
@ -569,214 +827,19 @@ winClipboardFlushXEvents(HWND hwnd,
|
|||
return winClipboardSelectionNotifyTargets(hwnd, iWindow, pDisplay, data, atoms);
|
||||
}
|
||||
|
||||
/* Retrieve the selection data and delete the property */
|
||||
iReturn = XGetWindowProperty(pDisplay,
|
||||
iWindow,
|
||||
atomLocalProperty,
|
||||
0,
|
||||
INT_MAX,
|
||||
True,
|
||||
AnyPropertyType,
|
||||
&xtpText.encoding,
|
||||
&xtpText.format,
|
||||
&xtpText.nitems,
|
||||
&ulReturnBytesLeft, &xtpText.value);
|
||||
if (iReturn != Success) {
|
||||
ErrorF("winClipboardFlushXEvents - SelectionNotify - "
|
||||
"XGetWindowProperty () failed, aborting: %d\n", iReturn);
|
||||
goto winClipboardFlushXEvents_SelectionNotify_Done;
|
||||
}
|
||||
|
||||
{
|
||||
char *pszAtomName = NULL;
|
||||
|
||||
winDebug("SelectionNotify - returned data %lu left %lu\n",
|
||||
xtpText.nitems, ulReturnBytesLeft);
|
||||
pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
|
||||
winDebug("Notify atom name %s\n", pszAtomName);
|
||||
XFree(pszAtomName);
|
||||
pszAtomName = NULL;
|
||||
}
|
||||
|
||||
if (data->fUseUnicode) {
|
||||
#ifdef X_HAVE_UTF8_STRING
|
||||
/* Convert the text property to a text list */
|
||||
iReturn = Xutf8TextPropertyToTextList(pDisplay,
|
||||
&xtpText,
|
||||
&ppszTextList, &iCount);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
iReturn = XmbTextPropertyToTextList(pDisplay,
|
||||
&xtpText,
|
||||
&ppszTextList, &iCount);
|
||||
}
|
||||
if (iReturn == Success || iReturn > 0) {
|
||||
/* Conversion succeeded or some unconvertible characters */
|
||||
if (ppszTextList != NULL) {
|
||||
int i;
|
||||
int iReturnDataLen = 0;
|
||||
for (i = 0; i < iCount; i++) {
|
||||
iReturnDataLen += strlen(ppszTextList[i]);
|
||||
}
|
||||
pszReturnData = malloc(iReturnDataLen + 1);
|
||||
pszReturnData[0] = '\0';
|
||||
for (i = 0; i < iCount; i++) {
|
||||
strcat(pszReturnData, ppszTextList[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ErrorF("winClipboardFlushXEvents - SelectionNotify - "
|
||||
"X*TextPropertyToTextList list_return is NULL.\n");
|
||||
pszReturnData = malloc(1);
|
||||
pszReturnData[0] = '\0';
|
||||
}
|
||||
}
|
||||
else {
|
||||
ErrorF("winClipboardFlushXEvents - SelectionNotify - "
|
||||
"X*TextPropertyToTextList returned: ");
|
||||
switch (iReturn) {
|
||||
case XNoMemory:
|
||||
ErrorF("XNoMemory\n");
|
||||
break;
|
||||
case XLocaleNotSupported:
|
||||
ErrorF("XLocaleNotSupported\n");
|
||||
break;
|
||||
case XConverterNotFound:
|
||||
ErrorF("XConverterNotFound\n");
|
||||
break;
|
||||
default:
|
||||
ErrorF("%d\n", iReturn);
|
||||
break;
|
||||
}
|
||||
pszReturnData = malloc(1);
|
||||
pszReturnData[0] = '\0';
|
||||
}
|
||||
|
||||
/* Free the data returned from XGetWindowProperty */
|
||||
if (ppszTextList)
|
||||
XFreeStringList(ppszTextList);
|
||||
ppszTextList = NULL;
|
||||
XFree(xtpText.value);
|
||||
xtpText.value = NULL;
|
||||
xtpText.nitems = 0;
|
||||
|
||||
/* Convert the X clipboard string to DOS format */
|
||||
winClipboardUNIXtoDOS(&pszReturnData, strlen(pszReturnData));
|
||||
|
||||
if (data->fUseUnicode) {
|
||||
/* Find out how much space needed to convert MBCS to Unicode */
|
||||
int iUnicodeLen = MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
pszReturnData, -1, NULL, 0);
|
||||
|
||||
/* NOTE: iUnicodeLen includes space for null terminator */
|
||||
pwszUnicodeStr = malloc(sizeof(wchar_t) * iUnicodeLen);
|
||||
if (!pwszUnicodeStr) {
|
||||
ErrorF("winClipboardFlushXEvents - SelectionNotify "
|
||||
"malloc failed for pwszUnicodeStr, aborting.\n");
|
||||
|
||||
/* Abort */
|
||||
fAbort = TRUE;
|
||||
goto winClipboardFlushXEvents_SelectionNotify_Done;
|
||||
}
|
||||
|
||||
/* Do the actual conversion */
|
||||
MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
pszReturnData,
|
||||
-1, pwszUnicodeStr, iUnicodeLen);
|
||||
|
||||
/* Allocate global memory for the X clipboard data */
|
||||
hGlobal = GlobalAlloc(GMEM_MOVEABLE,
|
||||
sizeof(wchar_t) * iUnicodeLen);
|
||||
}
|
||||
else {
|
||||
int iConvertDataLen = 0;
|
||||
pszConvertData = strdup(pszReturnData);
|
||||
iConvertDataLen = strlen(pszConvertData) + 1;
|
||||
|
||||
/* Allocate global memory for the X clipboard data */
|
||||
hGlobal = GlobalAlloc(GMEM_MOVEABLE, iConvertDataLen);
|
||||
}
|
||||
|
||||
free(pszReturnData);
|
||||
|
||||
/* Check that global memory was allocated */
|
||||
if (!hGlobal) {
|
||||
ErrorF("winClipboardFlushXEvents - SelectionNotify "
|
||||
"GlobalAlloc failed, aborting: %08x\n", (unsigned int)GetLastError());
|
||||
|
||||
/* Abort */
|
||||
fAbort = TRUE;
|
||||
goto winClipboardFlushXEvents_SelectionNotify_Done;
|
||||
}
|
||||
|
||||
/* Obtain a pointer to the global memory */
|
||||
pszGlobalData = GlobalLock(hGlobal);
|
||||
if (pszGlobalData == NULL) {
|
||||
ErrorF("winClipboardFlushXEvents - Could not lock global "
|
||||
"memory for clipboard transfer\n");
|
||||
|
||||
/* Abort */
|
||||
fAbort = TRUE;
|
||||
goto winClipboardFlushXEvents_SelectionNotify_Done;
|
||||
}
|
||||
|
||||
/* Copy the returned string into the global memory */
|
||||
if (data->fUseUnicode) {
|
||||
wcscpy((wchar_t *)pszGlobalData, pwszUnicodeStr);
|
||||
free(pwszUnicodeStr);
|
||||
pwszUnicodeStr = NULL;
|
||||
}
|
||||
else {
|
||||
strcpy(pszGlobalData, pszConvertData);
|
||||
free(pszConvertData);
|
||||
pszConvertData = NULL;
|
||||
}
|
||||
|
||||
/* Release the pointer to the global memory */
|
||||
GlobalUnlock(hGlobal);
|
||||
pszGlobalData = NULL;
|
||||
|
||||
/* Push the selection data to the Windows clipboard */
|
||||
if (data->fUseUnicode)
|
||||
SetClipboardData(CF_UNICODETEXT, hGlobal);
|
||||
else
|
||||
SetClipboardData(CF_TEXT, hGlobal);
|
||||
|
||||
/* Flag that SetClipboardData has been called */
|
||||
fSetClipboardData = FALSE;
|
||||
|
||||
/*
|
||||
* NOTE: Do not try to free pszGlobalData, it is owned by
|
||||
* Windows after the call to SetClipboardData ().
|
||||
*/
|
||||
|
||||
winClipboardFlushXEvents_SelectionNotify_Done:
|
||||
/* Free allocated resources */
|
||||
if (ppszTextList)
|
||||
XFreeStringList(ppszTextList);
|
||||
if (xtpText.value) {
|
||||
XFree(xtpText.value);
|
||||
xtpText.value = NULL;
|
||||
xtpText.nitems = 0;
|
||||
}
|
||||
free(pszConvertData);
|
||||
free(pwszUnicodeStr);
|
||||
if (hGlobal && pszGlobalData)
|
||||
GlobalUnlock(hGlobal);
|
||||
if (fSetClipboardData) {
|
||||
SetClipboardData(CF_UNICODETEXT, NULL);
|
||||
SetClipboardData(CF_TEXT, NULL);
|
||||
}
|
||||
return WIN_XEVENTS_NOTIFY_DATA;
|
||||
return winClipboardSelectionNotifyData(hwnd, iWindow, pDisplay, data, atoms);
|
||||
|
||||
case SelectionClear:
|
||||
winDebug("SelectionClear - doing nothing\n");
|
||||
break;
|
||||
|
||||
case PropertyNotify:
|
||||
/* If INCR is in progress, collect the data */
|
||||
if (data->incr &&
|
||||
(event.xproperty.atom == atoms->atomLocalProperty) &&
|
||||
(event.xproperty.state == PropertyNewValue))
|
||||
return winClipboardSelectionNotifyData(hwnd, iWindow, pDisplay, data, atoms);
|
||||
|
||||
break;
|
||||
|
||||
case MappingNotify:
|
||||
|
|
|
@ -39,8 +39,8 @@ XWin(1)
|
|||
.SH BUGS
|
||||
Only text clipboard contents are supported.
|
||||
|
||||
The INCR (Incrememntal transfer) clipboard protocol for clipboard contents larger than the maximum size of an
|
||||
X request is not supported.
|
||||
The INCR (Incremental transfer) clipboard protocol for clipboard contents larger than the maximum size of an X
|
||||
request (approximately 256K) is only supported for X -> Windows clipboard transfers.
|
||||
|
||||
Some X clients, notably ones written in Tcl/Tk, do not re-assert ownership of the PRIMARY selection or update
|
||||
it's timestamp when it's contents change, which currently prevents \fIxwinclip\fP from correctly noticing that
|
||||
|
@ -49,7 +49,8 @@ the PRIMARY selection's contents have changed.
|
|||
Windows clipboard rendering is synchronous in the WM_RENDER*FORMAT message (that is, we must have placed the
|
||||
contents onto the clipboard by the time we return from processing this message), but we must wait for the X
|
||||
client which owns the selection to convert the selection to our requested format. This is currently achieved
|
||||
using a fixed timeout of one second.
|
||||
using a fixed timeout. After requesting conversion of the selection, if no events are received from the X
|
||||
client which owns the selection for one second, the conversion is assumed to have failed.
|
||||
|
||||
The XWin(1) server should indicate somehow (by placing an atom on the root window?) that it is running with it's
|
||||
internal clipboard integration enabled, and xwinclip should notice this and exit with an appropriate error.
|
||||
|
|
Loading…
Reference in New Issue