diff options
author | marha <marha@users.sourceforge.net> | 2015-02-22 21:39:56 +0100 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2015-02-22 21:39:56 +0100 |
commit | 462f18c7b25fe3e467f837647d07ab0a78aa8d2b (patch) | |
tree | fc8013c0a1bac05a1945846c1697e973f4c35013 /xorg-server/hw/xwin | |
parent | 36f711ee12b6dd5184198abed3aa551efb585587 (diff) | |
download | vcxsrv-462f18c7b25fe3e467f837647d07ab0a78aa8d2b.tar.gz vcxsrv-462f18c7b25fe3e467f837647d07ab0a78aa8d2b.tar.bz2 vcxsrv-462f18c7b25fe3e467f837647d07ab0a78aa8d2b.zip |
Merged origin/release (checked in because wanted to merge new stuff)
Diffstat (limited to 'xorg-server/hw/xwin')
-rwxr-xr-x | xorg-server/hw/xwin/InitOutput.c | 4 | ||||
-rw-r--r-- | xorg-server/hw/xwin/XWin.rc | 1 | ||||
-rw-r--r-- | xorg-server/hw/xwin/man/XWin.man | 6 | ||||
-rwxr-xr-x | xorg-server/hw/xwin/winclipboard/internal.h | 38 | ||||
-rwxr-xr-x | xorg-server/hw/xwin/winclipboard/thread.c | 124 | ||||
-rw-r--r-- | xorg-server/hw/xwin/winclipboard/winclipboard.h | 4 | ||||
-rwxr-xr-x | xorg-server/hw/xwin/winclipboard/wndproc.c | 245 | ||||
-rwxr-xr-x | xorg-server/hw/xwin/winclipboard/xevents.c | 426 | ||||
-rw-r--r-- | xorg-server/hw/xwin/winclipboard/xwinclip.c | 7 | ||||
-rw-r--r-- | xorg-server/hw/xwin/winclipboard/xwinclip.man | 3 | ||||
-rwxr-xr-x[-rw-r--r--] | xorg-server/hw/xwin/winclipboardwrappers.c | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | xorg-server/hw/xwin/winprocarg.c | 27 | ||||
-rw-r--r-- | xorg-server/hw/xwin/winresource.h | 1 | ||||
-rw-r--r-- | xorg-server/hw/xwin/wintrayicon.c | 19 | ||||
-rwxr-xr-x | xorg-server/hw/xwin/winwndproc.c | 6 |
15 files changed, 624 insertions, 294 deletions
diff --git a/xorg-server/hw/xwin/InitOutput.c b/xorg-server/hw/xwin/InitOutput.c index 4e099d294..fe4755c03 100755 --- a/xorg-server/hw/xwin/InitOutput.c +++ b/xorg-server/hw/xwin/InitOutput.c @@ -814,6 +814,10 @@ winUseMsg(void) #ifdef XWIN_CLIPBOARD ErrorF("-nounicodeclipboard\n" "\tDo not use Unicode clipboard even if on a NT-based platform.\n"); + + ErrorF("-[no]primary\n" + "\tWhen clipboard integration is enabled, map the X11 PRIMARY selection\n" + "\tto the Windows clipboard. Default is enabled.\n"); #endif ErrorF("-refresh rate_in_Hz\n" diff --git a/xorg-server/hw/xwin/XWin.rc b/xorg-server/hw/xwin/XWin.rc index f94f5f995..4ff795027 100644 --- a/xorg-server/hw/xwin/XWin.rc +++ b/xorg-server/hw/xwin/XWin.rc @@ -138,6 +138,7 @@ BEGIN POPUP "TRAYICON_MENU" BEGIN MENUITEM "&Hide Root Window", ID_APP_HIDE_ROOT + MENUITEM "Clipboard may use &PRIMARY selection", ID_APP_MONITOR_PRIMARY MENUITEM "&About...", ID_APP_ABOUT MENUITEM SEPARATOR MENUITEM "E&xit...", ID_APP_EXIT diff --git a/xorg-server/hw/xwin/man/XWin.man b/xorg-server/hw/xwin/man/XWin.man index a043ac281..15a57db02 100644 --- a/xorg-server/hw/xwin/man/XWin.man +++ b/xorg-server/hw/xwin/man/XWin.man @@ -174,7 +174,7 @@ on remote hosts, when that information is available and it's useful to do so. .SH OPTIONS CONTROLLING WINDOWS INTEGRATION .TP 8 .B \-[no]clipboard -Enables [disables] the integration between the Cygwin/X clipboard and +Enables [disables] the integration between the X11 clipboard and \fIWindows\fP clipboard. The default is enabled. .TP 8 .B "\-emulate3buttons [\fItimeout\fP]" @@ -200,6 +200,10 @@ prevents the \fIWindows\fP mouse cursor from being drawn on top of the X cursor. This parameter has no effect unless \fB-swcursor\fP is also specified. .TP 8 +.B \-[no]primary +Clipboard integration may [will not] use the PRIMARY selection. +The default is enabled. +.TP 8 .B \-swcursor Disable the usage of the \fIWindows\fP cursor and use the X11 software cursor instead. .TP 8 diff --git a/xorg-server/hw/xwin/winclipboard/internal.h b/xorg-server/hw/xwin/winclipboard/internal.h index 55c7771af..73a330fc6 100755 --- a/xorg-server/hw/xwin/winclipboard/internal.h +++ b/xorg-server/hw/xwin/winclipboard/internal.h @@ -62,11 +62,13 @@ typedef int pid_t; #include "winmsg.h" #define WIN_XEVENTS_SUCCESS 0 -#define WIN_XEVENTS_CONVERT 2 -#define WIN_XEVENTS_NOTIFY 3 +#define WIN_XEVENTS_FAILED 1 +#define WIN_XEVENTS_NOTIFY_DATA 3 +#define WIN_XEVENTS_NOTIFY_TARGETS 4 #define WIN_LOCAL_PROPERTY "CYGX_CUT_BUFFER" #define WM_WM_REINIT (WM_USER + 200) +#define WM_WM_QUIT (WM_USER + 201) /* * References to external symbols @@ -95,6 +97,15 @@ void */ +typedef struct +{ + Atom atomClipboard; + Atom atomLocalProperty; + Atom atomUTF8String; + Atom atomCompoundText; + Atom atomTargets; +} ClipboardAtoms; + /* * winclipboardwndproc.c */ @@ -104,12 +115,33 @@ Bool winClipboardFlushWindowsMessageQueue(HWND hwnd); LRESULT CALLBACK winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); +typedef struct +{ + Display *pClipboardDisplay; + Window iClipboardWindow; + ClipboardAtoms *atoms; +} ClipboardWindowCreationParams; + /* * winclipboardxevents.c */ +typedef struct +{ + Bool fUseUnicode; + Atom *targetList; +} ClipboardConversionData; + int winClipboardFlushXEvents(HWND hwnd, - int iWindow, Display * pDisplay, Bool fUnicodeSupport, Bool ClipboardOpened); + Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atom); + + +Atom +winClipboardGetLastOwnedSelectionAtom(ClipboardAtoms *atoms); + +void +winClipboardInitMonitoredSelections(void); + #endif diff --git a/xorg-server/hw/xwin/winclipboard/thread.c b/xorg-server/hw/xwin/winclipboard/thread.c index 5dee3040e..42edad89c 100755 --- a/xorg-server/hw/xwin/winclipboard/thread.c +++ b/xorg-server/hw/xwin/winclipboard/thread.c @@ -35,16 +35,26 @@ #else #define HAS_WINSOCK 1 #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 <sys/types.h> #include <signal.h> #include <pthread.h> -#include "winclipboard.h" #include "windisplay.h" #ifdef __CYGWIN__ #include <errno.h> #endif #include "misc.h" #include "winmsg.h" +#include "winclipboard.h" #include "internal.h" /* Clipboard module constants */ @@ -90,7 +100,7 @@ Bool g_fUseUnicode = FALSE; */ static HWND -winClipboardCreateMessagingWindow(void); +winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms); static int winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr); @@ -107,7 +117,7 @@ winClipboardThreadExit(void *arg); Bool winClipboardProc(Bool fUseUnicode, char *szDisplay) { - Atom atomClipboard; + ClipboardAtoms atoms; int iReturn; HWND hwnd = NULL; int iConnectionNumber = 0; @@ -125,6 +135,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) int iSelectError; pthread_cleanup_push(&winClipboardThreadExit, NULL); + ClipboardConversionData data; winDebug ("winClipboardProc - Hello\n"); @@ -191,12 +202,15 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) iMaxDescriptor = iConnectionNumber + 1; #endif - /* Create atom */ - atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False); - XInternAtom (pDisplay, WIN_LOCAL_PROPERTY, False); - XInternAtom (pDisplay, "UTF8_STRING", False); - XInternAtom (pDisplay, "COMPOUND_TEXT", False); - XInternAtom (pDisplay, "TARGETS", False); + if (!XFixesQueryExtension(pDisplay, &xfixes_event_base, &xfixes_error_base)) + ErrorF ("winClipboardProc - XFixes extension not present\n"); + + /* Create atoms */ + atoms.atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False); + atoms.atomLocalProperty = XInternAtom (pDisplay, "CYGX_CUT_BUFFER", False); + atoms.atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False); + atoms.atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False); + atoms.atomTargets = XInternAtom (pDisplay, "TARGETS", False); /* Create a messaging window */ iWindow = XCreateSimpleWindow(pDisplay, @@ -218,6 +232,20 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) ErrorF("winClipboardProc - XSelectInput generated BadWindow " "on messaging window\n"); + XFixesSelectSelectionInput (pDisplay, + iWindow, + XA_PRIMARY, + XFixesSetSelectionOwnerNotifyMask | + XFixesSelectionWindowDestroyNotifyMask | + XFixesSelectionClientCloseNotifyMask); + + XFixesSelectSelectionInput (pDisplay, + iWindow, + atoms.atomClipboard, + XFixesSetSelectionOwnerNotifyMask | + XFixesSelectionWindowDestroyNotifyMask | + XFixesSelectionClientCloseNotifyMask); + /* Save the window in the screen privates */ g_iClipboardWindow = iWindow; @@ -248,28 +276,28 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) } } - /* Pre-flush X events */ - /* - * NOTE: Apparently you'll freeze if you don't do this, - * because there may be events in local data structures - * already. - */ - //winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode); - - /* Pre-flush Windows messages */ - winDebug ("Start flushing \n"); - if (!winClipboardFlushWindowsMessageQueue(hwnd)) - { - ErrorF ("winClipboardFlushWindowsMessageQueue - returned 0\n"); - goto thread_errorexit; - } - + data.fUseUnicode = fUseUnicode; winDebug ("winClipboardProc - Started\n"); /* Signal that the clipboard client has started */ g_fClipboardStarted = TRUE; - /* Loop for X events */ + /* Loop for events */ while (1) { + + /* Process X events */ + winClipboardFlushXEvents(hwnd, + iWindow, pDisplay, &data, &atoms); + + /* Process Windows messages */ + if (!winClipboardFlushWindowsMessageQueue(hwnd)) { + ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue trapped " + "WM_QUIT message, exiting main loop.\n"); + break; + } + + /* We need to ensure that all pending requests are sent */ + XFlush(pDisplay); + /* Setup the file descriptor set */ /* * NOTE: You have to do this before every call to select @@ -316,13 +344,10 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) break; } - /* Branch on which descriptor became active */ -// if (FD_ISSET (iConnectionNumber, &fdsRead)) { -// Also do it when no read since winClipboardFlushXEvents -// is sending the output. - /* Process X events */ - winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, FALSE); -// } + if (FD_ISSET(iConnectionNumber, &fdsRead)) { + winDebug + ("winClipboardProc - X connection ready, pumping X event queue\n"); + } #ifdef HAS_DEVWINDOWS /* Check for Windows event ready */ @@ -331,14 +356,16 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) if (1) #endif { - /* Process Windows messages */ - if (!winClipboardFlushWindowsMessageQueue(hwnd)) { - ErrorF("winClipboardProc - " - "winClipboardFlushWindowsMessageQueue trapped " - "WM_QUIT message, exiting main loop.\n"); - break; - } + winDebug + ("winClipboardProc - /dev/windows ready, pumping Windows message queue\n"); } + +#ifdef HAS_DEVWINDOWS + if (!(FD_ISSET(iConnectionNumber, &fdsRead)) && + !(FD_ISSET(fdMessageQueue, &fdsRead))) { + winDebug("winClipboardProc - Spurious wake, select() returned %d\n", iReturn); + } +#endif } /* Close our X window */ @@ -360,8 +387,11 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay) #if 0 /* - * FIXME: XCloseDisplay hangs if we call it, as of 2004/03/26. The - * XSync and XSelectInput calls did not help. + * FIXME: XCloseDisplay hangs if we call it + * + * XCloseDisplay() calls XSync(), so any outstanding errors are reported. + * If we are built into the server, this can deadlock if the server is + * in the process of exiting and waiting for this thread to exit. */ /* Discard any remaining events */ @@ -407,9 +437,10 @@ commonexit: */ HWND -winClipboardCreateMessagingWindow(void) +winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms) { WNDCLASSEX wc; + ClipboardWindowCreationParams cwcp; HWND hwnd; /* Setup our window class */ @@ -427,6 +458,11 @@ winClipboardCreateMessagingWindow(void) wc.hIconSm = 0; RegisterClassEx(&wc); + /* Information to be passed to WM_CREATE */ + cwcp.pClipboardDisplay = pDisplay; + cwcp.iClipboardWindow = iWindow; + cwcp.atoms = atoms; + /* Create the window */ hwnd = CreateWindowExA(0, /* Extended styles */ WIN_CLIPBOARD_WINDOW_CLASS, /* Class name */ @@ -439,7 +475,7 @@ winClipboardCreateMessagingWindow(void) (HWND) NULL, /* No parent or owner window */ (HMENU) NULL, /* No menu */ GetModuleHandle(NULL), /* Instance handle */ - NULL); /* Creation data */ + &cwcp); /* Creation data */ assert(hwnd != NULL); /* I'm not sure, but we may need to call this to start message processing */ diff --git a/xorg-server/hw/xwin/winclipboard/winclipboard.h b/xorg-server/hw/xwin/winclipboard/winclipboard.h index 7b172739a..d7d8efa15 100644 --- a/xorg-server/hw/xwin/winclipboard/winclipboard.h +++ b/xorg-server/hw/xwin/winclipboard/winclipboard.h @@ -27,6 +27,10 @@ #ifndef WINCLIPBOARD_H #define WINCLIPBOARD_H +#include <x11/Xdefs.h> + void winFixClipboardChain (int Removed); +extern Bool fPrimarySelection; + #endif diff --git a/xorg-server/hw/xwin/winclipboard/wndproc.c b/xorg-server/hw/xwin/winclipboard/wndproc.c index f5f931f74..d522e1f30 100755 --- a/xorg-server/hw/xwin/winclipboard/wndproc.c +++ b/xorg-server/hw/xwin/winclipboard/wndproc.c @@ -45,6 +45,7 @@ #include <sys/types.h> #include <sys/time.h> +#include <limits.h> #include "winclipboard.h" #include "misc.h" #include "winmsg.h" @@ -76,24 +77,15 @@ extern Bool g_fClipboardPrimary; static int winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay, - Bool fUseUnicode, int iTimeoutSec) + ClipboardConversionData *data, ClipboardAtoms *atoms, int iTimeoutSec) { int iConnNumber; struct timeval tv; int iReturn; DWORD dwStopTime = GetTickCount() + iTimeoutSec * 1000; - /* Make sure the output messages are sent before waiting on a response. */ - iReturn = winClipboardFlushXEvents (hwnd, - iWindow, - pDisplay, - fUseUnicode, - TRUE); - if (WIN_XEVENTS_NOTIFY == iReturn) - { - /* Bail out if notify processed */ - return iReturn; - } + winDebug("winProcessXEventsTimeout () - pumping X events for %d seconds\n", + iTimeoutSec); /* Get our connection number */ iConnNumber = ConnectionNumber(pDisplay); @@ -103,6 +95,19 @@ winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay, fd_set fdsRead; long remainingTime; + /* Process X events */ + iReturn = winClipboardFlushXEvents(hwnd, iWindow, pDisplay, data, atoms); + + winDebug("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n", iReturn); + + if ((WIN_XEVENTS_NOTIFY_DATA == iReturn) || (WIN_XEVENTS_NOTIFY_TARGETS == iReturn) || (WIN_XEVENTS_FAILED == iReturn)) { + /* Bail out */ + return iReturn; + } + + /* We need to ensure that all pending requests are sent */ + XFlush(pDisplay); + /* Setup the file descriptor set */ FD_ZERO(&fdsRead); FD_SET(iConnNumber, &fdsRead); @@ -130,24 +135,8 @@ winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay, break; } - /* Branch on which descriptor became active */ - if (FD_ISSET(iConnNumber, &fdsRead)) { - /* Process X events */ - /* Exit when we see that server is shutting down */ - iReturn = winClipboardFlushXEvents(hwnd, - iWindow, pDisplay, fUseUnicode, TRUE); - - winDebug - ("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n", - iReturn); - - if (WIN_XEVENTS_NOTIFY == iReturn) { - /* Bail out if notify processed */ - return iReturn; - } - } - else { - winDebug("winProcessXEventsTimeout - Spurious wake\n"); + if (!FD_ISSET(iConnNumber, &fdsRead)) { + winDebug("winProcessXEventsTimeout - Spurious wake, select() returned %d\n", iReturn); } } @@ -162,6 +151,7 @@ LRESULT CALLBACK winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND s_hwndNextViewer; + static Bool fRunning; /* Branch on message type */ switch (message) { @@ -174,6 +164,13 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) s_hwndNextViewer = NULL; g_hwndClipboard = NULL; + } + return 0; + + case WM_WM_QUIT: + { + winDebug("winClipboardWindowProc - WM_WM_QUIT\n"); + fRunning = FALSE; PostQuitMessage(0); } return 0; @@ -185,6 +182,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) winDebug("winClipboardWindowProc - WM_CREATE\n"); + fRunning = TRUE; /* Add ourselves to the clipboard viewer chain */ s_hwndNextViewer = SetClipboardViewer (hwnd); #ifdef _DEBUG @@ -300,6 +298,10 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) return 0; } + /* Bail when shutting down */ + if (!fRunning) + return 0; + /* * Do not take ownership of the X11 selections when something * other than CF_TEXT or CF_UNICODETEXT has been copied @@ -406,92 +408,153 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) winDebug("winClipboardWindowProc - WM_DESTROYCLIPBOARD - Ignored.\n"); return 0; - case WM_RENDERFORMAT: case WM_RENDERALLFORMATS: + winDebug("winClipboardWindowProc - WM_RENDERALLFORMATS - Hello.\n"); + + /* + WM_RENDERALLFORMATS is sent as we are shutting down, to render the + clipboard so it's contents remains available to other applications. + + Unfortunately, this can't work without major changes. The server is + already waiting for us to stop, so we can't ask for the rendering of + clipboard text now. + */ + + return 0; + + case WM_RENDERFORMAT: { int iReturn; Display *pDisplay = g_pClipboardDisplay; Window iWindow = g_iClipboardWindow; Bool fConvertToUnicode; + Bool pasted = FALSE; + Atom selection; + ClipboardConversionData data; + int best_target = 0; - winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n"); + winDebug("winClipboardWindowProc - WM_RENDERFORMAT %d - Hello.\n", + wParam); /* Flag whether to convert to Unicode or not */ - if (message == WM_RENDERALLFORMATS) - fConvertToUnicode = FALSE; - else - fConvertToUnicode = (CF_UNICODETEXT == wParam); + fConvertToUnicode = (CF_UNICODETEXT == wParam); - /* Request the selection contents */ - iReturn = XConvertSelection(pDisplay, - g_atomLastOwnedSelection, - XInternAtom(pDisplay, - "COMPOUND_TEXT", False), - XInternAtom(pDisplay, - WIN_LOCAL_PROPERTY, False), - iWindow, CurrentTime); - if (iReturn == BadAtom || iReturn == BadWindow) { - ErrorF ("winClipboardWindowProc - WM_RENDER*FORMAT - " - "XConvertSelection () failed\n"); - break; + selection = winClipboardGetLastOwnedSelectionAtom(atoms); + if (selection == None) { + ErrorF("winClipboardWindowProc - no monitored selection is owned\n"); + goto fake_paste; } - /* Special handling for WM_RENDERALLFORMATS */ - if (message == WM_RENDERALLFORMATS) { - /* We must open and empty the clipboard */ - if (!OpenClipboard(hwnd)) { - ErrorF ("winClipboardWindowProc - WM_RENDER*FORMATS - " - "OpenClipboard () failed: %08x\n", - GetLastError()); - break; - } + winDebug("winClipboardWindowProc - requesting targets for selection from owner\n"); - if (!EmptyClipboard()) { - ErrorF ("winClipboardWindowProc - WM_RENDER*FORMATS - " - "EmptyClipboard () failed: %08x\n", - GetLastError()); - CloseClipboard (); - break; - } + /* Request the selection's supported conversion targets */ + XConvertSelection(pDisplay, + selection, + atoms->atomTargets, + atoms->atomLocalProperty, + iWindow, CurrentTime); + + /* Process X events */ + data.fUseUnicode = fConvertToUnicode; + iReturn = winProcessXEventsTimeout(hwnd, + iWindow, + pDisplay, + &data, + atoms, + WIN_POLL_TIMEOUT); + + if (WIN_XEVENTS_NOTIFY_TARGETS != iReturn) { + ErrorF + ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_TARGETS\n"); + goto fake_paste; + } + + /* Choose the most preferred target */ + { + struct target_priority + { + Atom target; + unsigned int priority; + }; + + struct target_priority target_priority_table[] = + { + { atoms->atomCompoundText, 0 }, +#ifdef X_HAVE_UTF8_STRING + { atoms->atomUTF8String, 1 }, +#endif + { XA_STRING, 2 }, + }; + + int best_priority = INT_MAX; + + int i,j; + for (i = 0 ; data.targetList[i] != 0; i++) + { + for (j = 0; j < sizeof(target_priority_table)/sizeof(struct target_priority); j ++) + { + if ((data.targetList[i] == target_priority_table[j].target) && + (target_priority_table[j].priority < best_priority)) + { + best_target = target_priority_table[j].target; + best_priority = target_priority_table[j].priority; + } + } + } } - /* Process the SelectionNotify event */ + free(data.targetList); + data.targetList = 0; + + winDebug("winClipboardWindowProc - best target is %d\n", best_target); + + /* No useful targets found */ + if (best_target == 0) + goto fake_paste; + + winDebug("winClipboardWindowProc - requesting selection from owner\n"); + + /* Request the selection contents */ + XConvertSelection(pDisplay, + selection, + best_target, + atoms->atomLocalProperty, + iWindow, CurrentTime); + + /* Process X events */ iReturn = winProcessXEventsTimeout(hwnd, iWindow, pDisplay, - fConvertToUnicode, WIN_POLL_TIMEOUT); + &data, + atoms, + WIN_POLL_TIMEOUT); /* - * The last call to winProcessXEventsTimeout - * from above had better have seen a notify event, or else we - * are dealing with a buggy or old X11 app. In these cases we - * have to paste some fake data to the Win32 clipboard to - * satisfy the requirement that we write something to it. + * winProcessXEventsTimeout had better have seen a notify event, + * or else we are dealing with a buggy or old X11 app. */ - if (WIN_XEVENTS_NOTIFY != iReturn) { - ErrorF("winClipboardWindowProc - winProcessXEventsTimeout should have returned WIN_XEVENTS_NOTIFY was %d\n",iReturn); - /* Paste no data, to satisfy required call to SetClipboardData */ - SetClipboardData(CF_UNICODETEXT, NULL); - SetClipboardData(CF_TEXT, NULL); - + if (WIN_XEVENTS_NOTIFY_DATA != iReturn) { ErrorF - ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY\n"); + ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_DATA\n"); } - - /* Special handling for WM_RENDERALLFORMATS */ - if (message == WM_RENDERALLFORMATS) { - /* We must close the clipboard */ - - if (!CloseClipboard()) { - ErrorF ( - "winClipboardWindowProc - WM_RENDERALLFORMATS - " - "CloseClipboard () failed: %08x\n", - GetLastError()); - break; - } + else { + pasted = TRUE; } - winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Returning.\n"); + /* + * If we couldn't get the data from the X clipboard, we + * have to paste some fake data to the Win32 clipboard to + * satisfy the requirement that we write something to it. + */ + fake_paste: + if (!pasted) + { + /* Paste no data, to satisfy required call to SetClipboardData */ + SetClipboardData(CF_UNICODETEXT, NULL); + SetClipboardData(CF_TEXT, NULL); + } + + winDebug("winClipboardWindowProc - WM_RENDERFORMAT - Returning.\n"); return 0; } } diff --git a/xorg-server/hw/xwin/winclipboard/xevents.c b/xorg-server/hw/xwin/winclipboard/xevents.c index cfbf0121e..640efeb4e 100755 --- a/xorg-server/hw/xwin/winclipboard/xevents.c +++ b/xorg-server/hw/xwin/winclipboard/xevents.c @@ -36,10 +36,158 @@ #include "winclipboard.h" #include "misc.h" #include "winmsg.h" -#include "internal.h" +/* + * 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 <unistd.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; + +extern Bool g_fClipboardPrimary; + +/* + * 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; + } -extern Bool g_fClipboardPrimary; + /* 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(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] %d = %s\n", i, atom, pszAtomName); + XFree(pszAtomName); + } + + data->targetList[nitems] = 0; + + XFree(prop); + } + + return WIN_XEVENTS_NOTIFY_TARGETS; +} /* * Process any pending X events @@ -47,21 +195,13 @@ extern Bool g_fClipboardPrimary; int winClipboardFlushXEvents(HWND hwnd, - int iWindow, Display * pDisplay, Bool fUseUnicode, Bool ClipboardOpened) + Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms) { - static Atom atomLocalProperty; - static Atom atomCompoundText; - static Atom atomUTF8String; - static Atom atomTargets; - static int generation; - - if (generation != serverGeneration) { - generation = serverGeneration; - atomLocalProperty = XInternAtom(pDisplay, WIN_LOCAL_PROPERTY, False); - atomUTF8String = XInternAtom(pDisplay, "UTF8_STRING", False); - atomCompoundText = XInternAtom(pDisplay, "COMPOUND_TEXT", False); - atomTargets = XInternAtom(pDisplay, "TARGETS", False); - } + 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)) { @@ -74,15 +214,11 @@ winClipboardFlushXEvents(HWND hwnd, int iReturn; HGLOBAL hGlobal = NULL; XICCEncodingStyle xiccesStyle; - int iConvertDataLen = 0; char *pszConvertData = NULL; char *pszTextList[2] = { NULL }; int iCount; char **ppszTextList = NULL; wchar_t *pwszUnicodeStr = NULL; - int iUnicodeLen = 0; - int iReturnDataLen = 0; - int i; Bool fAbort = FALSE; Bool fCloseClipboard = FALSE; Bool fSetClipboardData = TRUE; @@ -90,8 +226,6 @@ winClipboardFlushXEvents(HWND hwnd, /* Get the next event - will not block because one is ready */ XNextEvent(pDisplay, &event); - winDebug ("Received event type %d\n",event.type); - /* Branch on the event type */ switch (event.type) { /* @@ -111,8 +245,6 @@ winClipboardFlushXEvents(HWND hwnd, winDebug("SelectionRequest - Target atom name %s\n", pszAtomName); XFree(pszAtomName); pszAtomName = NULL; - winDebug ("SelectionRequest - owner %d\n", event.xselectionrequest.owner); - winDebug ("SelectionRequest - requestor %d\n", event.xselectionrequest.requestor); } #endif @@ -182,8 +314,7 @@ winClipboardFlushXEvents(HWND hwnd, if (!OpenClipboard (hwnd)) { ErrorF ("winClipboardFlushXEvents - SelectionRequest - " - "OpenClipboard () failed: %08lx\n", - GetLastError ()); + "OpenClipboard () failed: %08lx\n", GetLastError()); /* Abort */ fAbort = TRUE; @@ -195,7 +326,7 @@ winClipboardFlushXEvents(HWND hwnd, } /* Check that clipboard format is available */ - if (fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) { + 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? */ @@ -212,7 +343,7 @@ winClipboardFlushXEvents(HWND hwnd, fAbort = TRUE; goto winClipboardFlushXEvents_SelectionRequest_Done; } - else if (!fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) { + else if (!data->fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) { ErrorF("winClipboardFlushXEvents - CF_TEXT is not " "available from Win32 clipboard. Aborting.\n"); @@ -234,7 +365,7 @@ winClipboardFlushXEvents(HWND hwnd, xiccesStyle = XStringStyle; /* Get a pointer to the clipboard text, in desired format */ - if (fUseUnicode) { + if (data->fUseUnicode) { /* Retrieve clipboard data */ hGlobal = GetClipboardData(CF_UNICODETEXT); } @@ -243,17 +374,17 @@ winClipboardFlushXEvents(HWND hwnd, hGlobal = GetClipboardData(CF_TEXT); } if (!hGlobal) { - if (GetLastError()==ERROR_CLIPBOARD_NOT_OPEN && ClipboardOpened) - { - ErrorF("We should not have received a SelectionRequest????\n" - "The owner is the clipboard, but in reality it was" - "an X window\n"); - /* Set the owner to None */ - if (g_fClipboardPrimary) XSetSelectionOwner (pDisplay, XA_PRIMARY, None, CurrentTime); - XSetSelectionOwner (pDisplay, XInternAtom (pDisplay, "CLIPBOARD", False), None, CurrentTime); - } - ErrorF ("winClipboardFlushXEvents - SelectionRequest - " - "GetClipboardData () failed: %08lx\n", GetLastError()); + if (GetLastError()==ERROR_CLIPBOARD_NOT_OPEN && ClipboardOpened) + { + ErrorF("We should not have received a SelectionRequest????\n" + "The owner is the clipboard, but in reality it was" + "an X window\n"); + /* Set the owner to None */ + if (g_fClipboardPrimary) XSetSelectionOwner (pDisplay, XA_PRIMARY, None, CurrentTime); + XSetSelectionOwner (pDisplay, XInternAtom (pDisplay, "CLIPBOARD", False), None, CurrentTime); + } + ErrorF ("winClipboardFlushXEvents - SelectionRequest - " + "GetClipboardData () failed: %08lx\n", GetLastError()); /* Abort */ fAbort = TRUE; @@ -262,8 +393,8 @@ winClipboardFlushXEvents(HWND hwnd, pszGlobalData = (char *) GlobalLock(hGlobal); /* Convert the Unicode string to UTF8 (MBCS) */ - if (fUseUnicode) { - iConvertDataLen = WideCharToMultiByte(CP_UTF8, + if (data->fUseUnicode) { + int iConvertDataLen = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) pszGlobalData, -1, NULL, 0, NULL, NULL); @@ -278,7 +409,6 @@ winClipboardFlushXEvents(HWND hwnd, } else { pszConvertData = strdup(pszGlobalData); - iConvertDataLen = strlen(pszConvertData) + 1; } /* Convert DOS string to UNIX string */ @@ -293,7 +423,7 @@ winClipboardFlushXEvents(HWND hwnd, xtpText.nitems = 0; /* Create the text property from the text list */ - if (fUseUnicode) { + if (data->fUseUnicode) { #ifdef X_HAVE_UTF8_STRING iReturn = Xutf8TextListToTextProperty(pDisplay, pszTextList, @@ -340,11 +470,11 @@ winClipboardFlushXEvents(HWND hwnd, /* Release the clipboard data */ GlobalUnlock(hGlobal); pszGlobalData = NULL; - if (fCloseClipboard) - { - fCloseClipboard = FALSE; - CloseClipboard (); - } + if (fCloseClipboard) + { + fCloseClipboard = FALSE; + CloseClipboard (); + } /* Clean up */ XFree(xtpText.value); xtpText.value = NULL; @@ -423,6 +553,7 @@ winClipboardFlushXEvents(HWND hwnd, /* * SelectionNotify */ + case SelectionNotify: #ifdef _DEBUG winDebug("winClipboardFlushXEvents - SelectionNotify\n"); @@ -435,82 +566,37 @@ winClipboardFlushXEvents(HWND hwnd, winDebug ("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n", pszAtomName); - winDebug ("SelectionNotify - requestor %d\n", event.xselectionrequest.requestor); XFree(pszAtomName); } #endif /* - * Request conversion of UTF8 and CompoundText targets. - */ - if (event.xselection.property == None) { - if (event.xselection.target == XA_STRING) { - winDebug("winClipboardFlushXEvents - SelectionNotify - " - "XA_STRING\n"); + SelectionNotify with property of None indicates either: - return WIN_XEVENTS_CONVERT; - } - else if (event.xselection.target == atomUTF8String) { - winDebug("winClipboardFlushXEvents - SelectionNotify - " - "Requesting conversion of UTF8 target.\n"); - - XConvertSelection(pDisplay, - event.xselection.selection, - XA_STRING, - atomLocalProperty, iWindow, CurrentTime); - - /* Process the ConvertSelection event */ - XFlush(pDisplay); - return WIN_XEVENTS_CONVERT; - } -#ifdef X_HAVE_UTF8_STRING - else if (event.xselection.target == atomCompoundText) { - winDebug("winClipboardFlushXEvents - SelectionNotify - " - "Requesting conversion of CompoundText target.\n"); - - XConvertSelection(pDisplay, - event.xselection.selection, - atomUTF8String, - atomLocalProperty, iWindow, CurrentTime); - - /* Process the ConvertSelection event */ - XFlush(pDisplay); - return WIN_XEVENTS_CONVERT; - } -#endif - else { + (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 - " - "Unknown format. Cannot request conversion, " - "aborting.\n"); - break; + "Conversion to format %d refused.\n", + event.xselection.target); + return WIN_XEVENTS_FAILED; } - } - /* Retrieve the size of the stored data */ - iReturn = XGetWindowProperty(pDisplay, iWindow, atomLocalProperty, 0, 0, /* Don't get data, just size */ - False, - AnyPropertyType, - &xtpText.encoding, - &xtpText.format, - &xtpText.nitems, - &ulReturnBytesLeft, &xtpText.value); - if (iReturn != Success) { - ErrorF("winClipboardFlushXEvents - SelectionNotify - " - "XGetWindowProperty () failed, aborting: %d\n", iReturn); - break; + if (event.xselection.target == atomTargets) { + return winClipboardSelectionNotifyTargets(hwnd, iWindow, pDisplay, data, atoms); } - winDebug("SelectionNotify - returned data %d left %d\n", - xtpText.nitems, ulReturnBytesLeft); - - /* Request the selection data */ + /* Retrieve the selection data and delete the property */ iReturn = XGetWindowProperty(pDisplay, iWindow, atomLocalProperty, 0, - ulReturnBytesLeft, - False, + INT_MAX, + True, AnyPropertyType, &xtpText.encoding, &xtpText.format, @@ -519,7 +605,7 @@ winClipboardFlushXEvents(HWND hwnd, if (iReturn != Success) { ErrorF("winClipboardFlushXEvents - SelectionNotify - " "XGetWindowProperty () failed, aborting: %d\n", iReturn); - break; + goto winClipboardFlushXEvents_SelectionNotify_Done; } #ifdef WINDBG @@ -535,7 +621,7 @@ winClipboardFlushXEvents(HWND hwnd, } #endif - if (fUseUnicode) { + if (data->fUseUnicode) { #ifdef X_HAVE_UTF8_STRING /* Convert the text property to a text list */ iReturn = Xutf8TextPropertyToTextList(pDisplay, @@ -551,7 +637,8 @@ winClipboardFlushXEvents(HWND hwnd, if (iReturn == Success || iReturn > 0) { /* Conversion succeeded or some unconvertible characters */ if (ppszTextList != NULL) { - iReturnDataLen = 0; + int i; + int iReturnDataLen = 0; for (i = 0; i < iCount; i++) { iReturnDataLen += strlen(ppszTextList[i]); } @@ -600,14 +687,14 @@ winClipboardFlushXEvents(HWND hwnd, /* Convert the X clipboard string to DOS format */ winClipboardUNIXtoDOS((unsigned char **)&pszReturnData, strlen(pszReturnData)); - if (fUseUnicode) { + if (data->fUseUnicode) { /* Find out how much space needed to convert MBCS to Unicode */ - iUnicodeLen = MultiByteToWideChar(CP_UTF8, + int iUnicodeLen = MultiByteToWideChar(CP_UTF8, 0, pszReturnData, -1, NULL, 0); - /* Allocate memory for the Unicode string */ - pwszUnicodeStr = malloc(sizeof(wchar_t) * (iUnicodeLen + 1)); + /* NOTE: iUnicodeLen includes space for null terminator */ + pwszUnicodeStr = malloc(sizeof(wchar_t) * iUnicodeLen); if (!pwszUnicodeStr) { ErrorF("winClipboardFlushXEvents - SelectionNotify " "malloc failed for pwszUnicodeStr, aborting.\n"); @@ -625,9 +712,10 @@ winClipboardFlushXEvents(HWND hwnd, /* Allocate global memory for the X clipboard data */ hGlobal = GlobalAlloc(GMEM_MOVEABLE, - sizeof(wchar_t) * (iUnicodeLen + 1)); + sizeof(wchar_t) * iUnicodeLen); } else { + int iConvertDataLen = 0; pszConvertData = strdup(pszReturnData); iConvertDataLen = strlen(pszConvertData) + 1; @@ -659,9 +747,8 @@ winClipboardFlushXEvents(HWND hwnd, } /* Copy the returned string into the global memory */ - if (fUseUnicode) { - memcpy(pszGlobalData, - pwszUnicodeStr, sizeof(wchar_t) * (iUnicodeLen + 1)); + if (data->fUseUnicode) { + wcscpy((wchar_t *)pszGlobalData, pwszUnicodeStr); free(pwszUnicodeStr); pwszUnicodeStr = NULL; } @@ -676,7 +763,7 @@ winClipboardFlushXEvents(HWND hwnd, pszGlobalData = NULL; /* Push the selection data to the Windows clipboard */ - if (fUseUnicode) + if (data->fUseUnicode) SetClipboardData(CF_UNICODETEXT, hGlobal); else SetClipboardData(CF_TEXT, hGlobal); @@ -706,39 +793,92 @@ winClipboardFlushXEvents(HWND hwnd, SetClipboardData(CF_UNICODETEXT, NULL); SetClipboardData(CF_TEXT, NULL); } - return WIN_XEVENTS_NOTIFY; + return WIN_XEVENTS_NOTIFY_DATA; - /* - * SelectionClear - */ - case SelectionClear: -#ifdef _DEBUG + case SelectionClear: winDebug("SelectionClear - doing nothing\n"); - { - char *pszAtomName; - - pszAtomName = XGetAtomName (pDisplay, - event.xselection.selection); - - winDebug ("SelectionClear - ATOM: %s\n", - pszAtomName); - winDebug ("SelectionClear - owner %d\n", event.xselectionrequest.owner); - - XFree (pszAtomName); - } -#endif break; case PropertyNotify: break; - + case MappingNotify: XRefreshKeyboardMapping((XMappingEvent *)&event); 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) && 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; } } diff --git a/xorg-server/hw/xwin/winclipboard/xwinclip.c b/xorg-server/hw/xwin/winclipboard/xwinclip.c index 3677974c4..856c4dd54 100644 --- a/xorg-server/hw/xwin/winclipboard/xwinclip.c +++ b/xorg-server/hw/xwin/winclipboard/xwinclip.c @@ -92,6 +92,13 @@ main (int argc, char *argv[]) continue; } + /* Look for -noprimary */ + if (!strcmp (argv[i], "-noprimary")) + { + fPrimarySelection = False; + continue; + } + /* Yack when we find a parameter that we don't know about */ printf ("Unknown parameter: %s\nExiting.\n", argv[i]); exit (1); diff --git a/xorg-server/hw/xwin/winclipboard/xwinclip.man b/xorg-server/hw/xwin/winclipboard/xwinclip.man index 822db91d4..a53dc3029 100644 --- a/xorg-server/hw/xwin/winclipboard/xwinclip.man +++ b/xorg-server/hw/xwin/winclipboard/xwinclip.man @@ -29,6 +29,9 @@ Specifies the X server display to connect to. .TP 8 .B \-nounicodeclipboard Do not use unicode text on the clipboard. +.TP 8 +.B \-noprimary +Do not monitor the PRIMARY selection. .SH "SEE ALSO" XWin(1) diff --git a/xorg-server/hw/xwin/winclipboardwrappers.c b/xorg-server/hw/xwin/winclipboardwrappers.c index 2671fc000..c0598f9b3 100644..100755 --- a/xorg-server/hw/xwin/winclipboardwrappers.c +++ b/xorg-server/hw/xwin/winclipboardwrappers.c @@ -33,6 +33,7 @@ #ifdef HAVE_XWIN_CONFIG_H #include <xwin-config.h> #endif + #include "win.h" #include "dixstruct.h" #include <X11/Xatom.h> @@ -52,19 +53,13 @@ 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. * Initializes internal clients that must not be started until diff --git a/xorg-server/hw/xwin/winprocarg.c b/xorg-server/hw/xwin/winprocarg.c index ad0b5bbe9..29fcbc9ed 100644..100755 --- a/xorg-server/hw/xwin/winprocarg.c +++ b/xorg-server/hw/xwin/winprocarg.c @@ -37,13 +37,8 @@ from The Open Group. #include "winmsg.h" #include "winmonitors.h" -/* - * References to external symbols - */ - #ifdef XWIN_CLIPBOARD -extern Bool g_fUnicodeClipboard; -extern Bool g_fClipboard; +#include "winclipboard/winclipboard.h" extern Bool g_fClipboardPrimary; #endif @@ -719,6 +714,26 @@ ddxProcessArgument(int argc, char *argv[], int i) /* Indicate that we have processed this argument */ return 1; } + + /* + * Look for the '-primary' argument + */ + if (IS_OPTION("-primary")) { + fPrimarySelection = TRUE; + + /* Indicate that we have processed this argument */ + return 1; + } + + /* + * Look for the '-noprimary' argument + */ + if (IS_OPTION("-noprimary")) { + fPrimarySelection = FALSE; + + /* Indicate that we have processed this argument */ + return 1; + } /* * Look for the '-clipboard' argument diff --git a/xorg-server/hw/xwin/winresource.h b/xorg-server/hw/xwin/winresource.h index 39b890c7c..b9f88c18f 100644 --- a/xorg-server/hw/xwin/winresource.h +++ b/xorg-server/hw/xwin/winresource.h @@ -43,6 +43,7 @@ #define ID_APP_HIDE_ROOT 201 #define ID_APP_ALWAYS_ON_TOP 202 #define ID_APP_ABOUT 203 +#define ID_APP_MONITOR_PRIMARY 204 #define ID_ABOUT_WEBSITE 303 diff --git a/xorg-server/hw/xwin/wintrayicon.c b/xorg-server/hw/xwin/wintrayicon.c index 3c7820cf7..7df1594e6 100644 --- a/xorg-server/hw/xwin/wintrayicon.c +++ b/xorg-server/hw/xwin/wintrayicon.c @@ -32,9 +32,13 @@ #ifdef HAVE_XWIN_CONFIG_H #include <xwin-config.h> #endif + #include "win.h" #include <shellapi.h> #include "winprefs.h" +#ifdef XWIN_CLIPBOARD +#include "winclipboard/winclipboard.h" +#endif static NOTIFYICONDATA nid; /* @@ -193,6 +197,21 @@ winHandleIconMessage(HWND hwnd, UINT message, RemoveMenu(hmenuTray, ID_APP_HIDE_ROOT, MF_BYCOMMAND); } +#ifdef XWIN_CLIPBOARD + if (g_fClipboard) { + /* Set menu state to indicate if 'Monitor Primary' is enabled or not */ + MENUITEMINFO mii = { 0 }; + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_STATE; + mii.fState = fPrimarySelection ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo(hmenuTray, ID_APP_MONITOR_PRIMARY, FALSE, &mii); + } + else { + /* Remove 'Monitor Primary' menu item */ + RemoveMenu(hmenuTray, ID_APP_MONITOR_PRIMARY, MF_BYCOMMAND); + } +#endif + SetupRootMenu(hmenuTray); /* diff --git a/xorg-server/hw/xwin/winwndproc.c b/xorg-server/hw/xwin/winwndproc.c index 9a150d57b..a88f7c68d 100755 --- a/xorg-server/hw/xwin/winwndproc.c +++ b/xorg-server/hw/xwin/winwndproc.c @@ -1189,6 +1189,12 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) return 0; #endif +#ifdef XWIN_CLIPBOARD + case ID_APP_MONITOR_PRIMARY: + fPrimarySelection = !fPrimarySelection; + return 0; +#endif + case ID_APP_ABOUT: /* Display the About box */ winDisplayAboutDialog(s_pScreenPriv); |