hw/xwin: Remove SetSelectionOwner wrapper, use XFixesSetSelectionOwnerNotify event instead

Use the XFixesSetSelectionNotify event instead of a SetSelectionOwner wrapper,
the completely equivalent client-side mechanism.

Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
Reviewed-by: Colin Harrison <colin.harrison@virgin.net>
This commit is contained in:
Jon TURNEY 2012-02-13 19:58:37 +00:00
parent ab55746c1b
commit a70c2384a2
10 changed files with 197 additions and 242 deletions

View File

@ -2143,7 +2143,7 @@ if test "x$XWIN" = xyes; then
AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support])
AC_CHECK_TOOL(WINDRES, windres)
PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau])
PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau xfixes])
if test "x$WINDOWSWM" = xauto; then
PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no])

View File

@ -39,7 +39,6 @@
#ifdef XWIN_CLIPBOARD
int winProcEstablishConnection(ClientPtr /* client */ );
int winProcSetSelectionOwner(ClientPtr /* client */ );
#endif
/*

View File

@ -116,7 +116,14 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
*/
int
winClipboardFlushXEvents(HWND hwnd,
int iWindow, Display * pDisplay, Bool fUnicodeSupport);
Atom
winClipboardGetLastOwnedSelectionAtom(void);
void
winClipboardInitMonitoredSelections(void);
#endif

View File

@ -35,25 +35,16 @@
#include <unistd.h>
#include <pthread.h>
#include "dixstruct.h"
#include "os.h"
#include "winclipboard.h"
#define WIN_CLIPBOARD_RETRIES 40
#define WIN_CLIPBOARD_DELAY 1
/*
* Local typedefs
*/
typedef int (*winDispatchProcPtr) (ClientPtr);
int winProcSetSelectionOwner(ClientPtr /* client */ );
/*
* References to external symbols
*/
extern winDispatchProcPtr winProcSetSelectionOwnerOrig;
extern Bool g_fClipboard;
extern HWND g_hwndClipboard;
extern Bool g_fClipboardStarted;
@ -108,12 +99,6 @@ winInitClipboard(void)
{
winDebug("winInitClipboard ()\n");
/* Wrap some internal server functions */
if (ProcVector[X_SetSelectionOwner] != winProcSetSelectionOwner) {
winProcSetSelectionOwnerOrig = ProcVector[X_SetSelectionOwner];
ProcVector[X_SetSelectionOwner] = winProcSetSelectionOwner;
}
/* Spawn a thread for the Clipboard module */
if (pthread_create(&g_ptClipboardProc, NULL, winClipboardThreadProc, NULL)) {
/* Bail if thread creation failed */

View File

@ -43,6 +43,7 @@
#include <errno.h>
#endif
#include "misc.h"
#include <X11/extensions/Xfixes.h>
#define WIN_CONNECT_RETRIES 40
#define WIN_CONNECT_DELAY 4
@ -66,6 +67,8 @@ static XIOErrorHandler g_winClipboardOldIOErrorHandler;
static pthread_t g_winClipboardProcThread;
Bool g_fUseUnicode = FALSE;
int xfixes_event_base;
int xfixes_error_base;
/*
* Local function prototypes
@ -206,6 +209,9 @@ winClipboardProc(void *pvNotUsed)
iMaxDescriptor = iConnectionNumber + 1;
#endif
if (!XFixesQueryExtension(pDisplay, &xfixes_event_base, &xfixes_error_base))
ErrorF ("winClipboardProc - XFixes extension not present\n");
/* Create atom */
atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
@ -229,9 +235,26 @@ winClipboardProc(void *pvNotUsed)
ErrorF("winClipboardProc - XSelectInput generated BadWindow "
"on messaging window\n");
XFixesSelectSelectionInput (pDisplay,
iWindow,
XA_PRIMARY,
XFixesSetSelectionOwnerNotifyMask |
XFixesSelectionWindowDestroyNotifyMask |
XFixesSelectionClientCloseNotifyMask);
XFixesSelectSelectionInput (pDisplay,
iWindow,
XInternAtom (pDisplay, "CLIPBOARD", False),
XFixesSetSelectionOwnerNotifyMask |
XFixesSelectionWindowDestroyNotifyMask |
XFixesSelectionClientCloseNotifyMask);
/* Save the window in the screen privates */
g_iClipboardWindow = iWindow;
/* Initialize monitored selection state */
winClipboardInitMonitoredSelections();
/* Create Windows messaging window */
hwnd = winClipboardCreateMessagingWindow();

View File

@ -50,7 +50,6 @@
extern void *g_pClipboardDisplay;
extern Window g_iClipboardWindow;
extern Atom g_atomLastOwnedSelection;
/*
* Process X events up to specified timeout
@ -423,7 +422,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/* Request the selection contents */
iReturn = XConvertSelection(pDisplay,
g_atomLastOwnedSelection,
winClipboardGetLastOwnedSelectionAtom(),
XInternAtom(pDisplay,
"COMPOUND_TEXT", False),
XInternAtom(pDisplay,

View File

@ -33,35 +33,21 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
#include "win.h"
#include "dixstruct.h"
#include <X11/Xatom.h>
/*
* Constants
*/
#define CLIP_NUM_SELECTIONS 2
#define CLIP_OWN_PRIMARY 0
#define CLIP_OWN_CLIPBOARD 1
/*
* Local function prototypes
*/
DISPATCH_PROC(winProcEstablishConnection);
DISPATCH_PROC(winProcSetSelectionOwner);
/*
* References to external symbols
*/
extern Bool g_fClipboardStarted;
extern Bool g_fClipboard;
extern Window g_iClipboardWindow;
extern Atom g_atomLastOwnedSelection;
extern HWND g_hwndClipboard;
/*
* Wrapper for internal EstablishConnection function.
@ -157,202 +143,3 @@ winProcEstablishConnection(ClientPtr client)
return iReturn;
}
/*
* Wrapper for internal SetSelectionOwner function.
* Grabs ownership of Windows clipboard when X11 clipboard owner changes.
*/
int
winProcSetSelectionOwner(ClientPtr client)
{
int i;
DrawablePtr pDrawable;
WindowPtr pWindow = None;
Bool fOwnedToNotOwned = FALSE;
static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None };
static unsigned long s_ulServerGeneration = 0;
REQUEST(xSetSelectionOwnerReq);
REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
winDebug("winProcSetSelectionOwner - Hello.\n");
/* Watch for server reset */
if (s_ulServerGeneration != serverGeneration) {
/* Save new generation number */
s_ulServerGeneration = serverGeneration;
/* Initialize static variables */
for (i = 0; i < CLIP_NUM_SELECTIONS; ++i)
s_iOwners[i] = None;
}
/* Abort if clipboard not completely initialized yet */
if (!g_fClipboardStarted) {
/* ErrorF ("winProcSetSelectionOwner - Clipboard not yet started, "
"aborting.\n"); */
goto winProcSetSelectionOwner_Done;
}
/* Grab window if we have one */
if (None != stuff->window) {
/* Grab the Window from the request */
int rc =
dixLookupWindow(&pWindow, stuff->window, client, DixReadAccess);
if (rc != Success) {
ErrorF("winProcSetSelectionOwner - Found BadWindow, aborting.\n");
goto winProcSetSelectionOwner_Done;
}
}
/* Now we either have a valid window or None */
/* Save selection owners for monitored selections, ignore other selections */
if (XA_PRIMARY == stuff->selection) {
/* Look for owned -> not owned transition */
if (None == stuff->window && None != s_iOwners[CLIP_OWN_PRIMARY]) {
fOwnedToNotOwned = TRUE;
winDebug("winProcSetSelectionOwner - PRIMARY - Going from "
"owned to not owned.\n");
/* Adjust last owned selection */
if (None != s_iOwners[CLIP_OWN_CLIPBOARD])
g_atomLastOwnedSelection = MakeAtom("CLIPBOARD", 9, TRUE);
else
g_atomLastOwnedSelection = None;
}
/* Save new selection owner or None */
s_iOwners[CLIP_OWN_PRIMARY] = stuff->window;
winDebug("winProcSetSelectionOwner - PRIMARY - Now owned by: %d\n",
stuff->window);
}
else if (MakeAtom("CLIPBOARD", 9, TRUE) == stuff->selection) {
/* Look for owned -> not owned transition */
if (None == stuff->window && None != s_iOwners[CLIP_OWN_CLIPBOARD]) {
fOwnedToNotOwned = TRUE;
winDebug("winProcSetSelectionOwner - CLIPBOARD - Going from "
"owned to not owned.\n");
/* Adjust last owned selection */
if (None != s_iOwners[CLIP_OWN_PRIMARY])
g_atomLastOwnedSelection = XA_PRIMARY;
else
g_atomLastOwnedSelection = None;
}
/* Save new selection owner or None */
s_iOwners[CLIP_OWN_CLIPBOARD] = stuff->window;
winDebug("winProcSetSelectionOwner - CLIPBOARD - Now owned by: %d\n",
stuff->window);
}
else
goto winProcSetSelectionOwner_Done;
/*
* At this point, if one of the selections is still owned by the
* clipboard manager then it should be marked as unowned since
* we will be taking ownership of the Win32 clipboard.
*/
if (g_iClipboardWindow == s_iOwners[CLIP_OWN_PRIMARY])
s_iOwners[CLIP_OWN_PRIMARY] = None;
if (g_iClipboardWindow == s_iOwners[CLIP_OWN_CLIPBOARD])
s_iOwners[CLIP_OWN_CLIPBOARD] = None;
/*
* Handle case when selection is being disowned,
* WM_DRAWCLIPBOARD did not do the disowning,
* both monitored selections are no longer owned,
* an owned to not owned transition was detected,
* and we currently own the Win32 clipboard.
*/
if (stuff->window == None
&& s_iOwners[CLIP_OWN_PRIMARY] == None
&& s_iOwners[CLIP_OWN_CLIPBOARD] == None
&& fOwnedToNotOwned
&& g_hwndClipboard != NULL && g_hwndClipboard == GetClipboardOwner()) {
winDebug("winProcSetSelectionOwner - We currently own the "
"clipboard and neither the PRIMARY nor the CLIPBOARD "
"selections are owned, releasing ownership of Win32 "
"clipboard.\n");
/* Release ownership of the Windows clipboard */
OpenClipboard(NULL);
EmptyClipboard();
CloseClipboard();
goto winProcSetSelectionOwner_Done;
}
/* Abort if no window at this point */
if (None == stuff->window) {
winDebug("winProcSetSelectionOwner - No window, returning.\n");
goto winProcSetSelectionOwner_Done;
}
/* Abort if invalid selection */
if (!ValidAtom(stuff->selection)) {
ErrorF("winProcSetSelectionOwner - Found BadAtom, aborting.\n");
goto winProcSetSelectionOwner_Done;
}
/* Cast Window to Drawable */
pDrawable = (DrawablePtr) pWindow;
/* Abort if clipboard manager is owning the selection */
if (pDrawable->id == g_iClipboardWindow) {
winDebug("winProcSetSelectionOwner - We changed ownership, "
"aborting.\n");
goto winProcSetSelectionOwner_Done;
}
/* Abort if root window is taking ownership */
if (pDrawable->id == 0) {
ErrorF("winProcSetSelectionOwner - Root window taking ownership, "
"aborting\n");
goto winProcSetSelectionOwner_Done;
}
/* Close clipboard if we have it open already */
if (GetOpenClipboardWindow() == g_hwndClipboard) {
CloseClipboard();
}
/* Access the Windows clipboard */
if (!OpenClipboard(g_hwndClipboard)) {
ErrorF("winProcSetSelectionOwner - OpenClipboard () failed: %08x\n",
(int) GetLastError());
goto winProcSetSelectionOwner_Done;
}
/* Take ownership of the Windows clipboard */
if (!EmptyClipboard()) {
ErrorF("winProcSetSelectionOwner - EmptyClipboard () failed: %08x\n",
(int) GetLastError());
goto winProcSetSelectionOwner_Done;
}
/* Advertise regular text and unicode */
SetClipboardData(CF_UNICODETEXT, NULL);
SetClipboardData(CF_TEXT, NULL);
/* Save handle to last owned selection */
g_atomLastOwnedSelection = stuff->selection;
/* Release the clipboard */
if (!CloseClipboard()) {
ErrorF("winProcSetSelectionOwner - CloseClipboard () failed: "
"%08x\n", (int) GetLastError());
goto winProcSetSelectionOwner_Done;
}
winProcSetSelectionOwner_Done:
return (*winProcSetSelectionOwnerOrig) (client);
}

View File

@ -33,8 +33,95 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
#include "winclipboard.h"
#include "misc.h"
#include <X11/extensions/Xfixes.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;
/*
* 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 Atom atomClipboard = 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 %x\n",
szSelectionNames[i], e->owner);
}
Atom
winClipboardGetLastOwnedSelectionAtom(void)
{
if (lastOwnedSelectionIndex == CLIP_OWN_NONE)
return None;
if (lastOwnedSelectionIndex == CLIP_OWN_PRIMARY)
return XA_PRIMARY;
if (lastOwnedSelectionIndex == CLIP_OWN_CLIPBOARD)
return atomClipboard;
return None;
}
void
winClipboardInitMonitoredSelections(void)
{
/* Initialize static variables */
for (int i = 0; i < CLIP_NUM_SELECTIONS; ++i)
s_iOwners[i] = None;
lastOwnedSelectionIndex = CLIP_OWN_NONE;
}
/*
* Process any pending X events
@ -52,6 +139,7 @@ winClipboardFlushXEvents(HWND hwnd,
if (generation != serverGeneration) {
generation = serverGeneration;
atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
atomLocalProperty = XInternAtom(pDisplay, WIN_LOCAL_PROPERTY, False);
atomUTF8String = XInternAtom(pDisplay, "UTF8_STRING", False);
atomCompoundText = XInternAtom(pDisplay, "COMPOUND_TEXT", False);
@ -77,7 +165,6 @@ winClipboardFlushXEvents(HWND hwnd,
wchar_t *pwszUnicodeStr = NULL;
int iUnicodeLen = 0;
int iReturnDataLen = 0;
int i;
Bool fAbort = FALSE;
Bool fCloseClipboard = FALSE;
Bool fSetClipboardData = TRUE;
@ -525,6 +612,8 @@ winClipboardFlushXEvents(HWND hwnd,
if (iReturn == Success || iReturn > 0) {
/* Conversion succeeded or some unconvertible characters */
if (ppszTextList != NULL) {
int i;
iReturnDataLen = 0;
for (i = 0; i < iCount; i++) {
iReturnDataLen += strlen(ppszTextList[i]);
@ -693,8 +782,78 @@ winClipboardFlushXEvents(HWND hwnd,
break;
default:
ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
event.type);
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) {
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;
}
}

View File

@ -86,7 +86,6 @@ pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER;
* Wrapped DIX functions
*/
winDispatchProcPtr winProcEstablishConnectionOrig = NULL;
winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL;
/*
* Clipboard variables
@ -98,7 +97,6 @@ Bool g_fClipboardStarted = FALSE;
HWND g_hwndClipboard = NULL;
void *g_pClipboardDisplay = NULL;
Window g_iClipboardWindow = None;
Atom g_atomLastOwnedSelection = None;
#endif
/*
@ -113,7 +111,6 @@ winInitializeGlobals(void)
#ifdef XWIN_CLIPBOARD
g_iClipboardWindow = None;
g_pClipboardDisplay = NULL;
g_atomLastOwnedSelection = None;
g_hwndClipboard = NULL;
#endif
}

View File

@ -72,7 +72,6 @@ typedef int (*winDispatchProcPtr) (ClientPtr);
* Wrapped DIX functions
*/
extern winDispatchProcPtr winProcEstablishConnectionOrig;
extern winDispatchProcPtr winProcSetSelectionOwnerOrig;
#endif
/* The global X default icons */