aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xwin/winclipboard/thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xwin/winclipboard/thread.c')
-rwxr-xr-x[-rw-r--r--]xorg-server/hw/xwin/winclipboard/thread.c396
1 files changed, 189 insertions, 207 deletions
diff --git a/xorg-server/hw/xwin/winclipboard/thread.c b/xorg-server/hw/xwin/winclipboard/thread.c
index c179e3f83..56f5484e6 100644..100755
--- a/xorg-server/hw/xwin/winclipboard/thread.c
+++ b/xorg-server/hw/xwin/winclipboard/thread.c
@@ -35,78 +35,63 @@
#else
#define HAS_WINSOCK 1
#endif
-
-/*
- * Including any server header might define the macro _XSERVER64 on 64 bit machines.
- * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
- * So let's undef that macro if necessary.
- */
-#ifdef _XSERVER64
-#undef _XSERVER64
-#endif
-
-#include <assert.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <setjmp.h>
+#include <sys/types.h>
+#include <signal.h>
#include <pthread.h>
-#include <sys/param.h> // for MAX() macro
-
-#ifdef HAS_WINSOCK
-#include <X11/Xwinsock.h>
-#else
+#include "winclipboard.h"
+#include "windisplay.h"
+#ifdef __CYGWIN__
#include <errno.h>
#endif
-
-#include <X11/Xatom.h>
-#include <X11/extensions/Xfixes.h>
-#include "winclipboard.h"
+#include "misc.h"
+#include "winmsg.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"
+#ifdef _MSC_VER
+#define snprintf _snprintf
#endif
+/*
+ * References to external symbols
+ */
+
+extern Bool g_fUnicodeClipboard;
+extern Bool g_fClipboardStarted;
+extern Bool g_fClipboardLaunched;
+extern HWND g_hwndClipboard;
+extern void *g_pClipboardDisplay;
+extern Window g_iClipboardWindow;
+extern Bool g_fClipboardPrimary;
/*
* Global variables
*/
-static HWND g_hwndClipboard = NULL;
static jmp_buf g_jmpEntry;
static XIOErrorHandler g_winClipboardOldIOErrorHandler;
static pthread_t g_winClipboardProcThread;
-int xfixes_event_base;
-int xfixes_error_base;
+Bool g_fUseUnicode = FALSE;
/*
* Local function prototypes
*/
-static HWND
-winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms);
-
static int
winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr);
static int
winClipboardIOErrorHandler(Display * pDisplay);
+static void
+winClipboardThreadExit(void *arg);
/*
- * Create X11 and Win32 messaging windows, and run message processing loop
- *
- * returns TRUE if shutdown was signalled to loop, FALSE if some error occurred
+ * Main thread function
*/
-Bool
-winClipboardProc(Bool fUseUnicode, char *szDisplay)
+void *
+winClipboardProc(void *pvNotUsed)
{
- ClipboardAtoms atoms;
+ Atom atomClipboard;
int iReturn;
HWND hwnd = NULL;
int iConnectionNumber = 0;
@@ -120,75 +105,118 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
int iMaxDescriptor;
Display *pDisplay = NULL;
Window iWindow = None;
+ int iRetries;
+ Bool fUseUnicode;
+ char szDisplay[512];
int iSelectError;
- Bool fShutdown = FALSE;
- static Bool fErrorHandlerSet = FALSE;
- winDebug("winClipboardProc - Hello\n");
+ pthread_cleanup_push(&winClipboardThreadExit, NULL);
- /* Allow multiple threads to access Xlib */
- if (XInitThreads() == 0) {
- ErrorF("winClipboardProc - XInitThreads failed.\n");
- goto winClipboardProc_Exit;
- }
+ winDebug ("winClipboardProc - Hello\n");
- /* See if X supports the current locale */
- if (XSupportsLocale() == False) {
- ErrorF("winClipboardProc - Warning: Locale not supported by X.\n");
- }
+ /* Do we use Unicode clipboard? */
+ fUseUnicode = g_fUnicodeClipboard;
- g_winClipboardProcThread = pthread_self();
+ /* Save the Unicode support flag in a global */
+ g_fUseUnicode = fUseUnicode;
+
+ /* Create Windows messaging window */
+ hwnd = winClipboardCreateMessagingWindow ();
+
+ /* Save copy of HWND in screen privates */
+ g_hwndClipboard = hwnd;
/* Set error handler */
- if (!fErrorHandlerSet) {
- XSetErrorHandler(winClipboardErrorHandler);
- g_winClipboardOldIOErrorHandler =
- XSetIOErrorHandler(winClipboardIOErrorHandler);
- fErrorHandlerSet = TRUE;
- }
+ XSetErrorHandler(winClipboardErrorHandler);
+ g_winClipboardProcThread = pthread_self();
+ g_winClipboardOldIOErrorHandler =
+ XSetIOErrorHandler(winClipboardIOErrorHandler);
/* Set jump point for Error exits */
- if (setjmp(g_jmpEntry)) {
+ iReturn = setjmp(g_jmpEntry);
+
+ /* Check if we should continue operations */
+ if (iReturn != WIN_JMP_ERROR_IO && iReturn != WIN_JMP_OKAY) {
+ /* setjmp returned an unknown value, exit */
+ ErrorF("winClipboardProc - setjmp returned: %d exiting\n", iReturn);
+ goto thread_errorexit;
+ }
+ 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");
- 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 */
+ winDebug ("winClipboardProc - DISPLAY=%s\n", szDisplay);
+
+ /* Open the X display */
+ do {
+ pDisplay = XOpenDisplay(szDisplay);
+ if (pDisplay == NULL) {
+ ErrorF("winClipboardProc - Could not open display, "
+ "try: %d, sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY);
+ ++iRetries;
+ sleep(WIN_CONNECT_DELAY);
+ continue;
+ }
+ else
+ break;
+ }
+ while (pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
+
/* Make sure that the display opened */
- pDisplay = XOpenDisplay(szDisplay);
if (pDisplay == NULL) {
ErrorF("winClipboardProc - Failed opening the display, giving up\n");
- goto winClipboardProc_Done;
+ goto thread_errorexit;
}
- ErrorF("winClipboardProc - XOpenDisplay () returned and "
+ /* Save the display in the screen privates */
+ g_pClipboardDisplay = pDisplay;
+
+ winDebug ("winClipboardProc - XOpenDisplay () returned and "
"successfully opened the display.\n");
/* Get our connection number */
iConnectionNumber = ConnectionNumber(pDisplay);
+ winDebug("Clipboard is using socket %d\n",iConnectionNumber);
+
#ifdef HAS_DEVWINDOWS
/* Open a file descriptor for the windows message queue */
- fdMessageQueue = open(WIN_MSG_QUEUE_FNAME, O_RDONLY);
+ fdMessageQueue = open (WIN_MSG_QUEUE_FNAME, _O_RDONLY);
if (fdMessageQueue == -1) {
ErrorF("winClipboardProc - Failed opening %s\n", WIN_MSG_QUEUE_FNAME);
- goto winClipboardProc_Done;
+ goto thread_errorexit;
}
/* Find max of our file descriptors */
- iMaxDescriptor = MAX(fdMessageQueue, iConnectionNumber) + 1;
+ iMaxDescriptor = max(fdMessageQueue, iConnectionNumber) + 1;
#else
iMaxDescriptor = iConnectionNumber + 1;
#endif
- if (!XFixesQueryExtension(pDisplay, &xfixes_event_base, &xfixes_error_base))
- ErrorF ("winClipboardProc - XFixes extension not present\n");
-
- /* Create atoms */
- 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 atom */
+ atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
+ XInternAtom (pDisplay, WIN_LOCAL_PROPERTY, False);
+ XInternAtom (pDisplay, "UTF8_STRING", False);
+ XInternAtom (pDisplay, "COMPOUND_TEXT", False);
+ XInternAtom (pDisplay, "TARGETS", False);
/* Create a messaging window */
iWindow = XCreateSimpleWindow(pDisplay,
@@ -200,7 +228,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
BlackPixel(pDisplay, 0));
if (iWindow == 0) {
ErrorF("winClipboardProc - Could not create an X window.\n");
- goto winClipboardProc_Done;
+ goto thread_errorexit;
}
XStoreName(pDisplay, iWindow, "xwinclip");
@@ -210,63 +238,56 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
ErrorF("winClipboardProc - XSelectInput generated BadWindow "
"on messaging window\n");
- XFixesSelectSelectionInput (pDisplay,
- iWindow,
- XA_PRIMARY,
- XFixesSetSelectionOwnerNotifyMask |
- XFixesSelectionWindowDestroyNotifyMask |
- XFixesSelectionClientCloseNotifyMask);
-
- XFixesSelectSelectionInput (pDisplay,
- iWindow,
- atoms.atomClipboard,
- XFixesSetSelectionOwnerNotifyMask |
- XFixesSelectionWindowDestroyNotifyMask |
- XFixesSelectionClientCloseNotifyMask);
-
-
- /* Initialize monitored selection state */
- winClipboardInitMonitoredSelections();
- /* Create Windows messaging window */
- hwnd = winClipboardCreateMessagingWindow(pDisplay, iWindow, &atoms);
-
- /* Save copy of HWND */
- g_hwndClipboard = hwnd;
+ /* Save the window in the screen privates */
+ g_iClipboardWindow = iWindow;
/* Assert ownership of selections if Win32 clipboard is owned */
if (NULL != GetClipboardOwner()) {
- /* PRIMARY */
- iReturn = XSetSelectionOwner(pDisplay, XA_PRIMARY,
- iWindow, CurrentTime);
- if (iReturn == BadAtom || iReturn == BadWindow ||
- XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
- ErrorF("winClipboardProc - Could not set PRIMARY owner\n");
- goto winClipboardProc_Done;
+ if (g_fClipboardPrimary)
+ {
+ /* PRIMARY */
+ winDebug("winClipboardProc - asserted ownership.\n");
+ iReturn = XSetSelectionOwner (pDisplay, XA_PRIMARY,
+ iWindow, CurrentTime);
+ if (iReturn == BadAtom || iReturn == BadWindow /*||
+ XGetSelectionOwner (pDisplay, XA_PRIMARY) != iWindow*/)
+ {
+ ErrorF ("winClipboardProc - Could not set PRIMARY owner\n");
+ goto thread_errorexit;
+ }
}
/* CLIPBOARD */
- iReturn = XSetSelectionOwner(pDisplay, atoms.atomClipboard,
+ iReturn = XSetSelectionOwner(pDisplay, atomClipboard,
iWindow, CurrentTime);
- if (iReturn == BadAtom || iReturn == BadWindow ||
- XGetSelectionOwner(pDisplay, atoms.atomClipboard) != iWindow) {
- ErrorF("winClipboardProc - Could not set CLIPBOARD owner\n");
- goto winClipboardProc_Done;
+ if (iReturn == BadAtom || iReturn == BadWindow /*||
+ XGetSelectionOwner (pDisplay, atomClipboard) != iWindow*/)
+ {
+ ErrorF ("winClipboardProc - Could not set CLIPBOARD owner\n");
+ goto thread_errorexit;
}
}
/* Pre-flush X events */
- /*
+ /*
* NOTE: Apparently you'll freeze if you don't do this,
* because there may be events in local data structures
* already.
*/
- winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms);
+ //winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
/* Pre-flush Windows messages */
- if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
- ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue failed\n");
+ winDebug ("Start flushing \n");
+ if (!winClipboardFlushWindowsMessageQueue(hwnd))
+ {
+ ErrorF ("winClipboardFlushWindowsMessageQueue - returned 0\n");
+ goto thread_errorexit;
}
+ winDebug ("winClipboardProc - Started\n");
+ /* Signal that the clipboard client has started */
+ g_fClipboardStarted = TRUE;
+
/* Loop for X events */
while (1) {
/* Setup the file descriptor set */
@@ -316,10 +337,12 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
}
/* Branch on which descriptor became active */
- if (FD_ISSET(iConnectionNumber, &fdsRead)) {
+// if (FD_ISSET (iConnectionNumber, &fdsRead)) {
+// Also do it when no read since winClipboardFlushXEvents
+// is sending the output.
/* Process X events */
- winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms);
- }
+ winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, FALSE);
+// }
#ifdef HAS_DEVWINDOWS
/* Check for Windows event ready */
@@ -338,23 +361,15 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
}
}
- winClipboardProc_Exit:
- /* broke out of while loop on a shutdown message */
- fShutdown = TRUE;
-
- winClipboardProc_Done:
- /* Close our Windows window */
- if (g_hwndClipboard) {
- winClipboardWindowDestroy();
- }
-
/* Close our X window */
if (pDisplay && iWindow) {
iReturn = XDestroyWindow(pDisplay, iWindow);
if (iReturn == BadWindow)
ErrorF("winClipboardProc - XDestroyWindow returned BadWindow.\n");
+#ifdef WINDBG
else
- ErrorF("winClipboardProc - XDestroyWindow succeeded.\n");
+ winDebug("winClipboardProc - XDestroyWindow succeeded.\n");
+#endif
}
#ifdef HAS_DEVWINDOWS
@@ -365,11 +380,8 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
#if 0
/*
- * FIXME: XCloseDisplay hangs if we call it
- *
- * XCloseDisplay() calls XSync(), so any outstanding errors are reported.
- * If we are built into the server, this can deadlock if the server is
- * in the process of exiting and waiting for this thread to exit.
+ * FIXME: XCloseDisplay hangs if we call it, as of 2004/03/26. The
+ * XSync and XSelectInput calls did not help.
*/
/* Discard any remaining events */
@@ -384,65 +396,30 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
}
#endif
- /* global clipboard variable reset */
- g_hwndClipboard = NULL;
+ goto commonexit;
- return fShutdown;
-}
+thread_errorexit:
+ if (g_pClipboardDisplay && g_iClipboardWindow)
+ {
+ iReturn = XDestroyWindow (g_pClipboardDisplay, g_iClipboardWindow);
+ if (iReturn == BadWindow)
+ ErrorF ("winClipboardProc - XDestroyWindow returned BadWindow.\n");
+#ifdef WINDBG
+ else
+ winDebug ("winClipboardProc - XDestroyWindow succeeded.\n");
+#endif
+ }
+ winDebug ("Clipboard thread died.\n");
-/*
- * Create the Windows window that we use to receive Windows messages
- */
+commonexit:
+ g_iClipboardWindow = None;
+ g_pClipboardDisplay = NULL;
+ g_fClipboardLaunched = FALSE;
+ g_fClipboardStarted = FALSE;
-static HWND
-winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms)
-{
- WNDCLASSEX wc;
- ClipboardWindowCreationParams cwcp;
- HWND hwnd;
-
- /* Setup our window class */
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = CS_HREDRAW | CS_VREDRAW;
- wc.lpfnWndProc = winClipboardWindowProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = GetModuleHandle(NULL);
- wc.hIcon = 0;
- wc.hCursor = 0;
- wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = WIN_CLIPBOARD_WINDOW_CLASS;
- wc.hIconSm = 0;
- RegisterClassEx(&wc);
-
- /* Information to be passed to WM_CREATE */
- cwcp.pClipboardDisplay = pDisplay;
- cwcp.iClipboardWindow = iWindow;
- cwcp.atoms = atoms;
-
- /* Create the window */
- hwnd = CreateWindowExA(0, /* Extended styles */
- WIN_CLIPBOARD_WINDOW_CLASS, /* Class name */
- WIN_CLIPBOARD_WINDOW_TITLE, /* Window name */
- WS_OVERLAPPED, /* Not visible anyway */
- CW_USEDEFAULT, /* Horizontal position */
- CW_USEDEFAULT, /* Vertical position */
- CW_USEDEFAULT, /* Right edge */
- CW_USEDEFAULT, /* Bottom edge */
- (HWND) NULL, /* No parent or owner window */
- (HMENU) NULL, /* No menu */
- GetModuleHandle(NULL), /* Instance handle */
- &cwcp); /* Creation data */
- assert(hwnd != NULL);
-
- /* I'm not sure, but we may need to call this to start message processing */
- ShowWindow(hwnd, SW_HIDE);
-
- /* Similarly, we may need a call to this even though we don't paint */
- UpdateWindow(hwnd);
-
- return hwnd;
+ pthread_cleanup_pop(0);
+
+ return NULL;
}
/*
@@ -456,8 +433,17 @@ winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr)
XGetErrorText(pDisplay, pErr->error_code, pszErrorMsg, sizeof(pszErrorMsg));
ErrorF("winClipboardErrorHandler - ERROR: \n\t%s\n"
- "\tSerial: %lu, Request Code: %d, Minor Code: %d\n",
- pszErrorMsg, pErr->serial, pErr->request_code, pErr->minor_code);
+ " errorCode %d\n"
+ " serial %lu\n"
+ " resourceID 0x%x\n"
+ " majorCode %d\n"
+ " minorCode %d\n"
+ , pszErrorMsg
+ , pErr->error_code
+ , pErr->serial
+ , pErr->resourceid
+ , pErr->request_code
+ , pErr->minor_code);
return 0;
}
@@ -472,7 +458,7 @@ winClipboardIOErrorHandler(Display * pDisplay)
if (pthread_equal(pthread_self(), g_winClipboardProcThread)) {
/* Restart at the main entry point */
- longjmp(g_jmpEntry, 2);
+ longjmp(g_jmpEntry, WIN_JMP_ERROR_IO);
}
if (g_winClipboardOldIOErrorHandler)
@@ -481,18 +467,14 @@ winClipboardIOErrorHandler(Display * pDisplay)
return 0;
}
-void
-winClipboardWindowDestroy(void)
-{
- if (g_hwndClipboard) {
- SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
- }
-}
+/*
+ * winClipboardThreadExit - Thread exit handler
+ */
-void
-winFixClipboardChain(void)
+static void
+winClipboardThreadExit(void *arg)
{
- if (g_hwndClipboard) {
- PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0);
- }
+ /* clipboard thread has exited, stop server as well */
+ AbortDDX(EXIT_ERR_ABORT);
+ TerminateProcess(GetCurrentProcess(),1);
}