summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2014-09-29 13:04:49 -0700
committerKeith Packard <keithp@keithp.com>2014-09-29 13:04:49 -0700
commit78c27d12e1f4857bfcfc92afbb69d5dd989232b9 (patch)
treedd73ab423772a4e899ec3f42d16dc64e77df62e3
parent6e50bfa706cd3ab884c933bf1f17c221a6208aa4 (diff)
parent1d6334dd0ca99923b6b55c5c047ef6b5c325f66c (diff)
Merge remote-tracking branch 'jturney/xwin-clipboard-refactoring'
-rw-r--r--configure.ac3
-rw-r--r--hw/xwin/InitInput.c1
-rw-r--r--hw/xwin/InitOutput.c38
-rw-r--r--hw/xwin/Makefile.am15
-rw-r--r--hw/xwin/win.h2
-rw-r--r--hw/xwin/winclipboard/Makefile.am25
-rw-r--r--hw/xwin/winclipboard/debug.c52
-rw-r--r--hw/xwin/winclipboard/internal.h (renamed from hw/xwin/winclipboard.h)79
-rw-r--r--hw/xwin/winclipboard/textconv.c (renamed from hw/xwin/winclipboardtextconv.c)18
-rw-r--r--hw/xwin/winclipboard/thread.c (renamed from hw/xwin/winclipboardthread.c)314
-rw-r--r--hw/xwin/winclipboard/winclipboard.h36
-rw-r--r--hw/xwin/winclipboard/wndproc.c (renamed from hw/xwin/winclipboardwndproc.c)126
-rw-r--r--hw/xwin/winclipboard/xevents.c (renamed from hw/xwin/winclipboardxevents.c)197
-rw-r--r--hw/xwin/winclipboard/xwinclip.c127
-rw-r--r--hw/xwin/winclipboard/xwinclip.man61
-rw-r--r--hw/xwin/winclipboardinit.c150
-rw-r--r--hw/xwin/winclipboardwrappers.c226
-rw-r--r--hw/xwin/windialogs.c7
-rw-r--r--hw/xwin/winglobals.c13
-rw-r--r--hw/xwin/winglobals.h4
-rw-r--r--hw/xwin/winwndproc.c3
21 files changed, 853 insertions, 644 deletions
diff --git a/configure.ac b/configure.ac
index 51e0f1fd1..30c0c5cd9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2142,7 +2142,7 @@ if test "x$XWIN" = xyes; then
AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support])
AC_CHECK_TOOL(WINDRES, windres)
- PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau])
+ PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau xfixes])
if test "x$WINDOWSWM" = xauto; then
PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no])
@@ -2600,6 +2600,7 @@ hw/xnest/man/Makefile
hw/xwin/Makefile
hw/xwin/glx/Makefile
hw/xwin/man/Makefile
+hw/xwin/winclipboard/Makefile
hw/xquartz/Makefile
hw/xquartz/GL/Makefile
hw/xquartz/bundle/Makefile
diff --git a/hw/xwin/InitInput.c b/hw/xwin/InitInput.c
index 38203c906..3e9ee41e6 100644
--- a/hw/xwin/InitInput.c
+++ b/hw/xwin/InitInput.c
@@ -39,7 +39,6 @@
#ifdef XWIN_CLIPBOARD
int winProcEstablishConnection(ClientPtr /* client */ );
-int winProcSetSelectionOwner(ClientPtr /* client */ );
#endif
/*
diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c
index 6b5c38d92..88bc85a44 100644
--- a/hw/xwin/InitOutput.c
+++ b/hw/xwin/InitOutput.c
@@ -66,24 +66,11 @@ typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner,
/*
* References to external symbols
*/
-#ifdef XWIN_CLIPBOARD
-extern Bool g_fUnicodeClipboard;
-extern Bool g_fClipboardLaunched;
-extern Bool g_fClipboardStarted;
-extern pthread_t g_ptClipboardProc;
-extern HWND g_hwndClipboard;
-extern Bool g_fClipboard;
-#endif
/*
* Function prototypes
*/
-#ifdef XWIN_CLIPBOARD
-static void
- winClipboardShutdown(void);
-#endif
-
static Bool
winCheckDisplayNumber(void);
@@ -125,31 +112,6 @@ static PixmapFormatRec g_PixmapFormats[] = {
const int NUMFORMATS = sizeof(g_PixmapFormats) / sizeof(g_PixmapFormats[0]);
-#ifdef XWIN_CLIPBOARD
-static void
-winClipboardShutdown(void)
-{
- /* Close down clipboard resources */
- if (g_fClipboard && g_fClipboardLaunched && g_fClipboardStarted) {
- /* Synchronously destroy the clipboard window */
- if (g_hwndClipboard != NULL) {
- SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
- /* NOTE: g_hwndClipboard is set to NULL in winclipboardthread.c */
- }
- else
- return;
-
- /* Wait for the clipboard thread to exit */
- pthread_join(g_ptClipboardProc, NULL);
-
- g_fClipboardLaunched = FALSE;
- g_fClipboardStarted = FALSE;
-
- winDebug("winClipboardShutdown - Clipboard thread has exited.\n");
- }
-}
-#endif
-
static const ExtensionModule xwinExtensions[] = {
#ifdef GLXEXT
{ GlxExtensionInit, "GLX", &noGlxExtension },
diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am
index 326ffa03d..2c7fde313 100644
--- a/hw/xwin/Makefile.am
+++ b/hw/xwin/Makefile.am
@@ -3,12 +3,9 @@ bin_PROGRAMS = XWin
if XWIN_CLIPBOARD
SRCS_CLIPBOARD = \
winclipboardinit.c \
- winclipboardtextconv.c \
- winclipboardthread.c \
- winclipboardwndproc.c \
- winclipboardwrappers.c \
- winclipboardxevents.c
+ winclipboardwrappers.c
DEFS_CLIPBOARD = -DXWIN_CLIPBOARD
+CLIPBOARD_LIBS = $(top_builddir)/hw/xwin/winclipboard/libXWinclipboard.la
endif
if XWIN_GLX_WINDOWS
@@ -110,7 +107,6 @@ SRCS = InitInput.c \
winwindow.c \
winwndproc.c \
ddraw.h \
- winclipboard.h \
winconfig.h \
win.h \
winglobals.h \
@@ -162,12 +158,15 @@ XWin_DEPENDENCIES = \
$(MULTIWINDOWEXTWM_LIBS) \
$(XWIN_GLX_LIBS) \
$(XWIN_LIBS) \
+ $(CLIPBOARD_LIBS) \
$(XSERVER_LIBS)
+
XWin_LDADD = \
$(MULTIWINDOWEXTWM_LIBS) \
$(XWIN_GLX_LIBS) \
$(XWIN_LIBS) \
+ $(CLIPBOARD_LIBS) \
$(XSERVER_LIBS) \
$(XWIN_GLX_SYS_LIBS) \
$(XSERVER_SYS_LIBS) \
@@ -210,5 +209,5 @@ EXTRA_DIST = \
relink:
$(AM_V_at)rm -f XWin$(EXEEXT) && $(MAKE) XWin$(EXEEXT)
-SUBDIRS = man $(GLX_DIR) .
-DIST_SUBDIRS = man glx .
+SUBDIRS = man $(GLX_DIR) winclipboard .
+DIST_SUBDIRS = man glx winclipboard .
diff --git a/hw/xwin/win.h b/hw/xwin/win.h
index a738a5940..7af35e71b 100644
--- a/hw/xwin/win.h
+++ b/hw/xwin/win.h
@@ -793,7 +793,7 @@ Bool
winInitClipboard(void);
void
- winFixClipboardChain(void);
+ winClipboardShutdown(void);
#endif
/*
diff --git a/hw/xwin/winclipboard/Makefile.am b/hw/xwin/winclipboard/Makefile.am
new file mode 100644
index 000000000..b1c95f4ef
--- /dev/null
+++ b/hw/xwin/winclipboard/Makefile.am
@@ -0,0 +1,25 @@
+noinst_LTLIBRARIES = libXWinclipboard.la
+
+libXWinclipboard_la_SOURCES = \
+ winclipboard.h \
+ textconv.c \
+ thread.c \
+ wndproc.c \
+ xevents.c
+
+libXWinclipboard_la_CFLAGS = -DHAVE_XWIN_CONFIG_H \
+ $(DIX_CFLAGS) \
+ $(XWINMODULES_CFLAGS)
+
+libXWinclipboard_la_LDFLAGS = -static -no-undefined
+
+bin_PROGRAMS = xwinclip
+
+xwinclip_SOURCES = xwinclip.c debug.c
+
+xwinclip_CFLAGS = $(XWINMODULES_CFLAGS)
+
+xwinclip_LDADD = libXWinclipboard.la $(XWINMODULES_LIBS) -lgdi32
+
+include $(top_srcdir)/manpages.am
+appman_PRE = xwinclip.man
diff --git a/hw/xwin/winclipboard/debug.c b/hw/xwin/winclipboard/debug.c
new file mode 100644
index 000000000..78ab6d902
--- /dev/null
+++ b/hw/xwin/winclipboard/debug.c
@@ -0,0 +1,52 @@
+//
+// Copyright © Jon TURNEY 2013
+//
+// This file is part of xwinclip.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice (including the next
+// paragraph) shall be included in all copies or substantial portions of the
+// Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#if 1
+int
+winDebug(const char *format, ...)
+{
+ int count;
+ va_list ap;
+ va_start(ap, format);
+ count = fprintf(stderr, "xwinclip: ");
+ count += vfprintf(stderr, format, ap);
+ va_end(ap);
+ return count;
+}
+#endif
+
+int
+ErrorF(const char *format, ...)
+{
+ int count;
+ va_list ap;
+ va_start(ap, format);
+ count = vfprintf(stderr, format, ap);
+ va_end(ap);
+ return count;
+}
diff --git a/hw/xwin/winclipboard.h b/hw/xwin/winclipboard/internal.h
index cb7769510..94956f80d 100644
--- a/hw/xwin/winclipboard.h
+++ b/hw/xwin/winclipboard/internal.h
@@ -1,5 +1,4 @@
-#ifndef _WINCLIPBOARD_H_
-#define _WINCLIPBOARD_H_
+
/*
*Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
*
@@ -30,46 +29,18 @@
* Authors: Harold L Hunt II
*/
-/* Standard library headers */
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#ifdef __CYGWIN__
-#include <sys/select.h>
-#else
-#include <X11/Xwinsock.h>
-#endif
-#include <fcntl.h>
-#include <setjmp.h>
-#include <pthread.h>
+#ifndef WINCLIPBOARD_INTERNAL_H
+#define WINCLIPBOARD_INTERNAL_H
/* X headers */
-#include <X11/X.h>
-#include <X11/Xatom.h>
-#include <X11/Xproto.h>
-#include <X11/Xutil.h>
-#include <X11/Xlocale.h>
+#include <X11/Xlib.h>
/* Windows headers */
#include <X11/Xwindows.h>
-/* Clipboard module constants */
-#define WIN_CLIPBOARD_WINDOW_CLASS "xwinclip"
-#define WIN_CLIPBOARD_WINDOW_TITLE "xwinclip"
-#ifdef HAS_DEVWINDOWS
-#define WIN_MSG_QUEUE_FNAME "/dev/windows"
-#endif
-#define WIN_CONNECT_RETRIES 40
-#define WIN_CONNECT_DELAY 4
-#define WIN_JMP_OKAY 0
-#define WIN_JMP_ERROR_IO 2
-#define WIN_LOCAL_PROPERTY "CYGX_CUT_BUFFER"
#define WIN_XEVENTS_SUCCESS 0
#define WIN_XEVENTS_CONVERT 2
#define WIN_XEVENTS_NOTIFY 3
-#define WIN_CLIPBOARD_RETRIES 40
-#define WIN_CLIPBOARD_DELAY 1
#define WM_WM_REINIT (WM_USER + 1)
@@ -77,18 +48,8 @@
* References to external symbols
*/
-extern char *display;
extern void winDebug(const char *format, ...);
-extern void winErrorFVerb(int verb, const char *format, ...);
-
-/*
- * winclipboardinit.c
- */
-
-Bool
- winInitClipboard(void);
-
-HWND winClipboardCreateMessagingWindow(void);
+extern void ErrorF(const char *format, ...);
/*
* winclipboardtextconv.c
@@ -104,23 +65,45 @@ void
* winclipboardthread.c
*/
-void *winClipboardProc(void *);
+
+typedef struct
+{
+ Atom atomClipboard;
+ Atom atomLocalProperty;
+ Atom atomUTF8String;
+ Atom atomCompoundText;
+ Atom atomTargets;
+} ClipboardAtoms;
/*
* winclipboardwndproc.c
*/
-BOOL winClipboardFlushWindowsMessageQueue(HWND hwnd);
+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
*/
int
-
winClipboardFlushXEvents(HWND hwnd,
- int iWindow, Display * pDisplay, Bool fUnicodeSupport);
+ Window iWindow, Display * pDisplay, Bool fUnicodeSupport, ClipboardAtoms *atom);
+
+
+Atom
+winClipboardGetLastOwnedSelectionAtom(ClipboardAtoms *atoms);
+
+void
+winClipboardInitMonitoredSelections(void);
+
#endif
diff --git a/hw/xwin/winclipboardtextconv.c b/hw/xwin/winclipboard/textconv.c
index fd405a02e..9c9cb3529 100644
--- a/hw/xwin/winclipboardtextconv.c
+++ b/hw/xwin/winclipboard/textconv.c
@@ -31,14 +31,18 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
-#include "win.h"
-#include <stdio.h>
-#include <stdlib.h>
-void
- winClipboardDOStoUNIX(char *pszSrc, int iLength);
-void
- winClipboardUNIXtoDOS(char **ppszData, int iLength);
+/*
+ * 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 <stdlib.h>
+#include "internal.h"
/*
* Convert \r\n to \n
diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboard/thread.c
index e70896081..c179e3f83 100644
--- a/hw/xwin/winclipboardthread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -35,42 +35,62 @@
#else
#define HAS_WINSOCK 1
#endif
-#include <sys/types.h>
-#include <signal.h>
-#include "winclipboard.h"
-#include "windisplay.h"
-#ifdef __CYGWIN__
-#include <errno.h>
-#endif
-#include "misc.h"
/*
- * References to external symbols
+ * 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
-extern Bool g_fUnicodeClipboard;
-extern Bool g_fClipboardStarted;
-extern Bool g_fClipboardLaunched;
-extern Bool g_fClipboard;
-extern HWND g_hwndClipboard;
-extern void *g_pClipboardDisplay;
-extern Window g_iClipboardWindow;
+#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <pthread.h>
+#include <sys/param.h> // for MAX() macro
+
+#ifdef HAS_WINSOCK
+#include <X11/Xwinsock.h>
+#else
+#include <errno.h>
+#endif
+
+#include <X11/Xatom.h>
+#include <X11/extensions/Xfixes.h>
+#include "winclipboard.h"
+#include "internal.h"
+
+#define WIN_CONNECT_RETRIES 40
+#define WIN_CONNECT_DELAY 4
+
+#define WIN_CLIPBOARD_WINDOW_CLASS "xwinclip"
+#define WIN_CLIPBOARD_WINDOW_TITLE "xwinclip"
+#ifdef HAS_DEVWINDOWS
+#define WIN_MSG_QUEUE_FNAME "/dev/windows"
+#endif
/*
* Global variables
*/
+static HWND g_hwndClipboard = NULL;
static jmp_buf g_jmpEntry;
-static int clipboardRestarts = 0;
static XIOErrorHandler g_winClipboardOldIOErrorHandler;
static pthread_t g_winClipboardProcThread;
-Bool g_fUseUnicode = FALSE;
+int xfixes_event_base;
+int xfixes_error_base;
/*
* Local function prototypes
*/
+static HWND
+winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms);
+
static int
winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr);
@@ -78,13 +98,15 @@ static int
winClipboardIOErrorHandler(Display * pDisplay);
/*
- * Main thread function
+ * Create X11 and Win32 messaging windows, and run message processing loop
+ *
+ * returns TRUE if shutdown was signalled to loop, FALSE if some error occurred
*/
-void *
-winClipboardProc(void *pvNotUsed)
+Bool
+winClipboardProc(Bool fUseUnicode, char *szDisplay)
{
- Atom atomClipboard;
+ ClipboardAtoms atoms;
int iReturn;
HWND hwnd = NULL;
int iConnectionNumber = 0;
@@ -98,19 +120,11 @@ winClipboardProc(void *pvNotUsed)
int iMaxDescriptor;
Display *pDisplay = NULL;
Window iWindow = None;
- int iRetries;
- Bool fUseUnicode;
- char szDisplay[512];
int iSelectError;
+ Bool fShutdown = FALSE;
+ static Bool fErrorHandlerSet = FALSE;
winDebug("winClipboardProc - Hello\n");
- ++clipboardRestarts;
-
- /* Do we use Unicode clipboard? */
- fUseUnicode = g_fUnicodeClipboard;
-
- /* Save the Unicode support flag in a global */
- g_fUseUnicode = fUseUnicode;
/* Allow multiple threads to access Xlib */
if (XInitThreads() == 0) {
@@ -123,70 +137,29 @@ winClipboardProc(void *pvNotUsed)
ErrorF("winClipboardProc - Warning: Locale not supported by X.\n");
}
- /* Set error handler */
- XSetErrorHandler(winClipboardErrorHandler);
g_winClipboardProcThread = pthread_self();
- g_winClipboardOldIOErrorHandler =
- XSetIOErrorHandler(winClipboardIOErrorHandler);
- /* Set jump point for Error exits */
- iReturn = setjmp(g_jmpEntry);
-
- /* Check if we should continue operations */
- if (iReturn != WIN_JMP_ERROR_IO && iReturn != WIN_JMP_OKAY) {
- /* setjmp returned an unknown value, exit */
- ErrorF("winClipboardProc - setjmp returned: %d exiting\n", iReturn);
- goto winClipboardProc_Exit;
- }
- else if (iReturn == WIN_JMP_ERROR_IO) {
- /* TODO: Cleanup the Win32 window and free any allocated memory */
- ErrorF("winClipboardProc - setjmp returned for IO Error Handler.\n");
- pthread_exit(NULL);
+ /* Set error handler */
+ if (!fErrorHandlerSet) {
+ XSetErrorHandler(winClipboardErrorHandler);
+ g_winClipboardOldIOErrorHandler =
+ XSetIOErrorHandler(winClipboardIOErrorHandler);
+ fErrorHandlerSet = TRUE;
}
- /* Use our generated cookie for authentication */
- winSetAuthorization();
-
- /* Initialize retry count */
- iRetries = 0;
-
- /* Setup the display connection string x */
- /*
- * NOTE: Always connect to screen 0 since we require that screen
- * numbers start at 0 and increase without gaps. We only need
- * to connect to one screen on the display to get events
- * for all screens on the display. That is why there is only
- * one clipboard client thread.
- */
- winGetDisplayName(szDisplay, 0);
-
- /* Print the display connection string */
- ErrorF("winClipboardProc - DISPLAY=%s\n", szDisplay);
-
- /* Open the X display */
- do {
- pDisplay = XOpenDisplay(szDisplay);
- if (pDisplay == NULL) {
- ErrorF("winClipboardProc - Could not open display, "
- "try: %d, sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY);
- ++iRetries;
- sleep(WIN_CONNECT_DELAY);
- continue;
- }
- else
- break;
+ /* Set jump point for Error exits */
+ if (setjmp(g_jmpEntry)) {
+ ErrorF("winClipboardProc - setjmp returned for IO Error Handler.\n");
+ goto winClipboardProc_Done;
}
- while (pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
/* Make sure that the display opened */
+ pDisplay = XOpenDisplay(szDisplay);
if (pDisplay == NULL) {
ErrorF("winClipboardProc - Failed opening the display, giving up\n");
goto winClipboardProc_Done;
}
- /* Save the display in the screen privates */
- g_pClipboardDisplay = pDisplay;
-
ErrorF("winClipboardProc - XOpenDisplay () returned and "
"successfully opened the display.\n");
@@ -202,13 +175,20 @@ winClipboardProc(void *pvNotUsed)
}
/* Find max of our file descriptors */
- iMaxDescriptor = max(fdMessageQueue, iConnectionNumber) + 1;
+ iMaxDescriptor = MAX(fdMessageQueue, iConnectionNumber) + 1;
#else
iMaxDescriptor = iConnectionNumber + 1;
#endif
- /* Create atom */
- atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", 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,
@@ -230,13 +210,27 @@ winClipboardProc(void *pvNotUsed)
ErrorF("winClipboardProc - XSelectInput generated BadWindow "
"on messaging window\n");
- /* Save the window in the screen privates */
- g_iClipboardWindow = iWindow;
+ XFixesSelectSelectionInput (pDisplay,
+ iWindow,
+ XA_PRIMARY,
+ XFixesSetSelectionOwnerNotifyMask |
+ XFixesSelectionWindowDestroyNotifyMask |
+ XFixesSelectionClientCloseNotifyMask);
+
+ XFixesSelectSelectionInput (pDisplay,
+ iWindow,
+ atoms.atomClipboard,
+ XFixesSetSelectionOwnerNotifyMask |
+ XFixesSelectionWindowDestroyNotifyMask |
+ XFixesSelectionClientCloseNotifyMask);
+
+ /* Initialize monitored selection state */
+ winClipboardInitMonitoredSelections();
/* Create Windows messaging window */
- hwnd = winClipboardCreateMessagingWindow();
+ hwnd = winClipboardCreateMessagingWindow(pDisplay, iWindow, &atoms);
- /* Save copy of HWND in screen privates */
+ /* Save copy of HWND */
g_hwndClipboard = hwnd;
/* Assert ownership of selections if Win32 clipboard is owned */
@@ -251,29 +245,27 @@ winClipboardProc(void *pvNotUsed)
}
/* CLIPBOARD */
- iReturn = XSetSelectionOwner(pDisplay, atomClipboard,
+ iReturn = XSetSelectionOwner(pDisplay, atoms.atomClipboard,
iWindow, CurrentTime);
if (iReturn == BadAtom || iReturn == BadWindow ||
- XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
+ XGetSelectionOwner(pDisplay, atoms.atomClipboard) != iWindow) {
ErrorF("winClipboardProc - Could not set CLIPBOARD owner\n");
goto winClipboardProc_Done;
}
}
/* 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);
+ winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms);
/* Pre-flush Windows messages */
- if (!winClipboardFlushWindowsMessageQueue(hwnd))
- return 0;
-
- /* Signal that the clipboard client has started */
- g_fClipboardStarted = TRUE;
+ if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
+ ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue failed\n");
+ }
/* Loop for X events */
while (1) {
@@ -326,7 +318,7 @@ winClipboardProc(void *pvNotUsed)
/* Branch on which descriptor became active */
if (FD_ISSET(iConnectionNumber, &fdsRead)) {
/* Process X events */
- winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
+ winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms);
}
#ifdef HAS_DEVWINDOWS
@@ -347,16 +339,13 @@ winClipboardProc(void *pvNotUsed)
}
winClipboardProc_Exit:
- /* disable the clipboard, which means the thread will die */
- g_fClipboard = FALSE;
+ /* broke out of while loop on a shutdown message */
+ fShutdown = TRUE;
winClipboardProc_Done:
/* Close our Windows window */
if (g_hwndClipboard) {
- /* Destroy the Window window (hwnd) */
- winDebug("winClipboardProc - Destroy Windows window\n");
- PostMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
- winClipboardFlushWindowsMessageQueue(g_hwndClipboard);
+ winClipboardWindowDestroy();
}
/* Close our X window */
@@ -376,8 +365,11 @@ winClipboardProc(void *pvNotUsed)
#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 */
@@ -393,42 +385,64 @@ winClipboardProc(void *pvNotUsed)
#endif
/* global clipboard variable reset */
- g_fClipboardLaunched = FALSE;
- g_fClipboardStarted = FALSE;
- g_iClipboardWindow = None;
- g_pClipboardDisplay = NULL;
g_hwndClipboard = NULL;
- /* checking if we need to restart */
- if (clipboardRestarts >= WIN_CLIPBOARD_RETRIES) {
- /* terminates clipboard thread but the main server still lives */
- ErrorF
- ("winClipboardProc - the clipboard thread has restarted %d times and seems to be unstable, disabling clipboard integration\n",
- clipboardRestarts);
- g_fClipboard = FALSE;
- return NULL;
- }
-
- if (g_fClipboard) {
- sleep(WIN_CLIPBOARD_DELAY);
- ErrorF("winClipboardProc - trying to restart clipboard thread \n");
- /* Create the clipboard client thread */
- if (!winInitClipboard()) {
- ErrorF("winClipboardProc - winClipboardInit failed.\n");
- return NULL;
- }
+ return fShutdown;
+}
- winDebug("winClipboardProc - winInitClipboard returned.\n");
- /* Flag that clipboard client has been launched */
- g_fClipboardLaunched = TRUE;
- }
- else {
- ErrorF("winClipboardProc - Clipboard disabled - Exit from server \n");
- /* clipboard thread has exited, stop server as well */
- raise(SIGTERM);
- }
+/*
+ * Create the Windows window that we use to receive Windows messages
+ */
- return NULL;
+static HWND
+winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms)
+{
+ WNDCLASSEX wc;
+ ClipboardWindowCreationParams cwcp;
+ HWND hwnd;
+
+ /* Setup our window class */
+ wc.cbSize = sizeof(WNDCLASSEX);
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = winClipboardWindowProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = GetModuleHandle(NULL);
+ wc.hIcon = 0;
+ wc.hCursor = 0;
+ wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = WIN_CLIPBOARD_WINDOW_CLASS;
+ 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 */
+ WIN_CLIPBOARD_WINDOW_TITLE, /* Window name */
+ WS_OVERLAPPED, /* Not visible anyway */
+ CW_USEDEFAULT, /* Horizontal position */
+ CW_USEDEFAULT, /* Vertical position */
+ CW_USEDEFAULT, /* Right edge */
+ CW_USEDEFAULT, /* Bottom edge */
+ (HWND) NULL, /* No parent or owner window */
+ (HMENU) NULL, /* No menu */
+ GetModuleHandle(NULL), /* Instance handle */
+ &cwcp); /* Creation data */
+ assert(hwnd != NULL);
+
+ /* I'm not sure, but we may need to call this to start message processing */
+ ShowWindow(hwnd, SW_HIDE);
+
+ /* Similarly, we may need a call to this even though we don't paint */
+ UpdateWindow(hwnd);
+
+ return hwnd;
}
/*
@@ -458,7 +472,7 @@ winClipboardIOErrorHandler(Display * pDisplay)
if (pthread_equal(pthread_self(), g_winClipboardProcThread)) {
/* Restart at the main entry point */
- longjmp(g_jmpEntry, WIN_JMP_ERROR_IO);
+ longjmp(g_jmpEntry, 2);
}
if (g_winClipboardOldIOErrorHandler)
@@ -466,3 +480,19 @@ winClipboardIOErrorHandler(Display * pDisplay)
return 0;
}
+
+void
+winClipboardWindowDestroy(void)
+{
+ if (g_hwndClipboard) {
+ SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
+ }
+}
+
+void
+winFixClipboardChain(void)
+{
+ if (g_hwndClipboard) {
+ PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0);
+ }
+}
diff --git a/hw/xwin/winclipboard/winclipboard.h b/hw/xwin/winclipboard/winclipboard.h
new file mode 100644
index 000000000..52481301b
--- /dev/null
+++ b/hw/xwin/winclipboard/winclipboard.h
@@ -0,0 +1,36 @@
+//
+// Copyright © Jon TURNEY 2013
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice (including the next
+// paragraph) shall be included in all copies or substantial portions of the
+// Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// File: winclipboard.h
+// Purpose: public interface to winclipboard library
+//
+
+#ifndef WINCLIPBOARD_H
+#define WINCLIPBOARD_H
+
+Bool winClipboardProc(Bool fUseUnicode, char *szDisplay);
+
+void winFixClipboardChain(void);
+
+void winClipboardWindowDestroy(void);
+
+#endif
diff --git a/hw/xwin/winclipboardwndproc.c b/hw/xwin/winclipboard/wndproc.c
index 90dc9e0bb..165ff558a 100644
--- a/hw/xwin/winclipboardwndproc.c
+++ b/hw/xwin/winclipboard/wndproc.c
@@ -33,10 +33,23 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
+/*
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
#include <sys/types.h>
#include <sys/time.h>
+
+#include <X11/Xatom.h>
+
+#include "internal.h"
#include "winclipboard.h"
-#include "misc.h"
/*
* Constants
@@ -44,21 +57,14 @@
#define WIN_POLL_TIMEOUT 1
-/*
- * References to external symbols
- */
-
-extern void *g_pClipboardDisplay;
-extern Window g_iClipboardWindow;
-extern Atom g_atomLastOwnedSelection;
/*
* Process X events up to specified timeout
*/
static int
-winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
- Bool fUseUnicode, int iTimeoutSec)
+winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay,
+ Bool fUseUnicode, ClipboardAtoms *atoms, int iTimeoutSec)
{
int iConnNumber;
struct timeval tv;
@@ -111,7 +117,7 @@ winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
/* Process X events */
/* Exit when we see that server is shutting down */
iReturn = winClipboardFlushXEvents(hwnd,
- iWindow, pDisplay, fUseUnicode);
+ iWindow, pDisplay, fUseUnicode, atoms);
winDebug
("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n",
@@ -139,6 +145,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND s_hwndNextViewer;
static Bool s_fCBCInitialized;
+ static Display *pDisplay;
+ static Window iWindow;
+ static ClipboardAtoms *atoms;
/* Branch on message type */
switch (message) {
@@ -159,9 +168,14 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HWND first, next;
DWORD error_code = 0;
+ ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams;
winDebug("winClipboardWindowProc - WM_CREATE\n");
+ pDisplay = cwcp->pClipboardDisplay;
+ iWindow = cwcp->iClipboardWindow;
+ atoms = cwcp->atoms;
+
first = GetClipboardViewer(); /* Get handle to first viewer in chain. */
if (first == hwnd)
return 0; /* Make sure it's not us! */
@@ -185,8 +199,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
s_hwndNextViewer = (HWND) lParam;
if (s_hwndNextViewer == hwnd) {
s_hwndNextViewer = NULL;
- winErrorFVerb(1, "winClipboardWindowProc - WM_CHANGECBCHAIN: "
- "attempted to set next window to ourselves.");
+ ErrorF("winClipboardWindowProc - WM_CHANGECBCHAIN: "
+ "attempted to set next window to ourselves.");
}
}
else if (s_hwndNextViewer)
@@ -241,20 +255,11 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_DRAWCLIPBOARD:
{
- static Atom atomClipboard;
- static int generation;
static Bool s_fProcessingDrawClipboard = FALSE;
- Display *pDisplay = g_pClipboardDisplay;
- Window iWindow = g_iClipboardWindow;
int iReturn;
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
- if (generation != serverGeneration) {
- generation = serverGeneration;
- atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
- }
-
/*
* We've occasionally seen a loop in the clipboard chain.
* Try and fix it on the first hint of recursion.
@@ -267,8 +272,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
s_fCBCInitialized = FALSE;
ChangeClipboardChain(hwnd, s_hwndNextViewer);
winFixClipboardChain();
- winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "Nested calls detected. Re-initing.\n");
+ ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "Nested calls detected. Re-initing.\n");
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
s_fProcessingDrawClipboard = FALSE;
return 0;
@@ -324,27 +329,27 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/* Release PRIMARY selection if owned */
iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY);
- if (iReturn == g_iClipboardWindow) {
+ if (iReturn == iWindow) {
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
"PRIMARY selection is owned by us.\n");
XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime);
}
else if (BadWindow == iReturn || BadAtom == iReturn)
- winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "XGetSelection failed for PRIMARY: %d\n",
- iReturn);
+ ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "XGetSelectionOwner failed for PRIMARY: %d\n",
+ iReturn);
/* Release CLIPBOARD selection if owned */
- iReturn = XGetSelectionOwner(pDisplay, atomClipboard);
- if (iReturn == g_iClipboardWindow) {
+ iReturn = XGetSelectionOwner(pDisplay, atoms->atomClipboard);
+ if (iReturn == iWindow) {
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "CLIPBOARD selection is owned by us.\n");
- XSetSelectionOwner(pDisplay, atomClipboard, None, CurrentTime);
+ "CLIPBOARD selection is owned by us, releasing\n");
+ XSetSelectionOwner(pDisplay, atoms->atomClipboard, None, CurrentTime);
}
else if (BadWindow == iReturn || BadAtom == iReturn)
- winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "XGetSelection failed for CLIPBOARD: %d\n",
- iReturn);
+ ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "XGetSelectionOwner failed for CLIPBOARD: %d\n",
+ iReturn);
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
s_fProcessingDrawClipboard = FALSE;
@@ -358,8 +363,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
XA_PRIMARY, iWindow, CurrentTime);
if (iReturn == BadAtom || iReturn == BadWindow ||
XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
- winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "Could not reassert ownership of PRIMARY\n");
+ ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "Could not reassert ownership of PRIMARY\n");
}
else {
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
@@ -368,12 +373,12 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/* Reassert ownership of the CLIPBOARD */
iReturn = XSetSelectionOwner(pDisplay,
- atomClipboard, iWindow, CurrentTime);
+ atoms->atomClipboard, iWindow, CurrentTime);
if (iReturn == BadAtom || iReturn == BadWindow ||
- XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
- winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
- "Could not reassert ownership of CLIPBOARD\n");
+ XGetSelectionOwner(pDisplay, atoms->atomClipboard) != iWindow) {
+ ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "Could not reassert ownership of CLIPBOARD\n");
}
else {
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
@@ -409,8 +414,6 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_RENDERALLFORMATS:
{
int iReturn;
- Display *pDisplay = g_pClipboardDisplay;
- Window iWindow = g_iClipboardWindow;
Bool fConvertToUnicode;
winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
@@ -423,15 +426,13 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/* Request the selection contents */
iReturn = XConvertSelection(pDisplay,
- g_atomLastOwnedSelection,
- XInternAtom(pDisplay,
- "COMPOUND_TEXT", False),
- XInternAtom(pDisplay,
- "CYGX_CUT_BUFFER", False),
+ winClipboardGetLastOwnedSelectionAtom(atoms),
+ atoms->atomCompoundText,
+ atoms->atomLocalProperty,
iWindow, CurrentTime);
if (iReturn == BadAtom || iReturn == BadWindow) {
- winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMAT - "
- "XConvertSelection () failed\n");
+ ErrorF("winClipboardWindowProc - WM_RENDER*FORMAT - "
+ "XConvertSelection () failed\n");
break;
}
@@ -445,16 +446,16 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
}
if (!OpenClipboard(hwnd)) {
- winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
- "OpenClipboard () failed: %08x\n",
- GetLastError());
+ ErrorF("winClipboardWindowProc - WM_RENDER*FORMATS - "
+ "OpenClipboard () failed: %08x\n",
+ GetLastError());
break;
}
if (!EmptyClipboard()) {
- winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
- "EmptyClipboard () failed: %08x\n",
- GetLastError());
+ ErrorF("winClipboardWindowProc - WM_RENDER*FORMATS - "
+ "EmptyClipboard () failed: %08x\n",
+ GetLastError());
break;
}
}
@@ -463,7 +464,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
iReturn = winProcessXEventsTimeout(hwnd,
iWindow,
pDisplay,
- fConvertToUnicode, WIN_POLL_TIMEOUT);
+ fConvertToUnicode,
+ atoms,
+ WIN_POLL_TIMEOUT);
/*
* The last call to winProcessXEventsTimeout
@@ -486,10 +489,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/* We must close the clipboard */
if (!CloseClipboard()) {
- winErrorFVerb(1,
- "winClipboardWindowProc - WM_RENDERALLFORMATS - "
- "CloseClipboard () failed: %08x\n",
- GetLastError());
+ ErrorF("winClipboardWindowProc - WM_RENDERALLFORMATS - "
+ "CloseClipboard () failed: %08x\n",
+ GetLastError());
break;
}
}
@@ -507,7 +509,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
* Process any pending Windows messages
*/
-BOOL
+Bool
winClipboardFlushWindowsMessageQueue(HWND hwnd)
{
MSG msg;
diff --git a/hw/xwin/winclipboardxevents.c b/hw/xwin/winclipboard/xevents.c
index 7d3c30e85..d0077b846 100644
--- a/hw/xwin/winclipboardxevents.c
+++ b/hw/xwin/winclipboard/xevents.c
@@ -33,8 +33,104 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
-#include "winclipboard.h"
-#include "misc.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 "internal.h"
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xfixes.h>
+
+/*
+ * Constants
+ */
+
+#define CLIP_NUM_SELECTIONS 2
+#define CLIP_OWN_NONE -1
+#define CLIP_OWN_PRIMARY 0
+#define CLIP_OWN_CLIPBOARD 1
+
+/*
+ * Global variables
+ */
+
+extern int xfixes_event_base;
+
+/*
+ * Local variables
+ */
+
+static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None, None };
+static const char *szSelectionNames[CLIP_NUM_SELECTIONS] =
+ { "PRIMARY", "CLIPBOARD" };
+
+static unsigned int lastOwnedSelectionIndex = CLIP_OWN_NONE;
+
+static void
+MonitorSelection(XFixesSelectionNotifyEvent * e, unsigned int i)
+{
+ /* Look for owned -> not owned transition */
+ if (None == e->owner && None != s_iOwners[i]) {
+ unsigned int other_index;
+
+ winDebug("MonitorSelection - %s - Going from owned to not owned.\n",
+ szSelectionNames[i]);
+
+ /* If this selection is not owned, the other monitored selection must be the most
+ recently owned, if it is owned at all */
+ if (i == CLIP_OWN_PRIMARY)
+ other_index = CLIP_OWN_CLIPBOARD;
+ if (i == CLIP_OWN_CLIPBOARD)
+ other_index = CLIP_OWN_PRIMARY;
+ if (None != s_iOwners[other_index])
+ lastOwnedSelectionIndex = other_index;
+ else
+ lastOwnedSelectionIndex = CLIP_OWN_NONE;
+ }
+
+ /* Save last owned selection */
+ if (None != e->owner) {
+ lastOwnedSelectionIndex = i;
+ }
+
+ /* Save new selection owner or None */
+ s_iOwners[i] = e->owner;
+ winDebug("MonitorSelection - %s - Now owned by XID %x\n",
+ szSelectionNames[i], e->owner);
+}
+
+Atom
+winClipboardGetLastOwnedSelectionAtom(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 */
+ for (int i = 0; i < CLIP_NUM_SELECTIONS; ++i)
+ s_iOwners[i] = None;
+
+ lastOwnedSelectionIndex = CLIP_OWN_NONE;
+}
/*
* Process any pending X events
@@ -42,21 +138,13 @@
int
winClipboardFlushXEvents(HWND hwnd,
- int iWindow, Display * pDisplay, Bool fUseUnicode)
+ Window iWindow, Display * pDisplay, Bool fUseUnicode, 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)) {
@@ -77,7 +165,6 @@ winClipboardFlushXEvents(HWND hwnd,
wchar_t *pwszUnicodeStr = NULL;
int iUnicodeLen = 0;
int iReturnDataLen = 0;
- int i;
Bool fAbort = FALSE;
Bool fCloseClipboard = FALSE;
Bool fSetClipboardData = TRUE;
@@ -525,6 +612,8 @@ winClipboardFlushXEvents(HWND hwnd,
if (iReturn == Success || iReturn > 0) {
/* Conversion succeeded or some unconvertible characters */
if (ppszTextList != NULL) {
+ int i;
+
iReturnDataLen = 0;
for (i = 0; i < iCount; i++) {
iReturnDataLen += strlen(ppszTextList[i]);
@@ -693,8 +782,78 @@ winClipboardFlushXEvents(HWND hwnd,
break;
default:
- ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
- event.type);
+ if (event.type == XFixesSetSelectionOwnerNotify + xfixes_event_base) {
+ XFixesSelectionNotifyEvent *e =
+ (XFixesSelectionNotifyEvent *) & event;
+
+ winDebug("winClipboardFlushXEvents - XFixesSetSelectionOwnerNotify\n");
+
+ /* Save selection owners for monitored selections, ignore other selections */
+ if (e->selection == XA_PRIMARY) {
+ MonitorSelection(e, CLIP_OWN_PRIMARY);
+ }
+ else if (e->selection == atomClipboard) {
+ MonitorSelection(e, CLIP_OWN_CLIPBOARD);
+ }
+ else
+ break;
+
+ /* Selection is being disowned */
+ if (e->owner == None) {
+ winDebug
+ ("winClipboardFlushXEvents - No window, returning.\n");
+ break;
+ }
+
+ /*
+ XXX: there are all kinds of wacky edge cases we might need here:
+ - we own windows clipboard, but neither PRIMARY nor CLIPBOARD have an owner, so we should disown it?
+ - root window is taking ownership?
+ */
+
+ /* If we are the owner of the most recently owned selection, don't go all recursive :) */
+ if ((lastOwnedSelectionIndex != CLIP_OWN_NONE) &&
+ (s_iOwners[lastOwnedSelectionIndex] == iWindow)) {
+ winDebug("winClipboardFlushXEvents - Ownership changed to us, aborting.\n");
+ break;
+ }
+
+ /* Close clipboard if we have it open already (possible? correct??) */
+ if (GetOpenClipboardWindow() == hwnd) {
+ CloseClipboard();
+ }
+
+ /* Access the Windows clipboard */
+ if (!OpenClipboard(hwnd)) {
+ ErrorF("winClipboardFlushXEvents - OpenClipboard () failed: %08x\n",
+ (int) GetLastError());
+ break;
+ }
+
+ /* Take ownership of the Windows clipboard */
+ if (!EmptyClipboard()) {
+ ErrorF("winClipboardFlushXEvents - EmptyClipboard () failed: %08x\n",
+ (int) GetLastError());
+ break;
+ }
+
+ /* Advertise regular text and unicode */
+ SetClipboardData(CF_UNICODETEXT, NULL);
+ SetClipboardData(CF_TEXT, NULL);
+
+ /* Release the clipboard */
+ if (!CloseClipboard()) {
+ ErrorF("winClipboardFlushXEvents - CloseClipboard () failed: %08x\n",
+ (int) GetLastError());
+ break;
+ }
+ }
+ /* XFixesSelectionWindowDestroyNotifyMask */
+ /* XFixesSelectionClientCloseNotifyMask */
+ else {
+ ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
+ event.type);
+ }
break;
}
}
diff --git a/hw/xwin/winclipboard/xwinclip.c b/hw/xwin/winclipboard/xwinclip.c
new file mode 100644
index 000000000..3677974c4
--- /dev/null
+++ b/hw/xwin/winclipboard/xwinclip.c
@@ -0,0 +1,127 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
+ *Copyright (C) Colin Harrison 2005-2008
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the copyright holder(s)
+ *and author(s) shall not be used in advertising or otherwise to promote
+ *the sale, use or other dealings in this Software without prior written
+ *authorization from the copyright holder(s) and author(s).
+ *
+ * Authors: Harold L Hunt II
+ * Colin Harrison
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+/*
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* X headers */
+#include <X11/Xlib.h>
+#ifdef X_LOCALE
+#include <X11/Xlocale.h>
+#else /* X_LOCALE */
+#include <locale.h>
+#endif /* X_LOCALE */
+
+#include "winclipboard.h"
+
+/*
+ * Main function
+ */
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+ char *pszDisplay = NULL;
+ int fUnicodeClipboard = 1;
+
+ /* Parse command-line parameters */
+ for (i = 1; i < argc; ++i)
+ {
+ /* Look for -display "display_name" or --display "display_name" */
+ if (i < argc - 1
+ && (!strcmp (argv[i], "-display")
+ || !strcmp (argv[i], "--display")))
+ {
+ /* Grab a pointer to the display parameter */
+ pszDisplay = argv[i + 1];
+
+ /* Skip the display argument */
+ i++;
+ continue;
+ }
+
+ /* Look for -nounicodeclipboard */
+ if (!strcmp (argv[i], "-nounicodeclipboard"))
+ {
+ fUnicodeClipboard = 0;
+ continue;
+ }
+
+ /* Yack when we find a parameter that we don't know about */
+ printf ("Unknown parameter: %s\nExiting.\n", argv[i]);
+ exit (1);
+ }
+
+ /* Do we have Unicode support? */
+ if (fUnicodeClipboard)
+ {
+ printf ("Unicode clipboard I/O\n");
+ }
+ else
+ {
+ printf ("Non Unicode clipboard I/O\n");
+ }
+
+ /* Apply locale specified in the LANG environment variable */
+ if (!setlocale (LC_ALL, ""))
+ {
+ printf ("setlocale() error\n");
+ exit (1);
+ }
+
+ /* See if X supports the current locale */
+ if (XSupportsLocale () == False)
+ {
+ printf ("Locale not supported by X, falling back to 'C' locale.\n");
+ setlocale(LC_ALL, "C");
+ }
+
+ winClipboardProc(fUnicodeClipboard, pszDisplay);
+
+ return 0;
+}
diff --git a/hw/xwin/winclipboard/xwinclip.man b/hw/xwin/winclipboard/xwinclip.man
new file mode 100644
index 000000000..822db91d4
--- /dev/null
+++ b/hw/xwin/winclipboard/xwinclip.man
@@ -0,0 +1,61 @@
+.TH xwinclip 1 __xorgversion__
+.SH NAME
+xwinclip - An X11 and Windows clipboard integration tool
+
+.SH SYNOPSIS
+.B xwinclip [OPTION]...
+
+.SH DESCRIPTION
+\fIxwinclip\fP is a tool for copying and pasting text between the Windows and X11 clipboard systems.
+
+\fIxwinclip\fP watches for updates to either clipboard and copies data between them when either one is updated.
+
+\fIxwinclip\fP monitors the X PRIMARY and CLIBPOARD selections for changes in ownership, and makes
+the contents of the most recent one to change available to paste from the Windows clipboard.
+
+It also monitors the contents of the Windows clipboard for changes, taking ownership of the PRIMARY and
+CLIPBOARD selections, and making the contents of the Windows clipboard available in them.
+
+.B Note well:
+The \fIXWin(1)\fP X server has internal clipboard integration that is enabled by default.
+Do \fINOT\fP run \fIxwinclip\fP unless \fIXWin(1)\fP has been started with the -noclipboard option.
+
+.SH OPTIONS
+\fIxwinclip\fP accepts the following optional command line switches:
+
+.TP 8
+.B \-display [display]
+Specifies the X server display to connect to.
+.TP 8
+.B \-nounicodeclipboard
+Do not use unicode text on the clipboard.
+
+.SH "SEE ALSO"
+XWin(1)
+
+.SH BUGS
+Only text clipboard contents are supported.
+
+The INCR (Incrememntal transfer) clipboard protocol for clipboard contents larger than the maximum size of an
+X request is not supported.
+
+Some X clients, notably ones written in Tcl/Tk, do not re-assert ownership of the PRIMARY selection or update
+it's timestamp when it's contents change, which currently prevents \fIxwinclip\fP from correctly noticing that
+the PRIMARY selection's contents have changed.
+
+Windows clipboard rendering is synchronous in the WM_RENDER*FORMAT message (that is, we must have placed the
+contents onto the clipboard by the time we return from processing this message), but we must wait for the X
+client which owns the selection to convert the selection to our requested format. This is currently achieved
+using a fixed timeout of one second.
+
+The XWin(1) server should indicate somehow (by placing an atom on the root window?) that it is running with it's
+internal clipboard integration enabled, and xwinclip should notice this and exit with an appropriate error.
+
+Probably many other bugs.
+
+.SH "CONFORMING TO"
+ICCCM (Inter-Client Communication Conventions Manual) 2.0
+
+.SH AUTHORS
+Contributors to xwinclip include Benjamin Riefenstahl, Roland Cassard, Brian Genisio, Colin Harrison,
+Harold L Hunt II, Matsuzaki Kensuke, Jon Turney, Chris Twiner and Jeremy Wilkins.
diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index 157006dab..8aef8fe02 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -31,25 +31,79 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
-#include "dixstruct.h"
-#include "winclipboard.h"
+
+#include <unistd.h>
+#include <pthread.h>
+
+#include "win.h"
+#include "winclipboard/winclipboard.h"
+#include "windisplay.h"
+
+#define WIN_CLIPBOARD_RETRIES 40
+#define WIN_CLIPBOARD_DELAY 1
/*
- * Local typedefs
+ * Local variables
*/
-typedef int (*winDispatchProcPtr) (ClientPtr);
-
-int winProcSetSelectionOwner(ClientPtr /* client */ );
+static pthread_t g_ptClipboardProc;
/*
- * References to external symbols
+ *
*/
+static void *
+winClipboardThreadProc(void *arg)
+{
+ char szDisplay[512];
+ int clipboardRestarts = 0;
+
+ while (1)
+ {
+ Bool fShutdown;
+
+ ++clipboardRestarts;
-extern pthread_t g_ptClipboardProc;
-extern winDispatchProcPtr winProcSetSelectionOwnerOrig;
-extern Bool g_fClipboard;
-extern HWND g_hwndClipboard;
+ /* Use our generated cookie for authentication */
+ winSetAuthorization();
+
+ /* Setup the display connection string */
+ /*
+ * NOTE: Always connect to screen 0 since we require that screen
+ * numbers start at 0 and increase without gaps. We only need
+ * to connect to one screen on the display to get events
+ * for all screens on the display. That is why there is only
+ * one clipboard client thread.
+ */
+ winGetDisplayName(szDisplay, 0);
+
+ /* Print the display connection string */
+ ErrorF("winClipboardThreadProc - DISPLAY=%s\n", szDisplay);
+
+ /* Flag that clipboard client has been launched */
+ g_fClipboardStarted = TRUE;
+
+ fShutdown = winClipboardProc(g_fUnicodeClipboard, szDisplay);
+
+ /* Flag that clipboard client has stopped */
+ g_fClipboardStarted = FALSE;
+
+ if (fShutdown)
+ break;
+
+ /* checking if we need to restart */
+ if (clipboardRestarts >= WIN_CLIPBOARD_RETRIES) {
+ /* terminates clipboard thread but the main server still lives */
+ ErrorF("winClipboardProc - the clipboard thread has restarted %d times and seems to be unstable, disabling clipboard integration\n", clipboardRestarts);
+ g_fClipboard = FALSE;
+ break;
+ }
+
+ sleep(WIN_CLIPBOARD_DELAY);
+ ErrorF("winClipboardProc - trying to restart clipboard thread \n");
+ }
+
+ return NULL;
+}
/*
* Intialize the Clipboard module
@@ -60,14 +114,8 @@ winInitClipboard(void)
{
winDebug("winInitClipboard ()\n");
- /* Wrap some internal server functions */
- if (ProcVector[X_SetSelectionOwner] != winProcSetSelectionOwner) {
- winProcSetSelectionOwnerOrig = ProcVector[X_SetSelectionOwner];
- ProcVector[X_SetSelectionOwner] = winProcSetSelectionOwner;
- }
-
/* Spawn a thread for the Clipboard module */
- if (pthread_create(&g_ptClipboardProc, NULL, winClipboardProc, NULL)) {
+ if (pthread_create(&g_ptClipboardProc, NULL, winClipboardThreadProc, NULL)) {
/* Bail if thread creation failed */
ErrorF("winInitClipboard - pthread_create failed.\n");
return FALSE;
@@ -76,59 +124,19 @@ winInitClipboard(void)
return TRUE;
}
-/*
- * Create the Windows window that we use to receive Windows messages
- */
-
-HWND
-winClipboardCreateMessagingWindow(void)
-{
- WNDCLASSEX wc;
- HWND hwnd;
-
- /* Setup our window class */
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = CS_HREDRAW | CS_VREDRAW;
- wc.lpfnWndProc = winClipboardWindowProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = GetModuleHandle(NULL);
- wc.hIcon = 0;
- wc.hCursor = 0;
- wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = WIN_CLIPBOARD_WINDOW_CLASS;
- wc.hIconSm = 0;
- RegisterClassEx(&wc);
-
- /* Create the window */
- hwnd = CreateWindowExA(0, /* Extended styles */
- WIN_CLIPBOARD_WINDOW_CLASS, /* Class name */
- WIN_CLIPBOARD_WINDOW_TITLE, /* Window name */
- WS_OVERLAPPED, /* Not visible anyway */
- CW_USEDEFAULT, /* Horizontal position */
- CW_USEDEFAULT, /* Vertical position */
- CW_USEDEFAULT, /* Right edge */
- CW_USEDEFAULT, /* Bottom edge */
- (HWND) NULL, /* No parent or owner window */
- (HMENU) NULL, /* No menu */
- GetModuleHandle(NULL), /* Instance handle */
- NULL); /* Creation data */
- assert(hwnd != NULL);
-
- /* I'm not sure, but we may need to call this to start message processing */
- ShowWindow(hwnd, SW_HIDE);
-
- /* Similarly, we may need a call to this even though we don't paint */
- UpdateWindow(hwnd);
-
- return hwnd;
-}
-
void
-winFixClipboardChain(void)
+winClipboardShutdown(void)
{
- if (g_fClipboard && g_hwndClipboard) {
- PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0);
- }
+ /* Close down clipboard resources */
+ if (g_fClipboard && g_fClipboardStarted) {
+ /* Synchronously destroy the clipboard window */
+ winClipboardWindowDestroy();
+
+ /* Wait for the clipboard thread to exit */
+ pthread_join(g_ptClipboardProc, NULL);
+
+ g_fClipboardStarted = FALSE;
+
+ winDebug("winClipboardShutdown - Clipboard thread has exited.\n");
+ }
}
diff --git a/hw/xwin/winclipboardwrappers.c b/hw/xwin/winclipboardwrappers.c
index bfd6bff8b..2679f4f98 100644
--- a/hw/xwin/winclipboardwrappers.c
+++ b/hw/xwin/winclipboardwrappers.c
@@ -33,36 +33,21 @@
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
+
#include "win.h"
#include "dixstruct.h"
-#include <X11/Xatom.h>
-
-/*
- * Constants
- */
-
-#define CLIP_NUM_SELECTIONS 2
-#define CLIP_OWN_PRIMARY 0
-#define CLIP_OWN_CLIPBOARD 1
/*
* Local function prototypes
*/
DISPATCH_PROC(winProcEstablishConnection);
-DISPATCH_PROC(winProcSetSelectionOwner);
/*
* References to external symbols
*/
-extern Bool g_fClipboardLaunched;
-extern Bool g_fClipboardStarted;
extern Bool g_fClipboard;
-extern Window g_iClipboardWindow;
-extern Atom g_atomLastOwnedSelection;
-extern HWND g_hwndClipboard;
-
/*
* Wrapper for internal EstablishConnection function.
@@ -127,13 +112,6 @@ winProcEstablishConnection(ClientPtr client)
/* Clear original function pointer */
winProcEstablishConnectionOrig = NULL;
- /* If the clipboard client has already been started, abort */
- if (g_fClipboardLaunched) {
- ErrorF("winProcEstablishConnection - Clipboard client already "
- "launched, returning.\n");
- return iReturn;
- }
-
/* Startup the clipboard client if clipboard mode is being used */
if (g_fClipboard) {
/*
@@ -163,207 +141,5 @@ winProcEstablishConnection(ClientPtr client)
ErrorF("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;
- Bool fOwnedToNotOwned = FALSE;
- static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None };
- static unsigned long s_ulServerGeneration = 0;
-
- REQUEST(xSetSelectionOwnerReq);
-
- REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
-
- winDebug("winProcSetSelectionOwner - Hello.\n");
-
- /* Watch for server reset */
- if (s_ulServerGeneration != serverGeneration) {
- /* Save new generation number */
- s_ulServerGeneration = serverGeneration;
-
- /* Initialize static variables */
- for (i = 0; i < CLIP_NUM_SELECTIONS; ++i)
- s_iOwners[i] = None;
- }
-
- /* Abort if clipboard not completely initialized yet */
- if (!g_fClipboardStarted) {
- /* ErrorF ("winProcSetSelectionOwner - Clipboard not yet started, "
- "aborting.\n"); */
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Grab window if we have one */
- if (None != stuff->window) {
- /* Grab the Window from the request */
- int rc =
- dixLookupWindow(&pWindow, stuff->window, client, DixReadAccess);
- if (rc != Success) {
- ErrorF("winProcSetSelectionOwner - Found BadWindow, aborting.\n");
- goto winProcSetSelectionOwner_Done;
- }
- }
-
- /* Now we either have a valid window or None */
-
- /* Save selection owners for monitored selections, ignore other selections */
- if (XA_PRIMARY == stuff->selection) {
- /* Look for owned -> not owned transition */
- if (None == stuff->window && None != s_iOwners[CLIP_OWN_PRIMARY]) {
- fOwnedToNotOwned = TRUE;
-
- winDebug("winProcSetSelectionOwner - PRIMARY - Going from "
- "owned to not owned.\n");
-
- /* Adjust last owned selection */
- if (None != s_iOwners[CLIP_OWN_CLIPBOARD])
- g_atomLastOwnedSelection = MakeAtom("CLIPBOARD", 9, TRUE);
- else
- g_atomLastOwnedSelection = None;
- }
-
- /* Save new selection owner or None */
- s_iOwners[CLIP_OWN_PRIMARY] = stuff->window;
-
- winDebug("winProcSetSelectionOwner - PRIMARY - Now owned by: %d\n",
- stuff->window);
- }
- else if (MakeAtom("CLIPBOARD", 9, TRUE) == stuff->selection) {
- /* Look for owned -> not owned transition */
- if (None == stuff->window && None != s_iOwners[CLIP_OWN_CLIPBOARD]) {
- fOwnedToNotOwned = TRUE;
-
- winDebug("winProcSetSelectionOwner - CLIPBOARD - Going from "
- "owned to not owned.\n");
-
- /* Adjust last owned selection */
- if (None != s_iOwners[CLIP_OWN_PRIMARY])
- g_atomLastOwnedSelection = XA_PRIMARY;
- else
- g_atomLastOwnedSelection = None;
- }
-
- /* Save new selection owner or None */
- s_iOwners[CLIP_OWN_CLIPBOARD] = stuff->window;
-
- winDebug("winProcSetSelectionOwner - CLIPBOARD - Now owned by: %d\n",
- stuff->window);
-
- }
- else
- goto winProcSetSelectionOwner_Done;
-
- /*
- * At this point, if one of the selections is still owned by the
- * clipboard manager then it should be marked as unowned since
- * we will be taking ownership of the Win32 clipboard.
- */
- if (g_iClipboardWindow == s_iOwners[CLIP_OWN_PRIMARY])
- s_iOwners[CLIP_OWN_PRIMARY] = None;
- if (g_iClipboardWindow == s_iOwners[CLIP_OWN_CLIPBOARD])
- s_iOwners[CLIP_OWN_CLIPBOARD] = None;
-
- /*
- * Handle case when selection is being disowned,
- * WM_DRAWCLIPBOARD did not do the disowning,
- * both monitored selections are no longer owned,
- * an owned to not owned transition was detected,
- * and we currently own the Win32 clipboard.
- */
- if (stuff->window == None
- && s_iOwners[CLIP_OWN_PRIMARY] == None
- && s_iOwners[CLIP_OWN_CLIPBOARD] == None
- && fOwnedToNotOwned
- && g_hwndClipboard != NULL && g_hwndClipboard == GetClipboardOwner()) {
- winDebug("winProcSetSelectionOwner - We currently own the "
- "clipboard and neither the PRIMARY nor the CLIPBOARD "
- "selections are owned, releasing ownership of Win32 "
- "clipboard.\n");
-
- /* Release ownership of the Windows clipboard */
- OpenClipboard(NULL);
- EmptyClipboard();
- CloseClipboard();
-
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Abort if no window at this point */
- if (None == stuff->window) {
- winDebug("winProcSetSelectionOwner - No window, returning.\n");
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Abort if invalid selection */
- if (!ValidAtom(stuff->selection)) {
- ErrorF("winProcSetSelectionOwner - Found BadAtom, aborting.\n");
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Cast Window to Drawable */
- pDrawable = (DrawablePtr) pWindow;
-
- /* Abort if clipboard manager is owning the selection */
- if (pDrawable->id == g_iClipboardWindow) {
- winDebug("winProcSetSelectionOwner - We changed ownership, "
- "aborting.\n");
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Abort if root window is taking ownership */
- if (pDrawable->id == 0) {
- ErrorF("winProcSetSelectionOwner - Root window taking ownership, "
- "aborting\n");
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Close clipboard if we have it open already */
- if (GetOpenClipboardWindow() == g_hwndClipboard) {
- CloseClipboard();
- }
-
- /* Access the Windows clipboard */
- if (!OpenClipboard(g_hwndClipboard)) {
- ErrorF("winProcSetSelectionOwner - OpenClipboard () failed: %08x\n",
- (int) GetLastError());
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Take ownership of the Windows clipboard */
- if (!EmptyClipboard()) {
- ErrorF("winProcSetSelectionOwner - EmptyClipboard () failed: %08x\n",
- (int) GetLastError());
- goto winProcSetSelectionOwner_Done;
- }
-
- /* Advertise regular text and unicode */
- SetClipboardData(CF_UNICODETEXT, NULL);
- SetClipboardData(CF_TEXT, NULL);
-
- /* Save handle to last owned selection */
- g_atomLastOwnedSelection = stuff->selection;
-
- /* Release the clipboard */
- if (!CloseClipboard()) {
- ErrorF("winProcSetSelectionOwner - CloseClipboard () failed: "
- "%08x\n", (int) GetLastError());
- goto winProcSetSelectionOwner_Done;
- }
-
- winProcSetSelectionOwner_Done:
- return (*winProcSetSelectionOwnerOrig) (client);
-}
diff --git a/hw/xwin/windialogs.c b/hw/xwin/windialogs.c
index c9af0e203..61f7fe0bd 100644
--- a/hw/xwin/windialogs.c
+++ b/hw/xwin/windialogs.c
@@ -37,13 +37,6 @@
#include "winprefs.h"
/*
- * References to external globals
- */
-
-#ifdef XWIN_CLIPBOARD
-extern Bool g_fClipboardStarted;
-#endif
-/*
* Local function prototypes
*/
diff --git a/hw/xwin/winglobals.c b/hw/xwin/winglobals.c
index b9ad294d5..ad82b83f6 100644
--- a/hw/xwin/winglobals.c
+++ b/hw/xwin/winglobals.c
@@ -86,7 +86,6 @@ pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER;
* Wrapped DIX functions
*/
winDispatchProcPtr winProcEstablishConnectionOrig = NULL;
-winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL;
/*
* Clipboard variables
@@ -94,13 +93,7 @@ winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL;
Bool g_fUnicodeClipboard = TRUE;
Bool g_fClipboard = TRUE;
-Bool g_fClipboardLaunched = FALSE;
Bool g_fClipboardStarted = FALSE;
-pthread_t g_ptClipboardProc;
-HWND g_hwndClipboard = NULL;
-void *g_pClipboardDisplay = NULL;
-Window g_iClipboardWindow = None;
-Atom g_atomLastOwnedSelection = None;
#endif
/*
@@ -112,10 +105,4 @@ void
winInitializeGlobals(void)
{
g_dwCurrentThreadID = GetCurrentThreadId();
-#ifdef XWIN_CLIPBOARD
- g_iClipboardWindow = None;
- g_pClipboardDisplay = NULL;
- g_atomLastOwnedSelection = None;
- g_hwndClipboard = NULL;
-#endif
}
diff --git a/hw/xwin/winglobals.h b/hw/xwin/winglobals.h
index 60c00da42..d7b813dbb 100644
--- a/hw/xwin/winglobals.h
+++ b/hw/xwin/winglobals.h
@@ -72,8 +72,10 @@ typedef int (*winDispatchProcPtr) (ClientPtr);
* Wrapped DIX functions
*/
extern winDispatchProcPtr winProcEstablishConnectionOrig;
-extern winDispatchProcPtr winProcSetSelectionOwnerOrig;
#endif
+extern Bool g_fUnicodeClipboard;
+extern Bool g_fClipboard;
+extern Bool g_fClipboardStarted;
/* The global X default icons */
#if defined(XWIN_MULTIWINDOW)
diff --git a/hw/xwin/winwndproc.c b/hw/xwin/winwndproc.c
index bee223de7..e3adb5605 100644
--- a/hw/xwin/winwndproc.c
+++ b/hw/xwin/winwndproc.c
@@ -42,6 +42,9 @@
#include "winmsg.h"
#include "winmonitors.h"
#include "inputstr.h"
+#ifdef XWIN_CLIPBOARD
+#include "winclipboard/winclipboard.h"
+#endif
/*
* Global variables