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; pthread_cleanup_push(&winClipboardThreadExit, NULL); winDebug ("winClipboardProc - Hello\n"); /* Do we use Unicode clipboard? */ fUseUnicode = g_fUnicodeClipboard; /* 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 */ XSetErrorHandler(winClipboardErrorHandler); g_winClipboardProcThread = pthread_self(); g_winClipboardOldIOErrorHandler = XSetIOErrorHandler(winClipboardIOErrorHandler); /* Set jump point for Error exits */ iReturn = setjmp(g_jmpEntry); /* Check if we should continue operations */ if (iReturn != WIN_JMP_ERROR_IO && iReturn != WIN_JMP_OKAY) { /* setjmp returned an unknown value, exit */ ErrorF("winClipboardProc - setjmp returned: %d exiting\n", iReturn); goto 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"); } /* 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 */ if (pDisplay == NULL) { ErrorF("winClipboardProc - Failed opening the display, giving up\n"); goto thread_errorexit; } /* 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); if (fdMessageQueue == -1) { ErrorF("winClipboardProc - Failed opening %s\n", WIN_MSG_QUEUE_FNAME); goto thread_errorexit; } /* Find max of our file descriptors */ iMaxDescriptor = max(fdMessageQueue, iConnectionNumber) + 1; #else iMaxDescriptor = iConnectionNumber + 1; #endif /* Create atoms */ atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False); atomClipboardManager = XInternAtom(pDisplay, "CLIPBOARD_MANAGER", 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, 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"); goto thread_errorexit; } XStoreName(pDisplay, iWindow, "xwinclip"); /* Select event types to watch */ if (XSelectInput(pDisplay, iWindow, PropertyChangeMask) == BadWindow) ErrorF("winClipboardProc - XSelectInput generated BadWindow " "on messaging window\n"); /* Save the window in the screen privates */ g_iClipboardWindow = iWindow; /* Assert ownership of selections if Win32 clipboard is owned */ if (NULL != GetClipboardOwner()) { 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, atomClipboard, iWindow, CurrentTime); 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); /* Pre-flush Windows messages */ 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 */ /* * 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(iConnectionNumber, &fdsRead); #ifdef HAS_DEVWINDOWS FD_SET(fdMessageQueue, &fdsRead); #else tvTimeout.tv_sec = 0; tvTimeout.tv_usec = 100; #endif /* 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 */ #ifdef HAS_DEVWINDOWS NULL /* No timeout */ #else &tvTimeout /* Set timeout */ #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; } /* Branch on which descriptor became active */ // if (FD_ISSET (iConnectionNumber, &fdsRead)) // { Also do it when no read since winClipboardFlushXEvents // is sending the output. /* Process X events */ /* Exit when we see that server is shutting down */ iReturn = winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, FALSE); if (WIN_XEVENTS_SHUTDOWN == iReturn) { ErrorF("winClipboardProc - winClipboardFlushXEvents " "trapped shutdown event, exiting main loop.\n"); break; } // } #ifdef HAS_DEVWINDOWS /* Check for Windows event ready */ if (FD_ISSET(fdMessageQueue, &fdsRead)) #else if (1) #endif { /* Process Windows messages */ if (!winClipboardFlushWindowsMessageQueue(hwnd)) { ErrorF("winClipboardProc - " "winClipboardFlushWindowsMessageQueue trapped " "WM_QUIT message, exiting main loop.\n"); break; } } } /* Close our X window */ if (pDisplay && iWindow) { iReturn = XDestroyWindow(pDisplay, iWindow); if (iReturn == BadWindow) ErrorF("winClipboardProc - XDestroyWindow returned BadWindow.\n"); #ifdef WINDBG else winDebug("winClipboardProc - XDestroyWindow succeeded.\n"); #endif } #ifdef HAS_DEVWINDOWS /* Close our Win32 message handle */ if (fdMessageQueue) close(fdMessageQueue); #endif #if 0 /* * FIXME: XCloseDisplay hangs if we call it, as of 2004/03/26. The * XSync and XSelectInput calls did not help. */ /* Discard any remaining events */ XSync(pDisplay, TRUE); /* Select event types to watch */ XSelectInput(pDisplay, DefaultRootWindow(pDisplay), None); /* Close our X display */ if (pDisplay) { XCloseDisplay(pDisplay); } #endif goto commonexit; 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"); commonexit: g_iClipboardWindow = None; g_pClipboardDisplay = NULL; g_fClipboardLaunched = FALSE; g_fClipboardStarted = FALSE; pthread_cleanup_pop(0); return NULL; }
/* * Try and open ~/.XWinrc and system.XWinrc * Load it into prefs structure for use by other functions */ void LoadPreferences(void) { char *home; char fname[PATH_MAX + NAME_MAX + 2]; char szDisplay[512]; char *szEnvDisplay; int i, j; char param[PARAM_MAX + 1]; char *srcParam, *dstParam; int parsed = FALSE; /* First, clear all preference settings */ memset(&pref, 0, sizeof(pref)); /* Now try and find a ~/.xwinrc file */ home = getenv("HOME"); if (home) { strcpy(fname, home); if (fname[strlen(fname) - 1] != '/') strcat(fname, "/"); strcat(fname, ".XWinrc"); parsed = winPrefsLoadPreferences(fname); } /* No home file found, check system default */ if (!parsed) { char buffer[MAX_PATH]; #ifdef RELOCATE_PROJECTROOT snprintf(buffer, sizeof(buffer), "%s\\system.XWinrc", winGetBaseDir()); #else strncpy(buffer, SYSCONFDIR "/X11/system.XWinrc", sizeof(buffer)); #endif buffer[sizeof(buffer) - 1] = 0; parsed = winPrefsLoadPreferences(buffer); } /* Neither user nor system configuration found, or were badly formed */ if (!parsed) { ErrorF ("LoadPreferences: See \"man XWinrc\" to customize the XWin menu.\n"); parsed = winPrefsLoadPreferences(NULL); } /* Setup a DISPLAY environment variable, need to allocate on heap */ /* because putenv doesn't copy the argument... */ winGetDisplayName(szDisplay, 0); szEnvDisplay = (char *) (malloc(strlen(szDisplay) + strlen("DISPLAY=") + 1)); if (szEnvDisplay) { snprintf(szEnvDisplay, 512, "DISPLAY=%s", szDisplay); putenv(szEnvDisplay); } /* Replace any "%display%" in menu commands with display string */ for (i = 0; i < pref.menuItems; i++) { for (j = 0; j < pref.menu[i].menuItems; j++) { if (pref.menu[i].menuItem[j].cmd == CMD_EXEC) { srcParam = pref.menu[i].menuItem[j].param; dstParam = param; while (*srcParam) { if (!strncmp(srcParam, "%display%", 9)) { memcpy(dstParam, szDisplay, strlen(szDisplay)); dstParam += strlen(szDisplay); srcParam += 9; } else { *dstParam = *srcParam; dstParam++; srcParam++; } } *dstParam = 0; strcpy(pref.menu[i].menuItem[j].param, param); } /* cmd==cmd_exec */ } /* for all menuitems */ } /* for all menus */ }