xserver-multidpi/hw/xwin/winclipboard/xevents.c
Jon TURNEY aa83c61f51 hw/xwin: printf format fixes for DWORD type
Some Win32 API types are different fundamental types in the 32-bit and 64-bit
versions.

This problem is then further compounded by the fact that whilst both 32-bit
Cygwin and 32-bit MinGW use the ILP32 data model, 64-bit MinGW uses the LLP64
data model, but 64-bit Cygwin uses the LP64 data model.

This makes it impossible to write printf format specifiers which are correct for
all those targets

In the Win32 API, DWORD is an unsigned, 32-bit type.  It is defined in terms of
an unsigned long, except in the LP64 data model, where it is an unsigned int.

It should always be safe to cast it to unsigned int and use %u or %x.

Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
Reviewed-by: Colin Harrison <colin.harrison@virgin.net>
2015-07-07 16:52:44 +01:00

865 lines
32 KiB
C

/*
*Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
*Copyright (C) Colin Harrison 2005-2008
*
*Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
*"Software"), to deal in the Software without restriction, including
*without limitation the rights to use, copy, modify, merge, publish,
*distribute, sublicense, and/or sell copies of the Software, and to
*permit persons to whom the Software is furnished to do so, subject to
*the following conditions:
*
*The above copyright notice and this permission notice shall be
*included in all copies or substantial portions of the Software.
*
*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
*NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
*ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
*CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
*WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*Except as contained in this notice, the name of the copyright holder(s)
*and author(s) shall not be used in advertising or otherwise to promote
*the sale, use or other dealings in this Software without prior written
*authorization from the copyright holder(s) and author(s).
*
* Authors: Harold L Hunt II
* Colin Harrison
*/
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
/*
* Including any server header might define the macro _XSERVER64 on 64 bit machines.
* That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
* So let's undef that macro if necessary.
*/
#ifdef _XSERVER64
#undef _XSERVER64
#endif
#include <limits.h>
#include <wchar.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xfixes.h>
#include "winclipboard.h"
#include "internal.h"
/*
* Constants
*/
#define CLIP_NUM_SELECTIONS 2
#define CLIP_OWN_NONE -1
#define CLIP_OWN_PRIMARY 0
#define CLIP_OWN_CLIPBOARD 1
/*
* Global variables
*/
extern int xfixes_event_base;
Bool fPrimarySelection = TRUE;
/*
* Local variables
*/
static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None, None };
static const char *szSelectionNames[CLIP_NUM_SELECTIONS] =
{ "PRIMARY", "CLIPBOARD" };
static unsigned int lastOwnedSelectionIndex = CLIP_OWN_NONE;
static void
MonitorSelection(XFixesSelectionNotifyEvent * e, unsigned int i)
{
/* Look for owned -> not owned transition */
if (None == e->owner && None != s_iOwners[i]) {
unsigned int other_index;
winDebug("MonitorSelection - %s - Going from owned to not owned.\n",
szSelectionNames[i]);
/* If this selection is not owned, the other monitored selection must be the most
recently owned, if it is owned at all */
if (i == CLIP_OWN_PRIMARY)
other_index = CLIP_OWN_CLIPBOARD;
if (i == CLIP_OWN_CLIPBOARD)
other_index = CLIP_OWN_PRIMARY;
if (None != s_iOwners[other_index])
lastOwnedSelectionIndex = other_index;
else
lastOwnedSelectionIndex = CLIP_OWN_NONE;
}
/* Save last owned selection */
if (None != e->owner) {
lastOwnedSelectionIndex = i;
}
/* Save new selection owner or None */
s_iOwners[i] = e->owner;
winDebug("MonitorSelection - %s - Now owned by XID %lx\n",
szSelectionNames[i], e->owner);
}
Atom
winClipboardGetLastOwnedSelectionAtom(ClipboardAtoms *atoms)
{
if (lastOwnedSelectionIndex == CLIP_OWN_NONE)
return None;
if (lastOwnedSelectionIndex == CLIP_OWN_PRIMARY)
return XA_PRIMARY;
if (lastOwnedSelectionIndex == CLIP_OWN_CLIPBOARD)
return atoms->atomClipboard;
return None;
}
void
winClipboardInitMonitoredSelections(void)
{
/* Initialize static variables */
int i;
for (i = 0; i < CLIP_NUM_SELECTIONS; ++i)
s_iOwners[i] = None;
lastOwnedSelectionIndex = CLIP_OWN_NONE;
}
static int
winClipboardSelectionNotifyTargets(HWND hwnd, Window iWindow, Display *pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms)
{
Atom type;
int format;
unsigned long nitems;
unsigned long after;
Atom *prop;
/* Retrieve the selection data and delete the property */
int iReturn = XGetWindowProperty(pDisplay,
iWindow,
atoms->atomLocalProperty,
0,
INT_MAX,
True,
AnyPropertyType,
&type,
&format,
&nitems,
&after,
(unsigned char **)&prop);
if (iReturn != Success) {
ErrorF("winClipboardFlushXEvents - SelectionNotify - "
"XGetWindowProperty () failed, aborting: %d\n", iReturn);
} else {
int i;
data->targetList = malloc((nitems+1)*sizeof(Atom));
for (i = 0; i < nitems; i++)
{
Atom atom = prop[i];
char *pszAtomName = XGetAtomName(pDisplay, atom);
data->targetList[i] = atom;
winDebug("winClipboardFlushXEvents - SelectionNotify - target[%d] %ld = %s\n", i, atom, pszAtomName);
XFree(pszAtomName);
}
data->targetList[nitems] = 0;
XFree(prop);
}
return WIN_XEVENTS_NOTIFY_TARGETS;
}
/*
* Process any pending X events
*/
int
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;
/* Process all pending events */
while (XPending(pDisplay)) {
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);
/* Branch on the event type */
switch (event.type) {
/*
* SelectionRequest
*/
case SelectionRequest:
{
char *pszAtomName = NULL;
winDebug("SelectionRequest - target %ld\n",
event.xselectionrequest.target);
pszAtomName = XGetAtomName(pDisplay,
event.xselectionrequest.target);
winDebug("SelectionRequest - Target atom name %s\n", pszAtomName);
XFree(pszAtomName);
pszAtomName = NULL;
}
/* Abort if invalid target type */
if (event.xselectionrequest.target != XA_STRING
&& event.xselectionrequest.target != atomUTF8String
&& event.xselectionrequest.target != atomCompoundText
&& event.xselectionrequest.target != atomTargets) {
/* Abort */
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
/* Handle targets type of request */
if (event.xselectionrequest.target == atomTargets) {
Atom atomTargetArr[] = { atomTargets,
atomCompoundText,
atomUTF8String,
XA_STRING
};
/* Try to change the property */
iReturn = XChangeProperty(pDisplay,
event.xselectionrequest.requestor,
event.xselectionrequest.property,
XA_ATOM,
32,
PropModeReplace,
(unsigned char *) atomTargetArr,
(sizeof(atomTargetArr)
/ sizeof(atomTargetArr[0])));
if (iReturn == BadAlloc
|| iReturn == BadAtom
|| iReturn == BadMatch
|| iReturn == BadValue || iReturn == BadWindow) {
ErrorF("winClipboardFlushXEvents - SelectionRequest - "
"XChangeProperty failed: %d\n", iReturn);
}
/* Setup selection notify xevent */
eventSelection.type = SelectionNotify;
eventSelection.send_event = True;
eventSelection.display = pDisplay;
eventSelection.requestor = event.xselectionrequest.requestor;
eventSelection.selection = event.xselectionrequest.selection;
eventSelection.target = event.xselectionrequest.target;
eventSelection.property = event.xselectionrequest.property;
eventSelection.time = event.xselectionrequest.time;
/*
* Notify the requesting window that
* the operation has completed
*/
iReturn = XSendEvent(pDisplay,
eventSelection.requestor,
False, 0L, (XEvent *) &eventSelection);
if (iReturn == BadValue || iReturn == BadWindow) {
ErrorF("winClipboardFlushXEvents - SelectionRequest - "
"XSendEvent () failed\n");
}
break;
}
/* Close clipboard if we have it open already */
if (GetOpenClipboardWindow() == hwnd) {
CloseClipboard();
}
/* Access the clipboard */
if (!OpenClipboard(hwnd)) {
ErrorF("winClipboardFlushXEvents - SelectionRequest - "
"OpenClipboard () failed: %08x\n", (unsigned int)GetLastError());
/* Abort */
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
/* Indicate that clipboard was opened */
fCloseClipboard = TRUE;
/* Check that clipboard format is available */
if (data->fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
static int count; /* Hack to stop acroread spamming the log */
static HWND lasthwnd; /* I've not seen any other client get here repeatedly? */
if (hwnd != lasthwnd)
count = 0;
count++;
if (count < 6)
ErrorF("winClipboardFlushXEvents - CF_UNICODETEXT is not "
"available from Win32 clipboard. Aborting %d.\n",
count);
lasthwnd = hwnd;
/* Abort */
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
else if (!data->fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) {
ErrorF("winClipboardFlushXEvents - CF_TEXT is not "
"available from Win32 clipboard. Aborting.\n");
/* Abort */
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
/* Setup the string style */
if (event.xselectionrequest.target == XA_STRING)
xiccesStyle = XStringStyle;
#ifdef X_HAVE_UTF8_STRING
else if (event.xselectionrequest.target == atomUTF8String)
xiccesStyle = XUTF8StringStyle;
#endif
else if (event.xselectionrequest.target == atomCompoundText)
xiccesStyle = XCompoundTextStyle;
else
xiccesStyle = XStringStyle;
/* Get a pointer to the clipboard text, in desired format */
if (data->fUseUnicode) {
/* Retrieve clipboard data */
hGlobal = GetClipboardData(CF_UNICODETEXT);
}
else {
/* Retrieve clipboard data */
hGlobal = GetClipboardData(CF_TEXT);
}
if (!hGlobal) {
ErrorF("winClipboardFlushXEvents - SelectionRequest - "
"GetClipboardData () failed: %08x\n", (unsigned int)GetLastError());
/* Abort */
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
pszGlobalData = (char *) GlobalLock(hGlobal);
/* Convert the Unicode string to UTF8 (MBCS) */
if (data->fUseUnicode) {
int iConvertDataLen = WideCharToMultiByte(CP_UTF8,
0,
(LPCWSTR) pszGlobalData,
-1, NULL, 0, NULL, NULL);
/* NOTE: iConvertDataLen includes space for null terminator */
pszConvertData = malloc(iConvertDataLen);
WideCharToMultiByte(CP_UTF8,
0,
(LPCWSTR) pszGlobalData,
-1,
pszConvertData,
iConvertDataLen, NULL, NULL);
}
else {
pszConvertData = strdup(pszGlobalData);
}
/* Convert DOS string to UNIX string */
winClipboardDOStoUNIX(pszConvertData, strlen(pszConvertData));
/* Setup our text list */
pszTextList[0] = pszConvertData;
pszTextList[1] = NULL;
/* Initialize the text property */
xtpText.value = NULL;
xtpText.nitems = 0;
/* Create the text property from the text list */
if (data->fUseUnicode) {
#ifdef X_HAVE_UTF8_STRING
iReturn = Xutf8TextListToTextProperty(pDisplay,
pszTextList,
1, xiccesStyle, &xtpText);
#endif
}
else {
iReturn = XmbTextListToTextProperty(pDisplay,
pszTextList,
1, xiccesStyle, &xtpText);
}
if (iReturn == XNoMemory || iReturn == XLocaleNotSupported) {
ErrorF("winClipboardFlushXEvents - SelectionRequest - "
"X*TextListToTextProperty failed: %d\n", iReturn);
/* Abort */
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
/* Free the converted string */
free(pszConvertData);
pszConvertData = NULL;
/* Copy the clipboard text to the requesting window */
iReturn = XChangeProperty(pDisplay,
event.xselectionrequest.requestor,
event.xselectionrequest.property,
event.xselectionrequest.target,
8,
PropModeReplace,
xtpText.value, xtpText.nitems);
if (iReturn == BadAlloc || iReturn == BadAtom
|| iReturn == BadMatch || iReturn == BadValue
|| iReturn == BadWindow) {
ErrorF("winClipboardFlushXEvents - SelectionRequest - "
"XChangeProperty failed: %d\n", iReturn);
/* Abort */
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
/* Release the clipboard data */
GlobalUnlock(hGlobal);
pszGlobalData = NULL;
fCloseClipboard = FALSE;
CloseClipboard();
/* Clean up */
XFree(xtpText.value);
xtpText.value = NULL;
xtpText.nitems = 0;
/* Setup selection notify event */
eventSelection.type = SelectionNotify;
eventSelection.send_event = True;
eventSelection.display = pDisplay;
eventSelection.requestor = event.xselectionrequest.requestor;
eventSelection.selection = event.xselectionrequest.selection;
eventSelection.target = event.xselectionrequest.target;
eventSelection.property = event.xselectionrequest.property;
eventSelection.time = event.xselectionrequest.time;
/* Notify the requesting window that the operation has completed */
iReturn = XSendEvent(pDisplay,
eventSelection.requestor,
False, 0L, (XEvent *) &eventSelection);
if (iReturn == BadValue || iReturn == BadWindow) {
ErrorF("winClipboardFlushXEvents - SelectionRequest - "
"XSendEvent () failed\n");
/* Abort */
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
winClipboardFlushXEvents_SelectionRequest_Done:
/* Free allocated resources */
if (xtpText.value) {
XFree(xtpText.value);
xtpText.value = NULL;
xtpText.nitems = 0;
}
free(pszConvertData);
if (hGlobal && pszGlobalData)
GlobalUnlock(hGlobal);
/*
* Send a SelectionNotify event to the requesting
* client when we abort.
*/
if (fAbort) {
/* Setup selection notify event */
eventSelection.type = SelectionNotify;
eventSelection.send_event = True;
eventSelection.display = pDisplay;
eventSelection.requestor = event.xselectionrequest.requestor;
eventSelection.selection = event.xselectionrequest.selection;
eventSelection.target = event.xselectionrequest.target;
eventSelection.property = None;
eventSelection.time = event.xselectionrequest.time;
/* Notify the requesting window that the operation is complete */
iReturn = XSendEvent(pDisplay,
eventSelection.requestor,
False, 0L, (XEvent *) &eventSelection);
if (iReturn == BadValue || iReturn == BadWindow) {
/*
* Should not be a problem if XSendEvent fails because
* the client may simply have exited.
*/
ErrorF("winClipboardFlushXEvents - SelectionRequest - "
"XSendEvent () failed for abort event.\n");
}
}
/* Close clipboard if it was opened */
if (fCloseClipboard) {
fCloseClipboard = FALSE;
CloseClipboard();
}
break;
/*
* SelectionNotify
*/
case SelectionNotify:
winDebug("winClipboardFlushXEvents - SelectionNotify\n");
{
char *pszAtomName;
pszAtomName = XGetAtomName(pDisplay,
event.xselection.selection);
winDebug
("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
pszAtomName);
XFree(pszAtomName);
}
/*
SelectionNotify with property of None indicates either:
(i) Generated by the X server if no owner for the specified selection exists
(perhaps it's disappeared on us mid-transaction), or
(ii) Sent by the selection owner when the requested selection conversion could
not be performed or server errors prevented the conversion data being returned
*/
if (event.xselection.property == None) {
ErrorF("winClipboardFlushXEvents - SelectionNotify - "
"Conversion to format %ld refused.\n",
event.xselection.target);
return WIN_XEVENTS_FAILED;
}
if (event.xselection.target == atomTargets) {
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;
case SelectionClear:
winDebug("SelectionClear - doing nothing\n");
break;
case PropertyNotify:
break;
case MappingNotify:
break;
default:
if (event.type == XFixesSetSelectionOwnerNotify + xfixes_event_base) {
XFixesSelectionNotifyEvent *e =
(XFixesSelectionNotifyEvent *) & event;
winDebug("winClipboardFlushXEvents - XFixesSetSelectionOwnerNotify\n");
/* Save selection owners for monitored selections, ignore other selections */
if ((e->selection == XA_PRIMARY) && fPrimarySelection) {
MonitorSelection(e, CLIP_OWN_PRIMARY);
}
else if (e->selection == atomClipboard) {
MonitorSelection(e, CLIP_OWN_CLIPBOARD);
}
else
break;
/* Selection is being disowned */
if (e->owner == None) {
winDebug
("winClipboardFlushXEvents - No window, returning.\n");
break;
}
/*
XXX: there are all kinds of wacky edge cases we might need here:
- we own windows clipboard, but neither PRIMARY nor CLIPBOARD have an owner, so we should disown it?
- root window is taking ownership?
*/
/* If we are the owner of the most recently owned selection, don't go all recursive :) */
if ((lastOwnedSelectionIndex != CLIP_OWN_NONE) &&
(s_iOwners[lastOwnedSelectionIndex] == iWindow)) {
winDebug("winClipboardFlushXEvents - Ownership changed to us, aborting.\n");
break;
}
/* Close clipboard if we have it open already (possible? correct??) */
if (GetOpenClipboardWindow() == hwnd) {
CloseClipboard();
}
/* Access the Windows clipboard */
if (!OpenClipboard(hwnd)) {
ErrorF("winClipboardFlushXEvents - OpenClipboard () failed: %08x\n",
(int) GetLastError());
break;
}
/* Take ownership of the Windows clipboard */
if (!EmptyClipboard()) {
ErrorF("winClipboardFlushXEvents - EmptyClipboard () failed: %08x\n",
(int) GetLastError());
break;
}
/* Advertise regular text and unicode */
SetClipboardData(CF_UNICODETEXT, NULL);
SetClipboardData(CF_TEXT, NULL);
/* Release the clipboard */
if (!CloseClipboard()) {
ErrorF("winClipboardFlushXEvents - CloseClipboard () failed: %08x\n",
(int) GetLastError());
break;
}
}
/* XFixesSelectionWindowDestroyNotifyMask */
/* XFixesSelectionClientCloseNotifyMask */
else {
ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
event.type);
}
break;
}
}
return WIN_XEVENTS_SUCCESS;
}