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_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support])
|
||||||
AC_CHECK_TOOL(WINDRES, windres)
|
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
|
if test "x$WINDOWSWM" = xauto; then
|
||||||
PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no])
|
PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no])
|
||||||
|
@ -2600,6 +2600,7 @@ hw/xnest/man/Makefile
|
||||||
hw/xwin/Makefile
|
hw/xwin/Makefile
|
||||||
hw/xwin/glx/Makefile
|
hw/xwin/glx/Makefile
|
||||||
hw/xwin/man/Makefile
|
hw/xwin/man/Makefile
|
||||||
|
hw/xwin/winclipboard/Makefile
|
||||||
hw/xquartz/Makefile
|
hw/xquartz/Makefile
|
||||||
hw/xquartz/GL/Makefile
|
hw/xquartz/GL/Makefile
|
||||||
hw/xquartz/bundle/Makefile
|
hw/xquartz/bundle/Makefile
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
|
|
||||||
#ifdef XWIN_CLIPBOARD
|
#ifdef XWIN_CLIPBOARD
|
||||||
int winProcEstablishConnection(ClientPtr /* client */ );
|
int winProcEstablishConnection(ClientPtr /* client */ );
|
||||||
int winProcSetSelectionOwner(ClientPtr /* client */ );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -66,24 +66,11 @@ typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner,
|
||||||
/*
|
/*
|
||||||
* References to external symbols
|
* 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
|
* Function prototypes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef XWIN_CLIPBOARD
|
|
||||||
static void
|
|
||||||
winClipboardShutdown(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static Bool
|
static Bool
|
||||||
winCheckDisplayNumber(void);
|
winCheckDisplayNumber(void);
|
||||||
|
|
||||||
|
@ -125,31 +112,6 @@ static PixmapFormatRec g_PixmapFormats[] = {
|
||||||
|
|
||||||
const int NUMFORMATS = sizeof(g_PixmapFormats) / sizeof(g_PixmapFormats[0]);
|
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[] = {
|
static const ExtensionModule xwinExtensions[] = {
|
||||||
#ifdef GLXEXT
|
#ifdef GLXEXT
|
||||||
{ GlxExtensionInit, "GLX", &noGlxExtension },
|
{ GlxExtensionInit, "GLX", &noGlxExtension },
|
||||||
|
|
|
@ -3,12 +3,9 @@ bin_PROGRAMS = XWin
|
||||||
if XWIN_CLIPBOARD
|
if XWIN_CLIPBOARD
|
||||||
SRCS_CLIPBOARD = \
|
SRCS_CLIPBOARD = \
|
||||||
winclipboardinit.c \
|
winclipboardinit.c \
|
||||||
winclipboardtextconv.c \
|
winclipboardwrappers.c
|
||||||
winclipboardthread.c \
|
|
||||||
winclipboardwndproc.c \
|
|
||||||
winclipboardwrappers.c \
|
|
||||||
winclipboardxevents.c
|
|
||||||
DEFS_CLIPBOARD = -DXWIN_CLIPBOARD
|
DEFS_CLIPBOARD = -DXWIN_CLIPBOARD
|
||||||
|
CLIPBOARD_LIBS = $(top_builddir)/hw/xwin/winclipboard/libXWinclipboard.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if XWIN_GLX_WINDOWS
|
if XWIN_GLX_WINDOWS
|
||||||
|
@ -110,7 +107,6 @@ SRCS = InitInput.c \
|
||||||
winwindow.c \
|
winwindow.c \
|
||||||
winwndproc.c \
|
winwndproc.c \
|
||||||
ddraw.h \
|
ddraw.h \
|
||||||
winclipboard.h \
|
|
||||||
winconfig.h \
|
winconfig.h \
|
||||||
win.h \
|
win.h \
|
||||||
winglobals.h \
|
winglobals.h \
|
||||||
|
@ -162,12 +158,15 @@ XWin_DEPENDENCIES = \
|
||||||
$(MULTIWINDOWEXTWM_LIBS) \
|
$(MULTIWINDOWEXTWM_LIBS) \
|
||||||
$(XWIN_GLX_LIBS) \
|
$(XWIN_GLX_LIBS) \
|
||||||
$(XWIN_LIBS) \
|
$(XWIN_LIBS) \
|
||||||
|
$(CLIPBOARD_LIBS) \
|
||||||
$(XSERVER_LIBS)
|
$(XSERVER_LIBS)
|
||||||
|
|
||||||
|
|
||||||
XWin_LDADD = \
|
XWin_LDADD = \
|
||||||
$(MULTIWINDOWEXTWM_LIBS) \
|
$(MULTIWINDOWEXTWM_LIBS) \
|
||||||
$(XWIN_GLX_LIBS) \
|
$(XWIN_GLX_LIBS) \
|
||||||
$(XWIN_LIBS) \
|
$(XWIN_LIBS) \
|
||||||
|
$(CLIPBOARD_LIBS) \
|
||||||
$(XSERVER_LIBS) \
|
$(XSERVER_LIBS) \
|
||||||
$(XWIN_GLX_SYS_LIBS) \
|
$(XWIN_GLX_SYS_LIBS) \
|
||||||
$(XSERVER_SYS_LIBS) \
|
$(XSERVER_SYS_LIBS) \
|
||||||
|
@ -210,5 +209,5 @@ EXTRA_DIST = \
|
||||||
relink:
|
relink:
|
||||||
$(AM_V_at)rm -f XWin$(EXEEXT) && $(MAKE) XWin$(EXEEXT)
|
$(AM_V_at)rm -f XWin$(EXEEXT) && $(MAKE) XWin$(EXEEXT)
|
||||||
|
|
||||||
SUBDIRS = man $(GLX_DIR) .
|
SUBDIRS = man $(GLX_DIR) winclipboard .
|
||||||
DIST_SUBDIRS = man glx .
|
DIST_SUBDIRS = man glx winclipboard .
|
||||||
|
|
|
@ -793,7 +793,7 @@ Bool
|
||||||
winInitClipboard(void);
|
winInitClipboard(void);
|
||||||
|
|
||||||
void
|
void
|
||||||
winFixClipboardChain(void);
|
winClipboardShutdown(void);
|
||||||
#endif
|
#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.
|
*Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
|
||||||
*
|
*
|
||||||
|
@ -30,46 +29,18 @@
|
||||||
* Authors: Harold L Hunt II
|
* Authors: Harold L Hunt II
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Standard library headers */
|
#ifndef WINCLIPBOARD_INTERNAL_H
|
||||||
#include <assert.h>
|
#define WINCLIPBOARD_INTERNAL_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>
|
|
||||||
|
|
||||||
/* X headers */
|
/* X headers */
|
||||||
#include <X11/X.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xatom.h>
|
|
||||||
#include <X11/Xproto.h>
|
|
||||||
#include <X11/Xutil.h>
|
|
||||||
#include <X11/Xlocale.h>
|
|
||||||
|
|
||||||
/* Windows headers */
|
/* Windows headers */
|
||||||
#include <X11/Xwindows.h>
|
#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_SUCCESS 0
|
||||||
#define WIN_XEVENTS_CONVERT 2
|
#define WIN_XEVENTS_CONVERT 2
|
||||||
#define WIN_XEVENTS_NOTIFY 3
|
#define WIN_XEVENTS_NOTIFY 3
|
||||||
#define WIN_CLIPBOARD_RETRIES 40
|
|
||||||
#define WIN_CLIPBOARD_DELAY 1
|
|
||||||
|
|
||||||
#define WM_WM_REINIT (WM_USER + 1)
|
#define WM_WM_REINIT (WM_USER + 1)
|
||||||
|
|
||||||
|
@ -77,18 +48,8 @@
|
||||||
* References to external symbols
|
* References to external symbols
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern char *display;
|
|
||||||
extern void winDebug(const char *format, ...);
|
extern void winDebug(const char *format, ...);
|
||||||
extern void winErrorFVerb(int verb, const char *format, ...);
|
extern void ErrorF(const char *format, ...);
|
||||||
|
|
||||||
/*
|
|
||||||
* winclipboardinit.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
Bool
|
|
||||||
winInitClipboard(void);
|
|
||||||
|
|
||||||
HWND winClipboardCreateMessagingWindow(void);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* winclipboardtextconv.c
|
* winclipboardtextconv.c
|
||||||
|
@ -104,23 +65,45 @@ void
|
||||||
* winclipboardthread.c
|
* winclipboardthread.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void *winClipboardProc(void *);
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Atom atomClipboard;
|
||||||
|
Atom atomLocalProperty;
|
||||||
|
Atom atomUTF8String;
|
||||||
|
Atom atomCompoundText;
|
||||||
|
Atom atomTargets;
|
||||||
|
} ClipboardAtoms;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* winclipboardwndproc.c
|
* winclipboardwndproc.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL winClipboardFlushWindowsMessageQueue(HWND hwnd);
|
Bool winClipboardFlushWindowsMessageQueue(HWND hwnd);
|
||||||
|
|
||||||
LRESULT CALLBACK
|
LRESULT CALLBACK
|
||||||
winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Display *pClipboardDisplay;
|
||||||
|
Window iClipboardWindow;
|
||||||
|
ClipboardAtoms *atoms;
|
||||||
|
} ClipboardWindowCreationParams;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* winclipboardxevents.c
|
* winclipboardxevents.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
||||||
winClipboardFlushXEvents(HWND hwnd,
|
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
|
#endif
|
|
@ -31,14 +31,18 @@
|
||||||
#ifdef HAVE_XWIN_CONFIG_H
|
#ifdef HAVE_XWIN_CONFIG_H
|
||||||
#include <xwin-config.h>
|
#include <xwin-config.h>
|
||||||
#endif
|
#endif
|
||||||
#include "win.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
void
|
/*
|
||||||
winClipboardDOStoUNIX(char *pszSrc, int iLength);
|
* Including any server header might define the macro _XSERVER64 on 64 bit machines.
|
||||||
void
|
* That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
|
||||||
winClipboardUNIXtoDOS(char **ppszData, int iLength);
|
* So let's undef that macro if necessary.
|
||||||
|
*/
|
||||||
|
#ifdef _XSERVER64
|
||||||
|
#undef _XSERVER64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert \r\n to \n
|
* Convert \r\n to \n
|
|
@ -35,42 +35,62 @@
|
||||||
#else
|
#else
|
||||||
#define HAS_WINSOCK 1
|
#define HAS_WINSOCK 1
|
||||||
#endif
|
#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;
|
#include <assert.h>
|
||||||
extern Bool g_fClipboardStarted;
|
#include <unistd.h>
|
||||||
extern Bool g_fClipboardLaunched;
|
#include <fcntl.h>
|
||||||
extern Bool g_fClipboard;
|
#include <setjmp.h>
|
||||||
extern HWND g_hwndClipboard;
|
#include <pthread.h>
|
||||||
extern void *g_pClipboardDisplay;
|
#include <sys/param.h> // for MAX() macro
|
||||||
extern Window g_iClipboardWindow;
|
|
||||||
|
#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
|
* Global variables
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static HWND g_hwndClipboard = NULL;
|
||||||
static jmp_buf g_jmpEntry;
|
static jmp_buf g_jmpEntry;
|
||||||
static int clipboardRestarts = 0;
|
|
||||||
static XIOErrorHandler g_winClipboardOldIOErrorHandler;
|
static XIOErrorHandler g_winClipboardOldIOErrorHandler;
|
||||||
static pthread_t g_winClipboardProcThread;
|
static pthread_t g_winClipboardProcThread;
|
||||||
|
|
||||||
Bool g_fUseUnicode = FALSE;
|
int xfixes_event_base;
|
||||||
|
int xfixes_error_base;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local function prototypes
|
* Local function prototypes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static HWND
|
||||||
|
winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr);
|
winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr);
|
||||||
|
|
||||||
|
@ -78,13 +98,15 @@ static int
|
||||||
winClipboardIOErrorHandler(Display * pDisplay);
|
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 *
|
Bool
|
||||||
winClipboardProc(void *pvNotUsed)
|
winClipboardProc(Bool fUseUnicode, char *szDisplay)
|
||||||
{
|
{
|
||||||
Atom atomClipboard;
|
ClipboardAtoms atoms;
|
||||||
int iReturn;
|
int iReturn;
|
||||||
HWND hwnd = NULL;
|
HWND hwnd = NULL;
|
||||||
int iConnectionNumber = 0;
|
int iConnectionNumber = 0;
|
||||||
|
@ -98,19 +120,11 @@ winClipboardProc(void *pvNotUsed)
|
||||||
int iMaxDescriptor;
|
int iMaxDescriptor;
|
||||||
Display *pDisplay = NULL;
|
Display *pDisplay = NULL;
|
||||||
Window iWindow = None;
|
Window iWindow = None;
|
||||||
int iRetries;
|
|
||||||
Bool fUseUnicode;
|
|
||||||
char szDisplay[512];
|
|
||||||
int iSelectError;
|
int iSelectError;
|
||||||
|
Bool fShutdown = FALSE;
|
||||||
|
static Bool fErrorHandlerSet = FALSE;
|
||||||
|
|
||||||
winDebug("winClipboardProc - Hello\n");
|
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 */
|
/* Allow multiple threads to access Xlib */
|
||||||
if (XInitThreads() == 0) {
|
if (XInitThreads() == 0) {
|
||||||
|
@ -123,70 +137,29 @@ winClipboardProc(void *pvNotUsed)
|
||||||
ErrorF("winClipboardProc - Warning: Locale not supported by X.\n");
|
ErrorF("winClipboardProc - Warning: Locale not supported by X.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set error handler */
|
|
||||||
XSetErrorHandler(winClipboardErrorHandler);
|
|
||||||
g_winClipboardProcThread = pthread_self();
|
g_winClipboardProcThread = pthread_self();
|
||||||
|
|
||||||
|
/* Set error handler */
|
||||||
|
if (!fErrorHandlerSet) {
|
||||||
|
XSetErrorHandler(winClipboardErrorHandler);
|
||||||
g_winClipboardOldIOErrorHandler =
|
g_winClipboardOldIOErrorHandler =
|
||||||
XSetIOErrorHandler(winClipboardIOErrorHandler);
|
XSetIOErrorHandler(winClipboardIOErrorHandler);
|
||||||
|
fErrorHandlerSet = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set jump point for Error exits */
|
/* Set jump point for Error exits */
|
||||||
iReturn = setjmp(g_jmpEntry);
|
if (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");
|
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 */
|
/* Make sure that the display opened */
|
||||||
|
pDisplay = XOpenDisplay(szDisplay);
|
||||||
if (pDisplay == NULL) {
|
if (pDisplay == NULL) {
|
||||||
ErrorF("winClipboardProc - Failed opening the display, giving up\n");
|
ErrorF("winClipboardProc - Failed opening the display, giving up\n");
|
||||||
goto winClipboardProc_Done;
|
goto winClipboardProc_Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the display in the screen privates */
|
|
||||||
g_pClipboardDisplay = pDisplay;
|
|
||||||
|
|
||||||
ErrorF("winClipboardProc - XOpenDisplay () returned and "
|
ErrorF("winClipboardProc - XOpenDisplay () returned and "
|
||||||
"successfully opened the display.\n");
|
"successfully opened the display.\n");
|
||||||
|
|
||||||
|
@ -202,13 +175,20 @@ winClipboardProc(void *pvNotUsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find max of our file descriptors */
|
/* Find max of our file descriptors */
|
||||||
iMaxDescriptor = max(fdMessageQueue, iConnectionNumber) + 1;
|
iMaxDescriptor = MAX(fdMessageQueue, iConnectionNumber) + 1;
|
||||||
#else
|
#else
|
||||||
iMaxDescriptor = iConnectionNumber + 1;
|
iMaxDescriptor = iConnectionNumber + 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Create atom */
|
if (!XFixesQueryExtension(pDisplay, &xfixes_event_base, &xfixes_error_base))
|
||||||
atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
|
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 */
|
/* Create a messaging window */
|
||||||
iWindow = XCreateSimpleWindow(pDisplay,
|
iWindow = XCreateSimpleWindow(pDisplay,
|
||||||
|
@ -230,13 +210,27 @@ winClipboardProc(void *pvNotUsed)
|
||||||
ErrorF("winClipboardProc - XSelectInput generated BadWindow "
|
ErrorF("winClipboardProc - XSelectInput generated BadWindow "
|
||||||
"on messaging window\n");
|
"on messaging window\n");
|
||||||
|
|
||||||
/* Save the window in the screen privates */
|
XFixesSelectSelectionInput (pDisplay,
|
||||||
g_iClipboardWindow = iWindow;
|
iWindow,
|
||||||
|
XA_PRIMARY,
|
||||||
|
XFixesSetSelectionOwnerNotifyMask |
|
||||||
|
XFixesSelectionWindowDestroyNotifyMask |
|
||||||
|
XFixesSelectionClientCloseNotifyMask);
|
||||||
|
|
||||||
|
XFixesSelectSelectionInput (pDisplay,
|
||||||
|
iWindow,
|
||||||
|
atoms.atomClipboard,
|
||||||
|
XFixesSetSelectionOwnerNotifyMask |
|
||||||
|
XFixesSelectionWindowDestroyNotifyMask |
|
||||||
|
XFixesSelectionClientCloseNotifyMask);
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialize monitored selection state */
|
||||||
|
winClipboardInitMonitoredSelections();
|
||||||
/* Create Windows messaging window */
|
/* 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;
|
g_hwndClipboard = hwnd;
|
||||||
|
|
||||||
/* Assert ownership of selections if Win32 clipboard is owned */
|
/* Assert ownership of selections if Win32 clipboard is owned */
|
||||||
|
@ -251,10 +245,10 @@ winClipboardProc(void *pvNotUsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CLIPBOARD */
|
/* CLIPBOARD */
|
||||||
iReturn = XSetSelectionOwner(pDisplay, atomClipboard,
|
iReturn = XSetSelectionOwner(pDisplay, atoms.atomClipboard,
|
||||||
iWindow, CurrentTime);
|
iWindow, CurrentTime);
|
||||||
if (iReturn == BadAtom || iReturn == BadWindow ||
|
if (iReturn == BadAtom || iReturn == BadWindow ||
|
||||||
XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
|
XGetSelectionOwner(pDisplay, atoms.atomClipboard) != iWindow) {
|
||||||
ErrorF("winClipboardProc - Could not set CLIPBOARD owner\n");
|
ErrorF("winClipboardProc - Could not set CLIPBOARD owner\n");
|
||||||
goto winClipboardProc_Done;
|
goto winClipboardProc_Done;
|
||||||
}
|
}
|
||||||
|
@ -266,14 +260,12 @@ winClipboardProc(void *pvNotUsed)
|
||||||
* because there may be events in local data structures
|
* because there may be events in local data structures
|
||||||
* already.
|
* already.
|
||||||
*/
|
*/
|
||||||
winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
|
winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms);
|
||||||
|
|
||||||
/* Pre-flush Windows messages */
|
/* Pre-flush Windows messages */
|
||||||
if (!winClipboardFlushWindowsMessageQueue(hwnd))
|
if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
|
||||||
return 0;
|
ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue failed\n");
|
||||||
|
}
|
||||||
/* Signal that the clipboard client has started */
|
|
||||||
g_fClipboardStarted = TRUE;
|
|
||||||
|
|
||||||
/* Loop for X events */
|
/* Loop for X events */
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -326,7 +318,7 @@ winClipboardProc(void *pvNotUsed)
|
||||||
/* Branch on which descriptor became active */
|
/* Branch on which descriptor became active */
|
||||||
if (FD_ISSET(iConnectionNumber, &fdsRead)) {
|
if (FD_ISSET(iConnectionNumber, &fdsRead)) {
|
||||||
/* Process X events */
|
/* Process X events */
|
||||||
winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
|
winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_DEVWINDOWS
|
#ifdef HAS_DEVWINDOWS
|
||||||
|
@ -347,16 +339,13 @@ winClipboardProc(void *pvNotUsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
winClipboardProc_Exit:
|
winClipboardProc_Exit:
|
||||||
/* disable the clipboard, which means the thread will die */
|
/* broke out of while loop on a shutdown message */
|
||||||
g_fClipboard = FALSE;
|
fShutdown = TRUE;
|
||||||
|
|
||||||
winClipboardProc_Done:
|
winClipboardProc_Done:
|
||||||
/* Close our Windows window */
|
/* Close our Windows window */
|
||||||
if (g_hwndClipboard) {
|
if (g_hwndClipboard) {
|
||||||
/* Destroy the Window window (hwnd) */
|
winClipboardWindowDestroy();
|
||||||
winDebug("winClipboardProc - Destroy Windows window\n");
|
|
||||||
PostMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
|
|
||||||
winClipboardFlushWindowsMessageQueue(g_hwndClipboard);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close our X window */
|
/* Close our X window */
|
||||||
|
@ -376,8 +365,11 @@ winClipboardProc(void *pvNotUsed)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
* FIXME: XCloseDisplay hangs if we call it, as of 2004/03/26. The
|
* FIXME: XCloseDisplay hangs if we call it
|
||||||
* XSync and XSelectInput calls did not help.
|
*
|
||||||
|
* 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 */
|
/* Discard any remaining events */
|
||||||
|
@ -393,42 +385,64 @@ winClipboardProc(void *pvNotUsed)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* global clipboard variable reset */
|
/* global clipboard variable reset */
|
||||||
g_fClipboardLaunched = FALSE;
|
|
||||||
g_fClipboardStarted = FALSE;
|
|
||||||
g_iClipboardWindow = None;
|
|
||||||
g_pClipboardDisplay = NULL;
|
|
||||||
g_hwndClipboard = NULL;
|
g_hwndClipboard = NULL;
|
||||||
|
|
||||||
/* checking if we need to restart */
|
return fShutdown;
|
||||||
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);
|
* Create the Windows window that we use to receive Windows messages
|
||||||
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");
|
static HWND
|
||||||
/* Flag that clipboard client has been launched */
|
winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms)
|
||||||
g_fClipboardLaunched = TRUE;
|
{
|
||||||
}
|
WNDCLASSEX wc;
|
||||||
else {
|
ClipboardWindowCreationParams cwcp;
|
||||||
ErrorF("winClipboardProc - Clipboard disabled - Exit from server \n");
|
HWND hwnd;
|
||||||
/* clipboard thread has exited, stop server as well */
|
|
||||||
raise(SIGTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)) {
|
if (pthread_equal(pthread_self(), g_winClipboardProcThread)) {
|
||||||
/* Restart at the main entry point */
|
/* Restart at the main entry point */
|
||||||
longjmp(g_jmpEntry, WIN_JMP_ERROR_IO);
|
longjmp(g_jmpEntry, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_winClipboardOldIOErrorHandler)
|
if (g_winClipboardOldIOErrorHandler)
|
||||||
|
@ -466,3 +480,19 @@ winClipboardIOErrorHandler(Display * pDisplay)
|
||||||
|
|
||||||
return 0;
|
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
|
#ifdef HAVE_XWIN_CONFIG_H
|
||||||
#include <xwin-config.h>
|
#include <xwin-config.h>
|
||||||
#endif
|
#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/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
#include "winclipboard.h"
|
#include "winclipboard.h"
|
||||||
#include "misc.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
|
@ -44,21 +57,14 @@
|
||||||
|
|
||||||
#define WIN_POLL_TIMEOUT 1
|
#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
|
* Process X events up to specified timeout
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
|
winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay,
|
||||||
Bool fUseUnicode, int iTimeoutSec)
|
Bool fUseUnicode, ClipboardAtoms *atoms, int iTimeoutSec)
|
||||||
{
|
{
|
||||||
int iConnNumber;
|
int iConnNumber;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
@ -111,7 +117,7 @@ winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
|
||||||
/* Process X events */
|
/* Process X events */
|
||||||
/* Exit when we see that server is shutting down */
|
/* Exit when we see that server is shutting down */
|
||||||
iReturn = winClipboardFlushXEvents(hwnd,
|
iReturn = winClipboardFlushXEvents(hwnd,
|
||||||
iWindow, pDisplay, fUseUnicode);
|
iWindow, pDisplay, fUseUnicode, atoms);
|
||||||
|
|
||||||
winDebug
|
winDebug
|
||||||
("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n",
|
("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n",
|
||||||
|
@ -139,6 +145,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
static HWND s_hwndNextViewer;
|
static HWND s_hwndNextViewer;
|
||||||
static Bool s_fCBCInitialized;
|
static Bool s_fCBCInitialized;
|
||||||
|
static Display *pDisplay;
|
||||||
|
static Window iWindow;
|
||||||
|
static ClipboardAtoms *atoms;
|
||||||
|
|
||||||
/* Branch on message type */
|
/* Branch on message type */
|
||||||
switch (message) {
|
switch (message) {
|
||||||
|
@ -159,9 +168,14 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
HWND first, next;
|
HWND first, next;
|
||||||
DWORD error_code = 0;
|
DWORD error_code = 0;
|
||||||
|
ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams;
|
||||||
|
|
||||||
winDebug("winClipboardWindowProc - WM_CREATE\n");
|
winDebug("winClipboardWindowProc - WM_CREATE\n");
|
||||||
|
|
||||||
|
pDisplay = cwcp->pClipboardDisplay;
|
||||||
|
iWindow = cwcp->iClipboardWindow;
|
||||||
|
atoms = cwcp->atoms;
|
||||||
|
|
||||||
first = GetClipboardViewer(); /* Get handle to first viewer in chain. */
|
first = GetClipboardViewer(); /* Get handle to first viewer in chain. */
|
||||||
if (first == hwnd)
|
if (first == hwnd)
|
||||||
return 0; /* Make sure it's not us! */
|
return 0; /* Make sure it's not us! */
|
||||||
|
@ -185,7 +199,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
s_hwndNextViewer = (HWND) lParam;
|
s_hwndNextViewer = (HWND) lParam;
|
||||||
if (s_hwndNextViewer == hwnd) {
|
if (s_hwndNextViewer == hwnd) {
|
||||||
s_hwndNextViewer = NULL;
|
s_hwndNextViewer = NULL;
|
||||||
winErrorFVerb(1, "winClipboardWindowProc - WM_CHANGECBCHAIN: "
|
ErrorF("winClipboardWindowProc - WM_CHANGECBCHAIN: "
|
||||||
"attempted to set next window to ourselves.");
|
"attempted to set next window to ourselves.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,20 +255,11 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
|
||||||
case WM_DRAWCLIPBOARD:
|
case WM_DRAWCLIPBOARD:
|
||||||
{
|
{
|
||||||
static Atom atomClipboard;
|
|
||||||
static int generation;
|
|
||||||
static Bool s_fProcessingDrawClipboard = FALSE;
|
static Bool s_fProcessingDrawClipboard = FALSE;
|
||||||
Display *pDisplay = g_pClipboardDisplay;
|
|
||||||
Window iWindow = g_iClipboardWindow;
|
|
||||||
int iReturn;
|
int iReturn;
|
||||||
|
|
||||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
|
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.
|
* We've occasionally seen a loop in the clipboard chain.
|
||||||
* Try and fix it on the first hint of recursion.
|
* Try and fix it on the first hint of recursion.
|
||||||
|
@ -267,7 +272,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
s_fCBCInitialized = FALSE;
|
s_fCBCInitialized = FALSE;
|
||||||
ChangeClipboardChain(hwnd, s_hwndNextViewer);
|
ChangeClipboardChain(hwnd, s_hwndNextViewer);
|
||||||
winFixClipboardChain();
|
winFixClipboardChain();
|
||||||
winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||||
"Nested calls detected. Re-initing.\n");
|
"Nested calls detected. Re-initing.\n");
|
||||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
|
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
|
||||||
s_fProcessingDrawClipboard = FALSE;
|
s_fProcessingDrawClipboard = FALSE;
|
||||||
|
@ -324,26 +329,26 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
|
||||||
/* Release PRIMARY selection if owned */
|
/* Release PRIMARY selection if owned */
|
||||||
iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY);
|
iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY);
|
||||||
if (iReturn == g_iClipboardWindow) {
|
if (iReturn == iWindow) {
|
||||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||||
"PRIMARY selection is owned by us.\n");
|
"PRIMARY selection is owned by us.\n");
|
||||||
XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime);
|
XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime);
|
||||||
}
|
}
|
||||||
else if (BadWindow == iReturn || BadAtom == iReturn)
|
else if (BadWindow == iReturn || BadAtom == iReturn)
|
||||||
winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||||
"XGetSelection failed for PRIMARY: %d\n",
|
"XGetSelectionOwner failed for PRIMARY: %d\n",
|
||||||
iReturn);
|
iReturn);
|
||||||
|
|
||||||
/* Release CLIPBOARD selection if owned */
|
/* Release CLIPBOARD selection if owned */
|
||||||
iReturn = XGetSelectionOwner(pDisplay, atomClipboard);
|
iReturn = XGetSelectionOwner(pDisplay, atoms->atomClipboard);
|
||||||
if (iReturn == g_iClipboardWindow) {
|
if (iReturn == iWindow) {
|
||||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||||
"CLIPBOARD selection is owned by us.\n");
|
"CLIPBOARD selection is owned by us, releasing\n");
|
||||||
XSetSelectionOwner(pDisplay, atomClipboard, None, CurrentTime);
|
XSetSelectionOwner(pDisplay, atoms->atomClipboard, None, CurrentTime);
|
||||||
}
|
}
|
||||||
else if (BadWindow == iReturn || BadAtom == iReturn)
|
else if (BadWindow == iReturn || BadAtom == iReturn)
|
||||||
winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||||
"XGetSelection failed for CLIPBOARD: %d\n",
|
"XGetSelectionOwner failed for CLIPBOARD: %d\n",
|
||||||
iReturn);
|
iReturn);
|
||||||
|
|
||||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
|
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
|
||||||
|
@ -358,7 +363,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
XA_PRIMARY, iWindow, CurrentTime);
|
XA_PRIMARY, iWindow, CurrentTime);
|
||||||
if (iReturn == BadAtom || iReturn == BadWindow ||
|
if (iReturn == BadAtom || iReturn == BadWindow ||
|
||||||
XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
|
XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
|
||||||
winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||||
"Could not reassert ownership of PRIMARY\n");
|
"Could not reassert ownership of PRIMARY\n");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -368,11 +373,11 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
|
||||||
/* Reassert ownership of the CLIPBOARD */
|
/* Reassert ownership of the CLIPBOARD */
|
||||||
iReturn = XSetSelectionOwner(pDisplay,
|
iReturn = XSetSelectionOwner(pDisplay,
|
||||||
atomClipboard, iWindow, CurrentTime);
|
atoms->atomClipboard, iWindow, CurrentTime);
|
||||||
|
|
||||||
if (iReturn == BadAtom || iReturn == BadWindow ||
|
if (iReturn == BadAtom || iReturn == BadWindow ||
|
||||||
XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
|
XGetSelectionOwner(pDisplay, atoms->atomClipboard) != iWindow) {
|
||||||
winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||||
"Could not reassert ownership of CLIPBOARD\n");
|
"Could not reassert ownership of CLIPBOARD\n");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -409,8 +414,6 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
case WM_RENDERALLFORMATS:
|
case WM_RENDERALLFORMATS:
|
||||||
{
|
{
|
||||||
int iReturn;
|
int iReturn;
|
||||||
Display *pDisplay = g_pClipboardDisplay;
|
|
||||||
Window iWindow = g_iClipboardWindow;
|
|
||||||
Bool fConvertToUnicode;
|
Bool fConvertToUnicode;
|
||||||
|
|
||||||
winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
|
winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
|
||||||
|
@ -423,14 +426,12 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
|
||||||
/* Request the selection contents */
|
/* Request the selection contents */
|
||||||
iReturn = XConvertSelection(pDisplay,
|
iReturn = XConvertSelection(pDisplay,
|
||||||
g_atomLastOwnedSelection,
|
winClipboardGetLastOwnedSelectionAtom(atoms),
|
||||||
XInternAtom(pDisplay,
|
atoms->atomCompoundText,
|
||||||
"COMPOUND_TEXT", False),
|
atoms->atomLocalProperty,
|
||||||
XInternAtom(pDisplay,
|
|
||||||
"CYGX_CUT_BUFFER", False),
|
|
||||||
iWindow, CurrentTime);
|
iWindow, CurrentTime);
|
||||||
if (iReturn == BadAtom || iReturn == BadWindow) {
|
if (iReturn == BadAtom || iReturn == BadWindow) {
|
||||||
winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMAT - "
|
ErrorF("winClipboardWindowProc - WM_RENDER*FORMAT - "
|
||||||
"XConvertSelection () failed\n");
|
"XConvertSelection () failed\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -445,14 +446,14 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!OpenClipboard(hwnd)) {
|
if (!OpenClipboard(hwnd)) {
|
||||||
winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
|
ErrorF("winClipboardWindowProc - WM_RENDER*FORMATS - "
|
||||||
"OpenClipboard () failed: %08x\n",
|
"OpenClipboard () failed: %08x\n",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EmptyClipboard()) {
|
if (!EmptyClipboard()) {
|
||||||
winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
|
ErrorF("winClipboardWindowProc - WM_RENDER*FORMATS - "
|
||||||
"EmptyClipboard () failed: %08x\n",
|
"EmptyClipboard () failed: %08x\n",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
break;
|
break;
|
||||||
|
@ -463,7 +464,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
iReturn = winProcessXEventsTimeout(hwnd,
|
iReturn = winProcessXEventsTimeout(hwnd,
|
||||||
iWindow,
|
iWindow,
|
||||||
pDisplay,
|
pDisplay,
|
||||||
fConvertToUnicode, WIN_POLL_TIMEOUT);
|
fConvertToUnicode,
|
||||||
|
atoms,
|
||||||
|
WIN_POLL_TIMEOUT);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The last call to winProcessXEventsTimeout
|
* The last call to winProcessXEventsTimeout
|
||||||
|
@ -486,8 +489,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
/* We must close the clipboard */
|
/* We must close the clipboard */
|
||||||
|
|
||||||
if (!CloseClipboard()) {
|
if (!CloseClipboard()) {
|
||||||
winErrorFVerb(1,
|
ErrorF("winClipboardWindowProc - WM_RENDERALLFORMATS - "
|
||||||
"winClipboardWindowProc - WM_RENDERALLFORMATS - "
|
|
||||||
"CloseClipboard () failed: %08x\n",
|
"CloseClipboard () failed: %08x\n",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
break;
|
break;
|
||||||
|
@ -507,7 +509,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
* Process any pending Windows messages
|
* Process any pending Windows messages
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL
|
Bool
|
||||||
winClipboardFlushWindowsMessageQueue(HWND hwnd)
|
winClipboardFlushWindowsMessageQueue(HWND hwnd)
|
||||||
{
|
{
|
||||||
MSG msg;
|
MSG msg;
|
|
@ -33,8 +33,104 @@
|
||||||
#ifdef HAVE_XWIN_CONFIG_H
|
#ifdef HAVE_XWIN_CONFIG_H
|
||||||
#include <xwin-config.h>
|
#include <xwin-config.h>
|
||||||
#endif
|
#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
|
* Process any pending X events
|
||||||
|
@ -42,21 +138,13 @@
|
||||||
|
|
||||||
int
|
int
|
||||||
winClipboardFlushXEvents(HWND hwnd,
|
winClipboardFlushXEvents(HWND hwnd,
|
||||||
int iWindow, Display * pDisplay, Bool fUseUnicode)
|
Window iWindow, Display * pDisplay, Bool fUseUnicode, ClipboardAtoms *atoms)
|
||||||
{
|
{
|
||||||
static Atom atomLocalProperty;
|
Atom atomClipboard = atoms->atomClipboard;
|
||||||
static Atom atomCompoundText;
|
Atom atomLocalProperty = atoms->atomLocalProperty;
|
||||||
static Atom atomUTF8String;
|
Atom atomUTF8String = atoms->atomUTF8String;
|
||||||
static Atom atomTargets;
|
Atom atomCompoundText = atoms->atomCompoundText;
|
||||||
static int generation;
|
Atom atomTargets = atoms->atomTargets;
|
||||||
|
|
||||||
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 */
|
/* Process all pending events */
|
||||||
while (XPending(pDisplay)) {
|
while (XPending(pDisplay)) {
|
||||||
|
@ -77,7 +165,6 @@ winClipboardFlushXEvents(HWND hwnd,
|
||||||
wchar_t *pwszUnicodeStr = NULL;
|
wchar_t *pwszUnicodeStr = NULL;
|
||||||
int iUnicodeLen = 0;
|
int iUnicodeLen = 0;
|
||||||
int iReturnDataLen = 0;
|
int iReturnDataLen = 0;
|
||||||
int i;
|
|
||||||
Bool fAbort = FALSE;
|
Bool fAbort = FALSE;
|
||||||
Bool fCloseClipboard = FALSE;
|
Bool fCloseClipboard = FALSE;
|
||||||
Bool fSetClipboardData = TRUE;
|
Bool fSetClipboardData = TRUE;
|
||||||
|
@ -525,6 +612,8 @@ winClipboardFlushXEvents(HWND hwnd,
|
||||||
if (iReturn == Success || iReturn > 0) {
|
if (iReturn == Success || iReturn > 0) {
|
||||||
/* Conversion succeeded or some unconvertible characters */
|
/* Conversion succeeded or some unconvertible characters */
|
||||||
if (ppszTextList != NULL) {
|
if (ppszTextList != NULL) {
|
||||||
|
int i;
|
||||||
|
|
||||||
iReturnDataLen = 0;
|
iReturnDataLen = 0;
|
||||||
for (i = 0; i < iCount; i++) {
|
for (i = 0; i < iCount; i++) {
|
||||||
iReturnDataLen += strlen(ppszTextList[i]);
|
iReturnDataLen += strlen(ppszTextList[i]);
|
||||||
|
@ -693,8 +782,78 @@ winClipboardFlushXEvents(HWND hwnd,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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",
|
ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
|
||||||
event.type);
|
event.type);
|
||||||
|
}
|
||||||
break;
|
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
|
#ifdef HAVE_XWIN_CONFIG_H
|
||||||
#include <xwin-config.h>
|
#include <xwin-config.h>
|
||||||
#endif
|
#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);
|
static pthread_t g_ptClipboardProc;
|
||||||
|
|
||||||
int winProcSetSelectionOwner(ClientPtr /* client */ );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* References to external symbols
|
*
|
||||||
*/
|
*/
|
||||||
|
static void *
|
||||||
|
winClipboardThreadProc(void *arg)
|
||||||
|
{
|
||||||
|
char szDisplay[512];
|
||||||
|
int clipboardRestarts = 0;
|
||||||
|
|
||||||
extern pthread_t g_ptClipboardProc;
|
while (1)
|
||||||
extern winDispatchProcPtr winProcSetSelectionOwnerOrig;
|
{
|
||||||
extern Bool g_fClipboard;
|
Bool fShutdown;
|
||||||
extern HWND g_hwndClipboard;
|
|
||||||
|
++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
|
* Intialize the Clipboard module
|
||||||
|
@ -60,14 +114,8 @@ winInitClipboard(void)
|
||||||
{
|
{
|
||||||
winDebug("winInitClipboard ()\n");
|
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 */
|
/* 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 */
|
/* Bail if thread creation failed */
|
||||||
ErrorF("winInitClipboard - pthread_create failed.\n");
|
ErrorF("winInitClipboard - pthread_create failed.\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -76,59 +124,19 @@ winInitClipboard(void)
|
||||||
return TRUE;
|
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
|
void
|
||||||
winFixClipboardChain(void)
|
winClipboardShutdown(void)
|
||||||
{
|
{
|
||||||
if (g_fClipboard && g_hwndClipboard) {
|
/* Close down clipboard resources */
|
||||||
PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0);
|
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
|
#ifdef HAVE_XWIN_CONFIG_H
|
||||||
#include <xwin-config.h>
|
#include <xwin-config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "win.h"
|
#include "win.h"
|
||||||
#include "dixstruct.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
|
* Local function prototypes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DISPATCH_PROC(winProcEstablishConnection);
|
DISPATCH_PROC(winProcEstablishConnection);
|
||||||
DISPATCH_PROC(winProcSetSelectionOwner);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* References to external symbols
|
* References to external symbols
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern Bool g_fClipboardLaunched;
|
|
||||||
extern Bool g_fClipboardStarted;
|
|
||||||
extern Bool g_fClipboard;
|
extern Bool g_fClipboard;
|
||||||
extern Window g_iClipboardWindow;
|
|
||||||
extern Atom g_atomLastOwnedSelection;
|
|
||||||
extern HWND g_hwndClipboard;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrapper for internal EstablishConnection function.
|
* Wrapper for internal EstablishConnection function.
|
||||||
|
@ -127,13 +112,6 @@ winProcEstablishConnection(ClientPtr client)
|
||||||
/* Clear original function pointer */
|
/* Clear original function pointer */
|
||||||
winProcEstablishConnectionOrig = NULL;
|
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 */
|
/* Startup the clipboard client if clipboard mode is being used */
|
||||||
if (g_fClipboard) {
|
if (g_fClipboard) {
|
||||||
/*
|
/*
|
||||||
|
@ -163,207 +141,5 @@ winProcEstablishConnection(ClientPtr client)
|
||||||
ErrorF("winProcEstablishConnection - winInitClipboard returned.\n");
|
ErrorF("winProcEstablishConnection - winInitClipboard returned.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flag that clipboard client has been launched */
|
|
||||||
g_fClipboardLaunched = TRUE;
|
|
||||||
|
|
||||||
return iReturn;
|
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 <shellapi.h>
|
||||||
#include "winprefs.h"
|
#include "winprefs.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* References to external globals
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef XWIN_CLIPBOARD
|
|
||||||
extern Bool g_fClipboardStarted;
|
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* Local function prototypes
|
* Local function prototypes
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -86,7 +86,6 @@ pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER;
|
||||||
* Wrapped DIX functions
|
* Wrapped DIX functions
|
||||||
*/
|
*/
|
||||||
winDispatchProcPtr winProcEstablishConnectionOrig = NULL;
|
winDispatchProcPtr winProcEstablishConnectionOrig = NULL;
|
||||||
winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clipboard variables
|
* Clipboard variables
|
||||||
|
@ -94,13 +93,7 @@ winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL;
|
||||||
|
|
||||||
Bool g_fUnicodeClipboard = TRUE;
|
Bool g_fUnicodeClipboard = TRUE;
|
||||||
Bool g_fClipboard = TRUE;
|
Bool g_fClipboard = TRUE;
|
||||||
Bool g_fClipboardLaunched = FALSE;
|
|
||||||
Bool g_fClipboardStarted = 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
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -112,10 +105,4 @@ void
|
||||||
winInitializeGlobals(void)
|
winInitializeGlobals(void)
|
||||||
{
|
{
|
||||||
g_dwCurrentThreadID = GetCurrentThreadId();
|
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
|
* Wrapped DIX functions
|
||||||
*/
|
*/
|
||||||
extern winDispatchProcPtr winProcEstablishConnectionOrig;
|
extern winDispatchProcPtr winProcEstablishConnectionOrig;
|
||||||
extern winDispatchProcPtr winProcSetSelectionOwnerOrig;
|
|
||||||
#endif
|
#endif
|
||||||
|
extern Bool g_fUnicodeClipboard;
|
||||||
|
extern Bool g_fClipboard;
|
||||||
|
extern Bool g_fClipboardStarted;
|
||||||
|
|
||||||
/* The global X default icons */
|
/* The global X default icons */
|
||||||
#if defined(XWIN_MULTIWINDOW)
|
#if defined(XWIN_MULTIWINDOW)
|
||||||
|
|
|
@ -42,6 +42,9 @@
|
||||||
#include "winmsg.h"
|
#include "winmsg.h"
|
||||||
#include "winmonitors.h"
|
#include "winmonitors.h"
|
||||||
#include "inputstr.h"
|
#include "inputstr.h"
|
||||||
|
#ifdef XWIN_CLIPBOARD
|
||||||
|
#include "winclipboard/winclipboard.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global variables
|
* Global variables
|
||||||
|
|
Loading…
Reference in New Issue