diff options
Diffstat (limited to 'xorg-server/hw/xwin/winclipboardwrappers.c')
-rw-r--r-- | xorg-server/hw/xwin/winclipboardwrappers.c | 198 |
1 files changed, 195 insertions, 3 deletions
diff --git a/xorg-server/hw/xwin/winclipboardwrappers.c b/xorg-server/hw/xwin/winclipboardwrappers.c index 2679f4f98..2671fc000 100644 --- a/xorg-server/hw/xwin/winclipboardwrappers.c +++ b/xorg-server/hw/xwin/winclipboardwrappers.c @@ -33,21 +33,37 @@ #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_fClipboardLaunched; +extern Bool g_fClipboardStarted; extern Bool g_fClipboard; +extern Window g_iClipboardWindow; +extern Atom g_atomLastOwnedSelection; +extern HWND g_hwndClipboard; +extern Bool g_fClipboardPrimary; + /* * Wrapper for internal EstablishConnection function. @@ -62,12 +78,14 @@ winProcEstablishConnection(ClientPtr client) static int s_iCallCount = 0; static unsigned long s_ulServerGeneration = 0; + #ifdef WINDBG if (s_iCallCount == 0) winDebug("winProcEstablishConnection - Hello\n"); + #endif /* Do nothing if clipboard is not enabled */ if (!g_fClipboard) { - ErrorF("winProcEstablishConnection - Clipboard is not enabled, " + winDebug ("winProcEstablishConnection - Clipboard is not enabled, " "returning.\n"); /* Unwrap the original function, call it, and return */ @@ -112,6 +130,13 @@ winProcEstablishConnection(ClientPtr client) /* Clear original function pointer */ winProcEstablishConnectionOrig = NULL; + /* If the clipboard client has already been started, abort */ + if (g_fClipboardLaunched) { + winDebug ("winProcEstablishConnection - Clipboard client already " + "launched, returning.\n"); + return iReturn; + } + /* Startup the clipboard client if clipboard mode is being used */ if (g_fClipboard) { /* @@ -138,8 +163,175 @@ winProcEstablishConnection(ClientPtr client) return iReturn; } - ErrorF("winProcEstablishConnection - winInitClipboard returned.\n"); + winDebug ("winProcEstablishConnection - winInitClipboard returned.\n"); } + /* Flag that clipboard client has been launched */ + g_fClipboardLaunched = TRUE; + 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; + 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) { + winDebug ("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 && g_fClipboardPrimary) { + /* Look for owned -> not owned transition */ + if (None == stuff->window && None != s_iOwners[CLIP_OWN_PRIMARY]) { + 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: 0x%x (clipboard is 0x%x)\n", + stuff->window,g_iClipboardWindow); + } + else if (MakeAtom("CLIPBOARD", 9, TRUE) == stuff->selection) { + /* Look for owned -> not owned transition */ + if (None == stuff->window && None != s_iOwners[CLIP_OWN_CLIPBOARD]) { + winDebug("winProcSetSelectionOwner - CLIPBOARD - Going from " + "owned to not owned.\n"); + + /* Adjust last owned selection */ + if ((None != s_iOwners[CLIP_OWN_PRIMARY]) && g_fClipboardPrimary) + 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: 0x%x, clipboard is 0x%x\n", + stuff->window,g_iClipboardWindow); + } + 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; + + /* 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)) { + winDebug ("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) { + winDebug ("winProcSetSelectionOwner - Root window taking ownership, " + "aborting\n"); + goto winProcSetSelectionOwner_Done; + } + + /* Access the Windows clipboard */ + if (!OpenClipboard(g_hwndClipboard)) { + ErrorF ("winProcSetSelectionOwner - OpenClipboard () failed: %08x, hwnd: %08x\n", + (int) GetLastError (),g_hwndClipboard); + goto winProcSetSelectionOwner_Done; + } + + /* Take ownership of the Windows clipboard */ + if (!EmptyClipboard()) { + ErrorF("winProcSetSelectionOwner - EmptyClipboard () failed: %08x\n", + (int) GetLastError()); + CloseClipboard (); + goto winProcSetSelectionOwner_Done; + } + + winDebug("winProcSetSelectionOwner - SetClipboardData NULL\n"); + /* 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); +} |