aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xwin
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xwin')
-rwxr-xr-xxorg-server/hw/xwin/InitOutput.c4
-rw-r--r--xorg-server/hw/xwin/XWin.rc1
-rw-r--r--xorg-server/hw/xwin/man/XWin.man6
-rwxr-xr-xxorg-server/hw/xwin/winclipboard/internal.h38
-rwxr-xr-xxorg-server/hw/xwin/winclipboard/thread.c124
-rw-r--r--xorg-server/hw/xwin/winclipboard/winclipboard.h4
-rwxr-xr-xxorg-server/hw/xwin/winclipboard/wndproc.c245
-rwxr-xr-xxorg-server/hw/xwin/winclipboard/xevents.c426
-rw-r--r--xorg-server/hw/xwin/winclipboard/xwinclip.c7
-rw-r--r--xorg-server/hw/xwin/winclipboard/xwinclip.man3
-rwxr-xr-x[-rw-r--r--]xorg-server/hw/xwin/winclipboardwrappers.c7
-rwxr-xr-x[-rw-r--r--]xorg-server/hw/xwin/winprocarg.c27
-rw-r--r--xorg-server/hw/xwin/winresource.h1
-rw-r--r--xorg-server/hw/xwin/wintrayicon.c19
-rwxr-xr-xxorg-server/hw/xwin/winwndproc.c6
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);