Merge remote-tracking branch 'jturney/xwin-clipboard-refactoring'
This commit is contained in:
commit
78c27d12e1
|
@ -2142,7 +2142,7 @@ if test "x$XWIN" = xyes; then
|
|||
AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support])
|
||||
AC_CHECK_TOOL(WINDRES, windres)
|
||||
|
||||
PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau])
|
||||
PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau xfixes])
|
||||
|
||||
if test "x$WINDOWSWM" = xauto; then
|
||||
PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no])
|
||||
|
@ -2600,6 +2600,7 @@ hw/xnest/man/Makefile
|
|||
hw/xwin/Makefile
|
||||
hw/xwin/glx/Makefile
|
||||
hw/xwin/man/Makefile
|
||||
hw/xwin/winclipboard/Makefile
|
||||
hw/xquartz/Makefile
|
||||
hw/xquartz/GL/Makefile
|
||||
hw/xquartz/bundle/Makefile
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
|
||||
#ifdef XWIN_CLIPBOARD
|
||||
int winProcEstablishConnection(ClientPtr /* client */ );
|
||||
int winProcSetSelectionOwner(ClientPtr /* client */ );
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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 .
|
||||
|
|
|
@ -793,7 +793,7 @@ Bool
|
|||
winInitClipboard(void);
|
||||
|
||||
void
|
||||
winFixClipboardChain(void);
|
||||
winClipboardShutdown(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// Copyright © Jon TURNEY 2013
|
||||
//
|
||||
// This file is part of xwinclip.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice (including the next
|
||||
// paragraph) shall be included in all copies or substantial portions of the
|
||||
// Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if 1
|
||||
int
|
||||
winDebug(const char *format, ...)
|
||||
{
|
||||
int count;
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
count = fprintf(stderr, "xwinclip: ");
|
||||
count += vfprintf(stderr, format, ap);
|
||||
va_end(ap);
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
ErrorF(const char *format, ...)
|
||||
{
|
||||
int count;
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
count = vfprintf(stderr, format, ap);
|
||||
va_end(ap);
|
||||
return count;
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _WINCLIPBOARD_H_
|
||||
#define _WINCLIPBOARD_H_
|
||||
|
||||
/*
|
||||
*Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
|
||||
*
|
||||
|
@ -30,46 +29,18 @@
|
|||
* Authors: Harold L Hunt II
|
||||
*/
|
||||
|
||||
/* Standard library headers */
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#ifdef __CYGWIN__
|
||||
#include <sys/select.h>
|
||||
#else
|
||||
#include <X11/Xwinsock.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <setjmp.h>
|
||||
#include <pthread.h>
|
||||
#ifndef WINCLIPBOARD_INTERNAL_H
|
||||
#define WINCLIPBOARD_INTERNAL_H
|
||||
|
||||
/* X headers */
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xlocale.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
/* Windows headers */
|
||||
#include <X11/Xwindows.h>
|
||||
|
||||
/* Clipboard module constants */
|
||||
#define WIN_CLIPBOARD_WINDOW_CLASS "xwinclip"
|
||||
#define WIN_CLIPBOARD_WINDOW_TITLE "xwinclip"
|
||||
#ifdef HAS_DEVWINDOWS
|
||||
#define WIN_MSG_QUEUE_FNAME "/dev/windows"
|
||||
#endif
|
||||
#define WIN_CONNECT_RETRIES 40
|
||||
#define WIN_CONNECT_DELAY 4
|
||||
#define WIN_JMP_OKAY 0
|
||||
#define WIN_JMP_ERROR_IO 2
|
||||
#define WIN_LOCAL_PROPERTY "CYGX_CUT_BUFFER"
|
||||
#define WIN_XEVENTS_SUCCESS 0
|
||||
#define WIN_XEVENTS_CONVERT 2
|
||||
#define WIN_XEVENTS_NOTIFY 3
|
||||
#define WIN_CLIPBOARD_RETRIES 40
|
||||
#define WIN_CLIPBOARD_DELAY 1
|
||||
|
||||
#define WM_WM_REINIT (WM_USER + 1)
|
||||
|
||||
|
@ -77,18 +48,8 @@
|
|||
* References to external symbols
|
||||
*/
|
||||
|
||||
extern char *display;
|
||||
extern void winDebug(const char *format, ...);
|
||||
extern void winErrorFVerb(int verb, const char *format, ...);
|
||||
|
||||
/*
|
||||
* winclipboardinit.c
|
||||
*/
|
||||
|
||||
Bool
|
||||
winInitClipboard(void);
|
||||
|
||||
HWND winClipboardCreateMessagingWindow(void);
|
||||
extern void ErrorF(const char *format, ...);
|
||||
|
||||
/*
|
||||
* winclipboardtextconv.c
|
||||
|
@ -104,23 +65,45 @@ void
|
|||
* winclipboardthread.c
|
||||
*/
|
||||
|
||||
void *winClipboardProc(void *);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Atom atomClipboard;
|
||||
Atom atomLocalProperty;
|
||||
Atom atomUTF8String;
|
||||
Atom atomCompoundText;
|
||||
Atom atomTargets;
|
||||
} ClipboardAtoms;
|
||||
|
||||
/*
|
||||
* winclipboardwndproc.c
|
||||
*/
|
||||
|
||||
BOOL winClipboardFlushWindowsMessageQueue(HWND hwnd);
|
||||
Bool winClipboardFlushWindowsMessageQueue(HWND hwnd);
|
||||
|
||||
LRESULT CALLBACK
|
||||
winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Display *pClipboardDisplay;
|
||||
Window iClipboardWindow;
|
||||
ClipboardAtoms *atoms;
|
||||
} ClipboardWindowCreationParams;
|
||||
|
||||
/*
|
||||
* winclipboardxevents.c
|
||||
*/
|
||||
|
||||
int
|
||||
|
||||
winClipboardFlushXEvents(HWND hwnd,
|
||||
int iWindow, Display * pDisplay, Bool fUnicodeSupport);
|
||||
Window iWindow, Display * pDisplay, Bool fUnicodeSupport, ClipboardAtoms *atom);
|
||||
|
||||
|
||||
Atom
|
||||
winClipboardGetLastOwnedSelectionAtom(ClipboardAtoms *atoms);
|
||||
|
||||
void
|
||||
winClipboardInitMonitoredSelections(void);
|
||||
|
||||
#endif
|
|
@ -31,14 +31,18 @@
|
|||
#ifdef HAVE_XWIN_CONFIG_H
|
||||
#include <xwin-config.h>
|
||||
#endif
|
||||
#include "win.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void
|
||||
winClipboardDOStoUNIX(char *pszSrc, int iLength);
|
||||
void
|
||||
winClipboardUNIXtoDOS(char **ppszData, int iLength);
|
||||
/*
|
||||
* Including any server header might define the macro _XSERVER64 on 64 bit machines.
|
||||
* That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
|
||||
* So let's undef that macro if necessary.
|
||||
*/
|
||||
#ifdef _XSERVER64
|
||||
#undef _XSERVER64
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "internal.h"
|
||||
|
||||
/*
|
||||
* Convert \r\n to \n
|
|
@ -35,42 +35,62 @@
|
|||
#else
|
||||
#define HAS_WINSOCK 1
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include "winclipboard.h"
|
||||
#include "windisplay.h"
|
||||
#ifdef __CYGWIN__
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include "misc.h"
|
||||
|
||||
/*
|
||||
* References to external symbols
|
||||
* Including any server header might define the macro _XSERVER64 on 64 bit machines.
|
||||
* That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
|
||||
* So let's undef that macro if necessary.
|
||||
*/
|
||||
#ifdef _XSERVER64
|
||||
#undef _XSERVER64
|
||||
#endif
|
||||
|
||||
extern Bool g_fUnicodeClipboard;
|
||||
extern Bool g_fClipboardStarted;
|
||||
extern Bool g_fClipboardLaunched;
|
||||
extern Bool g_fClipboard;
|
||||
extern HWND g_hwndClipboard;
|
||||
extern void *g_pClipboardDisplay;
|
||||
extern Window g_iClipboardWindow;
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <setjmp.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/param.h> // for MAX() macro
|
||||
|
||||
#ifdef HAS_WINSOCK
|
||||
#include <X11/Xwinsock.h>
|
||||
#else
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include "winclipboard.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define WIN_CONNECT_RETRIES 40
|
||||
#define WIN_CONNECT_DELAY 4
|
||||
|
||||
#define WIN_CLIPBOARD_WINDOW_CLASS "xwinclip"
|
||||
#define WIN_CLIPBOARD_WINDOW_TITLE "xwinclip"
|
||||
#ifdef HAS_DEVWINDOWS
|
||||
#define WIN_MSG_QUEUE_FNAME "/dev/windows"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Global variables
|
||||
*/
|
||||
|
||||
static HWND g_hwndClipboard = NULL;
|
||||
static jmp_buf g_jmpEntry;
|
||||
static int clipboardRestarts = 0;
|
||||
static XIOErrorHandler g_winClipboardOldIOErrorHandler;
|
||||
static pthread_t g_winClipboardProcThread;
|
||||
|
||||
Bool g_fUseUnicode = FALSE;
|
||||
int xfixes_event_base;
|
||||
int xfixes_error_base;
|
||||
|
||||
/*
|
||||
* Local function prototypes
|
||||
*/
|
||||
|
||||
static HWND
|
||||
winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms);
|
||||
|
||||
static int
|
||||
winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr);
|
||||
|
||||
|
@ -78,13 +98,15 @@ static int
|
|||
winClipboardIOErrorHandler(Display * pDisplay);
|
||||
|
||||
/*
|
||||
* Main thread function
|
||||
* Create X11 and Win32 messaging windows, and run message processing loop
|
||||
*
|
||||
* returns TRUE if shutdown was signalled to loop, FALSE if some error occurred
|
||||
*/
|
||||
|
||||
void *
|
||||
winClipboardProc(void *pvNotUsed)
|
||||
Bool
|
||||
winClipboardProc(Bool fUseUnicode, char *szDisplay)
|
||||
{
|
||||
Atom atomClipboard;
|
||||
ClipboardAtoms atoms;
|
||||
int iReturn;
|
||||
HWND hwnd = NULL;
|
||||
int iConnectionNumber = 0;
|
||||
|
@ -98,19 +120,11 @@ winClipboardProc(void *pvNotUsed)
|
|||
int iMaxDescriptor;
|
||||
Display *pDisplay = NULL;
|
||||
Window iWindow = None;
|
||||
int iRetries;
|
||||
Bool fUseUnicode;
|
||||
char szDisplay[512];
|
||||
int iSelectError;
|
||||
Bool fShutdown = FALSE;
|
||||
static Bool fErrorHandlerSet = FALSE;
|
||||
|
||||
winDebug("winClipboardProc - Hello\n");
|
||||
++clipboardRestarts;
|
||||
|
||||
/* Do we use Unicode clipboard? */
|
||||
fUseUnicode = g_fUnicodeClipboard;
|
||||
|
||||
/* Save the Unicode support flag in a global */
|
||||
g_fUseUnicode = fUseUnicode;
|
||||
|
||||
/* Allow multiple threads to access Xlib */
|
||||
if (XInitThreads() == 0) {
|
||||
|
@ -123,70 +137,29 @@ winClipboardProc(void *pvNotUsed)
|
|||
ErrorF("winClipboardProc - Warning: Locale not supported by X.\n");
|
||||
}
|
||||
|
||||
/* Set error handler */
|
||||
XSetErrorHandler(winClipboardErrorHandler);
|
||||
g_winClipboardProcThread = pthread_self();
|
||||
g_winClipboardOldIOErrorHandler =
|
||||
XSetIOErrorHandler(winClipboardIOErrorHandler);
|
||||
|
||||
/* Set error handler */
|
||||
if (!fErrorHandlerSet) {
|
||||
XSetErrorHandler(winClipboardErrorHandler);
|
||||
g_winClipboardOldIOErrorHandler =
|
||||
XSetIOErrorHandler(winClipboardIOErrorHandler);
|
||||
fErrorHandlerSet = TRUE;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
if (setjmp(g_jmpEntry)) {
|
||||
ErrorF("winClipboardProc - setjmp returned for IO Error Handler.\n");
|
||||
pthread_exit(NULL);
|
||||
goto winClipboardProc_Done;
|
||||
}
|
||||
|
||||
/* Use our generated cookie for authentication */
|
||||
winSetAuthorization();
|
||||
|
||||
/* Initialize retry count */
|
||||
iRetries = 0;
|
||||
|
||||
/* Setup the display connection string x */
|
||||
/*
|
||||
* NOTE: Always connect to screen 0 since we require that screen
|
||||
* numbers start at 0 and increase without gaps. We only need
|
||||
* to connect to one screen on the display to get events
|
||||
* for all screens on the display. That is why there is only
|
||||
* one clipboard client thread.
|
||||
*/
|
||||
winGetDisplayName(szDisplay, 0);
|
||||
|
||||
/* Print the display connection string */
|
||||
ErrorF("winClipboardProc - DISPLAY=%s\n", szDisplay);
|
||||
|
||||
/* Open the X display */
|
||||
do {
|
||||
pDisplay = XOpenDisplay(szDisplay);
|
||||
if (pDisplay == NULL) {
|
||||
ErrorF("winClipboardProc - Could not open display, "
|
||||
"try: %d, sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY);
|
||||
++iRetries;
|
||||
sleep(WIN_CONNECT_DELAY);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
while (pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
|
||||
|
||||
/* Make sure that the display opened */
|
||||
pDisplay = XOpenDisplay(szDisplay);
|
||||
if (pDisplay == NULL) {
|
||||
ErrorF("winClipboardProc - Failed opening the display, giving up\n");
|
||||
goto winClipboardProc_Done;
|
||||
}
|
||||
|
||||
/* Save the display in the screen privates */
|
||||
g_pClipboardDisplay = pDisplay;
|
||||
|
||||
ErrorF("winClipboardProc - XOpenDisplay () returned and "
|
||||
"successfully opened the display.\n");
|
||||
|
||||
|
@ -202,13 +175,20 @@ winClipboardProc(void *pvNotUsed)
|
|||
}
|
||||
|
||||
/* Find max of our file descriptors */
|
||||
iMaxDescriptor = max(fdMessageQueue, iConnectionNumber) + 1;
|
||||
iMaxDescriptor = MAX(fdMessageQueue, iConnectionNumber) + 1;
|
||||
#else
|
||||
iMaxDescriptor = iConnectionNumber + 1;
|
||||
#endif
|
||||
|
||||
/* Create atom */
|
||||
atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
|
||||
if (!XFixesQueryExtension(pDisplay, &xfixes_event_base, &xfixes_error_base))
|
||||
ErrorF ("winClipboardProc - XFixes extension not present\n");
|
||||
|
||||
/* Create atoms */
|
||||
atoms.atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
|
||||
atoms.atomLocalProperty = XInternAtom (pDisplay, "CYGX_CUT_BUFFER", False);
|
||||
atoms.atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False);
|
||||
atoms.atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False);
|
||||
atoms.atomTargets = XInternAtom (pDisplay, "TARGETS", False);
|
||||
|
||||
/* Create a messaging window */
|
||||
iWindow = XCreateSimpleWindow(pDisplay,
|
||||
|
@ -230,13 +210,27 @@ winClipboardProc(void *pvNotUsed)
|
|||
ErrorF("winClipboardProc - XSelectInput generated BadWindow "
|
||||
"on messaging window\n");
|
||||
|
||||
/* Save the window in the screen privates */
|
||||
g_iClipboardWindow = iWindow;
|
||||
XFixesSelectSelectionInput (pDisplay,
|
||||
iWindow,
|
||||
XA_PRIMARY,
|
||||
XFixesSetSelectionOwnerNotifyMask |
|
||||
XFixesSelectionWindowDestroyNotifyMask |
|
||||
XFixesSelectionClientCloseNotifyMask);
|
||||
|
||||
XFixesSelectSelectionInput (pDisplay,
|
||||
iWindow,
|
||||
atoms.atomClipboard,
|
||||
XFixesSetSelectionOwnerNotifyMask |
|
||||
XFixesSelectionWindowDestroyNotifyMask |
|
||||
XFixesSelectionClientCloseNotifyMask);
|
||||
|
||||
|
||||
/* Initialize monitored selection state */
|
||||
winClipboardInitMonitoredSelections();
|
||||
/* Create Windows messaging window */
|
||||
hwnd = winClipboardCreateMessagingWindow();
|
||||
hwnd = winClipboardCreateMessagingWindow(pDisplay, iWindow, &atoms);
|
||||
|
||||
/* Save copy of HWND in screen privates */
|
||||
/* Save copy of HWND */
|
||||
g_hwndClipboard = hwnd;
|
||||
|
||||
/* Assert ownership of selections if Win32 clipboard is owned */
|
||||
|
@ -251,29 +245,27 @@ winClipboardProc(void *pvNotUsed)
|
|||
}
|
||||
|
||||
/* CLIPBOARD */
|
||||
iReturn = XSetSelectionOwner(pDisplay, atomClipboard,
|
||||
iReturn = XSetSelectionOwner(pDisplay, atoms.atomClipboard,
|
||||
iWindow, CurrentTime);
|
||||
if (iReturn == BadAtom || iReturn == BadWindow ||
|
||||
XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
|
||||
XGetSelectionOwner(pDisplay, atoms.atomClipboard) != iWindow) {
|
||||
ErrorF("winClipboardProc - Could not set CLIPBOARD owner\n");
|
||||
goto winClipboardProc_Done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pre-flush X events */
|
||||
/*
|
||||
/*
|
||||
* NOTE: Apparently you'll freeze if you don't do this,
|
||||
* because there may be events in local data structures
|
||||
* already.
|
||||
*/
|
||||
winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
|
||||
winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms);
|
||||
|
||||
/* Pre-flush Windows messages */
|
||||
if (!winClipboardFlushWindowsMessageQueue(hwnd))
|
||||
return 0;
|
||||
|
||||
/* Signal that the clipboard client has started */
|
||||
g_fClipboardStarted = TRUE;
|
||||
if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
|
||||
ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue failed\n");
|
||||
}
|
||||
|
||||
/* Loop for X events */
|
||||
while (1) {
|
||||
|
@ -326,7 +318,7 @@ winClipboardProc(void *pvNotUsed)
|
|||
/* Branch on which descriptor became active */
|
||||
if (FD_ISSET(iConnectionNumber, &fdsRead)) {
|
||||
/* Process X events */
|
||||
winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
|
||||
winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms);
|
||||
}
|
||||
|
||||
#ifdef HAS_DEVWINDOWS
|
||||
|
@ -347,16 +339,13 @@ winClipboardProc(void *pvNotUsed)
|
|||
}
|
||||
|
||||
winClipboardProc_Exit:
|
||||
/* disable the clipboard, which means the thread will die */
|
||||
g_fClipboard = FALSE;
|
||||
/* broke out of while loop on a shutdown message */
|
||||
fShutdown = TRUE;
|
||||
|
||||
winClipboardProc_Done:
|
||||
/* Close our Windows window */
|
||||
if (g_hwndClipboard) {
|
||||
/* Destroy the Window window (hwnd) */
|
||||
winDebug("winClipboardProc - Destroy Windows window\n");
|
||||
PostMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
|
||||
winClipboardFlushWindowsMessageQueue(g_hwndClipboard);
|
||||
winClipboardWindowDestroy();
|
||||
}
|
||||
|
||||
/* Close our X window */
|
||||
|
@ -376,8 +365,11 @@ winClipboardProc(void *pvNotUsed)
|
|||
|
||||
#if 0
|
||||
/*
|
||||
* FIXME: XCloseDisplay hangs if we call it, as of 2004/03/26. The
|
||||
* XSync and XSelectInput calls did not help.
|
||||
* FIXME: XCloseDisplay hangs if we call it
|
||||
*
|
||||
* XCloseDisplay() calls XSync(), so any outstanding errors are reported.
|
||||
* If we are built into the server, this can deadlock if the server is
|
||||
* in the process of exiting and waiting for this thread to exit.
|
||||
*/
|
||||
|
||||
/* Discard any remaining events */
|
||||
|
@ -393,42 +385,64 @@ winClipboardProc(void *pvNotUsed)
|
|||
#endif
|
||||
|
||||
/* global clipboard variable reset */
|
||||
g_fClipboardLaunched = FALSE;
|
||||
g_fClipboardStarted = FALSE;
|
||||
g_iClipboardWindow = None;
|
||||
g_pClipboardDisplay = NULL;
|
||||
g_hwndClipboard = NULL;
|
||||
|
||||
/* checking if we need to restart */
|
||||
if (clipboardRestarts >= WIN_CLIPBOARD_RETRIES) {
|
||||
/* terminates clipboard thread but the main server still lives */
|
||||
ErrorF
|
||||
("winClipboardProc - the clipboard thread has restarted %d times and seems to be unstable, disabling clipboard integration\n",
|
||||
clipboardRestarts);
|
||||
g_fClipboard = FALSE;
|
||||
return NULL;
|
||||
}
|
||||
return fShutdown;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
/*
|
||||
* Create the Windows window that we use to receive Windows messages
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
static HWND
|
||||
winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms)
|
||||
{
|
||||
WNDCLASSEX wc;
|
||||
ClipboardWindowCreationParams cwcp;
|
||||
HWND hwnd;
|
||||
|
||||
return NULL;
|
||||
/* Setup our window class */
|
||||
wc.cbSize = sizeof(WNDCLASSEX);
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = winClipboardWindowProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = GetModuleHandle(NULL);
|
||||
wc.hIcon = 0;
|
||||
wc.hCursor = 0;
|
||||
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.lpszClassName = WIN_CLIPBOARD_WINDOW_CLASS;
|
||||
wc.hIconSm = 0;
|
||||
RegisterClassEx(&wc);
|
||||
|
||||
/* Information to be passed to WM_CREATE */
|
||||
cwcp.pClipboardDisplay = pDisplay;
|
||||
cwcp.iClipboardWindow = iWindow;
|
||||
cwcp.atoms = atoms;
|
||||
|
||||
/* Create the window */
|
||||
hwnd = CreateWindowExA(0, /* Extended styles */
|
||||
WIN_CLIPBOARD_WINDOW_CLASS, /* Class name */
|
||||
WIN_CLIPBOARD_WINDOW_TITLE, /* Window name */
|
||||
WS_OVERLAPPED, /* Not visible anyway */
|
||||
CW_USEDEFAULT, /* Horizontal position */
|
||||
CW_USEDEFAULT, /* Vertical position */
|
||||
CW_USEDEFAULT, /* Right edge */
|
||||
CW_USEDEFAULT, /* Bottom edge */
|
||||
(HWND) NULL, /* No parent or owner window */
|
||||
(HMENU) NULL, /* No menu */
|
||||
GetModuleHandle(NULL), /* Instance handle */
|
||||
&cwcp); /* Creation data */
|
||||
assert(hwnd != NULL);
|
||||
|
||||
/* I'm not sure, but we may need to call this to start message processing */
|
||||
ShowWindow(hwnd, SW_HIDE);
|
||||
|
||||
/* Similarly, we may need a call to this even though we don't paint */
|
||||
UpdateWindow(hwnd);
|
||||
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -458,7 +472,7 @@ winClipboardIOErrorHandler(Display * pDisplay)
|
|||
|
||||
if (pthread_equal(pthread_self(), g_winClipboardProcThread)) {
|
||||
/* Restart at the main entry point */
|
||||
longjmp(g_jmpEntry, WIN_JMP_ERROR_IO);
|
||||
longjmp(g_jmpEntry, 2);
|
||||
}
|
||||
|
||||
if (g_winClipboardOldIOErrorHandler)
|
||||
|
@ -466,3 +480,19 @@ winClipboardIOErrorHandler(Display * pDisplay)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
winClipboardWindowDestroy(void)
|
||||
{
|
||||
if (g_hwndClipboard) {
|
||||
SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
winFixClipboardChain(void)
|
||||
{
|
||||
if (g_hwndClipboard) {
|
||||
PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -33,10 +33,23 @@
|
|||
#ifdef HAVE_XWIN_CONFIG_H
|
||||
#include <xwin-config.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Including any server header might define the macro _XSERVER64 on 64 bit machines.
|
||||
* That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
|
||||
* So let's undef that macro if necessary.
|
||||
*/
|
||||
#ifdef _XSERVER64
|
||||
#undef _XSERVER64
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "winclipboard.h"
|
||||
#include "misc.h"
|
||||
|
||||
/*
|
||||
* Constants
|
||||
|
@ -44,21 +57,14 @@
|
|||
|
||||
#define WIN_POLL_TIMEOUT 1
|
||||
|
||||
/*
|
||||
* References to external symbols
|
||||
*/
|
||||
|
||||
extern void *g_pClipboardDisplay;
|
||||
extern Window g_iClipboardWindow;
|
||||
extern Atom g_atomLastOwnedSelection;
|
||||
|
||||
/*
|
||||
* Process X events up to specified timeout
|
||||
*/
|
||||
|
||||
static int
|
||||
winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
|
||||
Bool fUseUnicode, int iTimeoutSec)
|
||||
winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay,
|
||||
Bool fUseUnicode, ClipboardAtoms *atoms, int iTimeoutSec)
|
||||
{
|
||||
int iConnNumber;
|
||||
struct timeval tv;
|
||||
|
@ -111,7 +117,7 @@ winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
|
|||
/* Process X events */
|
||||
/* Exit when we see that server is shutting down */
|
||||
iReturn = winClipboardFlushXEvents(hwnd,
|
||||
iWindow, pDisplay, fUseUnicode);
|
||||
iWindow, pDisplay, fUseUnicode, atoms);
|
||||
|
||||
winDebug
|
||||
("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n",
|
||||
|
@ -139,6 +145,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
static HWND s_hwndNextViewer;
|
||||
static Bool s_fCBCInitialized;
|
||||
static Display *pDisplay;
|
||||
static Window iWindow;
|
||||
static ClipboardAtoms *atoms;
|
||||
|
||||
/* Branch on message type */
|
||||
switch (message) {
|
||||
|
@ -159,9 +168,14 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
HWND first, next;
|
||||
DWORD error_code = 0;
|
||||
ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams;
|
||||
|
||||
winDebug("winClipboardWindowProc - WM_CREATE\n");
|
||||
|
||||
pDisplay = cwcp->pClipboardDisplay;
|
||||
iWindow = cwcp->iClipboardWindow;
|
||||
atoms = cwcp->atoms;
|
||||
|
||||
first = GetClipboardViewer(); /* Get handle to first viewer in chain. */
|
||||
if (first == hwnd)
|
||||
return 0; /* Make sure it's not us! */
|
||||
|
@ -185,8 +199,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
s_hwndNextViewer = (HWND) lParam;
|
||||
if (s_hwndNextViewer == hwnd) {
|
||||
s_hwndNextViewer = NULL;
|
||||
winErrorFVerb(1, "winClipboardWindowProc - WM_CHANGECBCHAIN: "
|
||||
"attempted to set next window to ourselves.");
|
||||
ErrorF("winClipboardWindowProc - WM_CHANGECBCHAIN: "
|
||||
"attempted to set next window to ourselves.");
|
||||
}
|
||||
}
|
||||
else if (s_hwndNextViewer)
|
||||
|
@ -241,20 +255,11 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
case WM_DRAWCLIPBOARD:
|
||||
{
|
||||
static Atom atomClipboard;
|
||||
static int generation;
|
||||
static Bool s_fProcessingDrawClipboard = FALSE;
|
||||
Display *pDisplay = g_pClipboardDisplay;
|
||||
Window iWindow = g_iClipboardWindow;
|
||||
int iReturn;
|
||||
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
|
||||
|
||||
if (generation != serverGeneration) {
|
||||
generation = serverGeneration;
|
||||
atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
|
||||
}
|
||||
|
||||
/*
|
||||
* We've occasionally seen a loop in the clipboard chain.
|
||||
* Try and fix it on the first hint of recursion.
|
||||
|
@ -267,8 +272,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
s_fCBCInitialized = FALSE;
|
||||
ChangeClipboardChain(hwnd, s_hwndNextViewer);
|
||||
winFixClipboardChain();
|
||||
winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
"Nested calls detected. Re-initing.\n");
|
||||
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
"Nested calls detected. Re-initing.\n");
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
|
||||
s_fProcessingDrawClipboard = FALSE;
|
||||
return 0;
|
||||
|
@ -324,27 +329,27 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
/* Release PRIMARY selection if owned */
|
||||
iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY);
|
||||
if (iReturn == g_iClipboardWindow) {
|
||||
if (iReturn == iWindow) {
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
"PRIMARY selection is owned by us.\n");
|
||||
XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime);
|
||||
}
|
||||
else if (BadWindow == iReturn || BadAtom == iReturn)
|
||||
winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
"XGetSelection failed for PRIMARY: %d\n",
|
||||
iReturn);
|
||||
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
"XGetSelectionOwner failed for PRIMARY: %d\n",
|
||||
iReturn);
|
||||
|
||||
/* Release CLIPBOARD selection if owned */
|
||||
iReturn = XGetSelectionOwner(pDisplay, atomClipboard);
|
||||
if (iReturn == g_iClipboardWindow) {
|
||||
iReturn = XGetSelectionOwner(pDisplay, atoms->atomClipboard);
|
||||
if (iReturn == iWindow) {
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
"CLIPBOARD selection is owned by us.\n");
|
||||
XSetSelectionOwner(pDisplay, atomClipboard, None, CurrentTime);
|
||||
"CLIPBOARD selection is owned by us, releasing\n");
|
||||
XSetSelectionOwner(pDisplay, atoms->atomClipboard, None, CurrentTime);
|
||||
}
|
||||
else if (BadWindow == iReturn || BadAtom == iReturn)
|
||||
winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
"XGetSelection failed for CLIPBOARD: %d\n",
|
||||
iReturn);
|
||||
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
"XGetSelectionOwner failed for CLIPBOARD: %d\n",
|
||||
iReturn);
|
||||
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
|
||||
s_fProcessingDrawClipboard = FALSE;
|
||||
|
@ -358,8 +363,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
XA_PRIMARY, iWindow, CurrentTime);
|
||||
if (iReturn == BadAtom || iReturn == BadWindow ||
|
||||
XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
|
||||
winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
"Could not reassert ownership of PRIMARY\n");
|
||||
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
"Could not reassert ownership of PRIMARY\n");
|
||||
}
|
||||
else {
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
|
@ -368,12 +373,12 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
/* Reassert ownership of the CLIPBOARD */
|
||||
iReturn = XSetSelectionOwner(pDisplay,
|
||||
atomClipboard, iWindow, CurrentTime);
|
||||
atoms->atomClipboard, iWindow, CurrentTime);
|
||||
|
||||
if (iReturn == BadAtom || iReturn == BadWindow ||
|
||||
XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
|
||||
winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
"Could not reassert ownership of CLIPBOARD\n");
|
||||
XGetSelectionOwner(pDisplay, atoms->atomClipboard) != iWindow) {
|
||||
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
"Could not reassert ownership of CLIPBOARD\n");
|
||||
}
|
||||
else {
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
|
@ -409,8 +414,6 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
case WM_RENDERALLFORMATS:
|
||||
{
|
||||
int iReturn;
|
||||
Display *pDisplay = g_pClipboardDisplay;
|
||||
Window iWindow = g_iClipboardWindow;
|
||||
Bool fConvertToUnicode;
|
||||
|
||||
winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
|
||||
|
@ -423,15 +426,13 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
/* Request the selection contents */
|
||||
iReturn = XConvertSelection(pDisplay,
|
||||
g_atomLastOwnedSelection,
|
||||
XInternAtom(pDisplay,
|
||||
"COMPOUND_TEXT", False),
|
||||
XInternAtom(pDisplay,
|
||||
"CYGX_CUT_BUFFER", False),
|
||||
winClipboardGetLastOwnedSelectionAtom(atoms),
|
||||
atoms->atomCompoundText,
|
||||
atoms->atomLocalProperty,
|
||||
iWindow, CurrentTime);
|
||||
if (iReturn == BadAtom || iReturn == BadWindow) {
|
||||
winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMAT - "
|
||||
"XConvertSelection () failed\n");
|
||||
ErrorF("winClipboardWindowProc - WM_RENDER*FORMAT - "
|
||||
"XConvertSelection () failed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -445,16 +446,16 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
|
||||
if (!OpenClipboard(hwnd)) {
|
||||
winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
|
||||
"OpenClipboard () failed: %08x\n",
|
||||
GetLastError());
|
||||
ErrorF("winClipboardWindowProc - WM_RENDER*FORMATS - "
|
||||
"OpenClipboard () failed: %08x\n",
|
||||
GetLastError());
|
||||
break;
|
||||
}
|
||||
|
||||
if (!EmptyClipboard()) {
|
||||
winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
|
||||
"EmptyClipboard () failed: %08x\n",
|
||||
GetLastError());
|
||||
ErrorF("winClipboardWindowProc - WM_RENDER*FORMATS - "
|
||||
"EmptyClipboard () failed: %08x\n",
|
||||
GetLastError());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -463,7 +464,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
iReturn = winProcessXEventsTimeout(hwnd,
|
||||
iWindow,
|
||||
pDisplay,
|
||||
fConvertToUnicode, WIN_POLL_TIMEOUT);
|
||||
fConvertToUnicode,
|
||||
atoms,
|
||||
WIN_POLL_TIMEOUT);
|
||||
|
||||
/*
|
||||
* The last call to winProcessXEventsTimeout
|
||||
|
@ -486,10 +489,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
/* We must close the clipboard */
|
||||
|
||||
if (!CloseClipboard()) {
|
||||
winErrorFVerb(1,
|
||||
"winClipboardWindowProc - WM_RENDERALLFORMATS - "
|
||||
"CloseClipboard () failed: %08x\n",
|
||||
GetLastError());
|
||||
ErrorF("winClipboardWindowProc - WM_RENDERALLFORMATS - "
|
||||
"CloseClipboard () failed: %08x\n",
|
||||
GetLastError());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -507,7 +509,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
* Process any pending Windows messages
|
||||
*/
|
||||
|
||||
BOOL
|
||||
Bool
|
||||
winClipboardFlushWindowsMessageQueue(HWND hwnd)
|
||||
{
|
||||
MSG msg;
|
|
@ -33,8 +33,104 @@
|
|||
#ifdef HAVE_XWIN_CONFIG_H
|
||||
#include <xwin-config.h>
|
||||
#endif
|
||||
#include "winclipboard.h"
|
||||
#include "misc.h"
|
||||
|
||||
/*
|
||||
* Including any server header might define the macro _XSERVER64 on 64 bit machines.
|
||||
* That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
|
||||
* So let's undef that macro if necessary.
|
||||
*/
|
||||
#ifdef _XSERVER64
|
||||
#undef _XSERVER64
|
||||
#endif
|
||||
|
||||
#include "internal.h"
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
||||
#define CLIP_NUM_SELECTIONS 2
|
||||
#define CLIP_OWN_NONE -1
|
||||
#define CLIP_OWN_PRIMARY 0
|
||||
#define CLIP_OWN_CLIPBOARD 1
|
||||
|
||||
/*
|
||||
* Global variables
|
||||
*/
|
||||
|
||||
extern int xfixes_event_base;
|
||||
|
||||
/*
|
||||
* Local variables
|
||||
*/
|
||||
|
||||
static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None, None };
|
||||
static const char *szSelectionNames[CLIP_NUM_SELECTIONS] =
|
||||
{ "PRIMARY", "CLIPBOARD" };
|
||||
|
||||
static unsigned int lastOwnedSelectionIndex = CLIP_OWN_NONE;
|
||||
|
||||
static void
|
||||
MonitorSelection(XFixesSelectionNotifyEvent * e, unsigned int i)
|
||||
{
|
||||
/* Look for owned -> not owned transition */
|
||||
if (None == e->owner && None != s_iOwners[i]) {
|
||||
unsigned int other_index;
|
||||
|
||||
winDebug("MonitorSelection - %s - Going from owned to not owned.\n",
|
||||
szSelectionNames[i]);
|
||||
|
||||
/* If this selection is not owned, the other monitored selection must be the most
|
||||
recently owned, if it is owned at all */
|
||||
if (i == CLIP_OWN_PRIMARY)
|
||||
other_index = CLIP_OWN_CLIPBOARD;
|
||||
if (i == CLIP_OWN_CLIPBOARD)
|
||||
other_index = CLIP_OWN_PRIMARY;
|
||||
if (None != s_iOwners[other_index])
|
||||
lastOwnedSelectionIndex = other_index;
|
||||
else
|
||||
lastOwnedSelectionIndex = CLIP_OWN_NONE;
|
||||
}
|
||||
|
||||
/* Save last owned selection */
|
||||
if (None != e->owner) {
|
||||
lastOwnedSelectionIndex = i;
|
||||
}
|
||||
|
||||
/* Save new selection owner or None */
|
||||
s_iOwners[i] = e->owner;
|
||||
winDebug("MonitorSelection - %s - Now owned by XID %x\n",
|
||||
szSelectionNames[i], e->owner);
|
||||
}
|
||||
|
||||
Atom
|
||||
winClipboardGetLastOwnedSelectionAtom(ClipboardAtoms *atoms)
|
||||
{
|
||||
if (lastOwnedSelectionIndex == CLIP_OWN_NONE)
|
||||
return None;
|
||||
|
||||
if (lastOwnedSelectionIndex == CLIP_OWN_PRIMARY)
|
||||
return XA_PRIMARY;
|
||||
|
||||
if (lastOwnedSelectionIndex == CLIP_OWN_CLIPBOARD)
|
||||
return atoms->atomClipboard;
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
winClipboardInitMonitoredSelections(void)
|
||||
{
|
||||
/* Initialize static variables */
|
||||
for (int i = 0; i < CLIP_NUM_SELECTIONS; ++i)
|
||||
s_iOwners[i] = None;
|
||||
|
||||
lastOwnedSelectionIndex = CLIP_OWN_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process any pending X events
|
||||
|
@ -42,21 +138,13 @@
|
|||
|
||||
int
|
||||
winClipboardFlushXEvents(HWND hwnd,
|
||||
int iWindow, Display * pDisplay, Bool fUseUnicode)
|
||||
Window iWindow, Display * pDisplay, Bool fUseUnicode, ClipboardAtoms *atoms)
|
||||
{
|
||||
static Atom atomLocalProperty;
|
||||
static Atom atomCompoundText;
|
||||
static Atom atomUTF8String;
|
||||
static Atom atomTargets;
|
||||
static int generation;
|
||||
|
||||
if (generation != serverGeneration) {
|
||||
generation = serverGeneration;
|
||||
atomLocalProperty = XInternAtom(pDisplay, WIN_LOCAL_PROPERTY, False);
|
||||
atomUTF8String = XInternAtom(pDisplay, "UTF8_STRING", False);
|
||||
atomCompoundText = XInternAtom(pDisplay, "COMPOUND_TEXT", False);
|
||||
atomTargets = XInternAtom(pDisplay, "TARGETS", False);
|
||||
}
|
||||
Atom atomClipboard = atoms->atomClipboard;
|
||||
Atom atomLocalProperty = atoms->atomLocalProperty;
|
||||
Atom atomUTF8String = atoms->atomUTF8String;
|
||||
Atom atomCompoundText = atoms->atomCompoundText;
|
||||
Atom atomTargets = atoms->atomTargets;
|
||||
|
||||
/* Process all pending events */
|
||||
while (XPending(pDisplay)) {
|
||||
|
@ -77,7 +165,6 @@ winClipboardFlushXEvents(HWND hwnd,
|
|||
wchar_t *pwszUnicodeStr = NULL;
|
||||
int iUnicodeLen = 0;
|
||||
int iReturnDataLen = 0;
|
||||
int i;
|
||||
Bool fAbort = FALSE;
|
||||
Bool fCloseClipboard = FALSE;
|
||||
Bool fSetClipboardData = TRUE;
|
||||
|
@ -525,6 +612,8 @@ winClipboardFlushXEvents(HWND hwnd,
|
|||
if (iReturn == Success || iReturn > 0) {
|
||||
/* Conversion succeeded or some unconvertible characters */
|
||||
if (ppszTextList != NULL) {
|
||||
int i;
|
||||
|
||||
iReturnDataLen = 0;
|
||||
for (i = 0; i < iCount; i++) {
|
||||
iReturnDataLen += strlen(ppszTextList[i]);
|
||||
|
@ -693,8 +782,78 @@ winClipboardFlushXEvents(HWND hwnd,
|
|||
break;
|
||||
|
||||
default:
|
||||
ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
|
||||
event.type);
|
||||
if (event.type == XFixesSetSelectionOwnerNotify + xfixes_event_base) {
|
||||
XFixesSelectionNotifyEvent *e =
|
||||
(XFixesSelectionNotifyEvent *) & event;
|
||||
|
||||
winDebug("winClipboardFlushXEvents - XFixesSetSelectionOwnerNotify\n");
|
||||
|
||||
/* Save selection owners for monitored selections, ignore other selections */
|
||||
if (e->selection == XA_PRIMARY) {
|
||||
MonitorSelection(e, CLIP_OWN_PRIMARY);
|
||||
}
|
||||
else if (e->selection == atomClipboard) {
|
||||
MonitorSelection(e, CLIP_OWN_CLIPBOARD);
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
/* Selection is being disowned */
|
||||
if (e->owner == None) {
|
||||
winDebug
|
||||
("winClipboardFlushXEvents - No window, returning.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
XXX: there are all kinds of wacky edge cases we might need here:
|
||||
- we own windows clipboard, but neither PRIMARY nor CLIPBOARD have an owner, so we should disown it?
|
||||
- root window is taking ownership?
|
||||
*/
|
||||
|
||||
/* If we are the owner of the most recently owned selection, don't go all recursive :) */
|
||||
if ((lastOwnedSelectionIndex != CLIP_OWN_NONE) &&
|
||||
(s_iOwners[lastOwnedSelectionIndex] == iWindow)) {
|
||||
winDebug("winClipboardFlushXEvents - Ownership changed to us, aborting.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Close clipboard if we have it open already (possible? correct??) */
|
||||
if (GetOpenClipboardWindow() == hwnd) {
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
/* Access the Windows clipboard */
|
||||
if (!OpenClipboard(hwnd)) {
|
||||
ErrorF("winClipboardFlushXEvents - OpenClipboard () failed: %08x\n",
|
||||
(int) GetLastError());
|
||||
break;
|
||||
}
|
||||
|
||||
/* Take ownership of the Windows clipboard */
|
||||
if (!EmptyClipboard()) {
|
||||
ErrorF("winClipboardFlushXEvents - EmptyClipboard () failed: %08x\n",
|
||||
(int) GetLastError());
|
||||
break;
|
||||
}
|
||||
|
||||
/* Advertise regular text and unicode */
|
||||
SetClipboardData(CF_UNICODETEXT, NULL);
|
||||
SetClipboardData(CF_TEXT, NULL);
|
||||
|
||||
/* Release the clipboard */
|
||||
if (!CloseClipboard()) {
|
||||
ErrorF("winClipboardFlushXEvents - CloseClipboard () failed: %08x\n",
|
||||
(int) GetLastError());
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* XFixesSelectionWindowDestroyNotifyMask */
|
||||
/* XFixesSelectionClientCloseNotifyMask */
|
||||
else {
|
||||
ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
|
||||
event.type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
*Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
|
||||
*Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
|
||||
*Copyright (C) Colin Harrison 2005-2008
|
||||
*
|
||||
*Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
*"Software"), to deal in the Software without restriction, including
|
||||
*without limitation the rights to use, copy, modify, merge, publish,
|
||||
*distribute, sublicense, and/or sell copies of the Software, and to
|
||||
*permit persons to whom the Software is furnished to do so, subject to
|
||||
*the following conditions:
|
||||
*
|
||||
*The above copyright notice and this permission notice shall be
|
||||
*included in all copies or substantial portions of the Software.
|
||||
*
|
||||
*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
*NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
*ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
*CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
*WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*Except as contained in this notice, the name of the copyright holder(s)
|
||||
*and author(s) shall not be used in advertising or otherwise to promote
|
||||
*the sale, use or other dealings in this Software without prior written
|
||||
*authorization from the copyright holder(s) and author(s).
|
||||
*
|
||||
* Authors: Harold L Hunt II
|
||||
* Colin Harrison
|
||||
*/
|
||||
|
||||
#ifdef HAVE_XWIN_CONFIG_H
|
||||
#include <xwin-config.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Including any server header might define the macro _XSERVER64 on 64 bit machines.
|
||||
* That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
|
||||
* So let's undef that macro if necessary.
|
||||
*/
|
||||
#ifdef _XSERVER64
|
||||
#undef _XSERVER64
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* X headers */
|
||||
#include <X11/Xlib.h>
|
||||
#ifdef X_LOCALE
|
||||
#include <X11/Xlocale.h>
|
||||
#else /* X_LOCALE */
|
||||
#include <locale.h>
|
||||
#endif /* X_LOCALE */
|
||||
|
||||
#include "winclipboard.h"
|
||||
|
||||
/*
|
||||
* Main function
|
||||
*/
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
char *pszDisplay = NULL;
|
||||
int fUnicodeClipboard = 1;
|
||||
|
||||
/* Parse command-line parameters */
|
||||
for (i = 1; i < argc; ++i)
|
||||
{
|
||||
/* Look for -display "display_name" or --display "display_name" */
|
||||
if (i < argc - 1
|
||||
&& (!strcmp (argv[i], "-display")
|
||||
|| !strcmp (argv[i], "--display")))
|
||||
{
|
||||
/* Grab a pointer to the display parameter */
|
||||
pszDisplay = argv[i + 1];
|
||||
|
||||
/* Skip the display argument */
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Look for -nounicodeclipboard */
|
||||
if (!strcmp (argv[i], "-nounicodeclipboard"))
|
||||
{
|
||||
fUnicodeClipboard = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Yack when we find a parameter that we don't know about */
|
||||
printf ("Unknown parameter: %s\nExiting.\n", argv[i]);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Do we have Unicode support? */
|
||||
if (fUnicodeClipboard)
|
||||
{
|
||||
printf ("Unicode clipboard I/O\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("Non Unicode clipboard I/O\n");
|
||||
}
|
||||
|
||||
/* Apply locale specified in the LANG environment variable */
|
||||
if (!setlocale (LC_ALL, ""))
|
||||
{
|
||||
printf ("setlocale() error\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* See if X supports the current locale */
|
||||
if (XSupportsLocale () == False)
|
||||
{
|
||||
printf ("Locale not supported by X, falling back to 'C' locale.\n");
|
||||
setlocale(LC_ALL, "C");
|
||||
}
|
||||
|
||||
winClipboardProc(fUnicodeClipboard, pszDisplay);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -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.
|
|
@ -31,25 +31,79 @@
|
|||
#ifdef HAVE_XWIN_CONFIG_H
|
||||
#include <xwin-config.h>
|
||||
#endif
|
||||
#include "dixstruct.h"
|
||||
#include "winclipboard.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "win.h"
|
||||
#include "winclipboard/winclipboard.h"
|
||||
#include "windisplay.h"
|
||||
|
||||
#define WIN_CLIPBOARD_RETRIES 40
|
||||
#define WIN_CLIPBOARD_DELAY 1
|
||||
|
||||
/*
|
||||
* Local typedefs
|
||||
* Local variables
|
||||
*/
|
||||
|
||||
typedef int (*winDispatchProcPtr) (ClientPtr);
|
||||
|
||||
int winProcSetSelectionOwner(ClientPtr /* client */ );
|
||||
static pthread_t g_ptClipboardProc;
|
||||
|
||||
/*
|
||||
* References to external symbols
|
||||
*
|
||||
*/
|
||||
static void *
|
||||
winClipboardThreadProc(void *arg)
|
||||
{
|
||||
char szDisplay[512];
|
||||
int clipboardRestarts = 0;
|
||||
|
||||
extern pthread_t g_ptClipboardProc;
|
||||
extern winDispatchProcPtr winProcSetSelectionOwnerOrig;
|
||||
extern Bool g_fClipboard;
|
||||
extern HWND g_hwndClipboard;
|
||||
while (1)
|
||||
{
|
||||
Bool fShutdown;
|
||||
|
||||
++clipboardRestarts;
|
||||
|
||||
/* Use our generated cookie for authentication */
|
||||
winSetAuthorization();
|
||||
|
||||
/* Setup the display connection string */
|
||||
/*
|
||||
* NOTE: Always connect to screen 0 since we require that screen
|
||||
* numbers start at 0 and increase without gaps. We only need
|
||||
* to connect to one screen on the display to get events
|
||||
* for all screens on the display. That is why there is only
|
||||
* one clipboard client thread.
|
||||
*/
|
||||
winGetDisplayName(szDisplay, 0);
|
||||
|
||||
/* Print the display connection string */
|
||||
ErrorF("winClipboardThreadProc - DISPLAY=%s\n", szDisplay);
|
||||
|
||||
/* Flag that clipboard client has been launched */
|
||||
g_fClipboardStarted = TRUE;
|
||||
|
||||
fShutdown = winClipboardProc(g_fUnicodeClipboard, szDisplay);
|
||||
|
||||
/* Flag that clipboard client has stopped */
|
||||
g_fClipboardStarted = FALSE;
|
||||
|
||||
if (fShutdown)
|
||||
break;
|
||||
|
||||
/* checking if we need to restart */
|
||||
if (clipboardRestarts >= WIN_CLIPBOARD_RETRIES) {
|
||||
/* terminates clipboard thread but the main server still lives */
|
||||
ErrorF("winClipboardProc - the clipboard thread has restarted %d times and seems to be unstable, disabling clipboard integration\n", clipboardRestarts);
|
||||
g_fClipboard = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,36 +33,21 @@
|
|||
#ifdef HAVE_XWIN_CONFIG_H
|
||||
#include <xwin-config.h>
|
||||
#endif
|
||||
|
||||
#include "win.h"
|
||||
#include "dixstruct.h"
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
||||
#define CLIP_NUM_SELECTIONS 2
|
||||
#define CLIP_OWN_PRIMARY 0
|
||||
#define CLIP_OWN_CLIPBOARD 1
|
||||
|
||||
/*
|
||||
* Local function prototypes
|
||||
*/
|
||||
|
||||
DISPATCH_PROC(winProcEstablishConnection);
|
||||
DISPATCH_PROC(winProcSetSelectionOwner);
|
||||
|
||||
/*
|
||||
* References to external symbols
|
||||
*/
|
||||
|
||||
extern Bool g_fClipboardLaunched;
|
||||
extern Bool g_fClipboardStarted;
|
||||
extern Bool g_fClipboard;
|
||||
extern Window g_iClipboardWindow;
|
||||
extern Atom g_atomLastOwnedSelection;
|
||||
extern HWND g_hwndClipboard;
|
||||
|
||||
|
||||
/*
|
||||
* Wrapper for internal EstablishConnection function.
|
||||
|
@ -127,13 +112,6 @@ winProcEstablishConnection(ClientPtr client)
|
|||
/* Clear original function pointer */
|
||||
winProcEstablishConnectionOrig = NULL;
|
||||
|
||||
/* If the clipboard client has already been started, abort */
|
||||
if (g_fClipboardLaunched) {
|
||||
ErrorF("winProcEstablishConnection - Clipboard client already "
|
||||
"launched, returning.\n");
|
||||
return iReturn;
|
||||
}
|
||||
|
||||
/* Startup the clipboard client if clipboard mode is being used */
|
||||
if (g_fClipboard) {
|
||||
/*
|
||||
|
@ -163,207 +141,5 @@ winProcEstablishConnection(ClientPtr client)
|
|||
ErrorF("winProcEstablishConnection - winInitClipboard returned.\n");
|
||||
}
|
||||
|
||||
/* Flag that clipboard client has been launched */
|
||||
g_fClipboardLaunched = TRUE;
|
||||
|
||||
return iReturn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper for internal SetSelectionOwner function.
|
||||
* Grabs ownership of Windows clipboard when X11 clipboard owner changes.
|
||||
*/
|
||||
|
||||
int
|
||||
winProcSetSelectionOwner(ClientPtr client)
|
||||
{
|
||||
int i;
|
||||
DrawablePtr pDrawable;
|
||||
WindowPtr pWindow = None;
|
||||
Bool fOwnedToNotOwned = FALSE;
|
||||
static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None };
|
||||
static unsigned long s_ulServerGeneration = 0;
|
||||
|
||||
REQUEST(xSetSelectionOwnerReq);
|
||||
|
||||
REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
|
||||
|
||||
winDebug("winProcSetSelectionOwner - Hello.\n");
|
||||
|
||||
/* Watch for server reset */
|
||||
if (s_ulServerGeneration != serverGeneration) {
|
||||
/* Save new generation number */
|
||||
s_ulServerGeneration = serverGeneration;
|
||||
|
||||
/* Initialize static variables */
|
||||
for (i = 0; i < CLIP_NUM_SELECTIONS; ++i)
|
||||
s_iOwners[i] = None;
|
||||
}
|
||||
|
||||
/* Abort if clipboard not completely initialized yet */
|
||||
if (!g_fClipboardStarted) {
|
||||
/* ErrorF ("winProcSetSelectionOwner - Clipboard not yet started, "
|
||||
"aborting.\n"); */
|
||||
goto winProcSetSelectionOwner_Done;
|
||||
}
|
||||
|
||||
/* Grab window if we have one */
|
||||
if (None != stuff->window) {
|
||||
/* Grab the Window from the request */
|
||||
int rc =
|
||||
dixLookupWindow(&pWindow, stuff->window, client, DixReadAccess);
|
||||
if (rc != Success) {
|
||||
ErrorF("winProcSetSelectionOwner - Found BadWindow, aborting.\n");
|
||||
goto winProcSetSelectionOwner_Done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we either have a valid window or None */
|
||||
|
||||
/* Save selection owners for monitored selections, ignore other selections */
|
||||
if (XA_PRIMARY == stuff->selection) {
|
||||
/* Look for owned -> not owned transition */
|
||||
if (None == stuff->window && None != s_iOwners[CLIP_OWN_PRIMARY]) {
|
||||
fOwnedToNotOwned = TRUE;
|
||||
|
||||
winDebug("winProcSetSelectionOwner - PRIMARY - Going from "
|
||||
"owned to not owned.\n");
|
||||
|
||||
/* Adjust last owned selection */
|
||||
if (None != s_iOwners[CLIP_OWN_CLIPBOARD])
|
||||
g_atomLastOwnedSelection = MakeAtom("CLIPBOARD", 9, TRUE);
|
||||
else
|
||||
g_atomLastOwnedSelection = None;
|
||||
}
|
||||
|
||||
/* Save new selection owner or None */
|
||||
s_iOwners[CLIP_OWN_PRIMARY] = stuff->window;
|
||||
|
||||
winDebug("winProcSetSelectionOwner - PRIMARY - Now owned by: %d\n",
|
||||
stuff->window);
|
||||
}
|
||||
else if (MakeAtom("CLIPBOARD", 9, TRUE) == stuff->selection) {
|
||||
/* Look for owned -> not owned transition */
|
||||
if (None == stuff->window && None != s_iOwners[CLIP_OWN_CLIPBOARD]) {
|
||||
fOwnedToNotOwned = TRUE;
|
||||
|
||||
winDebug("winProcSetSelectionOwner - CLIPBOARD - Going from "
|
||||
"owned to not owned.\n");
|
||||
|
||||
/* Adjust last owned selection */
|
||||
if (None != s_iOwners[CLIP_OWN_PRIMARY])
|
||||
g_atomLastOwnedSelection = XA_PRIMARY;
|
||||
else
|
||||
g_atomLastOwnedSelection = None;
|
||||
}
|
||||
|
||||
/* Save new selection owner or None */
|
||||
s_iOwners[CLIP_OWN_CLIPBOARD] = stuff->window;
|
||||
|
||||
winDebug("winProcSetSelectionOwner - CLIPBOARD - Now owned by: %d\n",
|
||||
stuff->window);
|
||||
|
||||
}
|
||||
else
|
||||
goto winProcSetSelectionOwner_Done;
|
||||
|
||||
/*
|
||||
* At this point, if one of the selections is still owned by the
|
||||
* clipboard manager then it should be marked as unowned since
|
||||
* we will be taking ownership of the Win32 clipboard.
|
||||
*/
|
||||
if (g_iClipboardWindow == s_iOwners[CLIP_OWN_PRIMARY])
|
||||
s_iOwners[CLIP_OWN_PRIMARY] = None;
|
||||
if (g_iClipboardWindow == s_iOwners[CLIP_OWN_CLIPBOARD])
|
||||
s_iOwners[CLIP_OWN_CLIPBOARD] = None;
|
||||
|
||||
/*
|
||||
* Handle case when selection is being disowned,
|
||||
* WM_DRAWCLIPBOARD did not do the disowning,
|
||||
* both monitored selections are no longer owned,
|
||||
* an owned to not owned transition was detected,
|
||||
* and we currently own the Win32 clipboard.
|
||||
*/
|
||||
if (stuff->window == None
|
||||
&& s_iOwners[CLIP_OWN_PRIMARY] == None
|
||||
&& s_iOwners[CLIP_OWN_CLIPBOARD] == None
|
||||
&& fOwnedToNotOwned
|
||||
&& g_hwndClipboard != NULL && g_hwndClipboard == GetClipboardOwner()) {
|
||||
winDebug("winProcSetSelectionOwner - We currently own the "
|
||||
"clipboard and neither the PRIMARY nor the CLIPBOARD "
|
||||
"selections are owned, releasing ownership of Win32 "
|
||||
"clipboard.\n");
|
||||
|
||||
/* Release ownership of the Windows clipboard */
|
||||
OpenClipboard(NULL);
|
||||
EmptyClipboard();
|
||||
CloseClipboard();
|
||||
|
||||
goto winProcSetSelectionOwner_Done;
|
||||
}
|
||||
|
||||
/* Abort if no window at this point */
|
||||
if (None == stuff->window) {
|
||||
winDebug("winProcSetSelectionOwner - No window, returning.\n");
|
||||
goto winProcSetSelectionOwner_Done;
|
||||
}
|
||||
|
||||
/* Abort if invalid selection */
|
||||
if (!ValidAtom(stuff->selection)) {
|
||||
ErrorF("winProcSetSelectionOwner - Found BadAtom, aborting.\n");
|
||||
goto winProcSetSelectionOwner_Done;
|
||||
}
|
||||
|
||||
/* Cast Window to Drawable */
|
||||
pDrawable = (DrawablePtr) pWindow;
|
||||
|
||||
/* Abort if clipboard manager is owning the selection */
|
||||
if (pDrawable->id == g_iClipboardWindow) {
|
||||
winDebug("winProcSetSelectionOwner - We changed ownership, "
|
||||
"aborting.\n");
|
||||
goto winProcSetSelectionOwner_Done;
|
||||
}
|
||||
|
||||
/* Abort if root window is taking ownership */
|
||||
if (pDrawable->id == 0) {
|
||||
ErrorF("winProcSetSelectionOwner - Root window taking ownership, "
|
||||
"aborting\n");
|
||||
goto winProcSetSelectionOwner_Done;
|
||||
}
|
||||
|
||||
/* Close clipboard if we have it open already */
|
||||
if (GetOpenClipboardWindow() == g_hwndClipboard) {
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
/* Access the Windows clipboard */
|
||||
if (!OpenClipboard(g_hwndClipboard)) {
|
||||
ErrorF("winProcSetSelectionOwner - OpenClipboard () failed: %08x\n",
|
||||
(int) GetLastError());
|
||||
goto winProcSetSelectionOwner_Done;
|
||||
}
|
||||
|
||||
/* Take ownership of the Windows clipboard */
|
||||
if (!EmptyClipboard()) {
|
||||
ErrorF("winProcSetSelectionOwner - EmptyClipboard () failed: %08x\n",
|
||||
(int) GetLastError());
|
||||
goto winProcSetSelectionOwner_Done;
|
||||
}
|
||||
|
||||
/* Advertise regular text and unicode */
|
||||
SetClipboardData(CF_UNICODETEXT, NULL);
|
||||
SetClipboardData(CF_TEXT, NULL);
|
||||
|
||||
/* Save handle to last owned selection */
|
||||
g_atomLastOwnedSelection = stuff->selection;
|
||||
|
||||
/* Release the clipboard */
|
||||
if (!CloseClipboard()) {
|
||||
ErrorF("winProcSetSelectionOwner - CloseClipboard () failed: "
|
||||
"%08x\n", (int) GetLastError());
|
||||
goto winProcSetSelectionOwner_Done;
|
||||
}
|
||||
|
||||
winProcSetSelectionOwner_Done:
|
||||
return (*winProcSetSelectionOwnerOrig) (client);
|
||||
}
|
||||
|
|
|
@ -36,13 +36,6 @@
|
|||
#include <shellapi.h>
|
||||
#include "winprefs.h"
|
||||
|
||||
/*
|
||||
* References to external globals
|
||||
*/
|
||||
|
||||
#ifdef XWIN_CLIPBOARD
|
||||
extern Bool g_fClipboardStarted;
|
||||
#endif
|
||||
/*
|
||||
* Local function prototypes
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -42,6 +42,9 @@
|
|||
#include "winmsg.h"
|
||||
#include "winmonitors.h"
|
||||
#include "inputstr.h"
|
||||
#ifdef XWIN_CLIPBOARD
|
||||
#include "winclipboard/winclipboard.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Global variables
|
||||
|
|
Loading…
Reference in New Issue