diff options
Diffstat (limited to 'hw/xwin/winclipboardthread.c')
-rw-r--r-- | hw/xwin/winclipboardthread.c | 463 |
1 files changed, 463 insertions, 0 deletions
diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboardthread.c new file mode 100644 index 000000000..ce4590b98 --- /dev/null +++ b/hw/xwin/winclipboardthread.c @@ -0,0 +1,463 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *The above copyright notice and this permission notice shall be + *included in all copies or substantial portions of the Software. + * + *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT 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 XFree86 Project + *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 XFree86 Project. + * + * Authors: Harold L Hunt II + */ +/* $XFree86: xc/programs/Xserver/hw/xwin/winclipboardthread.c,v 1.1 2003/02/12 15:01:38 alanh Exp $ */ + +#include "winclipboard.h" + +/* + * References to external symbols + */ + +extern Bool g_fCalledSetLocale; + + +/* + * Global variables + */ + +static jmp_buf g_jmpEntry; + + +/* + * Local function prototypes + */ + +static int +winClipboardErrorHandler (Display *pDisplay, XErrorEvent *pErr); + +static int +winClipboardIOErrorHandler (Display *pDisplay); + + +/* + * Main thread function + */ + +void * +winClipboardProc (void *pArg) +{ + Atom atomClipboard, atomClipboardManager; + Atom atomLocalProperty, atomCompoundText; + Atom atomUTF8String, atomTargets; + int iReturn; + HWND hwnd = NULL; + int iConnectionNumber; + int fdMessageQueue; + fd_set fdsRead; + int iMaxDescriptor; + Display *pDisplay; + Window iWindow; + Atom atomDeleteWindow; + Bool fReturn; + int iRetries; + Bool fUnicodeSupport; + char szDisplay[512]; + int i; + ClipboardProcArgPtr pProcArg = (ClipboardProcArgPtr) pArg; + + ErrorF ("winClipboardProc - Hello\n"); + + /* Check that argument pointer is not invalid */ + if (pArg == NULL) + { + ErrorF ("winClipboardProc - pArg is NULL, bailing.\n"); + pthread_exit (NULL); + } + + ErrorF ("winClipboardProc - Calling pthread_mutex_lock ()\n"); + + /* Grab our garbage mutex to satisfy pthread_cond_wait */ + iReturn = pthread_mutex_lock (pProcArg->ppmServerStarted); + if (iReturn != 0) + { + ErrorF ("winClipboardProc - pthread_mutex_lock () failed: %d\n", + iReturn); + pthread_exit (NULL); + } + + ErrorF ("winClipboardProc - pthread_mutex_lock () returned.\n"); + + /* Do we have Unicode support? */ + fUnicodeSupport = winClipboardDetectUnicodeSupport (); + + /* Set the current locale? What does this do? */ + if (fUnicodeSupport && !g_fCalledSetLocale) + { + ErrorF ("winClipboardProc - Calling setlocale ()\n"); + if (!setlocale (LC_ALL, "")) + { + ErrorF ("winClipboardProc - setlocale () error\n"); + pthread_exit (NULL); + } + ErrorF ("winClipboardProc - setlocale () returned\n"); + + /* See if X supports the current locale */ + if (XSupportsLocale () == False) + { + ErrorF ("winClipboardProc - Locale not supported by X\n"); + pthread_exit (NULL); + } + } + + /* Flag that we have called setlocale */ + g_fCalledSetLocale = TRUE; + + /* Release the garbage mutex */ + pthread_mutex_unlock (pProcArg->ppmServerStarted); + + ErrorF ("winClipboardProc - pthread_mutex_unlock () returned.\n"); + + /* Allow multiple threads to access Xlib */ + if (XInitThreads () == 0) + { + ErrorF ("winClipboardProc - XInitThreads failed.\n"); + pthread_exit (NULL); + } + + ErrorF ("winClipboardProc - XInitThreads () returned.\n"); + + /* Set jump point for Error exits */ + iReturn = setjmp (g_jmpEntry); + + /* Check if we should continue operations */ + if (iReturn != WIN_JMP_ERROR_IO + && iReturn != WIN_JMP_OKAY) + { + /* setjmp returned an unknown value, exit */ + ErrorF ("winClipboardProc - setjmp returned: %d exiting\n", + iReturn); + pthread_exit (NULL); + } + else if (iReturn == WIN_JMP_ERROR_IO) + { + ErrorF ("winClipboardProc - setjmp returned and hwnd: %08x\n", hwnd); + } + + /* Initialize retry count */ + iRetries = 0; + +#if 0 + /* Setup the display connection string x */ + snprintf (szDisplay, 512, "127.0.0.1:%s.%d", display, pProcArg->dwScreen); +#else + /* Setup the display connection string x */ + snprintf (szDisplay, 512, ":%s.%d", display, pProcArg->dwScreen); +#endif + + /* Print the display connection string */ + ErrorF ("winClipboardProc - DISPLAY=%s\n", szDisplay); + + /* Open the X display */ + do + { + pDisplay = XOpenDisplay (szDisplay); + if (pDisplay == NULL) + { + ErrorF ("winClipboardProc - Could not open display, " + "try: %d, sleeping: %d\n", + iRetries + 1, WIN_CONNECT_DELAY); + ++iRetries; + sleep (WIN_CONNECT_DELAY); + continue; + } + else + break; + } + while (pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES); + + /* Make sure that the display opened */ + if (pDisplay == NULL) + { + ErrorF ("winClipboardProc - Failed opening the display, giving up\n"); + pthread_exit (NULL); + } + + ErrorF ("winClipboardProc - XOpenDisplay () returned and " + "successfully opened the display.\n"); + + /* Create Windows messaging window */ + hwnd = winClipboardCreateMessagingWindow (); + + /* Get our connection number */ + iConnectionNumber = ConnectionNumber (pDisplay); + + /* Open a file descriptor for the windows message queue */ + fdMessageQueue = open (WIN_MSG_QUEUE_FNAME, O_RDONLY); + if (fdMessageQueue == -1) + { + ErrorF ("winClipboardProc - Failed opening %s\n", WIN_MSG_QUEUE_FNAME); + pthread_exit (NULL); + } + + /* Find max of our file descriptors */ + iMaxDescriptor = max (fdMessageQueue, iConnectionNumber) + 1; + + /* Select event types to watch */ + if (XSelectInput (pDisplay, + DefaultRootWindow (pDisplay), + SubstructureNotifyMask | + StructureNotifyMask | + PropertyChangeMask) == BadWindow) + ErrorF ("winClipboardProc - XSelectInput generated BadWindow " + "on RootWindow\n\n"); + + /* Create a messaging window */ + iWindow = XCreateSimpleWindow (pDisplay, + DefaultRootWindow (pDisplay), + 1, 1, + 500, 500, + 0, + BlackPixel (pDisplay, 0), + BlackPixel (pDisplay, 0)); + if (iWindow == 0) + { + ErrorF ("winClipboardProc - Could not create a window\n"); + pthread_exit (NULL); + } + + /* This looks like our only hope for getting a message before shutdown */ + /* Register for WM_DELETE_WINDOW message from window manager */ + atomDeleteWindow = XInternAtom (pDisplay, "WM_DELETE_WINDOW", False); + XSetWMProtocols (pDisplay, iWindow, &atomDeleteWindow, 1); + + /* Set error handler */ + XSetErrorHandler (winClipboardErrorHandler); + XSetIOErrorHandler (winClipboardIOErrorHandler); + + /* Create an atom for CLIPBOARD_MANAGER */ + atomClipboardManager = XInternAtom (pDisplay, "CLIPBOARD_MANAGER", False); + if (atomClipboardManager == None) + { + ErrorF ("winClipboardProc - Could not create CLIPBOARD_MANAGER atom\n"); + pthread_exit (NULL); + } + + /* Assert ownership of CLIPBOARD_MANAGER */ + iReturn = XSetSelectionOwner (pDisplay, atomClipboardManager, + iWindow, CurrentTime); + if (iReturn == BadAtom || iReturn == BadWindow) + { + ErrorF ("winClipboardProc - Could not set CLIPBOARD_MANAGER owner\n"); + pthread_exit (NULL); + } + + /* Create an atom for CLIPBOARD */ + atomClipboard = XInternAtom (pDisplay, "CLIPBOARD", False); + if (atomClipboard == None) + { + ErrorF ("winClipboardProc - Could not create CLIPBOARD atom\n"); + pthread_exit (NULL); + } + + /* Assert ownership of CLIPBOARD */ + iReturn = XSetSelectionOwner (pDisplay, atomClipboard, + iWindow, CurrentTime); + if (iReturn == BadAtom || iReturn == BadWindow) + { + ErrorF ("winClipboardProc - Could not set CLIPBOARD owner\n"); + pthread_exit (NULL); + } + + /* Assert ownership of PRIMARY */ + iReturn = XSetSelectionOwner (pDisplay, XA_PRIMARY, + iWindow, CurrentTime); + if (iReturn == BadAtom || iReturn == BadWindow) + { + ErrorF ("winClipboardProc - Could not set PRIMARY owner\n"); + pthread_exit (NULL); + } + + /* Local property to hold pasted data */ + atomLocalProperty = XInternAtom (pDisplay, "CYGX_CUT_BUFFER", False); + if (atomLocalProperty == None) + { + ErrorF ("winClipboardProc - Could not create CYGX_CUT_BUFFER atom\n"); + pthread_exit (NULL); + } + + /* Create an atom for UTF8_STRING */ + atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False); + if (atomUTF8String == None) + { + ErrorF ("winClipboardProc - Could not create UTF8_STRING atom\n"); + pthread_exit (NULL); + } + + /* Create an atom for COMPOUND_TEXT */ + atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False); + if (atomCompoundText == None) + { + ErrorF ("winClipboardProc - Could not create COMPOUND_TEXT atom\n"); + pthread_exit (NULL); + } + + /* Create an atom for TARGETS */ + atomTargets = XInternAtom (pDisplay, "TARGETS", False); + if (atomTargets == None) + { + ErrorF ("winClipboardProc - Could not create TARGETS atom\n"); + pthread_exit (NULL); + } + + /* 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, + atomClipboard, + atomLocalProperty, + atomUTF8String, + atomCompoundText, + atomTargets, + atomDeleteWindow, + iWindow, + pDisplay, + fUnicodeSupport); + + /* Pre-flush Windows messages */ + if (!winClipboardFlushWindowsMessageQueue (hwnd)) + return 0; + + /* Loop for X events */ + while (1) + { + /* Setup the file descriptor set */ + /* + * NOTE: You have to do this before every call to select + * because select modifies the mask to indicate + * which descriptors are ready. + */ + FD_ZERO (&fdsRead); + FD_SET (fdMessageQueue, &fdsRead); + FD_SET (iConnectionNumber, &fdsRead); + + /* Wait for a Windows event or an X event */ + iReturn = select (iMaxDescriptor, /* Highest fds number */ + &fdsRead, /* Read mask */ + NULL, /* No write mask */ + NULL, /* No exception mask */ + NULL); /* No timeout */ + if (iReturn <= 0) + { + ErrorF ("winClipboardProc - Call to select () failed: %d. " + "Bailing.\n", iReturn); + break; + } + + /* Branch on which descriptor became active */ + if (FD_ISSET (iConnectionNumber, &fdsRead)) + { + /* X event ready */ +#if 0 + ErrorF ("winClipboardProc - X event ready\n"); +#endif + + /* Process X events */ + /* Exit when we see that server is shutting down */ + fReturn = winClipboardFlushXEvents (hwnd, + atomClipboard, + atomLocalProperty, + atomUTF8String, + atomCompoundText, + atomTargets, + atomDeleteWindow, + iWindow, + pDisplay, + fUnicodeSupport); + if (!fReturn) + { + ErrorF ("winClipboardProc - Caught WM_DELETE_WINDOW - " + "shutting down\n"); + break; + } + } + + /* Check for Windows event ready */ + if (FD_ISSET (fdMessageQueue, &fdsRead)) + { + /* Windows event ready */ +#if 0 + ErrorF ("winClipboardProc - Windows event ready\n"); +#endif + + /* Process Windows messages */ + if (!winClipboardFlushWindowsMessageQueue (hwnd)) + break; + } + } + + return 0; +} + + +/* + * winClipboardErrorHandler - Our application specific error handler + */ + +static int +winClipboardErrorHandler (Display *pDisplay, XErrorEvent *pErr) +{ + char pszErrorMsg[100]; + + XGetErrorText (pDisplay, + pErr->error_code, + pszErrorMsg, + sizeof (pszErrorMsg)); + ErrorF ("winClipboardErrorHandler - ERROR: \n\t%s\n", pszErrorMsg); + + if (pErr->error_code==BadWindow + || pErr->error_code==BadMatch + || pErr->error_code==BadDrawable) + { + pthread_exit (NULL); + } + + pthread_exit (NULL); + + return 0; +} + + +/* + * winClipboardIOErrorHandler - Our application specific IO error handler + */ + +static int +winClipboardIOErrorHandler (Display *pDisplay) +{ + printf ("\nwinClipboardIOErrorHandler!\n\n"); + + /* Restart at the main entry point */ + longjmp (g_jmpEntry, WIN_JMP_ERROR_IO); + + return 0; +} |