From 30eb28e89e513ba7c04e8424be0cba326a01882b Mon Sep 17 00:00:00 2001 From: marha Date: Wed, 1 Oct 2014 20:47:44 +0200 Subject: libxtrans pixman fontconfig mesa xserver xkeyboard-config git update 1 Oct 2014 plink 10277 xserver commit d3d845ca9e92f0a2ccde93f4242d7769cfe14164 xkeyboard-config commit 73aa90ce32967747c84a1b5fe32cee329bc3bbcf pixman commit f078727f392bc9f235df916e75634ed87177b9b4 libxtrans commit 7cbad9fe2e61cd9d5caeaf361826a6f4bd320f03 fontconfig commit 1082161ea303cf2bbc13b62a191662984131e820 mesa commit 4f7916ab4f8093fa33519dfa3d08e73b4d35ebe3 --- xorg-server/hw/xwin/InitInput.c | 1 - xorg-server/hw/xwin/InitOutput.c | 38 -- xorg-server/hw/xwin/Makefile.am | 15 +- xorg-server/hw/xwin/win.h | 2 +- xorg-server/hw/xwin/winclipboard.h | 126 ---- xorg-server/hw/xwin/winclipboard/Makefile.am | 25 + xorg-server/hw/xwin/winclipboard/debug.c | 52 ++ xorg-server/hw/xwin/winclipboard/internal.h | 109 +++ xorg-server/hw/xwin/winclipboard/textconv.c | 151 +++++ xorg-server/hw/xwin/winclipboard/thread.c | 498 ++++++++++++++ xorg-server/hw/xwin/winclipboard/winclipboard.h | 36 + xorg-server/hw/xwin/winclipboard/wndproc.c | 531 +++++++++++++++ xorg-server/hw/xwin/winclipboard/xevents.c | 862 ++++++++++++++++++++++++ xorg-server/hw/xwin/winclipboard/xwinclip.c | 127 ++++ xorg-server/hw/xwin/winclipboard/xwinclip.man | 61 ++ xorg-server/hw/xwin/winclipboardinit.c | 150 +++-- xorg-server/hw/xwin/winclipboardtextconv.c | 147 ---- xorg-server/hw/xwin/winclipboardthread.c | 468 ------------- xorg-server/hw/xwin/winclipboardwndproc.c | 529 --------------- xorg-server/hw/xwin/winclipboardwrappers.c | 226 +------ xorg-server/hw/xwin/winclipboardxevents.c | 703 ------------------- xorg-server/hw/xwin/windialogs.c | 7 - xorg-server/hw/xwin/winglobals.c | 13 - xorg-server/hw/xwin/winglobals.h | 4 +- xorg-server/hw/xwin/winwndproc.c | 3 + 25 files changed, 2546 insertions(+), 2338 deletions(-) delete mode 100644 xorg-server/hw/xwin/winclipboard.h create mode 100644 xorg-server/hw/xwin/winclipboard/Makefile.am create mode 100644 xorg-server/hw/xwin/winclipboard/debug.c create mode 100644 xorg-server/hw/xwin/winclipboard/internal.h create mode 100644 xorg-server/hw/xwin/winclipboard/textconv.c create mode 100644 xorg-server/hw/xwin/winclipboard/thread.c create mode 100644 xorg-server/hw/xwin/winclipboard/winclipboard.h create mode 100644 xorg-server/hw/xwin/winclipboard/wndproc.c create mode 100644 xorg-server/hw/xwin/winclipboard/xevents.c create mode 100644 xorg-server/hw/xwin/winclipboard/xwinclip.c create mode 100644 xorg-server/hw/xwin/winclipboard/xwinclip.man delete mode 100644 xorg-server/hw/xwin/winclipboardtextconv.c delete mode 100644 xorg-server/hw/xwin/winclipboardthread.c delete mode 100644 xorg-server/hw/xwin/winclipboardwndproc.c delete mode 100644 xorg-server/hw/xwin/winclipboardxevents.c (limited to 'xorg-server/hw/xwin') diff --git a/xorg-server/hw/xwin/InitInput.c b/xorg-server/hw/xwin/InitInput.c index 38203c906..3e9ee41e6 100644 --- a/xorg-server/hw/xwin/InitInput.c +++ b/xorg-server/hw/xwin/InitInput.c @@ -39,7 +39,6 @@ #ifdef XWIN_CLIPBOARD int winProcEstablishConnection(ClientPtr /* client */ ); -int winProcSetSelectionOwner(ClientPtr /* client */ ); #endif /* diff --git a/xorg-server/hw/xwin/InitOutput.c b/xorg-server/hw/xwin/InitOutput.c index 6b5c38d92..88bc85a44 100644 --- a/xorg-server/hw/xwin/InitOutput.c +++ b/xorg-server/hw/xwin/InitOutput.c @@ -66,24 +66,11 @@ typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner, /* * References to external symbols */ -#ifdef XWIN_CLIPBOARD -extern Bool g_fUnicodeClipboard; -extern Bool g_fClipboardLaunched; -extern Bool g_fClipboardStarted; -extern pthread_t g_ptClipboardProc; -extern HWND g_hwndClipboard; -extern Bool g_fClipboard; -#endif /* * Function prototypes */ -#ifdef XWIN_CLIPBOARD -static void - winClipboardShutdown(void); -#endif - static Bool winCheckDisplayNumber(void); @@ -125,31 +112,6 @@ static PixmapFormatRec g_PixmapFormats[] = { const int NUMFORMATS = sizeof(g_PixmapFormats) / sizeof(g_PixmapFormats[0]); -#ifdef XWIN_CLIPBOARD -static void -winClipboardShutdown(void) -{ - /* Close down clipboard resources */ - if (g_fClipboard && g_fClipboardLaunched && g_fClipboardStarted) { - /* Synchronously destroy the clipboard window */ - if (g_hwndClipboard != NULL) { - SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0); - /* NOTE: g_hwndClipboard is set to NULL in winclipboardthread.c */ - } - else - return; - - /* Wait for the clipboard thread to exit */ - pthread_join(g_ptClipboardProc, NULL); - - g_fClipboardLaunched = FALSE; - g_fClipboardStarted = FALSE; - - winDebug("winClipboardShutdown - Clipboard thread has exited.\n"); - } -} -#endif - static const ExtensionModule xwinExtensions[] = { #ifdef GLXEXT { GlxExtensionInit, "GLX", &noGlxExtension }, diff --git a/xorg-server/hw/xwin/Makefile.am b/xorg-server/hw/xwin/Makefile.am index 326ffa03d..2c7fde313 100644 --- a/xorg-server/hw/xwin/Makefile.am +++ b/xorg-server/hw/xwin/Makefile.am @@ -3,12 +3,9 @@ bin_PROGRAMS = XWin if XWIN_CLIPBOARD SRCS_CLIPBOARD = \ winclipboardinit.c \ - winclipboardtextconv.c \ - winclipboardthread.c \ - winclipboardwndproc.c \ - winclipboardwrappers.c \ - winclipboardxevents.c + winclipboardwrappers.c DEFS_CLIPBOARD = -DXWIN_CLIPBOARD +CLIPBOARD_LIBS = $(top_builddir)/hw/xwin/winclipboard/libXWinclipboard.la endif if XWIN_GLX_WINDOWS @@ -110,7 +107,6 @@ SRCS = InitInput.c \ winwindow.c \ winwndproc.c \ ddraw.h \ - winclipboard.h \ winconfig.h \ win.h \ winglobals.h \ @@ -162,12 +158,15 @@ XWin_DEPENDENCIES = \ $(MULTIWINDOWEXTWM_LIBS) \ $(XWIN_GLX_LIBS) \ $(XWIN_LIBS) \ + $(CLIPBOARD_LIBS) \ $(XSERVER_LIBS) + XWin_LDADD = \ $(MULTIWINDOWEXTWM_LIBS) \ $(XWIN_GLX_LIBS) \ $(XWIN_LIBS) \ + $(CLIPBOARD_LIBS) \ $(XSERVER_LIBS) \ $(XWIN_GLX_SYS_LIBS) \ $(XSERVER_SYS_LIBS) \ @@ -210,5 +209,5 @@ EXTRA_DIST = \ relink: $(AM_V_at)rm -f XWin$(EXEEXT) && $(MAKE) XWin$(EXEEXT) -SUBDIRS = man $(GLX_DIR) . -DIST_SUBDIRS = man glx . +SUBDIRS = man $(GLX_DIR) winclipboard . +DIST_SUBDIRS = man glx winclipboard . diff --git a/xorg-server/hw/xwin/win.h b/xorg-server/hw/xwin/win.h index a738a5940..7af35e71b 100644 --- a/xorg-server/hw/xwin/win.h +++ b/xorg-server/hw/xwin/win.h @@ -793,7 +793,7 @@ Bool winInitClipboard(void); void - winFixClipboardChain(void); + winClipboardShutdown(void); #endif /* diff --git a/xorg-server/hw/xwin/winclipboard.h b/xorg-server/hw/xwin/winclipboard.h deleted file mode 100644 index cb7769510..000000000 --- a/xorg-server/hw/xwin/winclipboard.h +++ /dev/null @@ -1,126 +0,0 @@ -#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 -#include -#include -#include -#ifdef __CYGWIN__ -#include -#else -#include -#endif -#include -#include -#include - -/* X headers */ -#include -#include -#include -#include -#include - -/* Windows headers */ -#include - -/* Clipboard module constants */ -#define WIN_CLIPBOARD_WINDOW_CLASS "xwinclip" -#define WIN_CLIPBOARD_WINDOW_TITLE "xwinclip" -#ifdef HAS_DEVWINDOWS -#define WIN_MSG_QUEUE_FNAME "/dev/windows" -#endif -#define WIN_CONNECT_RETRIES 40 -#define WIN_CONNECT_DELAY 4 -#define WIN_JMP_OKAY 0 -#define WIN_JMP_ERROR_IO 2 -#define WIN_LOCAL_PROPERTY "CYGX_CUT_BUFFER" -#define WIN_XEVENTS_SUCCESS 0 -#define WIN_XEVENTS_CONVERT 2 -#define WIN_XEVENTS_NOTIFY 3 -#define WIN_CLIPBOARD_RETRIES 40 -#define WIN_CLIPBOARD_DELAY 1 - -#define WM_WM_REINIT (WM_USER + 1) - -/* - * 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); - -/* - * 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); -#endif 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 +#include + +#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 100644 index 000000000..94956f80d --- /dev/null +++ b/xorg-server/hw/xwin/winclipboard/internal.h @@ -0,0 +1,109 @@ + +/* + *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 + */ + +#ifndef WINCLIPBOARD_INTERNAL_H +#define WINCLIPBOARD_INTERNAL_H + +/* X headers */ +#include + +/* Windows headers */ +#include + +#define WIN_XEVENTS_SUCCESS 0 +#define WIN_XEVENTS_CONVERT 2 +#define WIN_XEVENTS_NOTIFY 3 + +#define WM_WM_REINIT (WM_USER + 1) + +/* + * References to external symbols + */ + +extern void winDebug(const char *format, ...); +extern void ErrorF(const char *format, ...); + +/* + * winclipboardtextconv.c + */ + +void + winClipboardDOStoUNIX(char *pszData, int iLength); + +void + winClipboardUNIXtoDOS(char **ppszData, int iLength); + +/* + * winclipboardthread.c + */ + + +typedef struct +{ + Atom atomClipboard; + Atom atomLocalProperty; + Atom atomUTF8String; + Atom atomCompoundText; + Atom atomTargets; +} ClipboardAtoms; + +/* + * winclipboardwndproc.c + */ + +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, + Window iWindow, Display * pDisplay, Bool fUnicodeSupport, ClipboardAtoms *atom); + + +Atom +winClipboardGetLastOwnedSelectionAtom(ClipboardAtoms *atoms); + +void +winClipboardInitMonitoredSelections(void); + +#endif 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 +#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 +#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 100644 index 000000000..c179e3f83 --- /dev/null +++ b/xorg-server/hw/xwin/winclipboard/thread.c @@ -0,0 +1,498 @@ +/* + *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 +#else +#define HAS_WINSOCK 1 +#endif + +/* + * Including any server header might define the macro _XSERVER64 on 64 bit machines. + * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen. + * So let's undef that macro if necessary. + */ +#ifdef _XSERVER64 +#undef _XSERVER64 +#endif + +#include +#include +#include +#include +#include +#include // for MAX() macro + +#ifdef HAS_WINSOCK +#include +#else +#include +#endif + +#include +#include +#include "winclipboard.h" +#include "internal.h" + +#define WIN_CONNECT_RETRIES 40 +#define WIN_CONNECT_DELAY 4 + +#define WIN_CLIPBOARD_WINDOW_CLASS "xwinclip" +#define WIN_CLIPBOARD_WINDOW_TITLE "xwinclip" +#ifdef HAS_DEVWINDOWS +#define WIN_MSG_QUEUE_FNAME "/dev/windows" +#endif + +/* + * Global variables + */ + +static HWND g_hwndClipboard = NULL; +static jmp_buf g_jmpEntry; +static XIOErrorHandler g_winClipboardOldIOErrorHandler; +static pthread_t g_winClipboardProcThread; + +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); + +/* + * Create X11 and Win32 messaging windows, and run message processing loop + * + * returns TRUE if shutdown was signalled to loop, FALSE if some error occurred + */ + +Bool +winClipboardProc(Bool fUseUnicode, char *szDisplay) +{ + ClipboardAtoms atoms; + 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 iSelectError; + Bool fShutdown = FALSE; + static Bool fErrorHandlerSet = FALSE; + + winDebug("winClipboardProc - Hello\n"); + + /* Allow multiple threads to access Xlib */ + if (XInitThreads() == 0) { + ErrorF("winClipboardProc - XInitThreads failed.\n"); + goto winClipboardProc_Exit; + } + + /* See if X supports the current locale */ + if (XSupportsLocale() == False) { + ErrorF("winClipboardProc - Warning: Locale not supported by X.\n"); + } + + g_winClipboardProcThread = pthread_self(); + + /* Set error handler */ + if (!fErrorHandlerSet) { + XSetErrorHandler(winClipboardErrorHandler); + g_winClipboardOldIOErrorHandler = + XSetIOErrorHandler(winClipboardIOErrorHandler); + fErrorHandlerSet = TRUE; + } + + /* Set jump point for Error exits */ + if (setjmp(g_jmpEntry)) { + ErrorF("winClipboardProc - setjmp returned for IO Error Handler.\n"); + goto winClipboardProc_Done; + } + + /* Make sure that the display opened */ + pDisplay = XOpenDisplay(szDisplay); + if (pDisplay == NULL) { + ErrorF("winClipboardProc - Failed opening the display, giving up\n"); + goto winClipboardProc_Done; + } + + ErrorF("winClipboardProc - XOpenDisplay () returned and " + "successfully opened the display.\n"); + + /* Get our connection number */ + iConnectionNumber = ConnectionNumber(pDisplay); + +#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 winClipboardProc_Done; + } + + /* Find max of our file descriptors */ + 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 */ + 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, + 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 winClipboardProc_Done; + } + + XStoreName(pDisplay, iWindow, "xwinclip"); + + /* Select event types to watch */ + if (XSelectInput(pDisplay, iWindow, PropertyChangeMask) == BadWindow) + ErrorF("winClipboardProc - XSelectInput generated BadWindow " + "on messaging window\n"); + + XFixesSelectSelectionInput (pDisplay, + iWindow, + XA_PRIMARY, + XFixesSetSelectionOwnerNotifyMask | + XFixesSelectionWindowDestroyNotifyMask | + XFixesSelectionClientCloseNotifyMask); + + XFixesSelectSelectionInput (pDisplay, + iWindow, + atoms.atomClipboard, + XFixesSetSelectionOwnerNotifyMask | + XFixesSelectionWindowDestroyNotifyMask | + XFixesSelectionClientCloseNotifyMask); + + + /* Initialize monitored selection state */ + winClipboardInitMonitoredSelections(); + /* Create Windows messaging window */ + hwnd = winClipboardCreateMessagingWindow(pDisplay, iWindow, &atoms); + + /* Save copy of HWND */ + g_hwndClipboard = hwnd; + + /* Assert ownership of selections if Win32 clipboard is owned */ + if (NULL != GetClipboardOwner()) { + /* PRIMARY */ + 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 winClipboardProc_Done; + } + + /* CLIPBOARD */ + iReturn = XSetSelectionOwner(pDisplay, atoms.atomClipboard, + iWindow, CurrentTime); + if (iReturn == BadAtom || iReturn == BadWindow || + 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, &atoms); + + /* Pre-flush Windows messages */ + if (!winClipboardFlushWindowsMessageQueue(hwnd)) { + ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue failed\n"); + } + + /* 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)) { + /* Process X events */ + winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms); + } + +#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; + } + } + } + + winClipboardProc_Exit: + /* broke out of while loop on a shutdown message */ + fShutdown = TRUE; + + winClipboardProc_Done: + /* Close our Windows window */ + if (g_hwndClipboard) { + winClipboardWindowDestroy(); + } + + /* Close our X window */ + if (pDisplay && iWindow) { + iReturn = XDestroyWindow(pDisplay, iWindow); + if (iReturn == BadWindow) + ErrorF("winClipboardProc - XDestroyWindow returned BadWindow.\n"); + else + ErrorF("winClipboardProc - XDestroyWindow succeeded.\n"); + } + +#ifdef HAS_DEVWINDOWS + /* Close our Win32 message handle */ + if (fdMessageQueue) + close(fdMessageQueue); +#endif + +#if 0 + /* + * 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 */ + XSync(pDisplay, TRUE); + + /* Select event types to watch */ + XSelectInput(pDisplay, DefaultRootWindow(pDisplay), None); + + /* Close our X display */ + if (pDisplay) { + XCloseDisplay(pDisplay); + } +#endif + + /* global clipboard variable reset */ + g_hwndClipboard = NULL; + + return fShutdown; +} + +/* + * Create the Windows window that we use to receive Windows messages + */ + +static HWND +winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms) +{ + WNDCLASSEX wc; + ClipboardWindowCreationParams cwcp; + HWND hwnd; + + /* Setup our window class */ + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = winClipboardWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetModuleHandle(NULL); + wc.hIcon = 0; + wc.hCursor = 0; + wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = WIN_CLIPBOARD_WINDOW_CLASS; + wc.hIconSm = 0; + RegisterClassEx(&wc); + + /* Information to be passed to WM_CREATE */ + cwcp.pClipboardDisplay = pDisplay; + cwcp.iClipboardWindow = iWindow; + cwcp.atoms = atoms; + + /* Create the window */ + hwnd = CreateWindowExA(0, /* Extended styles */ + WIN_CLIPBOARD_WINDOW_CLASS, /* Class name */ + WIN_CLIPBOARD_WINDOW_TITLE, /* Window name */ + WS_OVERLAPPED, /* Not visible anyway */ + CW_USEDEFAULT, /* Horizontal position */ + CW_USEDEFAULT, /* Vertical position */ + CW_USEDEFAULT, /* Right edge */ + CW_USEDEFAULT, /* Bottom edge */ + (HWND) NULL, /* No parent or owner window */ + (HMENU) NULL, /* No menu */ + GetModuleHandle(NULL), /* Instance handle */ + &cwcp); /* Creation data */ + assert(hwnd != NULL); + + /* I'm not sure, but we may need to call this to start message processing */ + ShowWindow(hwnd, SW_HIDE); + + /* Similarly, we may need a call to this even though we don't paint */ + UpdateWindow(hwnd); + + return hwnd; +} + +/* + * 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" + "\tSerial: %lu, Request Code: %d, Minor Code: %d\n", + pszErrorMsg, pErr->serial, 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, 2); + } + + if (g_winClipboardOldIOErrorHandler) + g_winClipboardOldIOErrorHandler(pDisplay); + + return 0; +} + +void +winClipboardWindowDestroy(void) +{ + if (g_hwndClipboard) { + SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0); + } +} + +void +winFixClipboardChain(void) +{ + if (g_hwndClipboard) { + PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0); + } +} diff --git a/xorg-server/hw/xwin/winclipboard/winclipboard.h b/xorg-server/hw/xwin/winclipboard/winclipboard.h new file mode 100644 index 000000000..52481301b --- /dev/null +++ b/xorg-server/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/xorg-server/hw/xwin/winclipboard/wndproc.c b/xorg-server/hw/xwin/winclipboard/wndproc.c new file mode 100644 index 000000000..165ff558a --- /dev/null +++ b/xorg-server/hw/xwin/winclipboard/wndproc.c @@ -0,0 +1,531 @@ +/* + *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 +#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 +#include + +#include + +#include "internal.h" +#include "winclipboard.h" + +/* + * Constants + */ + +#define WIN_POLL_TIMEOUT 1 + + +/* + * Process X events up to specified timeout + */ + +static int +winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay, + Bool fUseUnicode, ClipboardAtoms *atoms, int iTimeoutSec) +{ + int iConnNumber; + struct timeval tv; + int iReturn; + DWORD dwStopTime = GetTickCount() + iTimeoutSec * 1000; + + winDebug("winProcessXEventsTimeout () - pumping X events for %d seconds\n", + iTimeoutSec); + + /* Get our connection number */ + iConnNumber = ConnectionNumber(pDisplay); + + /* Loop for X events */ + while (1) { + fd_set fdsRead; + long remainingTime; + + /* We need to ensure that all pending events are processed */ + XSync(pDisplay, FALSE); + + /* 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. " + "Bailing.\n", iReturn); + 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, atoms); + + 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; + static Bool s_fCBCInitialized; + static Display *pDisplay; + static Window iWindow; + static ClipboardAtoms *atoms; + + /* 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; + + PostQuitMessage(0); + } + return 0; + + case WM_CREATE: + { + HWND first, next; + DWORD error_code = 0; + ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams; + + winDebug("winClipboardWindowProc - WM_CREATE\n"); + + pDisplay = cwcp->pClipboardDisplay; + iWindow = cwcp->iClipboardWindow; + atoms = cwcp->atoms; + + first = GetClipboardViewer(); /* Get handle to first viewer in chain. */ + if (first == hwnd) + return 0; /* Make sure it's not us! */ + /* Add ourselves to the clipboard viewer chain */ + next = SetClipboardViewer(hwnd); + error_code = GetLastError(); + if (SUCCEEDED(error_code) && (next == first)) /* SetClipboardViewer must have succeeded, and the handle */ + s_hwndNextViewer = next; /* it returned must have been the first window in the chain */ + else + s_fCBCInitialized = FALSE; + } + 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) { + s_hwndNextViewer = NULL; + ErrorF("winClipboardWindowProc - WM_CHANGECBCHAIN: " + "attempted to set next window to ourselves."); + } + } + 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; + + winDebug("winClipboardWindowProc - WM_WM_REINIT: Enter\n"); + + first = GetClipboardViewer(); /* Get handle to first viewer in chain. */ + if (first == hwnd) + return 0; /* Make sure it's not us! */ + winDebug(" WM_WM_REINIT: Replacing us(%x) with %x at head " + "of chain\n", hwnd, s_hwndNextViewer); + s_fCBCInitialized = FALSE; + ChangeClipboardChain(hwnd, s_hwndNextViewer); + s_hwndNextViewer = NULL; + s_fCBCInitialized = FALSE; + winDebug(" WM_WM_REINIT: Putting us back at head of chain.\n"); + first = GetClipboardViewer(); /* Get handle to first viewer in chain. */ + if (first == hwnd) + return 0; /* Make sure it's not us! */ + next = SetClipboardViewer(hwnd); + error_code = GetLastError(); + if (SUCCEEDED(error_code) && (next == first)) /* SetClipboardViewer must have succeeded, and the handle */ + s_hwndNextViewer = next; /* it returned must have been the first window in the chain */ + else + s_fCBCInitialized = FALSE; + } + winDebug("winClipboardWindowProc - WM_WM_REINIT: Exit\n"); + return 0; + + case WM_DRAWCLIPBOARD: + { + static Bool s_fProcessingDrawClipboard = FALSE; + int iReturn; + + winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n"); + + /* + * 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 */ + s_fCBCInitialized = FALSE; + ChangeClipboardChain(hwnd, s_hwndNextViewer); + winFixClipboardChain(); + ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - " + "Nested calls detected. Re-initing.\n"); + winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n"); + s_fProcessingDrawClipboard = FALSE; + return 0; + } + + /* Bail on first message */ + if (!s_fCBCInitialized) { + s_fCBCInitialized = TRUE; + s_fProcessingDrawClipboard = FALSE; + winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n"); + return 0; + } + + /* + * NOTE: We cannot bail out when NULL == GetClipboardOwner () + * because some applications deal with the clipboard in a manner + * that causes the clipboard owner to be NULL when they are in + * fact taking ownership. One example of this is the Win32 + * native compile of emacs. + */ + + /* Bail when we still own the clipboard */ + if (hwnd == GetClipboardOwner()) { + + winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - " + "We own the clipboard, returning.\n"); + winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n"); + s_fProcessingDrawClipboard = FALSE; + if (s_hwndNextViewer) + SendMessage(s_hwndNextViewer, message, wParam, lParam); + 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); + + winDebug("winClipboardWindowProc - XSync done.\n"); + + /* Release PRIMARY selection if owned */ + iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY); + if (iReturn == iWindow) { + winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - " + "PRIMARY selection is owned by us.\n"); + XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime); + } + else if (BadWindow == iReturn || BadAtom == iReturn) + ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - " + "XGetSelectionOwner failed for PRIMARY: %d\n", + iReturn); + + /* Release CLIPBOARD selection if owned */ + iReturn = XGetSelectionOwner(pDisplay, atoms->atomClipboard); + if (iReturn == iWindow) { + winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - " + "CLIPBOARD selection is owned by us, releasing\n"); + XSetSelectionOwner(pDisplay, atoms->atomClipboard, None, CurrentTime); + } + else if (BadWindow == iReturn || BadAtom == iReturn) + ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - " + "XGetSelectionOwner 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; + } + + /* 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, + atoms->atomClipboard, iWindow, CurrentTime); + + if (iReturn == BadAtom || iReturn == BadWindow || + XGetSelectionOwner(pDisplay, atoms->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; + 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, + winClipboardGetLastOwnedSelectionAtom(atoms), + atoms->atomCompoundText, + atoms->atomLocalProperty, + 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 */ + + /* Close clipboard if we have it open already */ + if (GetOpenClipboardWindow() == hwnd) { + CloseClipboard(); + } + + 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()); + break; + } + } + + /* Process the SelectionNotify event */ + iReturn = winProcessXEventsTimeout(hwnd, + iWindow, + pDisplay, + fConvertToUnicode, + atoms, + WIN_POLL_TIMEOUT); + + /* + * The last call to winProcessXEventsTimeout + * from above had better have seen a notify event, or else we + * are dealing with a buggy or old X11 app. In these cases we + * have to paste some fake data to the Win32 clipboard to + * satisfy the requirement that we write something to it. + */ + if (WIN_XEVENTS_NOTIFY != 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 100644 index 000000000..d0077b846 --- /dev/null +++ b/xorg-server/hw/xwin/winclipboard/xevents.c @@ -0,0 +1,862 @@ +/* + *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 +#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 "internal.h" +#include +#include +#include + +/* + * 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 + */ + +int +winClipboardFlushXEvents(HWND hwnd, + Window iWindow, Display * pDisplay, Bool fUseUnicode, ClipboardAtoms *atoms) +{ + 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)) { + 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; + Bool fAbort = FALSE; + Bool fCloseClipboard = FALSE; + Bool fSetClipboardData = TRUE; + + /* Get the next event - will not block because one is ready */ + XNextEvent(pDisplay, &event); + + /* Branch on the event type */ + switch (event.type) { + /* + * SelectionRequest + */ + + case SelectionRequest: + { + 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; + } + + /* 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; + } + + /* Close clipboard if we have it open already */ + if (GetOpenClipboardWindow() == hwnd) { + CloseClipboard(); + } + + /* Access the clipboard */ + 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) { + 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; + 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: + + winDebug("winClipboardFlushXEvents - SelectionNotify\n"); + { + char *pszAtomName; + + pszAtomName = XGetAtomName(pDisplay, + event.xselection.selection); + + winDebug + ("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n", + pszAtomName); + XFree(pszAtomName); + } + + /* + * 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; + } + + { + 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; + } + + 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) { + int i; + + iReturnDataLen = 0; + for (i = 0; i < iCount; i++) { + iReturnDataLen += strlen(ppszTextList[i]); + } + pszReturnData = 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 = 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 = 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(&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; + + case SelectionClear: + winDebug("SelectionClear - doing nothing\n"); + break; + + case PropertyNotify: + break; + + case MappingNotify: + break; + + default: + 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; + } + } + + 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 +#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 +#include +#include + +/* X headers */ +#include +#ifdef X_LOCALE +#include +#else /* X_LOCALE */ +#include +#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. diff --git a/xorg-server/hw/xwin/winclipboardinit.c b/xorg-server/hw/xwin/winclipboardinit.c index 157006dab..8aef8fe02 100644 --- a/xorg-server/hw/xwin/winclipboardinit.c +++ b/xorg-server/hw/xwin/winclipboardinit.c @@ -31,25 +31,79 @@ #ifdef HAVE_XWIN_CONFIG_H #include #endif -#include "dixstruct.h" -#include "winclipboard.h" + +#include +#include + +#include "win.h" +#include "winclipboard/winclipboard.h" +#include "windisplay.h" + +#define WIN_CLIPBOARD_RETRIES 40 +#define WIN_CLIPBOARD_DELAY 1 /* - * Local typedefs + * Local variables */ -typedef int (*winDispatchProcPtr) (ClientPtr); - -int winProcSetSelectionOwner(ClientPtr /* client */ ); +static pthread_t g_ptClipboardProc; /* - * References to external symbols + * */ +static void * +winClipboardThreadProc(void *arg) +{ + char szDisplay[512]; + int clipboardRestarts = 0; + + while (1) + { + Bool fShutdown; + + ++clipboardRestarts; -extern pthread_t g_ptClipboardProc; -extern winDispatchProcPtr winProcSetSelectionOwnerOrig; -extern Bool g_fClipboard; -extern HWND g_hwndClipboard; + /* Use our generated cookie for authentication */ + winSetAuthorization(); + + /* Setup the display connection string */ + /* + * NOTE: Always connect to screen 0 since we require that screen + * numbers start at 0 and increase without gaps. We only need + * to connect to one screen on the display to get events + * for all screens on the display. That is why there is only + * one clipboard client thread. + */ + winGetDisplayName(szDisplay, 0); + + /* Print the display connection string */ + ErrorF("winClipboardThreadProc - DISPLAY=%s\n", szDisplay); + + /* Flag that clipboard client has been launched */ + g_fClipboardStarted = TRUE; + + fShutdown = winClipboardProc(g_fUnicodeClipboard, szDisplay); + + /* Flag that clipboard client has stopped */ + g_fClipboardStarted = FALSE; + + if (fShutdown) + break; + + /* checking if we need to restart */ + if (clipboardRestarts >= WIN_CLIPBOARD_RETRIES) { + /* terminates clipboard thread but the main server still lives */ + ErrorF("winClipboardProc - the clipboard thread has restarted %d times and seems to be unstable, disabling clipboard integration\n", clipboardRestarts); + g_fClipboard = FALSE; + break; + } + + sleep(WIN_CLIPBOARD_DELAY); + ErrorF("winClipboardProc - trying to restart clipboard thread \n"); + } + + return NULL; +} /* * Intialize the Clipboard module @@ -60,14 +114,8 @@ winInitClipboard(void) { winDebug("winInitClipboard ()\n"); - /* Wrap some internal server functions */ - if (ProcVector[X_SetSelectionOwner] != winProcSetSelectionOwner) { - winProcSetSelectionOwnerOrig = ProcVector[X_SetSelectionOwner]; - ProcVector[X_SetSelectionOwner] = winProcSetSelectionOwner; - } - /* Spawn a thread for the Clipboard module */ - if (pthread_create(&g_ptClipboardProc, NULL, winClipboardProc, NULL)) { + if (pthread_create(&g_ptClipboardProc, NULL, winClipboardThreadProc, NULL)) { /* Bail if thread creation failed */ ErrorF("winInitClipboard - pthread_create failed.\n"); return FALSE; @@ -76,59 +124,19 @@ winInitClipboard(void) return TRUE; } -/* - * Create the Windows window that we use to receive Windows messages - */ - -HWND -winClipboardCreateMessagingWindow(void) -{ - WNDCLASSEX wc; - HWND hwnd; - - /* Setup our window class */ - wc.cbSize = sizeof(WNDCLASSEX); - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = winClipboardWindowProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = GetModuleHandle(NULL); - wc.hIcon = 0; - wc.hCursor = 0; - wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); - wc.lpszMenuName = NULL; - wc.lpszClassName = WIN_CLIPBOARD_WINDOW_CLASS; - wc.hIconSm = 0; - RegisterClassEx(&wc); - - /* Create the window */ - hwnd = CreateWindowExA(0, /* Extended styles */ - WIN_CLIPBOARD_WINDOW_CLASS, /* Class name */ - WIN_CLIPBOARD_WINDOW_TITLE, /* Window name */ - WS_OVERLAPPED, /* Not visible anyway */ - CW_USEDEFAULT, /* Horizontal position */ - CW_USEDEFAULT, /* Vertical position */ - CW_USEDEFAULT, /* Right edge */ - CW_USEDEFAULT, /* Bottom edge */ - (HWND) NULL, /* No parent or owner window */ - (HMENU) NULL, /* No menu */ - GetModuleHandle(NULL), /* Instance handle */ - NULL); /* Creation data */ - assert(hwnd != NULL); - - /* I'm not sure, but we may need to call this to start message processing */ - ShowWindow(hwnd, SW_HIDE); - - /* Similarly, we may need a call to this even though we don't paint */ - UpdateWindow(hwnd); - - return hwnd; -} - void -winFixClipboardChain(void) +winClipboardShutdown(void) { - if (g_fClipboard && g_hwndClipboard) { - PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0); - } + /* Close down clipboard resources */ + if (g_fClipboard && g_fClipboardStarted) { + /* Synchronously destroy the clipboard window */ + winClipboardWindowDestroy(); + + /* Wait for the clipboard thread to exit */ + pthread_join(g_ptClipboardProc, NULL); + + g_fClipboardStarted = FALSE; + + winDebug("winClipboardShutdown - Clipboard thread has exited.\n"); + } } diff --git a/xorg-server/hw/xwin/winclipboardtextconv.c b/xorg-server/hw/xwin/winclipboardtextconv.c deleted file mode 100644 index fd405a02e..000000000 --- a/xorg-server/hw/xwin/winclipboardtextconv.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - *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 -#endif -#include "win.h" -#include -#include - -void - winClipboardDOStoUNIX(char *pszSrc, int iLength); -void - winClipboardUNIXtoDOS(char **ppszData, int iLength); - -/* - * 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/winclipboardthread.c b/xorg-server/hw/xwin/winclipboardthread.c deleted file mode 100644 index e70896081..000000000 --- a/xorg-server/hw/xwin/winclipboardthread.c +++ /dev/null @@ -1,468 +0,0 @@ -/* - *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 -#else -#define HAS_WINSOCK 1 -#endif -#include -#include -#include "winclipboard.h" -#include "windisplay.h" -#ifdef __CYGWIN__ -#include -#endif -#include "misc.h" - -/* - * References to external symbols - */ - -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; - -/* - * Global variables - */ - -static jmp_buf g_jmpEntry; -static int clipboardRestarts = 0; -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); - -/* - * 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; - - winDebug("winClipboardProc - Hello\n"); - ++clipboardRestarts; - - /* Do we use Unicode clipboard? */ - fUseUnicode = g_fUnicodeClipboard; - - /* Save the Unicode support flag in a global */ - g_fUseUnicode = fUseUnicode; - - /* Allow multiple threads to access Xlib */ - if (XInitThreads() == 0) { - ErrorF("winClipboardProc - XInitThreads failed.\n"); - goto winClipboardProc_Exit; - } - - /* See if X supports the current locale */ - if (XSupportsLocale() == False) { - ErrorF("winClipboardProc - Warning: Locale not supported by X.\n"); - } - - /* Set error handler */ - XSetErrorHandler(winClipboardErrorHandler); - g_winClipboardProcThread = pthread_self(); - g_winClipboardOldIOErrorHandler = - XSetIOErrorHandler(winClipboardIOErrorHandler); - - /* Set jump point for Error exits */ - iReturn = setjmp(g_jmpEntry); - - /* Check if we should continue operations */ - if (iReturn != WIN_JMP_ERROR_IO && iReturn != WIN_JMP_OKAY) { - /* setjmp returned an unknown value, exit */ - ErrorF("winClipboardProc - setjmp returned: %d exiting\n", iReturn); - goto winClipboardProc_Exit; - } - else if (iReturn == WIN_JMP_ERROR_IO) { - /* TODO: Cleanup the Win32 window and free any allocated memory */ - ErrorF("winClipboardProc - setjmp returned for IO Error Handler.\n"); - pthread_exit(NULL); - } - - /* 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 */ - if (pDisplay == NULL) { - ErrorF("winClipboardProc - Failed opening the display, giving up\n"); - goto winClipboardProc_Done; - } - - /* Save the display in the screen privates */ - g_pClipboardDisplay = pDisplay; - - ErrorF("winClipboardProc - XOpenDisplay () returned and " - "successfully opened the display.\n"); - - /* Get our connection number */ - iConnectionNumber = ConnectionNumber(pDisplay); - -#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 winClipboardProc_Done; - } - - /* Find max of our file descriptors */ - iMaxDescriptor = max(fdMessageQueue, iConnectionNumber) + 1; -#else - iMaxDescriptor = iConnectionNumber + 1; -#endif - - /* Create atom */ - atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", 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 winClipboardProc_Done; - } - - 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; - - /* Create Windows messaging window */ - hwnd = winClipboardCreateMessagingWindow(); - - /* Save copy of HWND in screen privates */ - g_hwndClipboard = hwnd; - - /* Assert ownership of selections if Win32 clipboard is owned */ - if (NULL != GetClipboardOwner()) { - /* PRIMARY */ - 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 winClipboardProc_Done; - } - - /* 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 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); - - /* Pre-flush Windows messages */ - if (!winClipboardFlushWindowsMessageQueue(hwnd)) - return 0; - - /* 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)) { - /* Process X events */ - winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode); - } - -#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; - } - } - } - - winClipboardProc_Exit: - /* disable the clipboard, which means the thread will die */ - g_fClipboard = FALSE; - - 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); - } - - /* Close our X window */ - if (pDisplay && iWindow) { - iReturn = XDestroyWindow(pDisplay, iWindow); - if (iReturn == BadWindow) - ErrorF("winClipboardProc - XDestroyWindow returned BadWindow.\n"); - else - ErrorF("winClipboardProc - XDestroyWindow succeeded.\n"); - } - -#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 - - /* 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; - } - - 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); - } - - 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" - "\tSerial: %lu, Request Code: %d, Minor Code: %d\n", - pszErrorMsg, pErr->serial, 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; -} diff --git a/xorg-server/hw/xwin/winclipboardwndproc.c b/xorg-server/hw/xwin/winclipboardwndproc.c deleted file mode 100644 index 90dc9e0bb..000000000 --- a/xorg-server/hw/xwin/winclipboardwndproc.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - *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 -#endif -#include -#include -#include "winclipboard.h" -#include "misc.h" - -/* - * Constants - */ - -#define WIN_POLL_TIMEOUT 1 - -/* - * References to external symbols - */ - -extern void *g_pClipboardDisplay; -extern Window g_iClipboardWindow; -extern Atom g_atomLastOwnedSelection; - -/* - * Process X events up to specified timeout - */ - -static int -winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay, - Bool fUseUnicode, int iTimeoutSec) -{ - int iConnNumber; - struct timeval tv; - int iReturn; - DWORD dwStopTime = GetTickCount() + iTimeoutSec * 1000; - - winDebug("winProcessXEventsTimeout () - pumping X events for %d seconds\n", - iTimeoutSec); - - /* Get our connection number */ - iConnNumber = ConnectionNumber(pDisplay); - - /* Loop for X events */ - while (1) { - fd_set fdsRead; - long remainingTime; - - /* We need to ensure that all pending events are processed */ - XSync(pDisplay, FALSE); - - /* 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. " - "Bailing.\n", iReturn); - 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); - - 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; - static Bool s_fCBCInitialized; - - /* 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; - - PostQuitMessage(0); - } - return 0; - - case WM_CREATE: - { - HWND first, next; - DWORD error_code = 0; - - winDebug("winClipboardWindowProc - WM_CREATE\n"); - - first = GetClipboardViewer(); /* Get handle to first viewer in chain. */ - if (first == hwnd) - return 0; /* Make sure it's not us! */ - /* Add ourselves to the clipboard viewer chain */ - next = SetClipboardViewer(hwnd); - error_code = GetLastError(); - if (SUCCEEDED(error_code) && (next == first)) /* SetClipboardViewer must have succeeded, and the handle */ - s_hwndNextViewer = next; /* it returned must have been the first window in the chain */ - else - s_fCBCInitialized = FALSE; - } - 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) { - s_hwndNextViewer = NULL; - winErrorFVerb(1, "winClipboardWindowProc - WM_CHANGECBCHAIN: " - "attempted to set next window to ourselves."); - } - } - 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; - - winDebug("winClipboardWindowProc - WM_WM_REINIT: Enter\n"); - - first = GetClipboardViewer(); /* Get handle to first viewer in chain. */ - if (first == hwnd) - return 0; /* Make sure it's not us! */ - winDebug(" WM_WM_REINIT: Replacing us(%x) with %x at head " - "of chain\n", hwnd, s_hwndNextViewer); - s_fCBCInitialized = FALSE; - ChangeClipboardChain(hwnd, s_hwndNextViewer); - s_hwndNextViewer = NULL; - s_fCBCInitialized = FALSE; - winDebug(" WM_WM_REINIT: Putting us back at head of chain.\n"); - first = GetClipboardViewer(); /* Get handle to first viewer in chain. */ - if (first == hwnd) - return 0; /* Make sure it's not us! */ - next = SetClipboardViewer(hwnd); - error_code = GetLastError(); - if (SUCCEEDED(error_code) && (next == first)) /* SetClipboardViewer must have succeeded, and the handle */ - s_hwndNextViewer = next; /* it returned must have been the first window in the chain */ - else - s_fCBCInitialized = FALSE; - } - 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: 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. - */ - if (!s_fProcessingDrawClipboard) { - s_fProcessingDrawClipboard = TRUE; - } - else { - /* Attempt to break the nesting by getting out of the chain, twice?, and then fix and bail */ - s_fCBCInitialized = FALSE; - ChangeClipboardChain(hwnd, s_hwndNextViewer); - winFixClipboardChain(); - winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - " - "Nested calls detected. Re-initing.\n"); - winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n"); - s_fProcessingDrawClipboard = FALSE; - return 0; - } - - /* Bail on first message */ - if (!s_fCBCInitialized) { - s_fCBCInitialized = TRUE; - s_fProcessingDrawClipboard = FALSE; - winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n"); - return 0; - } - - /* - * NOTE: We cannot bail out when NULL == GetClipboardOwner () - * because some applications deal with the clipboard in a manner - * that causes the clipboard owner to be NULL when they are in - * fact taking ownership. One example of this is the Win32 - * native compile of emacs. - */ - - /* Bail when we still own the clipboard */ - if (hwnd == GetClipboardOwner()) { - - winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - " - "We own the clipboard, returning.\n"); - winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n"); - s_fProcessingDrawClipboard = FALSE; - if (s_hwndNextViewer) - SendMessage(s_hwndNextViewer, message, wParam, lParam); - 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); - - winDebug("winClipboardWindowProc - XSync done.\n"); - - /* 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) - winErrorFVerb(1, "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) - winErrorFVerb(1, "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; - } - - /* Reassert ownership of PRIMARY */ - iReturn = XSetSelectionOwner(pDisplay, - 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"); - } - 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) { - winErrorFVerb(1, "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, - "CYGX_CUT_BUFFER", False), - iWindow, CurrentTime); - if (iReturn == BadAtom || iReturn == BadWindow) { - winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMAT - " - "XConvertSelection () failed\n"); - break; - } - - /* Special handling for WM_RENDERALLFORMATS */ - if (message == WM_RENDERALLFORMATS) { - /* We must open and empty the clipboard */ - - /* Close clipboard if we have it open already */ - if (GetOpenClipboardWindow() == hwnd) { - CloseClipboard(); - } - - if (!OpenClipboard(hwnd)) { - winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - " - "OpenClipboard () failed: %08x\n", - GetLastError()); - break; - } - - if (!EmptyClipboard()) { - winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - " - "EmptyClipboard () failed: %08x\n", - GetLastError()); - 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) { - /* 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()) { - winErrorFVerb(1, - "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/winclipboardwrappers.c b/xorg-server/hw/xwin/winclipboardwrappers.c index bfd6bff8b..2679f4f98 100644 --- a/xorg-server/hw/xwin/winclipboardwrappers.c +++ b/xorg-server/hw/xwin/winclipboardwrappers.c @@ -33,36 +33,21 @@ #ifdef HAVE_XWIN_CONFIG_H #include #endif + #include "win.h" #include "dixstruct.h" -#include - -/* - * Constants - */ - -#define CLIP_NUM_SELECTIONS 2 -#define CLIP_OWN_PRIMARY 0 -#define CLIP_OWN_CLIPBOARD 1 /* * Local function prototypes */ DISPATCH_PROC(winProcEstablishConnection); -DISPATCH_PROC(winProcSetSelectionOwner); /* * References to external symbols */ -extern Bool g_fClipboardLaunched; -extern Bool g_fClipboardStarted; extern Bool g_fClipboard; -extern Window g_iClipboardWindow; -extern Atom g_atomLastOwnedSelection; -extern HWND g_hwndClipboard; - /* * Wrapper for internal EstablishConnection function. @@ -127,13 +112,6 @@ winProcEstablishConnection(ClientPtr client) /* Clear original function pointer */ winProcEstablishConnectionOrig = NULL; - /* If the clipboard client has already been started, abort */ - if (g_fClipboardLaunched) { - ErrorF("winProcEstablishConnection - Clipboard client already " - "launched, returning.\n"); - return iReturn; - } - /* Startup the clipboard client if clipboard mode is being used */ if (g_fClipboard) { /* @@ -163,207 +141,5 @@ winProcEstablishConnection(ClientPtr client) ErrorF("winProcEstablishConnection - winInitClipboard returned.\n"); } - /* Flag that clipboard client has been launched */ - g_fClipboardLaunched = TRUE; - return iReturn; } - -/* - * Wrapper for internal SetSelectionOwner function. - * Grabs ownership of Windows clipboard when X11 clipboard owner changes. - */ - -int -winProcSetSelectionOwner(ClientPtr client) -{ - int i; - DrawablePtr pDrawable; - WindowPtr pWindow = None; - Bool fOwnedToNotOwned = FALSE; - static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None }; - static unsigned long s_ulServerGeneration = 0; - - REQUEST(xSetSelectionOwnerReq); - - REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); - - winDebug("winProcSetSelectionOwner - Hello.\n"); - - /* Watch for server reset */ - if (s_ulServerGeneration != serverGeneration) { - /* Save new generation number */ - s_ulServerGeneration = serverGeneration; - - /* Initialize static variables */ - for (i = 0; i < CLIP_NUM_SELECTIONS; ++i) - s_iOwners[i] = None; - } - - /* Abort if clipboard not completely initialized yet */ - if (!g_fClipboardStarted) { - /* ErrorF ("winProcSetSelectionOwner - Clipboard not yet started, " - "aborting.\n"); */ - goto winProcSetSelectionOwner_Done; - } - - /* Grab window if we have one */ - if (None != stuff->window) { - /* Grab the Window from the request */ - int rc = - dixLookupWindow(&pWindow, stuff->window, client, DixReadAccess); - if (rc != Success) { - ErrorF("winProcSetSelectionOwner - Found BadWindow, aborting.\n"); - goto winProcSetSelectionOwner_Done; - } - } - - /* Now we either have a valid window or None */ - - /* Save selection owners for monitored selections, ignore other selections */ - if (XA_PRIMARY == stuff->selection) { - /* Look for owned -> not owned transition */ - if (None == stuff->window && None != s_iOwners[CLIP_OWN_PRIMARY]) { - fOwnedToNotOwned = TRUE; - - winDebug("winProcSetSelectionOwner - PRIMARY - Going from " - "owned to not owned.\n"); - - /* Adjust last owned selection */ - if (None != s_iOwners[CLIP_OWN_CLIPBOARD]) - g_atomLastOwnedSelection = MakeAtom("CLIPBOARD", 9, TRUE); - else - g_atomLastOwnedSelection = None; - } - - /* Save new selection owner or None */ - s_iOwners[CLIP_OWN_PRIMARY] = stuff->window; - - winDebug("winProcSetSelectionOwner - PRIMARY - Now owned by: %d\n", - stuff->window); - } - else if (MakeAtom("CLIPBOARD", 9, TRUE) == stuff->selection) { - /* Look for owned -> not owned transition */ - if (None == stuff->window && None != s_iOwners[CLIP_OWN_CLIPBOARD]) { - fOwnedToNotOwned = TRUE; - - winDebug("winProcSetSelectionOwner - CLIPBOARD - Going from " - "owned to not owned.\n"); - - /* Adjust last owned selection */ - if (None != s_iOwners[CLIP_OWN_PRIMARY]) - g_atomLastOwnedSelection = XA_PRIMARY; - else - g_atomLastOwnedSelection = None; - } - - /* Save new selection owner or None */ - s_iOwners[CLIP_OWN_CLIPBOARD] = stuff->window; - - winDebug("winProcSetSelectionOwner - CLIPBOARD - Now owned by: %d\n", - stuff->window); - - } - else - goto winProcSetSelectionOwner_Done; - - /* - * At this point, if one of the selections is still owned by the - * clipboard manager then it should be marked as unowned since - * we will be taking ownership of the Win32 clipboard. - */ - if (g_iClipboardWindow == s_iOwners[CLIP_OWN_PRIMARY]) - s_iOwners[CLIP_OWN_PRIMARY] = None; - if (g_iClipboardWindow == s_iOwners[CLIP_OWN_CLIPBOARD]) - s_iOwners[CLIP_OWN_CLIPBOARD] = None; - - /* - * Handle case when selection is being disowned, - * WM_DRAWCLIPBOARD did not do the disowning, - * both monitored selections are no longer owned, - * an owned to not owned transition was detected, - * and we currently own the Win32 clipboard. - */ - if (stuff->window == None - && s_iOwners[CLIP_OWN_PRIMARY] == None - && s_iOwners[CLIP_OWN_CLIPBOARD] == None - && fOwnedToNotOwned - && g_hwndClipboard != NULL && g_hwndClipboard == GetClipboardOwner()) { - winDebug("winProcSetSelectionOwner - We currently own the " - "clipboard and neither the PRIMARY nor the CLIPBOARD " - "selections are owned, releasing ownership of Win32 " - "clipboard.\n"); - - /* Release ownership of the Windows clipboard */ - OpenClipboard(NULL); - EmptyClipboard(); - CloseClipboard(); - - goto winProcSetSelectionOwner_Done; - } - - /* Abort if no window at this point */ - if (None == stuff->window) { - winDebug("winProcSetSelectionOwner - No window, returning.\n"); - goto winProcSetSelectionOwner_Done; - } - - /* Abort if invalid selection */ - if (!ValidAtom(stuff->selection)) { - ErrorF("winProcSetSelectionOwner - Found BadAtom, aborting.\n"); - goto winProcSetSelectionOwner_Done; - } - - /* Cast Window to Drawable */ - pDrawable = (DrawablePtr) pWindow; - - /* Abort if clipboard manager is owning the selection */ - if (pDrawable->id == g_iClipboardWindow) { - winDebug("winProcSetSelectionOwner - We changed ownership, " - "aborting.\n"); - goto winProcSetSelectionOwner_Done; - } - - /* Abort if root window is taking ownership */ - if (pDrawable->id == 0) { - ErrorF("winProcSetSelectionOwner - Root window taking ownership, " - "aborting\n"); - goto winProcSetSelectionOwner_Done; - } - - /* Close clipboard if we have it open already */ - if (GetOpenClipboardWindow() == g_hwndClipboard) { - CloseClipboard(); - } - - /* Access the Windows clipboard */ - if (!OpenClipboard(g_hwndClipboard)) { - ErrorF("winProcSetSelectionOwner - OpenClipboard () failed: %08x\n", - (int) GetLastError()); - goto winProcSetSelectionOwner_Done; - } - - /* Take ownership of the Windows clipboard */ - if (!EmptyClipboard()) { - ErrorF("winProcSetSelectionOwner - EmptyClipboard () failed: %08x\n", - (int) GetLastError()); - goto winProcSetSelectionOwner_Done; - } - - /* Advertise regular text and unicode */ - SetClipboardData(CF_UNICODETEXT, NULL); - SetClipboardData(CF_TEXT, NULL); - - /* Save handle to last owned selection */ - g_atomLastOwnedSelection = stuff->selection; - - /* Release the clipboard */ - if (!CloseClipboard()) { - ErrorF("winProcSetSelectionOwner - CloseClipboard () failed: " - "%08x\n", (int) GetLastError()); - goto winProcSetSelectionOwner_Done; - } - - winProcSetSelectionOwner_Done: - return (*winProcSetSelectionOwnerOrig) (client); -} diff --git a/xorg-server/hw/xwin/winclipboardxevents.c b/xorg-server/hw/xwin/winclipboardxevents.c deleted file mode 100644 index 7d3c30e85..000000000 --- a/xorg-server/hw/xwin/winclipboardxevents.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - *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 -#endif -#include "winclipboard.h" -#include "misc.h" - -/* - * Process any pending X events - */ - -int -winClipboardFlushXEvents(HWND hwnd, - int iWindow, Display * pDisplay, Bool fUseUnicode) -{ - 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); - - /* Branch on the event type */ - switch (event.type) { - /* - * SelectionRequest - */ - - case SelectionRequest: - { - 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; - } - - /* 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; - } - - /* Close clipboard if we have it open already */ - if (GetOpenClipboardWindow() == hwnd) { - CloseClipboard(); - } - - /* Access the clipboard */ - 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) { - 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; - 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: - - winDebug("winClipboardFlushXEvents - SelectionNotify\n"); - { - char *pszAtomName; - - pszAtomName = XGetAtomName(pDisplay, - event.xselection.selection); - - winDebug - ("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n", - pszAtomName); - XFree(pszAtomName); - } - - /* - * 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; - } - - { - 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; - } - - 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 = 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 = 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 = 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(&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; - - case SelectionClear: - winDebug("SelectionClear - doing nothing\n"); - break; - - case PropertyNotify: - break; - - case MappingNotify: - break; - - default: - ErrorF("winClipboardFlushXEvents - unexpected event type %d\n", - event.type); - break; - } - } - - return WIN_XEVENTS_SUCCESS; -} diff --git a/xorg-server/hw/xwin/windialogs.c b/xorg-server/hw/xwin/windialogs.c index c9af0e203..61f7fe0bd 100644 --- a/xorg-server/hw/xwin/windialogs.c +++ b/xorg-server/hw/xwin/windialogs.c @@ -36,13 +36,6 @@ #include #include "winprefs.h" -/* - * References to external globals - */ - -#ifdef XWIN_CLIPBOARD -extern Bool g_fClipboardStarted; -#endif /* * Local function prototypes */ diff --git a/xorg-server/hw/xwin/winglobals.c b/xorg-server/hw/xwin/winglobals.c index b9ad294d5..ad82b83f6 100644 --- a/xorg-server/hw/xwin/winglobals.c +++ b/xorg-server/hw/xwin/winglobals.c @@ -86,7 +86,6 @@ pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER; * Wrapped DIX functions */ winDispatchProcPtr winProcEstablishConnectionOrig = NULL; -winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL; /* * Clipboard variables @@ -94,13 +93,7 @@ winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL; Bool g_fUnicodeClipboard = TRUE; Bool g_fClipboard = TRUE; -Bool g_fClipboardLaunched = FALSE; Bool g_fClipboardStarted = FALSE; -pthread_t g_ptClipboardProc; -HWND g_hwndClipboard = NULL; -void *g_pClipboardDisplay = NULL; -Window g_iClipboardWindow = None; -Atom g_atomLastOwnedSelection = None; #endif /* @@ -112,10 +105,4 @@ void winInitializeGlobals(void) { g_dwCurrentThreadID = GetCurrentThreadId(); -#ifdef XWIN_CLIPBOARD - g_iClipboardWindow = None; - g_pClipboardDisplay = NULL; - g_atomLastOwnedSelection = None; - g_hwndClipboard = NULL; -#endif } diff --git a/xorg-server/hw/xwin/winglobals.h b/xorg-server/hw/xwin/winglobals.h index 60c00da42..d7b813dbb 100644 --- a/xorg-server/hw/xwin/winglobals.h +++ b/xorg-server/hw/xwin/winglobals.h @@ -72,8 +72,10 @@ typedef int (*winDispatchProcPtr) (ClientPtr); * Wrapped DIX functions */ extern winDispatchProcPtr winProcEstablishConnectionOrig; -extern winDispatchProcPtr winProcSetSelectionOwnerOrig; #endif +extern Bool g_fUnicodeClipboard; +extern Bool g_fClipboard; +extern Bool g_fClipboardStarted; /* The global X default icons */ #if defined(XWIN_MULTIWINDOW) diff --git a/xorg-server/hw/xwin/winwndproc.c b/xorg-server/hw/xwin/winwndproc.c index bee223de7..e3adb5605 100644 --- a/xorg-server/hw/xwin/winwndproc.c +++ b/xorg-server/hw/xwin/winwndproc.c @@ -42,6 +42,9 @@ #include "winmsg.h" #include "winmonitors.h" #include "inputstr.h" +#ifdef XWIN_CLIPBOARD +#include "winclipboard/winclipboard.h" +#endif /* * Global variables -- cgit v1.2.3