winclipboardthread.c [plain text]
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
#include <sys/types.h>
#include "winclipboard.h"
#ifdef __CYGWIN__
#include <errno.h>
#endif
#include "X11/Xauth.h"
#define AUTH_NAME "MIT-MAGIC-COOKIE-1"
extern Bool g_fUnicodeClipboard;
extern unsigned long serverGeneration;
#if defined(XCSECURITY)
extern unsigned int g_uiAuthDataLen;
extern char *g_pAuthData;
#endif
extern Bool g_fClipboardStarted;
extern HWND g_hwndClipboard;
extern void *g_pClipboardDisplay;
extern Window g_iClipboardWindow;
static jmp_buf g_jmpEntry;
Bool g_fUnicodeSupport = FALSE;
Bool g_fUseUnicode = FALSE;
static int
winClipboardErrorHandler (Display *pDisplay, XErrorEvent *pErr);
static int
winClipboardIOErrorHandler (Display *pDisplay);
void *
winClipboardProc (void *pvNotUsed)
{
Atom atomClipboard, atomClipboardManager;
int iReturn;
HWND hwnd = NULL;
int iConnectionNumber = 0;
#ifdef HAS_DEVWINDOWS
int fdMessageQueue = 0;
#else
struct timeval tvTimeout;
#endif
fd_set fdsRead;
int iMaxDescriptor;
Display *pDisplay = NULL;
Window iWindow = None;
int iRetries;
Bool fUseUnicode;
char szDisplay[512];
int iSelectError;
ErrorF ("winClipboardProc - Hello\n");
g_fUnicodeSupport = winClipboardDetectUnicodeSupport ();
fUseUnicode = g_fUnicodeClipboard && g_fUnicodeSupport;
g_fUseUnicode = fUseUnicode;
if (XInitThreads () == 0)
{
ErrorF ("winClipboardProc - XInitThreads failed.\n");
pthread_exit (NULL);
}
if (XSupportsLocale () == False)
{
ErrorF ("winClipboardProc - Locale not supported by X. Exiting.\n");
pthread_exit (NULL);
}
iReturn = setjmp (g_jmpEntry);
if (iReturn != WIN_JMP_ERROR_IO
&& iReturn != WIN_JMP_OKAY)
{
ErrorF ("winClipboardProc - setjmp returned: %d exiting\n",
iReturn);
pthread_exit (NULL);
}
else if (iReturn == WIN_JMP_ERROR_IO)
{
ErrorF ("winClipboardProc - setjmp returned for IO Error Handler.\n");
pthread_exit (NULL);
}
#if defined(XCSECURITY)
XSetAuthorization (AUTH_NAME,
strlen (AUTH_NAME),
g_pAuthData,
g_uiAuthDataLen);
#endif
XSetErrorHandler (winClipboardErrorHandler);
XSetIOErrorHandler (winClipboardIOErrorHandler);
iRetries = 0;
snprintf (szDisplay,
512,
"127.0.0.1:%s.0",
display);
ErrorF ("winClipboardProc - DISPLAY=%s\n", szDisplay);
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);
if (pDisplay == NULL)
{
ErrorF ("winClipboardProc - Failed opening the display, giving up\n");
pthread_exit (NULL);
}
g_pClipboardDisplay = pDisplay;
ErrorF ("winClipboardProc - XOpenDisplay () returned and "
"successfully opened the display.\n");
iConnectionNumber = ConnectionNumber (pDisplay);
#ifdef HAS_DEVWINDOWS
fdMessageQueue = open (WIN_MSG_QUEUE_FNAME, O_RDONLY);
if (fdMessageQueue == -1)
{
ErrorF ("winClipboardProc - Failed opening %s\n", WIN_MSG_QUEUE_FNAME);
pthread_exit (NULL);
}
iMaxDescriptor = max (fdMessageQueue, iConnectionNumber) + 1;
#else
iMaxDescriptor = iConnectionNumber + 1;
#endif
if (XSelectInput (pDisplay,
DefaultRootWindow (pDisplay),
SubstructureNotifyMask |
StructureNotifyMask |
PropertyChangeMask) == BadWindow)
ErrorF ("winClipboardProc - XSelectInput generated BadWindow "
"on RootWindow\n\n");
atomClipboard = XInternAtom (pDisplay, "CLIPBOARD", False);
atomClipboardManager = XInternAtom (pDisplay, "CLIPBOARD_MANAGER", False);
iWindow = XCreateSimpleWindow (pDisplay,
DefaultRootWindow (pDisplay),
1, 1,
500, 500,
0,
BlackPixel (pDisplay, 0),
BlackPixel (pDisplay, 0));
if (iWindow == 0)
{
ErrorF ("winClipboardProc - Could not create an X window.\n");
pthread_exit (NULL);
}
g_iClipboardWindow = iWindow;
hwnd = winClipboardCreateMessagingWindow ();
g_hwndClipboard = hwnd;
if (NULL != GetClipboardOwner ())
{
iReturn = XSetSelectionOwner (pDisplay, XA_PRIMARY,
iWindow, CurrentTime);
if (iReturn == BadAtom || iReturn == BadWindow)
{
ErrorF ("winClipboardProc - Could not set PRIMARY owner\n");
pthread_exit (NULL);
}
iReturn = XSetSelectionOwner (pDisplay, atomClipboard,
iWindow, CurrentTime);
if (iReturn == BadAtom || iReturn == BadWindow)
{
ErrorF ("winClipboardProc - Could not set CLIPBOARD owner\n");
pthread_exit (NULL);
}
}
winClipboardFlushXEvents (hwnd,
iWindow,
pDisplay,
fUseUnicode);
if (!winClipboardFlushWindowsMessageQueue (hwnd))
return 0;
g_fClipboardStarted = TRUE;
while (1)
{
FD_ZERO (&fdsRead);
FD_SET (iConnectionNumber, &fdsRead);
#ifdef HAS_DEVWINDOWS
FD_SET (fdMessageQueue, &fdsRead);
#else
tvTimeout.tv_sec = 0;
tvTimeout.tv_usec = 100;
#endif
iReturn = select (iMaxDescriptor,
&fdsRead,
NULL,
NULL,
#ifdef HAS_DEVWINDOWS
NULL
#else
&tvTimeout
#endif
);
#ifndef HAS_WINSOCK
iSelectError = errno;
#else
iSelectError = WSAGetLastError();
#endif
if (iReturn < 0)
{
#ifndef HAS_WINSOCK
if (iSelectError == EINTR)
#else
if (iSelectError == WSAEINTR)
#endif
continue;
ErrorF ("winClipboardProc - Call to select () failed: %d. "
"Bailing.\n", iReturn);
break;
}
if (FD_ISSET (iConnectionNumber, &fdsRead))
{
iReturn = winClipboardFlushXEvents (hwnd,
iWindow,
pDisplay,
fUseUnicode);
if (WIN_XEVENTS_SHUTDOWN == iReturn)
{
ErrorF ("winClipboardProc - winClipboardFlushXEvents "
"trapped shutdown event, exiting main loop.\n");
break;
}
}
#ifdef HAS_DEVWINDOWS
if (FD_ISSET (fdMessageQueue, &fdsRead))
#else
if (1)
#endif
{
if (!winClipboardFlushWindowsMessageQueue (hwnd))
{
ErrorF ("winClipboardProc - "
"winClipboardFlushWindowsMessageQueue trapped "
"WM_QUIT message, exiting main loop.\n");
break;
}
}
}
if (pDisplay && iWindow)
{
iReturn = XDestroyWindow (pDisplay, iWindow);
if (iReturn == BadWindow)
ErrorF ("winClipboardProc - XDestroyWindow returned BadWindow.\n");
else
ErrorF ("winClipboardProc - XDestroyWindow succeeded.\n");
}
#ifdef HAS_DEVWINDOWS
if (fdMessageQueue)
close (fdMessageQueue);
#endif
#if 0
XSync (pDisplay, TRUE);
XSelectInput (pDisplay,
DefaultRootWindow (pDisplay),
None);
if (pDisplay)
{
XCloseDisplay (pDisplay);
}
#endif
g_iClipboardWindow = None;
g_pClipboardDisplay = NULL;
g_hwndClipboard = NULL;
return NULL;
}
static int
winClipboardErrorHandler (Display *pDisplay, XErrorEvent *pErr)
{
char pszErrorMsg[100];
XGetErrorText (pDisplay,
pErr->error_code,
pszErrorMsg,
sizeof (pszErrorMsg));
ErrorF ("winClipboardErrorHandler - ERROR: \n\t%s\n"
"\tSerial: %d, Request Code: %d, Minor Code: %d\n",
pszErrorMsg,
pErr->serial,
pErr->request_code,
pErr->minor_code);
return 0;
}
static int
winClipboardIOErrorHandler (Display *pDisplay)
{
ErrorF ("\nwinClipboardIOErrorHandler!\n\n");
longjmp (g_jmpEntry, WIN_JMP_ERROR_IO);
return 0;
}