diff options
author | Jon TURNEY <jon.turney@dronecode.org.uk> | 2013-06-20 21:18:52 +0100 |
---|---|---|
committer | Jon TURNEY <jon.turney@dronecode.org.uk> | 2013-06-20 21:18:52 +0100 |
commit | 4f0fbb7414e8e3c26d9a0a21421ff90cf841cbb3 (patch) | |
tree | 8c5b08b3754e17933f1c64b6614c13ba2fd888cd | |
parent | 6c4ea309427b9cd95a72185a84aee569a0a673ab (diff) | |
parent | deed8fb257d2d73d22941dd5bbdd4bab3ef1d3f8 (diff) |
Merge branch 'clipboard-64bit-fix' into cygwin-release-1.14xserver-cygwin-1.14.1-2
21 files changed, 847 insertions, 696 deletions
diff --git a/configure.ac b/configure.ac index cd3fb381e..730cac951 100644 --- a/configure.ac +++ b/configure.ac @@ -1906,7 +1906,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 x11-xcb xcb-image xcb-icccm]) + PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau xfixes x11-xcb xcb-image xcb-icccm]) if test "x$WINDOWSWM" = xauto; then PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no]) @@ -2313,6 +2313,7 @@ hw/xwin/Makefile hw/xwin/glx/Makefile hw/xwin/man/Makefile hw/xwin/wmutil/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 395b533fc..c42418c23 100644 --- a/hw/xwin/InitInput.c +++ b/hw/xwin/InitInput.c @@ -39,8 +39,6 @@ #ifdef XWIN_CLIPBOARD int winProcEstablishConnection(ClientPtr /* client */ ); -int winProcQueryTree(ClientPtr /* client */ ); -int winProcSetSelectionOwner(ClientPtr /* client */ ); #endif /* diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c index 9afd6a72b..91a711709 100644 --- a/hw/xwin/InitOutput.c +++ b/hw/xwin/InitOutput.c @@ -63,27 +63,12 @@ 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 - extern Bool noRRXineramaExtension; /* * Function prototypes */ -#ifdef XWIN_CLIPBOARD -static void - winClipboardShutdown(void); -#endif - - void winLogCommandLine(int argc, char *argv[]); @@ -127,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 28abb5345..b38d9568f 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 @@ -111,7 +108,6 @@ SRCS = InitInput.c \ winwindow.c \ winwndproc.c \ ddraw.h \ - winclipboard.h \ winconfig.h \ win.h \ winglobals.h \ @@ -157,7 +153,7 @@ XWIN_LIBS += $(top_builddir)/pseudoramiX/libPseudoramiX.la XWin_DEPENDENCIES = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) XWin_LDADD = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) \ - $(XWIN_GLX_SYS_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS) $(MULTIWINDOW_SYS_LIBS) + $(CLIPBOARD_LIBS) $(XWIN_GLX_SYS_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS) $(MULTIWINDOW_SYS_LIBS) XWin_LDFLAGS = -mwindows -static .rc.o: @@ -193,5 +189,5 @@ EXTRA_DIST = \ relink: $(AM_V_at)rm -f XWin$(EXEEXT) && $(MAKE) XWin$(EXEEXT) -SUBDIRS = man $(GLX_DIR) wmutil . +SUBDIRS = man $(GLX_DIR) wmutil winclipboard . DIST_SUBDIRS = man glx . diff --git a/hw/xwin/win.h b/hw/xwin/win.h index 5e0ca8901..883409c43 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 ad994d5ad..3f9746933 100644 --- a/hw/xwin/winclipboard.h +++ b/hw/xwin/winclipboard/internal.h @@ -1,5 +1,3 @@ -#ifndef _WINCLIPBOARD_H_ -#define _WINCLIPBOARD_H_ /* *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved. * @@ -30,46 +28,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/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_SHUTDOWN 1 #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 +47,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,26 +64,47 @@ void * winclipboardthread.c */ -void *winClipboardProc(void *); - void - winDeinitClipboard(void); +winClipboardWindowDestroy(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 7b8eb9826..2870a9b8a 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 eb121e96b..15a515649 100644 --- a/hw/xwin/winclipboardthread.c +++ b/hw/xwin/winclipboard/thread.c @@ -35,61 +35,78 @@ #else #define HAS_WINSOCK 1 #endif -#include <sys/types.h> -#include <signal.h> -#include "winclipboard.h" -#ifdef __CYGWIN__ + +/* + * 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 <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 "misc.h" -extern winSetAuthorization(void); -extern void winGetDisplayName(char *szDisplay, unsigned int screen); +#include <X11/Xatom.h> +#include <X11/extensions/Xfixes.h> +#include "winclipboard.h" +#include "internal.h" -/* - * References to external symbols - */ +#define WIN_CONNECT_RETRIES 40 +#define WIN_CONNECT_DELAY 4 -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; +#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); static int winClipboardIOErrorHandler(Display * pDisplay); -static void -winClipboardThreadExit(void *arg); - /* - * 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, atomClipboardManager; + ClipboardAtoms atoms; int iReturn; HWND hwnd = NULL; int iConnectionNumber = 0; @@ -103,87 +120,36 @@ winClipboardProc(void *pvNotUsed) int iMaxDescriptor; Display *pDisplay = NULL; Window iWindow = None; - int iRetries; - Bool fUseUnicode; - char szDisplay[512]; int iSelectError; - - pthread_cleanup_push(&winClipboardThreadExit, NULL); + Bool fShutdown = 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; - /* Set error handler */ - XSetErrorHandler(winClipboardErrorHandler); - g_winClipboardProcThread = pthread_self(); - g_winClipboardOldIOErrorHandler = - XSetIOErrorHandler(winClipboardIOErrorHandler); + static Bool fErrorHandlerSet = FALSE; - /* Set jump point for Error exits */ - iReturn = setjmp(g_jmpEntry); + g_winClipboardProcThread = pthread_self(); - /* 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; + if (! fErrorHandlerSet) { + XSetErrorHandler(winClipboardErrorHandler); + g_winClipboardOldIOErrorHandler = + XSetIOErrorHandler(winClipboardIOErrorHandler); + fErrorHandlerSet = TRUE; } - else if (iReturn == WIN_JMP_ERROR_IO) { - /* TODO: Cleanup the Win32 window and free any allocated memory */ + + /* Set jump point for Error exits */ + if (setjmp(g_jmpEntry)) { ErrorF("winClipboardProc - setjmp returned for IO Error Handler.\n"); goto winClipboardProc_Done; } - /* 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; - } - 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 a global used by the wndproc */ - g_pClipboardDisplay = pDisplay; - ErrorF("winClipboardProc - XOpenDisplay () returned and " "successfully opened the display.\n"); @@ -199,14 +165,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 + if (!XFixesQueryExtension(pDisplay, &xfixes_event_base, &xfixes_error_base)) + ErrorF ("winClipboardProc - XFixes extension not present\n"); + /* Create atoms */ - atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False); - atomClipboardManager = XInternAtom(pDisplay, "CLIPBOARD_MANAGER", False); + 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, @@ -228,13 +200,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 */ @@ -249,22 +235,22 @@ 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)) { @@ -272,9 +258,6 @@ winClipboardProc(void *pvNotUsed) pthread_exit(NULL); } - /* Signal that the clipboard client has started */ - g_fClipboardStarted = TRUE; - /* Loop for X events */ while (1) { /* Setup the file descriptor set */ @@ -333,14 +316,8 @@ winClipboardProc(void *pvNotUsed) ("winClipboardProc - X connection ready, pumping X event queue\n"); /* Process X events */ - /* Exit when we see that server is shutting down */ - iReturn = winClipboardFlushXEvents(hwnd, - iWindow, pDisplay, fUseUnicode); - if (WIN_XEVENTS_SHUTDOWN == iReturn) { - ErrorF("winClipboardProc - winClipboardFlushXEvents " - "trapped shutdown event, exiting main loop.\n"); - break; - } + winClipboardFlushXEvents(hwnd, + iWindow, pDisplay, fUseUnicode, &atoms); } #ifdef HAS_DEVWINDOWS @@ -370,17 +347,13 @@ winClipboardProc(void *pvNotUsed) #endif } - 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 */ @@ -400,8 +373,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 */ @@ -417,43 +393,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 recieve Windows messages + */ - pthread_cleanup_pop(0); - return NULL; +static HWND +winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms) +{ + 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); + + /* Information to be passed to WM_CREATE */ + ClipboardWindowCreationParams cwcp; + 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; } /* @@ -483,7 +480,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) @@ -492,13 +489,18 @@ winClipboardIOErrorHandler(Display * pDisplay) return 0; } -/* - * winClipboardThreadExit - Thread exit handler - */ +void +winClipboardWindowDestroy(void) +{ + if (g_hwndClipboard) { + SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0); + } +} -static void -winClipboardThreadExit(void *arg) +void +winFixClipboardChain(void) { - /* clipboard thread has exited, stop server as well */ - kill(getpid(), SIGTERM); + 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 222446b4a..a171ca595 100644 --- a/hw/xwin/winclipboardwndproc.c +++ b/hw/xwin/winclipboard/wndproc.c @@ -33,15 +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 "winclipboard.h" -#include "misc.h" -#include "winmsg.h" - -extern void winFixClipboardChain(void); +#include <X11/Xatom.h> +#include "internal.h" +#include "winclipboard.h" /* * Constants @@ -49,32 +57,14 @@ extern void winFixClipboardChain(void); #define WIN_POLL_TIMEOUT 1 -/* - * References to external symbols - */ - -extern Bool g_fUseUnicode; -extern void *g_pClipboardDisplay; -extern Window g_iClipboardWindow; -extern Atom g_atomLastOwnedSelection; - -/* - * Local function prototypes - */ - -static int - - -winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay, - Bool fUseUnicode, int iTimeoutSec); /* * 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; @@ -127,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", @@ -155,11 +145,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND s_hwndNextViewer; static Bool s_fCBCInitialized; - -#if CYGDEBUG - winDebugWin32Message("winClipboardWindowProc", hwnd, message, wParam, - lParam); -#endif + static Display *pDisplay; + static Window iWindow; + static ClipboardAtoms *atoms; /* Branch on message type */ switch (message) { @@ -183,6 +171,11 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) winDebug("winClipboardWindowProc - WM_CREATE\n"); + ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams; + 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! */ @@ -206,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) @@ -262,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. @@ -288,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; @@ -337,7 +321,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) winDebug("winClipboardWindowProc: %d formats\n", CountClipboardFormats()); - { + + if (OpenClipboard(hwnd)) { unsigned int format = 0; do { @@ -357,7 +342,13 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) else if (format > 0) winDebug("winClipboardWindowProc: %d\n", format); } while (format != 0); + CloseClipboard(); + } + else { + winDebug + ("WindowProc: could not open clipboard to enumerate formats\n"); } + /* * We need to make sure that the X Server has processed * previous XSetSelectionOwner messages. @@ -368,27 +359,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, releasing\n"); XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime); } else if (BadWindow == iReturn || BadAtom == iReturn) - winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - " - "XGetSelectionOwner 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, releasing\n"); - XSetSelectionOwner(pDisplay, atomClipboard, None, CurrentTime); + XSetSelectionOwner(pDisplay, atoms->atomClipboard, None, CurrentTime); } else if (BadWindow == iReturn || BadAtom == iReturn) - winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - " - "XGetSelectionOwner 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; @@ -402,8 +393,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 - " @@ -412,12 +403,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 - " @@ -453,8 +444,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; if (message == WM_RENDERALLFORMATS) @@ -471,15 +460,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; } @@ -493,16 +480,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; } } @@ -511,7 +498,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 @@ -534,10 +523,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; } } @@ -555,7 +543,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 a4d193d93..1622d3223 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; @@ -545,6 +632,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]); @@ -706,8 +795,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 304e6df9f..de305ecbd 100644 --- a/hw/xwin/winclipboardinit.c +++ b/hw/xwin/winclipboardinit.c @@ -31,25 +31,78 @@ #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" + +#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; + + /* 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; + } -extern pthread_t g_ptClipboardProc; -extern winDispatchProcPtr winProcSetSelectionOwnerOrig; -extern Bool g_fClipboard; -extern HWND g_hwndClipboard; + sleep(WIN_CLIPBOARD_DELAY); + ErrorF("winClipboardProc - trying to restart clipboard thread \n"); + } + + return NULL; +} /* * Intialize the Clipboard module @@ -60,14 +113,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 +123,20 @@ winInitClipboard(void) return TRUE; } -/* - * Create the Windows window that we use to recieve 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 27b9872ff..2679f4f98 100644 --- a/hw/xwin/winclipboardwrappers.c +++ b/hw/xwin/winclipboardwrappers.c @@ -33,38 +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 unsigned int g_uiAuthDataLen; -extern char *g_pAuthData; -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. @@ -129,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) { /* @@ -165,211 +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. atom 0x%08x window XID 0x%08x \n", - stuff->selection, stuff->window); - - /* 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 XID 0x%08x\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 XID 0x%08x\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 87d58ae19..725a4619d 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 fd6c1b490..ad82b83f6 100644 --- a/hw/xwin/winglobals.c +++ b/hw/xwin/winglobals.c @@ -86,8 +86,6 @@ pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER; * Wrapped DIX functions */ winDispatchProcPtr winProcEstablishConnectionOrig = NULL; -winDispatchProcPtr winProcQueryTreeOrig = NULL; -winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL; /* * Clipboard variables @@ -95,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 /* @@ -113,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 d5da35f4a..5df4b608e 100644 --- a/hw/xwin/winglobals.h +++ b/hw/xwin/winglobals.h @@ -70,9 +70,10 @@ typedef int (*winDispatchProcPtr) (ClientPtr); * Wrapped DIX functions */ extern winDispatchProcPtr winProcEstablishConnectionOrig; -extern winDispatchProcPtr winProcQueryTreeOrig; -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 16bacd9ce..2829d5f8e 100644 --- a/hw/xwin/winwndproc.c +++ b/hw/xwin/winwndproc.c @@ -44,6 +44,9 @@ #include "inputstr.h" #include "wmutil/mouse.h" #include "wmutil/keyboard.h" +#ifdef XWIN_CLIPBOARD +#include "winclipboard/winclipboard.h" +#endif /* * Global variables |