aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xwin/winclipboard
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xwin/winclipboard')
-rw-r--r--xorg-server/hw/xwin/winclipboard/Makefile.am25
-rw-r--r--xorg-server/hw/xwin/winclipboard/debug.c52
-rwxr-xr-xxorg-server/hw/xwin/winclipboard/internal.h125
-rw-r--r--xorg-server/hw/xwin/winclipboard/makefile18
-rw-r--r--xorg-server/hw/xwin/winclipboard/textconv.c151
-rwxr-xr-xxorg-server/hw/xwin/winclipboard/thread.c480
-rw-r--r--xorg-server/hw/xwin/winclipboard/winclipboard.h31
-rwxr-xr-xxorg-server/hw/xwin/winclipboard/wndproc.c516
-rwxr-xr-xxorg-server/hw/xwin/winclipboard/xevents.c747
-rw-r--r--xorg-server/hw/xwin/winclipboard/xwinclip.c127
-rw-r--r--xorg-server/hw/xwin/winclipboard/xwinclip.man61
11 files changed, 2333 insertions, 0 deletions
diff --git a/xorg-server/hw/xwin/winclipboard/Makefile.am b/xorg-server/hw/xwin/winclipboard/Makefile.am
new file mode 100644
index 000000000..b1c95f4ef
--- /dev/null
+++ b/xorg-server/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/xorg-server/hw/xwin/winclipboard/debug.c b/xorg-server/hw/xwin/winclipboard/debug.c
new file mode 100644
index 000000000..78ab6d902
--- /dev/null
+++ b/xorg-server/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/xorg-server/hw/xwin/winclipboard/internal.h b/xorg-server/hw/xwin/winclipboard/internal.h
new file mode 100755
index 000000000..d42497cc9
--- /dev/null
+++ b/xorg-server/hw/xwin/winclipboard/internal.h
@@ -0,0 +1,125 @@
+#ifndef _WINCLIPBOARD_H_
+#define _WINCLIPBOARD_H_
+/*
+ *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
+ *
+ *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 HAROLD L HUNT II 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 Harold L Hunt II
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from Harold L Hunt II.
+ *
+ * Authors: Harold L Hunt II
+ */
+
+/* Standard library headers */
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+#ifdef __CYGWIN__
+#include <sys/select.h>
+#else
+#include <X11/Xwinsock.h>
+#endif
+#include <fcntl.h>
+#include <setjmp.h>
+#ifdef _MSC_VER
+typedef int pid_t;
+#endif
+#include <pthread.h>
+
+/* X headers */
+#include <X11/X.h>
+#include <X11/Xatom.h>
+#include <X11/Xproto.h>
+#include <X11/Xutil.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
+
+#include "winmsg.h"
+
+/*
+ * References to external symbols
+ */
+
+extern char *display;
+/*
+ * winclipboardinit.c
+ */
+
+Bool
+ winInitClipboard(void);
+
+HWND winClipboardCreateMessagingWindow(void);
+
+/*
+ * winclipboardtextconv.c
+ */
+
+void
+ winClipboardDOStoUNIX(char *pszData, int iLength);
+
+void
+ winClipboardUNIXtoDOS(char **ppszData, int iLength);
+
+/*
+ * winclipboardthread.c
+ */
+
+void *winClipboardProc(void *);
+
+/*
+ * winclipboardwndproc.c
+ */
+
+BOOL winClipboardFlushWindowsMessageQueue(HWND hwnd);
+
+LRESULT CALLBACK
+winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+/*
+ * winclipboardxevents.c
+ */
+
+int
+
+winClipboardFlushXEvents(HWND hwnd,
+ int iWindow, Display * pDisplay, Bool fUnicodeSupport, Bool ClipboardOpened);
+#endif
diff --git a/xorg-server/hw/xwin/winclipboard/makefile b/xorg-server/hw/xwin/winclipboard/makefile
new file mode 100644
index 000000000..f49117b3e
--- /dev/null
+++ b/xorg-server/hw/xwin/winclipboard/makefile
@@ -0,0 +1,18 @@
+LIBRARY = libXWinclipboard
+
+CSRCS = \
+ textconv.c \
+ thread.c \
+ wndproc.c \
+ xevents.c
+
+INCLUDES += ..
+
+DEFINES += HAVE_XWIN_CONFIG_H
+DEFINES += XWIN_CLIPBOARD
+DEFINES += XWIN_MULTIWINDOW
+DEFINES += XWIN_GLX_WINDOWS
+DEFINES += XWIN_RANDR
+DEFINES += RELOCATE_PROJECTROOT
+DEFINES += PTW32_STATIC_LIB
+
diff --git a/xorg-server/hw/xwin/winclipboard/textconv.c b/xorg-server/hw/xwin/winclipboard/textconv.c
new file mode 100644
index 000000000..9c9cb3529
--- /dev/null
+++ b/xorg-server/hw/xwin/winclipboard/textconv.c
@@ -0,0 +1,151 @@
+/*
+ *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
+ *
+ *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 HAROLD L HUNT II 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 Harold L Hunt II
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from Harold L Hunt II.
+ *
+ * Authors: Harold L Hunt II
+ */
+
+#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 <stdlib.h>
+#include "internal.h"
+
+/*
+ * Convert \r\n to \n
+ *
+ * NOTE: This was heavily inspired by, Cygwin's
+ * winsup/cygwin/fhandler.cc/fhandler_base::read ()
+ */
+
+void
+winClipboardDOStoUNIX(char *pszSrc, int iLength)
+{
+ char *pszDest = pszSrc;
+ char *pszEnd = pszSrc + iLength;
+
+ /* Loop until the last character */
+ while (pszSrc < pszEnd) {
+ /* Copy the current source character to current destination character */
+ *pszDest = *pszSrc;
+
+ /* Advance to the next source character */
+ pszSrc++;
+
+ /* Don't advance the destination character if we need to drop an \r */
+ if (*pszDest != '\r' || *pszSrc != '\n')
+ pszDest++;
+ }
+
+ /* Move the terminating null */
+ *pszDest = '\0';
+}
+
+/*
+ * Convert \n to \r\n
+ */
+
+void
+winClipboardUNIXtoDOS(char **ppszData, int iLength)
+{
+ int iNewlineCount = 0;
+ char *pszSrc = *ppszData;
+ char *pszEnd = pszSrc + iLength;
+ char *pszDest = NULL, *pszDestBegin = NULL;
+
+ winDebug("UNIXtoDOS () - Original data:'%s'\n", *ppszData);
+
+ /* Count \n characters without leading \r */
+ while (pszSrc < pszEnd) {
+ /* Skip ahead two character if found set of \r\n */
+ if (*pszSrc == '\r' && pszSrc + 1 < pszEnd && *(pszSrc + 1) == '\n') {
+ pszSrc += 2;
+ continue;
+ }
+
+ /* Increment the count if found naked \n */
+ if (*pszSrc == '\n') {
+ iNewlineCount++;
+ }
+
+ pszSrc++;
+ }
+
+ /* Return if no naked \n's */
+ if (iNewlineCount == 0)
+ return;
+
+ /* Allocate a new string */
+ pszDestBegin = pszDest = malloc(iLength + iNewlineCount + 1);
+
+ /* Set source pointer to beginning of data string */
+ pszSrc = *ppszData;
+
+ /* Loop through all characters in source string */
+ while (pszSrc < pszEnd) {
+ /* Copy line endings that are already valid */
+ if (*pszSrc == '\r' && pszSrc + 1 < pszEnd && *(pszSrc + 1) == '\n') {
+ *pszDest = *pszSrc;
+ *(pszDest + 1) = *(pszSrc + 1);
+ pszDest += 2;
+ pszSrc += 2;
+ continue;
+ }
+
+ /* Add \r to naked \n's */
+ if (*pszSrc == '\n') {
+ *pszDest = '\r';
+ *(pszDest + 1) = *pszSrc;
+ pszDest += 2;
+ pszSrc += 1;
+ continue;
+ }
+
+ /* Copy normal characters */
+ *pszDest = *pszSrc;
+ pszSrc++;
+ pszDest++;
+ }
+
+ /* Put terminating null at end of new string */
+ *pszDest = '\0';
+
+ /* Swap string pointers */
+ free(*ppszData);
+ *ppszData = pszDestBegin;
+
+ winDebug("UNIXtoDOS () - Final string:'%s'\n", pszDestBegin);
+}
diff --git a/xorg-server/hw/xwin/winclipboard/thread.c b/xorg-server/hw/xwin/winclipboard/thread.c
new file mode 100755
index 000000000..56f5484e6
--- /dev/null
+++ b/xorg-server/hw/xwin/winclipboard/thread.c
@@ -0,0 +1,480 @@
+/*
+ *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 HAROLD L HUNT II 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>
+#else
+#define HAS_WINSOCK 1
+#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 "internal.h"
+
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
+/*
+ * References to external symbols
+ */
+
+extern Bool g_fUnicodeClipboard;
+extern Bool g_fClipboardStarted;
+extern Bool g_fClipboardLaunched;
+extern HWND g_hwndClipboard;
+extern void *g_pClipboardDisplay;
+extern Window g_iClipboardWindow;
+extern Bool g_fClipboardPrimary;
+
+/*
+ * Global variables
+ */
+
+static jmp_buf g_jmpEntry;
+static XIOErrorHandler g_winClipboardOldIOErrorHandler;
+static pthread_t g_winClipboardProcThread;
+
+Bool g_fUseUnicode = FALSE;
+
+/*
+ * Local function prototypes
+ */
+
+static int
+ winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr);
+
+static int
+ winClipboardIOErrorHandler(Display * pDisplay);
+
+static void
+winClipboardThreadExit(void *arg);
+/*
+ * Main thread function
+ */
+
+void *
+winClipboardProc(void *pvNotUsed)
+{
+ Atom atomClipboard;
+ int iReturn;
+ HWND hwnd = NULL;
+ int iConnectionNumber = 0;
+
+#ifdef HAS_DEVWINDOWS
+ int fdMessageQueue = 0;
+#else
+ struct timeval tvTimeout;
+#endif
+ fd_set fdsRead;
+ int iMaxDescriptor;
+ Display *pDisplay = NULL;
+ Window iWindow = None;
+ int iRetries;
+ Bool fUseUnicode;
+ char szDisplay[512];
+ int iSelectError;
+
+ pthread_cleanup_push(&winClipboardThreadExit, NULL);
+
+ winDebug ("winClipboardProc - Hello\n");
+
+ /* Do we use Unicode clipboard? */
+ fUseUnicode = g_fUnicodeClipboard;
+
+ /* Save the Unicode support flag in a global */
+ g_fUseUnicode = fUseUnicode;
+
+ /* Create Windows messaging window */
+ hwnd = winClipboardCreateMessagingWindow ();
+
+ /* Save copy of HWND in screen privates */
+ g_hwndClipboard = hwnd;
+
+ /* 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 thread_errorexit;
+ }
+ 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");
+ }
+
+ /* 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 */
+ winDebug ("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;
+ }
+ while (pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
+
+ /* Make sure that the display opened */
+ if (pDisplay == NULL) {
+ ErrorF("winClipboardProc - Failed opening the display, giving up\n");
+ goto thread_errorexit;
+ }
+
+ /* Save the display in the screen privates */
+ g_pClipboardDisplay = pDisplay;
+
+ winDebug ("winClipboardProc - XOpenDisplay () returned and "
+ "successfully opened the display.\n");
+
+ /* Get our connection number */
+ iConnectionNumber = ConnectionNumber(pDisplay);
+
+ winDebug("Clipboard is using socket %d\n",iConnectionNumber);
+
+#ifdef HAS_DEVWINDOWS
+ /* Open a file descriptor for the windows message queue */
+ fdMessageQueue = open (WIN_MSG_QUEUE_FNAME, _O_RDONLY);
+ if (fdMessageQueue == -1) {
+ ErrorF("winClipboardProc - Failed opening %s\n", WIN_MSG_QUEUE_FNAME);
+ goto thread_errorexit;
+ }
+
+ /* Find max of our file descriptors */
+ iMaxDescriptor = max(fdMessageQueue, iConnectionNumber) + 1;
+#else
+ 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);
+
+ /* Create a messaging window */
+ iWindow = XCreateSimpleWindow(pDisplay,
+ DefaultRootWindow(pDisplay),
+ 1, 1,
+ 500, 500,
+ 0,
+ BlackPixel(pDisplay, 0),
+ BlackPixel(pDisplay, 0));
+ if (iWindow == 0) {
+ ErrorF("winClipboardProc - Could not create an X window.\n");
+ goto thread_errorexit;
+ }
+
+ XStoreName(pDisplay, iWindow, "xwinclip");
+
+ /* Select event types to watch */
+ if (XSelectInput(pDisplay, iWindow, PropertyChangeMask) == BadWindow)
+ ErrorF("winClipboardProc - XSelectInput generated BadWindow "
+ "on messaging window\n");
+
+ /* Save the window in the screen privates */
+ g_iClipboardWindow = iWindow;
+
+ /* Assert ownership of selections if Win32 clipboard is owned */
+ if (NULL != GetClipboardOwner()) {
+ if (g_fClipboardPrimary)
+ {
+ /* PRIMARY */
+ winDebug("winClipboardProc - asserted ownership.\n");
+ iReturn = XSetSelectionOwner (pDisplay, XA_PRIMARY,
+ iWindow, CurrentTime);
+ if (iReturn == BadAtom || iReturn == BadWindow /*||
+ XGetSelectionOwner (pDisplay, XA_PRIMARY) != iWindow*/)
+ {
+ ErrorF ("winClipboardProc - Could not set PRIMARY owner\n");
+ goto thread_errorexit;
+ }
+ }
+
+ /* CLIPBOARD */
+ iReturn = XSetSelectionOwner(pDisplay, atomClipboard,
+ iWindow, CurrentTime);
+ if (iReturn == BadAtom || iReturn == BadWindow /*||
+ XGetSelectionOwner (pDisplay, atomClipboard) != iWindow*/)
+ {
+ ErrorF ("winClipboardProc - Could not set CLIPBOARD owner\n");
+ goto thread_errorexit;
+ }
+ }
+
+ /* 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;
+ }
+
+ winDebug ("winClipboardProc - Started\n");
+ /* Signal that the clipboard client has started */
+ g_fClipboardStarted = TRUE;
+
+ /* Loop for X events */
+ while (1) {
+ /* Setup the file descriptor set */
+ /*
+ * NOTE: You have to do this before every call to select
+ * because select modifies the mask to indicate
+ * which descriptors are ready.
+ */
+ FD_ZERO(&fdsRead);
+ FD_SET(iConnectionNumber, &fdsRead);
+#ifdef HAS_DEVWINDOWS
+ FD_SET(fdMessageQueue, &fdsRead);
+#else
+ tvTimeout.tv_sec = 0;
+ tvTimeout.tv_usec = 100;
+#endif
+
+ /* Wait for a Windows event or an X event */
+ iReturn = select(iMaxDescriptor, /* Highest fds number */
+ &fdsRead, /* Read mask */
+ NULL, /* No write mask */
+ NULL, /* No exception mask */
+#ifdef HAS_DEVWINDOWS
+ NULL /* No timeout */
+#else
+ &tvTimeout /* Set timeout */
+#endif
+ );
+
+#ifndef HAS_WINSOCK
+ iSelectError = errno;
+#else
+ iSelectError = WSAGetLastError();
+#endif
+
+ if (iReturn < 0) {
+#ifndef HAS_WINSOCK
+ if (iSelectError == EINTR)
+#else
+ if (iSelectError == WSAEINTR)
+#endif
+ continue;
+
+ ErrorF("winClipboardProc - Call to select () failed: %d. "
+ "Bailing.\n", iReturn);
+ 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);
+// }
+
+#ifdef HAS_DEVWINDOWS
+ /* Check for Windows event ready */
+ if (FD_ISSET(fdMessageQueue, &fdsRead))
+#else
+ if (1)
+#endif
+ {
+ /* Process Windows messages */
+ if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
+ ErrorF("winClipboardProc - "
+ "winClipboardFlushWindowsMessageQueue trapped "
+ "WM_QUIT message, exiting main loop.\n");
+ break;
+ }
+ }
+ }
+
+ /* Close our X window */
+ if (pDisplay && iWindow) {
+ iReturn = XDestroyWindow(pDisplay, iWindow);
+ if (iReturn == BadWindow)
+ ErrorF("winClipboardProc - XDestroyWindow returned BadWindow.\n");
+#ifdef WINDBG
+ else
+ winDebug("winClipboardProc - XDestroyWindow succeeded.\n");
+#endif
+ }
+
+#ifdef HAS_DEVWINDOWS
+ /* Close our Win32 message handle */
+ if (fdMessageQueue)
+ close(fdMessageQueue);
+#endif
+
+#if 0
+ /*
+ * FIXME: XCloseDisplay hangs if we call it, as of 2004/03/26. The
+ * XSync and XSelectInput calls did not help.
+ */
+
+ /* Discard any remaining events */
+ XSync(pDisplay, TRUE);
+
+ /* Select event types to watch */
+ XSelectInput(pDisplay, DefaultRootWindow(pDisplay), None);
+
+ /* Close our X display */
+ if (pDisplay) {
+ XCloseDisplay(pDisplay);
+ }
+#endif
+
+ goto commonexit;
+
+thread_errorexit:
+ if (g_pClipboardDisplay && g_iClipboardWindow)
+ {
+ iReturn = XDestroyWindow (g_pClipboardDisplay, g_iClipboardWindow);
+ if (iReturn == BadWindow)
+ ErrorF ("winClipboardProc - XDestroyWindow returned BadWindow.\n");
+#ifdef WINDBG
+ else
+ winDebug ("winClipboardProc - XDestroyWindow succeeded.\n");
+#endif
+ }
+ winDebug ("Clipboard thread died.\n");
+
+commonexit:
+ g_iClipboardWindow = None;
+ g_pClipboardDisplay = NULL;
+ g_fClipboardLaunched = FALSE;
+ g_fClipboardStarted = FALSE;
+
+ pthread_cleanup_pop(0);
+
+ return NULL;
+}
+
+/*
+ * winClipboardErrorHandler - Our application specific error handler
+ */
+
+static int
+winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr)
+{
+ char pszErrorMsg[100];
+
+ XGetErrorText(pDisplay, pErr->error_code, pszErrorMsg, sizeof(pszErrorMsg));
+ ErrorF("winClipboardErrorHandler - ERROR: \n\t%s\n"
+ " errorCode %d\n"
+ " serial %lu\n"
+ " resourceID 0x%x\n"
+ " majorCode %d\n"
+ " minorCode %d\n"
+ , pszErrorMsg
+ , pErr->error_code
+ , pErr->serial
+ , pErr->resourceid
+ , pErr->request_code
+ , pErr->minor_code);
+ return 0;
+}
+
+/*
+ * winClipboardIOErrorHandler - Our application specific IO error handler
+ */
+
+static int
+winClipboardIOErrorHandler(Display * pDisplay)
+{
+ ErrorF("winClipboardIOErrorHandler!\n");
+
+ if (pthread_equal(pthread_self(), g_winClipboardProcThread)) {
+ /* Restart at the main entry point */
+ longjmp(g_jmpEntry, WIN_JMP_ERROR_IO);
+ }
+
+ if (g_winClipboardOldIOErrorHandler)
+ g_winClipboardOldIOErrorHandler(pDisplay);
+
+ return 0;
+}
+
+/*
+ * winClipboardThreadExit - Thread exit handler
+ */
+
+static void
+winClipboardThreadExit(void *arg)
+{
+ /* clipboard thread has exited, stop server as well */
+ AbortDDX(EXIT_ERR_ABORT);
+ TerminateProcess(GetCurrentProcess(),1);
+}
diff --git a/xorg-server/hw/xwin/winclipboard/winclipboard.h b/xorg-server/hw/xwin/winclipboard/winclipboard.h
new file mode 100644
index 000000000..e4011a172
--- /dev/null
+++ b/xorg-server/hw/xwin/winclipboard/winclipboard.h
@@ -0,0 +1,31 @@
+//
+// 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
+
+
+#endif
diff --git a/xorg-server/hw/xwin/winclipboard/wndproc.c b/xorg-server/hw/xwin/winclipboard/wndproc.c
new file mode 100755
index 000000000..0819de4a5
--- /dev/null
+++ b/xorg-server/hw/xwin/winclipboard/wndproc.c
@@ -0,0 +1,516 @@
+/*
+ *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 HAROLD L HUNT II 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
+#include <sys/types.h>
+#include <sys/time.h>
+#include "winclipboard.h"
+#include "misc.h"
+#include "winmsg.h"
+#include "objbase.h"
+#include "ddraw.h"
+#include "winwindow.h"
+#include "internal.h"
+
+/*
+ * Constants
+ */
+
+#define WIN_POLL_TIMEOUT 1
+
+/*
+ * References to external symbols
+ */
+
+extern void *g_pClipboardDisplay;
+extern Window g_iClipboardWindow;
+extern Atom g_atomLastOwnedSelection;
+extern Bool g_fClipboardStarted;
+extern HWND g_hwndClipboard;
+extern Bool g_fClipboardPrimary;
+
+/*
+ * Process X events up to specified timeout
+ */
+
+static int
+winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
+ Bool fUseUnicode, 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;
+ }
+
+ /* Get our connection number */
+ iConnNumber = ConnectionNumber(pDisplay);
+
+ /* Loop for X events */
+ while (1) {
+ fd_set fdsRead;
+ long remainingTime;
+
+ /* Setup the file descriptor set */
+ FD_ZERO(&fdsRead);
+ FD_SET(iConnNumber, &fdsRead);
+
+ /* Adjust timeout */
+ remainingTime = dwStopTime - GetTickCount();
+ tv.tv_sec = remainingTime / 1000;
+ tv.tv_usec = (remainingTime % 1000) * 1000;
+ winDebug("winProcessXEventsTimeout () - %d milliseconds left\n",
+ remainingTime);
+
+ /* Break out if no time left */
+ if (remainingTime <= 0)
+ return WIN_XEVENTS_SUCCESS;
+
+ /* Wait for an X event */
+ iReturn = select(iConnNumber + 1, /* Highest fds number */
+ &fdsRead, /* Read mask */
+ NULL, /* No write mask */
+ NULL, /* No exception mask */
+ &tv); /* Timeout */
+ if (iReturn < 0) {
+ ErrorF("winProcessXEventsTimeout - Call to select () failed: %d (%x). "
+ "Bailing.\n", iReturn, WSAGetLastError());
+ 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");
+ }
+ }
+
+ return WIN_XEVENTS_SUCCESS;
+}
+
+/*
+ * Process a given Windows message
+ */
+
+LRESULT CALLBACK
+winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static HWND s_hwndNextViewer;
+
+ /* Branch on message type */
+ switch (message) {
+ case WM_DESTROY:
+ {
+ winDebug("winClipboardWindowProc - WM_DESTROY\n");
+
+ /* Remove ourselves from the clipboard chain */
+ ChangeClipboardChain(hwnd, s_hwndNextViewer);
+
+ s_hwndNextViewer = NULL;
+ g_hwndClipboard = NULL;
+ PostQuitMessage(0);
+ }
+ return 0;
+
+ case WM_CREATE:
+ {
+ HWND first, next;
+ DWORD error_code = 0;
+
+ winDebug("winClipboardWindowProc - WM_CREATE\n");
+
+ /* Add ourselves to the clipboard viewer chain */
+ s_hwndNextViewer = SetClipboardViewer (hwnd);
+ #ifdef _DEBUG
+ if (s_hwndNextViewer== hwnd)
+ {
+ ErrorF("WM_CREATE: SetClipboardViewer returned own window. This causes an endless loop, so reset s_hwndNextViewer. ");
+ s_hwndNextViewer=NULL;
+ }
+ #endif
+
+ }
+ return 0;
+
+ case WM_CHANGECBCHAIN:
+ {
+ winDebug("winClipboardWindowProc - WM_CHANGECBCHAIN: wParam(%x) "
+ "lParam(%x) s_hwndNextViewer(%x)\n",
+ wParam, lParam, s_hwndNextViewer);
+
+ if ((HWND) wParam == s_hwndNextViewer) {
+ s_hwndNextViewer = (HWND) lParam;
+ if (s_hwndNextViewer == hwnd) {
+ winDebug("WM_CHANGECBCHAIN: trying to set s_hwndNextViewer to own window. Resetting it back to NULL. ");
+ s_hwndNextViewer=NULL; /* This would cause an endless loop, so break it by ending the loop here. I have seen this happening, why??? */
+ }
+ }
+ else if (s_hwndNextViewer)
+ SendMessage(s_hwndNextViewer, message, wParam, lParam);
+
+ }
+ winDebug("winClipboardWindowProc - WM_CHANGECBCHAIN: Exit\n");
+ return 0;
+
+ case WM_WM_REINIT:
+ {
+ /* Ensure that we're in the clipboard chain. Some apps,
+ * WinXP's remote desktop for one, don't play nice with the
+ * chain. This message is called whenever we receive a
+ * WM_ACTIVATEAPP message to ensure that we continue to
+ * receive clipboard messages.
+ *
+ * It might be possible to detect if we're still in the chain
+ * by calling SendMessage (GetClipboardViewer(),
+ * WM_DRAWCLIPBOARD, 0, 0); and then seeing if we get the
+ * WM_DRAWCLIPBOARD message. That, however, might be more
+ * expensive than just putting ourselves back into the chain.
+ */
+
+ HWND first, next;
+ DWORD error_code = 0;
+ if (!g_hwndClipboard)
+ return 0;
+ winDebug("winClipboardWindowProc - WM_WM_REINIT: Enter\n");
+
+ first = GetClipboardViewer(); /* Get handle to first viewer in chain. */
+ if (first != hwnd)
+ {
+ winDebug (" WM_WM_REINIT: Replacing us(%x) with %x at head "
+ "of chain\n", hwnd, s_hwndNextViewer);
+ if (!wParam) ChangeClipboardChain (hwnd, s_hwndNextViewer); /* When wParam is set, the window was already removed from the chain */
+ winDebug (" WM_WM_REINIT: Putting us back at head of chain.\n");
+ s_hwndNextViewer = SetClipboardViewer (hwnd);
+ #ifdef _DEBUG
+ if (s_hwndNextViewer== hwnd)
+ {
+ ErrorF("WM_WM_REINIT: SetClipboardViewer returned own window. This causes an endless loop, so reset s_hwndNextViewer. ");
+ s_hwndNextViewer=NULL;
+ }
+ #endif
+ }
+ winDebug ("winClipboardWindowProc - WM_WM_REINIT: Exit\n");
+ }
+ return 0;
+
+ 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 0x%x 0x%x 0x%x: Enter\n",hwnd,wParam,lParam);
+
+ if (!g_fClipboardStarted) {
+ winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit with no processing\n");
+ if (s_hwndNextViewer)
+ SendMessage (s_hwndNextViewer, message, wParam, lParam);
+ return 0;
+ }
+
+ 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.
+ */
+ if (!s_fProcessingDrawClipboard) {
+ s_fProcessingDrawClipboard = TRUE;
+ }
+ else {
+ /* Attempt to break the nesting by getting out of the chain, twice?, and then fix and bail */
+ ChangeClipboardChain(hwnd, s_hwndNextViewer);
+ winFixClipboardChain(1);
+ ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "Nested calls detected. Re-initing.\n");
+ winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
+ s_fProcessingDrawClipboard = FALSE;
+ return 0;
+ }
+
+ /*
+ * Do not take ownership of the X11 selections when something
+ * other than CF_TEXT or CF_UNICODETEXT has been copied
+ * into the Win32 clipboard.
+ */
+ if (!IsClipboardFormatAvailable(CF_TEXT)
+ && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
+
+ winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "Clipboard does not contain CF_TEXT nor "
+ "CF_UNICODETEXT.\n");
+
+ /*
+ * We need to make sure that the X Server has processed
+ * previous XSetSelectionOwner messages.
+ */
+ XSync(pDisplay, FALSE);
+
+ if (g_fClipboardPrimary)
+ {
+ /* Release PRIMARY selection if owned */
+ iReturn = XGetSelectionOwner (pDisplay, XA_PRIMARY);
+ if (iReturn == g_iClipboardWindow) {
+ winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "PRIMARY selection is owned by us.\n");
+ XSetSelectionOwner (pDisplay, XA_PRIMARY, None, CurrentTime);
+ }
+ else if (BadWindow == iReturn || BadAtom == iReturn)
+ ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "XGetSelection failed for PRIMARY: %d\n",
+ iReturn);
+ }
+ /* Release CLIPBOARD selection if owned */
+ iReturn = XGetSelectionOwner(pDisplay, atomClipboard);
+ if (iReturn == g_iClipboardWindow) {
+ winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "CLIPBOARD selection is owned by us.\n");
+ XSetSelectionOwner(pDisplay, atomClipboard, None, CurrentTime);
+ }
+ else if (BadWindow == iReturn || BadAtom == iReturn)
+ ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "XGetSelection failed for CLIPBOARD: %d\n",
+ iReturn);
+
+ winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
+ s_fProcessingDrawClipboard = FALSE;
+ if (s_hwndNextViewer)
+ SendMessage(s_hwndNextViewer, message, wParam, lParam);
+ return 0;
+ }
+ /* Only reassert ownership when we did not change the clipboard ourselves */
+ if (hwnd!=(HWND)wParam) {
+ if (g_fClipboardPrimary) {
+ /* Reassert ownership of PRIMARY */
+ iReturn = XSetSelectionOwner (pDisplay,
+ XA_PRIMARY, iWindow, CurrentTime);
+ if (iReturn == BadAtom || iReturn == BadWindow ||
+ XGetSelectionOwner (pDisplay, XA_PRIMARY) != iWindow) {
+ ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "Could not reassert ownership of PRIMARY\n");
+ }
+ else {
+ winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "Reasserted ownership of PRIMARY\n");
+ }
+ }
+ /* Reassert ownership of the CLIPBOARD */
+ iReturn = XSetSelectionOwner (pDisplay,
+ atomClipboard, iWindow, CurrentTime);
+
+ if (iReturn == BadAtom || iReturn == BadWindow ||
+ XGetSelectionOwner (pDisplay, atomClipboard) != iWindow) {
+ ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "Could not reassert ownership of CLIPBOARD\n");
+ }
+ else {
+ winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ "Reasserted ownership of CLIPBOARD\n");
+ }
+
+ /* Flush the pending SetSelectionOwner event now */
+ XFlush (pDisplay);
+ }
+
+ s_fProcessingDrawClipboard = FALSE;
+ winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
+ /* Pass the message on the next window in the clipboard viewer chain */
+ if (s_hwndNextViewer)
+ SendMessage(s_hwndNextViewer, message, wParam, lParam);
+ return 0;
+
+ }
+ case WM_DESTROYCLIPBOARD:
+ /*
+ * NOTE: Intentionally do nothing.
+ * Changes in the Win32 clipboard are handled by WM_DRAWCLIPBOARD
+ * above. We only process this message to conform to the specs
+ * for delayed clipboard rendering in Win32. You might think
+ * that we need to release ownership of the X11 selections, but
+ * we do not, because a WM_DRAWCLIPBOARD message will closely
+ * follow this message and reassert ownership of the X11
+ * selections, handling the issue for us.
+ */
+ winDebug("winClipboardWindowProc - WM_DESTROYCLIPBOARD - Ignored.\n");
+ return 0;
+
+ case WM_RENDERFORMAT:
+ case WM_RENDERALLFORMATS:
+ {
+ int iReturn;
+ Display *pDisplay = g_pClipboardDisplay;
+ Window iWindow = g_iClipboardWindow;
+ Bool fConvertToUnicode;
+
+ winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
+
+ /* Flag whether to convert to Unicode or not */
+ if (message == WM_RENDERALLFORMATS)
+ fConvertToUnicode = FALSE;
+ else
+ 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;
+ }
+
+ /* 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;
+ }
+
+ if (!EmptyClipboard()) {
+ ErrorF ("winClipboardWindowProc - WM_RENDER*FORMATS - "
+ "EmptyClipboard () failed: %08x\n",
+ GetLastError());
+ CloseClipboard ();
+ break;
+ }
+ }
+
+ /* Process the SelectionNotify event */
+ iReturn = winProcessXEventsTimeout(hwnd,
+ iWindow,
+ pDisplay,
+ fConvertToUnicode, 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.
+ */
+ 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);
+
+ ErrorF
+ ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY\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;
+ }
+ }
+
+ winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Returning.\n");
+ return 0;
+ }
+ }
+
+ /* Let Windows perform default processing for unhandled messages */
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+/*
+ * Process any pending Windows messages
+ */
+
+BOOL
+winClipboardFlushWindowsMessageQueue(HWND hwnd)
+{
+ MSG msg;
+
+ /* Flush the messaging window queue */
+ /* NOTE: Do not pass the hwnd of our messaging window to PeekMessage,
+ * as this will filter out many non-window-specific messages that
+ * are sent to our thread, such as WM_QUIT.
+ */
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+ /* Dispatch the message if not WM_QUIT */
+ if (msg.message == WM_QUIT)
+ return FALSE;
+ else
+ DispatchMessage(&msg);
+ }
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winclipboard/xevents.c b/xorg-server/hw/xwin/winclipboard/xevents.c
new file mode 100755
index 000000000..cfbf0121e
--- /dev/null
+++ b/xorg-server/hw/xwin/winclipboard/xevents.c
@@ -0,0 +1,747 @@
+/*
+ *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 HAROLD L HUNT II 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
+#include "winclipboard.h"
+#include "misc.h"
+#include "winmsg.h"
+#include "internal.h"
+#include <unistd.h>
+
+extern Bool g_fClipboardPrimary;
+
+/*
+ * Process any pending X events
+ */
+
+int
+winClipboardFlushXEvents(HWND hwnd,
+ int iWindow, Display * pDisplay, Bool fUseUnicode, Bool ClipboardOpened)
+{
+ 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);
+ }
+
+ /* Process all pending events */
+ while (XPending(pDisplay)) {
+ XTextProperty xtpText = { 0 };
+ XEvent event;
+ XSelectionEvent eventSelection;
+ unsigned long ulReturnBytesLeft;
+ char *pszReturnData = NULL;
+ char *pszGlobalData = NULL;
+ 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;
+
+ /* 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) {
+ /*
+ * SelectionRequest
+ */
+
+ case SelectionRequest:
+#ifdef _DEBUG
+ {
+ char *pszAtomName = NULL;
+
+ winDebug("SelectionRequest - target %d\n",
+ event.xselectionrequest.target);
+
+ pszAtomName = XGetAtomName(pDisplay,
+ event.xselectionrequest.target);
+ 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
+
+ /* Abort if invalid target type */
+ if (event.xselectionrequest.target != XA_STRING
+ && event.xselectionrequest.target != atomUTF8String
+ && event.xselectionrequest.target != atomCompoundText
+ && event.xselectionrequest.target != atomTargets) {
+ /* Abort */
+ fAbort = TRUE;
+ goto winClipboardFlushXEvents_SelectionRequest_Done;
+ }
+
+ /* Handle targets type of request */
+ if (event.xselectionrequest.target == atomTargets) {
+ Atom atomTargetArr[] = { atomTargets,
+ atomCompoundText,
+ atomUTF8String,
+ XA_STRING
+ };
+
+ /* Try to change the property */
+ iReturn = XChangeProperty(pDisplay,
+ event.xselectionrequest.requestor,
+ event.xselectionrequest.property,
+ XA_ATOM,
+ 32,
+ PropModeReplace,
+ (unsigned char *) atomTargetArr,
+ (sizeof(atomTargetArr)
+ / sizeof(atomTargetArr[0])));
+ if (iReturn == BadAlloc
+ || iReturn == BadAtom
+ || iReturn == BadMatch
+ || iReturn == BadValue || iReturn == BadWindow) {
+ ErrorF("winClipboardFlushXEvents - SelectionRequest - "
+ "XChangeProperty failed: %d\n", iReturn);
+ }
+
+ /* Setup selection notify xevent */
+ eventSelection.type = SelectionNotify;
+ eventSelection.send_event = True;
+ eventSelection.display = pDisplay;
+ eventSelection.requestor = event.xselectionrequest.requestor;
+ eventSelection.selection = event.xselectionrequest.selection;
+ eventSelection.target = event.xselectionrequest.target;
+ eventSelection.property = event.xselectionrequest.property;
+ eventSelection.time = event.xselectionrequest.time;
+
+ /*
+ * Notify the requesting window that
+ * the operation has completed
+ */
+ iReturn = XSendEvent(pDisplay,
+ eventSelection.requestor,
+ False, 0L, (XEvent *) &eventSelection);
+ if (iReturn == BadValue || iReturn == BadWindow) {
+ ErrorF("winClipboardFlushXEvents - SelectionRequest - "
+ "XSendEvent () failed\n");
+ }
+ break;
+ }
+
+ /* Access the clipboard */
+ if (!ClipboardOpened)
+ {
+ if (!OpenClipboard (hwnd))
+ {
+ ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
+ "OpenClipboard () failed: %08lx\n",
+ GetLastError ());
+
+ /* Abort */
+ fAbort = TRUE;
+ goto winClipboardFlushXEvents_SelectionRequest_Done;
+ }
+
+ /* Indicate that clipboard was opened */
+ fCloseClipboard = TRUE;
+ }
+
+ /* Check that clipboard format is available */
+ if (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? */
+
+ if (hwnd != lasthwnd)
+ count = 0;
+ count++;
+ if (count < 6)
+ ErrorF("winClipboardFlushXEvents - CF_UNICODETEXT is not "
+ "available from Win32 clipboard. Aborting %d.\n",
+ count);
+ lasthwnd = hwnd;
+
+ /* Abort */
+ fAbort = TRUE;
+ goto winClipboardFlushXEvents_SelectionRequest_Done;
+ }
+ else if (!fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) {
+ ErrorF("winClipboardFlushXEvents - CF_TEXT is not "
+ "available from Win32 clipboard. Aborting.\n");
+
+ /* Abort */
+ fAbort = TRUE;
+ goto winClipboardFlushXEvents_SelectionRequest_Done;
+ }
+
+ /* Setup the string style */
+ if (event.xselectionrequest.target == XA_STRING)
+ xiccesStyle = XStringStyle;
+#ifdef X_HAVE_UTF8_STRING
+ else if (event.xselectionrequest.target == atomUTF8String)
+ xiccesStyle = XUTF8StringStyle;
+#endif
+ else if (event.xselectionrequest.target == atomCompoundText)
+ xiccesStyle = XCompoundTextStyle;
+ else
+ xiccesStyle = XStringStyle;
+
+ /* Get a pointer to the clipboard text, in desired format */
+ if (fUseUnicode) {
+ /* Retrieve clipboard data */
+ hGlobal = GetClipboardData(CF_UNICODETEXT);
+ }
+ else {
+ /* Retrieve clipboard data */
+ 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());
+
+ /* Abort */
+ fAbort = TRUE;
+ goto winClipboardFlushXEvents_SelectionRequest_Done;
+ }
+ pszGlobalData = (char *) GlobalLock(hGlobal);
+
+ /* Convert the Unicode string to UTF8 (MBCS) */
+ if (fUseUnicode) {
+ iConvertDataLen = WideCharToMultiByte(CP_UTF8,
+ 0,
+ (LPCWSTR) pszGlobalData,
+ -1, NULL, 0, NULL, NULL);
+ /* NOTE: iConvertDataLen includes space for null terminator */
+ pszConvertData = malloc(iConvertDataLen);
+ WideCharToMultiByte(CP_UTF8,
+ 0,
+ (LPCWSTR) pszGlobalData,
+ -1,
+ pszConvertData,
+ iConvertDataLen, NULL, NULL);
+ }
+ else {
+ pszConvertData = strdup(pszGlobalData);
+ iConvertDataLen = strlen(pszConvertData) + 1;
+ }
+
+ /* Convert DOS string to UNIX string */
+ winClipboardDOStoUNIX(pszConvertData, strlen(pszConvertData));
+
+ /* Setup our text list */
+ pszTextList[0] = pszConvertData;
+ pszTextList[1] = NULL;
+
+ /* Initialize the text property */
+ xtpText.value = NULL;
+ xtpText.nitems = 0;
+
+ /* Create the text property from the text list */
+ if (fUseUnicode) {
+#ifdef X_HAVE_UTF8_STRING
+ iReturn = Xutf8TextListToTextProperty(pDisplay,
+ pszTextList,
+ 1, xiccesStyle, &xtpText);
+#endif
+ }
+ else {
+ iReturn = XmbTextListToTextProperty(pDisplay,
+ pszTextList,
+ 1, xiccesStyle, &xtpText);
+ }
+ if (iReturn == XNoMemory || iReturn == XLocaleNotSupported) {
+ ErrorF("winClipboardFlushXEvents - SelectionRequest - "
+ "X*TextListToTextProperty failed: %d\n", iReturn);
+
+ /* Abort */
+ fAbort = TRUE;
+ goto winClipboardFlushXEvents_SelectionRequest_Done;
+ }
+
+ /* Free the converted string */
+ free(pszConvertData);
+ pszConvertData = NULL;
+
+ /* Copy the clipboard text to the requesting window */
+ iReturn = XChangeProperty(pDisplay,
+ event.xselectionrequest.requestor,
+ event.xselectionrequest.property,
+ event.xselectionrequest.target,
+ 8,
+ PropModeReplace,
+ xtpText.value, xtpText.nitems);
+ if (iReturn == BadAlloc || iReturn == BadAtom
+ || iReturn == BadMatch || iReturn == BadValue
+ || iReturn == BadWindow) {
+ ErrorF("winClipboardFlushXEvents - SelectionRequest - "
+ "XChangeProperty failed: %d\n", iReturn);
+
+ /* Abort */
+ fAbort = TRUE;
+ goto winClipboardFlushXEvents_SelectionRequest_Done;
+ }
+
+ /* Release the clipboard data */
+ GlobalUnlock(hGlobal);
+ pszGlobalData = NULL;
+ if (fCloseClipboard)
+ {
+ fCloseClipboard = FALSE;
+ CloseClipboard ();
+ }
+ /* Clean up */
+ XFree(xtpText.value);
+ xtpText.value = NULL;
+ xtpText.nitems = 0;
+
+ /* Setup selection notify event */
+ eventSelection.type = SelectionNotify;
+ eventSelection.send_event = True;
+ eventSelection.display = pDisplay;
+ eventSelection.requestor = event.xselectionrequest.requestor;
+ eventSelection.selection = event.xselectionrequest.selection;
+ eventSelection.target = event.xselectionrequest.target;
+ eventSelection.property = event.xselectionrequest.property;
+ eventSelection.time = event.xselectionrequest.time;
+
+ /* Notify the requesting window that the operation has completed */
+ iReturn = XSendEvent(pDisplay,
+ eventSelection.requestor,
+ False, 0L, (XEvent *) &eventSelection);
+ if (iReturn == BadValue || iReturn == BadWindow) {
+ ErrorF("winClipboardFlushXEvents - SelectionRequest - "
+ "XSendEvent () failed\n");
+
+ /* Abort */
+ fAbort = TRUE;
+ goto winClipboardFlushXEvents_SelectionRequest_Done;
+ }
+
+ winClipboardFlushXEvents_SelectionRequest_Done:
+ /* Free allocated resources */
+ if (xtpText.value) {
+ XFree(xtpText.value);
+ xtpText.value = NULL;
+ xtpText.nitems = 0;
+ }
+ free(pszConvertData);
+ if (hGlobal && pszGlobalData)
+ GlobalUnlock(hGlobal);
+
+ /*
+ * Send a SelectionNotify event to the requesting
+ * client when we abort.
+ */
+ if (fAbort) {
+ /* Setup selection notify event */
+ eventSelection.type = SelectionNotify;
+ eventSelection.send_event = True;
+ eventSelection.display = pDisplay;
+ eventSelection.requestor = event.xselectionrequest.requestor;
+ eventSelection.selection = event.xselectionrequest.selection;
+ eventSelection.target = event.xselectionrequest.target;
+ eventSelection.property = None;
+ eventSelection.time = event.xselectionrequest.time;
+
+ /* Notify the requesting window that the operation is complete */
+ iReturn = XSendEvent(pDisplay,
+ eventSelection.requestor,
+ False, 0L, (XEvent *) &eventSelection);
+ if (iReturn == BadValue || iReturn == BadWindow) {
+ /*
+ * Should not be a problem if XSendEvent fails because
+ * the client may simply have exited.
+ */
+ ErrorF("winClipboardFlushXEvents - SelectionRequest - "
+ "XSendEvent () failed for abort event.\n");
+ }
+ }
+
+ /* Close clipboard if it was opened */
+ if (fCloseClipboard) {
+ fCloseClipboard = FALSE;
+ CloseClipboard();
+ }
+ break;
+
+ /*
+ * SelectionNotify
+ */
+ case SelectionNotify:
+#ifdef _DEBUG
+ winDebug("winClipboardFlushXEvents - SelectionNotify\n");
+ {
+ char *pszAtomName;
+
+ pszAtomName = XGetAtomName(pDisplay,
+ event.xselection.selection);
+
+ 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");
+
+ 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 {
+ ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+ "Unknown format. Cannot request conversion, "
+ "aborting.\n");
+ break;
+ }
+ }
+
+ /* 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;
+ }
+
+ winDebug("SelectionNotify - returned data %d left %d\n",
+ xtpText.nitems, ulReturnBytesLeft);
+
+ /* Request the selection data */
+ iReturn = XGetWindowProperty(pDisplay,
+ iWindow,
+ atomLocalProperty,
+ 0,
+ ulReturnBytesLeft,
+ False,
+ AnyPropertyType,
+ &xtpText.encoding,
+ &xtpText.format,
+ &xtpText.nitems,
+ &ulReturnBytesLeft, &xtpText.value);
+ if (iReturn != Success) {
+ ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+ "XGetWindowProperty () failed, aborting: %d\n", iReturn);
+ break;
+ }
+
+#ifdef WINDBG
+ {
+ char *pszAtomName = NULL;
+
+ winDebug("SelectionNotify - returned data %d left %d\n",
+ xtpText.nitems, ulReturnBytesLeft);
+ pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
+ winDebug("Notify atom name %s\n", pszAtomName);
+ XFree(pszAtomName);
+ pszAtomName = NULL;
+ }
+#endif
+
+ if (fUseUnicode) {
+#ifdef X_HAVE_UTF8_STRING
+ /* Convert the text property to a text list */
+ iReturn = Xutf8TextPropertyToTextList(pDisplay,
+ &xtpText,
+ &ppszTextList, &iCount);
+#endif
+ }
+ else {
+ iReturn = XmbTextPropertyToTextList(pDisplay,
+ &xtpText,
+ &ppszTextList, &iCount);
+ }
+ if (iReturn == Success || iReturn > 0) {
+ /* Conversion succeeded or some unconvertible characters */
+ if (ppszTextList != NULL) {
+ iReturnDataLen = 0;
+ for (i = 0; i < iCount; i++) {
+ iReturnDataLen += strlen(ppszTextList[i]);
+ }
+ pszReturnData = (char *) malloc(iReturnDataLen + 1);
+ pszReturnData[0] = '\0';
+ for (i = 0; i < iCount; i++) {
+ strcat(pszReturnData, ppszTextList[i]);
+ }
+ }
+ else {
+ ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+ "X*TextPropertyToTextList list_return is NULL.\n");
+ pszReturnData = (char *) malloc(1);
+ pszReturnData[0] = '\0';
+ }
+ }
+ else {
+ ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+ "X*TextPropertyToTextList returned: ");
+ switch (iReturn) {
+ case XNoMemory:
+ ErrorF("XNoMemory\n");
+ break;
+ case XLocaleNotSupported:
+ ErrorF("XLocaleNotSupported\n");
+ break;
+ case XConverterNotFound:
+ ErrorF("XConverterNotFound\n");
+ break;
+ default:
+ ErrorF("%d\n", iReturn);
+ break;
+ }
+ pszReturnData = (char *) malloc(1);
+ pszReturnData[0] = '\0';
+ }
+
+ /* Free the data returned from XGetWindowProperty */
+ if (ppszTextList)
+ XFreeStringList(ppszTextList);
+ ppszTextList = NULL;
+ XFree(xtpText.value);
+ xtpText.value = NULL;
+ xtpText.nitems = 0;
+
+ /* Convert the X clipboard string to DOS format */
+ winClipboardUNIXtoDOS((unsigned char **)&pszReturnData, strlen(pszReturnData));
+
+ if (fUseUnicode) {
+ /* Find out how much space needed to convert MBCS to Unicode */
+ iUnicodeLen = MultiByteToWideChar(CP_UTF8,
+ 0,
+ pszReturnData, -1, NULL, 0);
+
+ /* Allocate memory for the Unicode string */
+ pwszUnicodeStr = malloc(sizeof(wchar_t) * (iUnicodeLen + 1));
+ if (!pwszUnicodeStr) {
+ ErrorF("winClipboardFlushXEvents - SelectionNotify "
+ "malloc failed for pwszUnicodeStr, aborting.\n");
+
+ /* Abort */
+ fAbort = TRUE;
+ goto winClipboardFlushXEvents_SelectionNotify_Done;
+ }
+
+ /* Do the actual conversion */
+ MultiByteToWideChar(CP_UTF8,
+ 0,
+ pszReturnData,
+ -1, pwszUnicodeStr, iUnicodeLen);
+
+ /* Allocate global memory for the X clipboard data */
+ hGlobal = GlobalAlloc(GMEM_MOVEABLE,
+ sizeof(wchar_t) * (iUnicodeLen + 1));
+ }
+ else {
+ pszConvertData = strdup(pszReturnData);
+ iConvertDataLen = strlen(pszConvertData) + 1;
+
+ /* Allocate global memory for the X clipboard data */
+ hGlobal = GlobalAlloc(GMEM_MOVEABLE, iConvertDataLen);
+ }
+
+ free(pszReturnData);
+
+ /* Check that global memory was allocated */
+ if (!hGlobal) {
+ ErrorF("winClipboardFlushXEvents - SelectionNotify "
+ "GlobalAlloc failed, aborting: %ld\n", GetLastError());
+
+ /* Abort */
+ fAbort = TRUE;
+ goto winClipboardFlushXEvents_SelectionNotify_Done;
+ }
+
+ /* Obtain a pointer to the global memory */
+ pszGlobalData = GlobalLock(hGlobal);
+ if (pszGlobalData == NULL) {
+ ErrorF("winClipboardFlushXEvents - Could not lock global "
+ "memory for clipboard transfer\n");
+
+ /* Abort */
+ fAbort = TRUE;
+ goto winClipboardFlushXEvents_SelectionNotify_Done;
+ }
+
+ /* Copy the returned string into the global memory */
+ if (fUseUnicode) {
+ memcpy(pszGlobalData,
+ pwszUnicodeStr, sizeof(wchar_t) * (iUnicodeLen + 1));
+ free(pwszUnicodeStr);
+ pwszUnicodeStr = NULL;
+ }
+ else {
+ strcpy(pszGlobalData, pszConvertData);
+ free(pszConvertData);
+ pszConvertData = NULL;
+ }
+
+ /* Release the pointer to the global memory */
+ GlobalUnlock(hGlobal);
+ pszGlobalData = NULL;
+
+ /* Push the selection data to the Windows clipboard */
+ if (fUseUnicode)
+ SetClipboardData(CF_UNICODETEXT, hGlobal);
+ else
+ SetClipboardData(CF_TEXT, hGlobal);
+
+ /* Flag that SetClipboardData has been called */
+ fSetClipboardData = FALSE;
+
+ /*
+ * NOTE: Do not try to free pszGlobalData, it is owned by
+ * Windows after the call to SetClipboardData ().
+ */
+
+ winClipboardFlushXEvents_SelectionNotify_Done:
+ /* Free allocated resources */
+ if (ppszTextList)
+ XFreeStringList(ppszTextList);
+ if (xtpText.value) {
+ XFree(xtpText.value);
+ xtpText.value = NULL;
+ xtpText.nitems = 0;
+ }
+ free(pszConvertData);
+ free(pwszUnicodeStr);
+ if (hGlobal && pszGlobalData)
+ GlobalUnlock(hGlobal);
+ if (fSetClipboardData) {
+ SetClipboardData(CF_UNICODETEXT, NULL);
+ SetClipboardData(CF_TEXT, NULL);
+ }
+ return WIN_XEVENTS_NOTIFY;
+
+ /*
+ * SelectionClear
+ */
+ case SelectionClear:
+#ifdef _DEBUG
+ 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);
+ break;
+ }
+ }
+
+ return WIN_XEVENTS_SUCCESS;
+}
diff --git a/xorg-server/hw/xwin/winclipboard/xwinclip.c b/xorg-server/hw/xwin/winclipboard/xwinclip.c
new file mode 100644
index 000000000..3677974c4
--- /dev/null
+++ b/xorg-server/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/xorg-server/hw/xwin/winclipboard/xwinclip.man b/xorg-server/hw/xwin/winclipboard/xwinclip.man
new file mode 100644
index 000000000..822db91d4
--- /dev/null
+++ b/xorg-server/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.