xref: /OK3568_Linux_fs/external/xserver/hw/xwin/winclipboard/thread.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
3*4882a593Smuzhiyun  *Copyright (C) Colin Harrison 2005-2008
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *Permission is hereby granted, free of charge, to any person obtaining
6*4882a593Smuzhiyun  * a copy of this software and associated documentation files (the
7*4882a593Smuzhiyun  *"Software"), to deal in the Software without restriction, including
8*4882a593Smuzhiyun  *without limitation the rights to use, copy, modify, merge, publish,
9*4882a593Smuzhiyun  *distribute, sublicense, and/or sell copies of the Software, and to
10*4882a593Smuzhiyun  *permit persons to whom the Software is furnished to do so, subject to
11*4882a593Smuzhiyun  *the following conditions:
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  *The above copyright notice and this permission notice shall be
14*4882a593Smuzhiyun  *included in all copies or substantial portions of the Software.
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17*4882a593Smuzhiyun  *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*4882a593Smuzhiyun  *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19*4882a593Smuzhiyun  *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
20*4882a593Smuzhiyun  *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21*4882a593Smuzhiyun  *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22*4882a593Smuzhiyun  *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23*4882a593Smuzhiyun  *
24*4882a593Smuzhiyun  *Except as contained in this notice, the name of the copyright holder(s)
25*4882a593Smuzhiyun  *and author(s) shall not be used in advertising or otherwise to promote
26*4882a593Smuzhiyun  *the sale, use or other dealings in this Software without prior written
27*4882a593Smuzhiyun  *authorization from the copyright holder(s) and author(s).
28*4882a593Smuzhiyun  *
29*4882a593Smuzhiyun  * Authors:	Harold L Hunt II
30*4882a593Smuzhiyun  *              Colin Harrison
31*4882a593Smuzhiyun  */
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #ifdef HAVE_XWIN_CONFIG_H
34*4882a593Smuzhiyun #include <xwin-config.h>
35*4882a593Smuzhiyun #else
36*4882a593Smuzhiyun #define HAS_WINSOCK 1
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun /*
40*4882a593Smuzhiyun  * Including any server header might define the macro _XSERVER64 on 64 bit machines.
41*4882a593Smuzhiyun  * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
42*4882a593Smuzhiyun  * So let's undef that macro if necessary.
43*4882a593Smuzhiyun  */
44*4882a593Smuzhiyun #ifdef _XSERVER64
45*4882a593Smuzhiyun #undef _XSERVER64
46*4882a593Smuzhiyun #endif
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun #include <assert.h>
49*4882a593Smuzhiyun #include <unistd.h>
50*4882a593Smuzhiyun #include <fcntl.h>
51*4882a593Smuzhiyun #include <setjmp.h>
52*4882a593Smuzhiyun #include <pthread.h>
53*4882a593Smuzhiyun #include <sys/param.h> // for MAX() macro
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #ifdef HAS_WINSOCK
56*4882a593Smuzhiyun #include <X11/Xwinsock.h>
57*4882a593Smuzhiyun #else
58*4882a593Smuzhiyun #include <errno.h>
59*4882a593Smuzhiyun #endif
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun #include <X11/Xatom.h>
62*4882a593Smuzhiyun #include <X11/extensions/Xfixes.h>
63*4882a593Smuzhiyun #include "winclipboard.h"
64*4882a593Smuzhiyun #include "internal.h"
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun #define WIN_CONNECT_RETRIES			40
67*4882a593Smuzhiyun #define WIN_CONNECT_DELAY			4
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun #define WIN_CLIPBOARD_WINDOW_CLASS		"xwinclip"
70*4882a593Smuzhiyun #define WIN_CLIPBOARD_WINDOW_TITLE		"xwinclip"
71*4882a593Smuzhiyun #ifdef HAS_DEVWINDOWS
72*4882a593Smuzhiyun #define WIN_MSG_QUEUE_FNAME "/dev/windows"
73*4882a593Smuzhiyun #endif
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun /*
76*4882a593Smuzhiyun  * Global variables
77*4882a593Smuzhiyun  */
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun static HWND g_hwndClipboard = NULL;
80*4882a593Smuzhiyun static jmp_buf g_jmpEntry;
81*4882a593Smuzhiyun static XIOErrorHandler g_winClipboardOldIOErrorHandler;
82*4882a593Smuzhiyun static pthread_t g_winClipboardProcThread;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun int xfixes_event_base;
85*4882a593Smuzhiyun int xfixes_error_base;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun Bool g_fHasModernClipboardApi = FALSE;
88*4882a593Smuzhiyun ADDCLIPBOARDFORMATLISTENERPROC g_fpAddClipboardFormatListener;
89*4882a593Smuzhiyun REMOVECLIPBOARDFORMATLISTENERPROC g_fpRemoveClipboardFormatListener;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun /*
92*4882a593Smuzhiyun  * Local function prototypes
93*4882a593Smuzhiyun  */
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun static HWND
96*4882a593Smuzhiyun winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms);
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun static int
99*4882a593Smuzhiyun  winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr);
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun static int
102*4882a593Smuzhiyun  winClipboardIOErrorHandler(Display * pDisplay);
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun /*
105*4882a593Smuzhiyun  * Create X11 and Win32 messaging windows, and run message processing loop
106*4882a593Smuzhiyun  *
107*4882a593Smuzhiyun  * returns TRUE if shutdown was signalled to loop, FALSE if some error occurred
108*4882a593Smuzhiyun  */
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun Bool
winClipboardProc(Bool fUseUnicode,char * szDisplay)111*4882a593Smuzhiyun winClipboardProc(Bool fUseUnicode, char *szDisplay)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun     ClipboardAtoms atoms;
114*4882a593Smuzhiyun     int iReturn;
115*4882a593Smuzhiyun     HWND hwnd = NULL;
116*4882a593Smuzhiyun     int iConnectionNumber = 0;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun #ifdef HAS_DEVWINDOWS
119*4882a593Smuzhiyun     int fdMessageQueue = 0;
120*4882a593Smuzhiyun #else
121*4882a593Smuzhiyun     struct timeval tvTimeout;
122*4882a593Smuzhiyun #endif
123*4882a593Smuzhiyun     fd_set fdsRead;
124*4882a593Smuzhiyun     int iMaxDescriptor;
125*4882a593Smuzhiyun     Display *pDisplay = NULL;
126*4882a593Smuzhiyun     Window iWindow = None;
127*4882a593Smuzhiyun     int iSelectError;
128*4882a593Smuzhiyun     Bool fShutdown = FALSE;
129*4882a593Smuzhiyun     static Bool fErrorHandlerSet = FALSE;
130*4882a593Smuzhiyun     ClipboardConversionData data;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun     winDebug("winClipboardProc - Hello\n");
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun     /* Allow multiple threads to access Xlib */
135*4882a593Smuzhiyun     if (XInitThreads() == 0) {
136*4882a593Smuzhiyun         ErrorF("winClipboardProc - XInitThreads failed.\n");
137*4882a593Smuzhiyun         goto winClipboardProc_Exit;
138*4882a593Smuzhiyun     }
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun     /* See if X supports the current locale */
141*4882a593Smuzhiyun     if (XSupportsLocale() == False) {
142*4882a593Smuzhiyun         ErrorF("winClipboardProc - Warning: Locale not supported by X.\n");
143*4882a593Smuzhiyun     }
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun     g_fpAddClipboardFormatListener = (ADDCLIPBOARDFORMATLISTENERPROC)GetProcAddress(GetModuleHandle("user32"),"AddClipboardFormatListener");
146*4882a593Smuzhiyun     g_fpRemoveClipboardFormatListener = (REMOVECLIPBOARDFORMATLISTENERPROC)GetProcAddress(GetModuleHandle("user32"),"RemoveClipboardFormatListener");
147*4882a593Smuzhiyun     g_fHasModernClipboardApi = g_fpAddClipboardFormatListener && g_fpRemoveClipboardFormatListener;
148*4882a593Smuzhiyun     ErrorF("OS maintains clipboard viewer chain: %s\n", g_fHasModernClipboardApi ? "yes" : "no");
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun     g_winClipboardProcThread = pthread_self();
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun     /* Set error handler */
153*4882a593Smuzhiyun     if (!fErrorHandlerSet) {
154*4882a593Smuzhiyun       XSetErrorHandler(winClipboardErrorHandler);
155*4882a593Smuzhiyun       g_winClipboardOldIOErrorHandler =
156*4882a593Smuzhiyun          XSetIOErrorHandler(winClipboardIOErrorHandler);
157*4882a593Smuzhiyun       fErrorHandlerSet = TRUE;
158*4882a593Smuzhiyun     }
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun     /* Set jump point for Error exits */
161*4882a593Smuzhiyun     if (setjmp(g_jmpEntry)) {
162*4882a593Smuzhiyun         ErrorF("winClipboardProc - setjmp returned for IO Error Handler.\n");
163*4882a593Smuzhiyun         goto winClipboardProc_Done;
164*4882a593Smuzhiyun     }
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun     /* Make sure that the display opened */
167*4882a593Smuzhiyun     pDisplay = XOpenDisplay(szDisplay);
168*4882a593Smuzhiyun     if (pDisplay == NULL) {
169*4882a593Smuzhiyun         ErrorF("winClipboardProc - Failed opening the display, giving up\n");
170*4882a593Smuzhiyun         goto winClipboardProc_Done;
171*4882a593Smuzhiyun     }
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun     ErrorF("winClipboardProc - XOpenDisplay () returned and "
174*4882a593Smuzhiyun            "successfully opened the display.\n");
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun     /* Get our connection number */
177*4882a593Smuzhiyun     iConnectionNumber = ConnectionNumber(pDisplay);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun #ifdef HAS_DEVWINDOWS
180*4882a593Smuzhiyun     /* Open a file descriptor for the windows message queue */
181*4882a593Smuzhiyun     fdMessageQueue = open(WIN_MSG_QUEUE_FNAME, O_RDONLY);
182*4882a593Smuzhiyun     if (fdMessageQueue == -1) {
183*4882a593Smuzhiyun         ErrorF("winClipboardProc - Failed opening %s\n", WIN_MSG_QUEUE_FNAME);
184*4882a593Smuzhiyun         goto winClipboardProc_Done;
185*4882a593Smuzhiyun     }
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun     /* Find max of our file descriptors */
188*4882a593Smuzhiyun     iMaxDescriptor = MAX(fdMessageQueue, iConnectionNumber) + 1;
189*4882a593Smuzhiyun #else
190*4882a593Smuzhiyun     iMaxDescriptor = iConnectionNumber + 1;
191*4882a593Smuzhiyun #endif
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun     if (!XFixesQueryExtension(pDisplay, &xfixes_event_base, &xfixes_error_base))
194*4882a593Smuzhiyun       ErrorF ("winClipboardProc - XFixes extension not present\n");
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun     /* Create atoms */
197*4882a593Smuzhiyun     atoms.atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
198*4882a593Smuzhiyun     atoms.atomLocalProperty = XInternAtom (pDisplay, "CYGX_CUT_BUFFER", False);
199*4882a593Smuzhiyun     atoms.atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False);
200*4882a593Smuzhiyun     atoms.atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False);
201*4882a593Smuzhiyun     atoms.atomTargets = XInternAtom (pDisplay, "TARGETS", False);
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun     /* Create a messaging window */
204*4882a593Smuzhiyun     iWindow = XCreateSimpleWindow(pDisplay,
205*4882a593Smuzhiyun                                   DefaultRootWindow(pDisplay),
206*4882a593Smuzhiyun                                   1, 1,
207*4882a593Smuzhiyun                                   500, 500,
208*4882a593Smuzhiyun                                   0,
209*4882a593Smuzhiyun                                   BlackPixel(pDisplay, 0),
210*4882a593Smuzhiyun                                   BlackPixel(pDisplay, 0));
211*4882a593Smuzhiyun     if (iWindow == 0) {
212*4882a593Smuzhiyun         ErrorF("winClipboardProc - Could not create an X window.\n");
213*4882a593Smuzhiyun         goto winClipboardProc_Done;
214*4882a593Smuzhiyun     }
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun     XStoreName(pDisplay, iWindow, "xwinclip");
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun     /* Select event types to watch */
219*4882a593Smuzhiyun     if (XSelectInput(pDisplay, iWindow, PropertyChangeMask) == BadWindow)
220*4882a593Smuzhiyun         ErrorF("winClipboardProc - XSelectInput generated BadWindow "
221*4882a593Smuzhiyun                "on messaging window\n");
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun     XFixesSelectSelectionInput (pDisplay,
224*4882a593Smuzhiyun                                 iWindow,
225*4882a593Smuzhiyun                                 XA_PRIMARY,
226*4882a593Smuzhiyun                                 XFixesSetSelectionOwnerNotifyMask |
227*4882a593Smuzhiyun                                 XFixesSelectionWindowDestroyNotifyMask |
228*4882a593Smuzhiyun                                 XFixesSelectionClientCloseNotifyMask);
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun     XFixesSelectSelectionInput (pDisplay,
231*4882a593Smuzhiyun                                 iWindow,
232*4882a593Smuzhiyun                                 atoms.atomClipboard,
233*4882a593Smuzhiyun                                 XFixesSetSelectionOwnerNotifyMask |
234*4882a593Smuzhiyun                                 XFixesSelectionWindowDestroyNotifyMask |
235*4882a593Smuzhiyun                                 XFixesSelectionClientCloseNotifyMask);
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun     /* Initialize monitored selection state */
239*4882a593Smuzhiyun     winClipboardInitMonitoredSelections();
240*4882a593Smuzhiyun     /* Create Windows messaging window */
241*4882a593Smuzhiyun     hwnd = winClipboardCreateMessagingWindow(pDisplay, iWindow, &atoms);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun     /* Save copy of HWND */
244*4882a593Smuzhiyun     g_hwndClipboard = hwnd;
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun     /* Assert ownership of selections if Win32 clipboard is owned */
247*4882a593Smuzhiyun     if (NULL != GetClipboardOwner()) {
248*4882a593Smuzhiyun         /* PRIMARY */
249*4882a593Smuzhiyun         iReturn = XSetSelectionOwner(pDisplay, XA_PRIMARY,
250*4882a593Smuzhiyun                                      iWindow, CurrentTime);
251*4882a593Smuzhiyun         if (iReturn == BadAtom || iReturn == BadWindow ||
252*4882a593Smuzhiyun             XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
253*4882a593Smuzhiyun             ErrorF("winClipboardProc - Could not set PRIMARY owner\n");
254*4882a593Smuzhiyun             goto winClipboardProc_Done;
255*4882a593Smuzhiyun         }
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun         /* CLIPBOARD */
258*4882a593Smuzhiyun         iReturn = XSetSelectionOwner(pDisplay, atoms.atomClipboard,
259*4882a593Smuzhiyun                                      iWindow, CurrentTime);
260*4882a593Smuzhiyun         if (iReturn == BadAtom || iReturn == BadWindow ||
261*4882a593Smuzhiyun             XGetSelectionOwner(pDisplay, atoms.atomClipboard) != iWindow) {
262*4882a593Smuzhiyun             ErrorF("winClipboardProc - Could not set CLIPBOARD owner\n");
263*4882a593Smuzhiyun             goto winClipboardProc_Done;
264*4882a593Smuzhiyun         }
265*4882a593Smuzhiyun     }
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun     data.fUseUnicode = fUseUnicode;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun     /* Loop for events */
270*4882a593Smuzhiyun     while (1) {
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun         /* Process X events */
273*4882a593Smuzhiyun         winClipboardFlushXEvents(hwnd,
274*4882a593Smuzhiyun                                  iWindow, pDisplay, &data, &atoms);
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun         /* Process Windows messages */
277*4882a593Smuzhiyun         if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
278*4882a593Smuzhiyun           ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue trapped "
279*4882a593Smuzhiyun                        "WM_QUIT message, exiting main loop.\n");
280*4882a593Smuzhiyun           break;
281*4882a593Smuzhiyun         }
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun         /* We need to ensure that all pending requests are sent */
284*4882a593Smuzhiyun         XFlush(pDisplay);
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun         /* Setup the file descriptor set */
287*4882a593Smuzhiyun         /*
288*4882a593Smuzhiyun          * NOTE: You have to do this before every call to select
289*4882a593Smuzhiyun          *       because select modifies the mask to indicate
290*4882a593Smuzhiyun          *       which descriptors are ready.
291*4882a593Smuzhiyun          */
292*4882a593Smuzhiyun         FD_ZERO(&fdsRead);
293*4882a593Smuzhiyun         FD_SET(iConnectionNumber, &fdsRead);
294*4882a593Smuzhiyun #ifdef HAS_DEVWINDOWS
295*4882a593Smuzhiyun         FD_SET(fdMessageQueue, &fdsRead);
296*4882a593Smuzhiyun #else
297*4882a593Smuzhiyun         tvTimeout.tv_sec = 0;
298*4882a593Smuzhiyun         tvTimeout.tv_usec = 100;
299*4882a593Smuzhiyun #endif
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun         /* Wait for a Windows event or an X event */
302*4882a593Smuzhiyun         iReturn = select(iMaxDescriptor,        /* Highest fds number */
303*4882a593Smuzhiyun                          &fdsRead,      /* Read mask */
304*4882a593Smuzhiyun                          NULL,  /* No write mask */
305*4882a593Smuzhiyun                          NULL,  /* No exception mask */
306*4882a593Smuzhiyun #ifdef HAS_DEVWINDOWS
307*4882a593Smuzhiyun                          NULL   /* No timeout */
308*4882a593Smuzhiyun #else
309*4882a593Smuzhiyun                          &tvTimeout     /* Set timeout */
310*4882a593Smuzhiyun #endif
311*4882a593Smuzhiyun             );
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun #ifndef HAS_WINSOCK
314*4882a593Smuzhiyun         iSelectError = errno;
315*4882a593Smuzhiyun #else
316*4882a593Smuzhiyun         iSelectError = WSAGetLastError();
317*4882a593Smuzhiyun #endif
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun         if (iReturn < 0) {
320*4882a593Smuzhiyun #ifndef HAS_WINSOCK
321*4882a593Smuzhiyun             if (iSelectError == EINTR)
322*4882a593Smuzhiyun #else
323*4882a593Smuzhiyun             if (iSelectError == WSAEINTR)
324*4882a593Smuzhiyun #endif
325*4882a593Smuzhiyun                 continue;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun             ErrorF("winClipboardProc - Call to select () failed: %d.  "
328*4882a593Smuzhiyun                    "Bailing.\n", iReturn);
329*4882a593Smuzhiyun             break;
330*4882a593Smuzhiyun         }
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun         if (FD_ISSET(iConnectionNumber, &fdsRead)) {
333*4882a593Smuzhiyun             winDebug
334*4882a593Smuzhiyun                 ("winClipboardProc - X connection ready, pumping X event queue\n");
335*4882a593Smuzhiyun         }
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun #ifdef HAS_DEVWINDOWS
338*4882a593Smuzhiyun         /* Check for Windows event ready */
339*4882a593Smuzhiyun         if (FD_ISSET(fdMessageQueue, &fdsRead))
340*4882a593Smuzhiyun #else
341*4882a593Smuzhiyun         if (1)
342*4882a593Smuzhiyun #endif
343*4882a593Smuzhiyun         {
344*4882a593Smuzhiyun             winDebug
345*4882a593Smuzhiyun                 ("winClipboardProc - /dev/windows ready, pumping Windows message queue\n");
346*4882a593Smuzhiyun         }
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun #ifdef HAS_DEVWINDOWS
349*4882a593Smuzhiyun         if (!(FD_ISSET(iConnectionNumber, &fdsRead)) &&
350*4882a593Smuzhiyun             !(FD_ISSET(fdMessageQueue, &fdsRead))) {
351*4882a593Smuzhiyun             winDebug("winClipboardProc - Spurious wake, select() returned %d\n", iReturn);
352*4882a593Smuzhiyun         }
353*4882a593Smuzhiyun #endif
354*4882a593Smuzhiyun     }
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun  winClipboardProc_Exit:
357*4882a593Smuzhiyun     /* broke out of while loop on a shutdown message */
358*4882a593Smuzhiyun     fShutdown = TRUE;
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun  winClipboardProc_Done:
361*4882a593Smuzhiyun     /* Close our Windows window */
362*4882a593Smuzhiyun     if (g_hwndClipboard) {
363*4882a593Smuzhiyun         DestroyWindow(g_hwndClipboard);
364*4882a593Smuzhiyun     }
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun     /* Close our X window */
367*4882a593Smuzhiyun     if (pDisplay && iWindow) {
368*4882a593Smuzhiyun         iReturn = XDestroyWindow(pDisplay, iWindow);
369*4882a593Smuzhiyun         if (iReturn == BadWindow)
370*4882a593Smuzhiyun             ErrorF("winClipboardProc - XDestroyWindow returned BadWindow.\n");
371*4882a593Smuzhiyun         else
372*4882a593Smuzhiyun             ErrorF("winClipboardProc - XDestroyWindow succeeded.\n");
373*4882a593Smuzhiyun     }
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun #ifdef HAS_DEVWINDOWS
376*4882a593Smuzhiyun     /* Close our Win32 message handle */
377*4882a593Smuzhiyun     if (fdMessageQueue)
378*4882a593Smuzhiyun         close(fdMessageQueue);
379*4882a593Smuzhiyun #endif
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun #if 0
382*4882a593Smuzhiyun     /*
383*4882a593Smuzhiyun      * FIXME: XCloseDisplay hangs if we call it
384*4882a593Smuzhiyun      *
385*4882a593Smuzhiyun      * XCloseDisplay() calls XSync(), so any outstanding errors are reported.
386*4882a593Smuzhiyun      * If we are built into the server, this can deadlock if the server is
387*4882a593Smuzhiyun      * in the process of exiting and waiting for this thread to exit.
388*4882a593Smuzhiyun      */
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun     /* Discard any remaining events */
391*4882a593Smuzhiyun     XSync(pDisplay, TRUE);
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun     /* Select event types to watch */
394*4882a593Smuzhiyun     XSelectInput(pDisplay, DefaultRootWindow(pDisplay), None);
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun     /* Close our X display */
397*4882a593Smuzhiyun     if (pDisplay) {
398*4882a593Smuzhiyun         XCloseDisplay(pDisplay);
399*4882a593Smuzhiyun     }
400*4882a593Smuzhiyun #endif
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun     /* global clipboard variable reset */
403*4882a593Smuzhiyun     g_hwndClipboard = NULL;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun     return fShutdown;
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun /*
409*4882a593Smuzhiyun  * Create the Windows window that we use to receive Windows messages
410*4882a593Smuzhiyun  */
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun static HWND
winClipboardCreateMessagingWindow(Display * pDisplay,Window iWindow,ClipboardAtoms * atoms)413*4882a593Smuzhiyun winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun     WNDCLASSEX wc;
416*4882a593Smuzhiyun     ClipboardWindowCreationParams cwcp;
417*4882a593Smuzhiyun     HWND hwnd;
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun     /* Setup our window class */
420*4882a593Smuzhiyun     wc.cbSize = sizeof(WNDCLASSEX);
421*4882a593Smuzhiyun     wc.style = CS_HREDRAW | CS_VREDRAW;
422*4882a593Smuzhiyun     wc.lpfnWndProc = winClipboardWindowProc;
423*4882a593Smuzhiyun     wc.cbClsExtra = 0;
424*4882a593Smuzhiyun     wc.cbWndExtra = 0;
425*4882a593Smuzhiyun     wc.hInstance = GetModuleHandle(NULL);
426*4882a593Smuzhiyun     wc.hIcon = 0;
427*4882a593Smuzhiyun     wc.hCursor = 0;
428*4882a593Smuzhiyun     wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
429*4882a593Smuzhiyun     wc.lpszMenuName = NULL;
430*4882a593Smuzhiyun     wc.lpszClassName = WIN_CLIPBOARD_WINDOW_CLASS;
431*4882a593Smuzhiyun     wc.hIconSm = 0;
432*4882a593Smuzhiyun     RegisterClassEx(&wc);
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun     /* Information to be passed to WM_CREATE */
435*4882a593Smuzhiyun     cwcp.pClipboardDisplay = pDisplay;
436*4882a593Smuzhiyun     cwcp.iClipboardWindow = iWindow;
437*4882a593Smuzhiyun     cwcp.atoms = atoms;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun     /* Create the window */
440*4882a593Smuzhiyun     hwnd = CreateWindowExA(0,   /* Extended styles */
441*4882a593Smuzhiyun                            WIN_CLIPBOARD_WINDOW_CLASS,  /* Class name */
442*4882a593Smuzhiyun                            WIN_CLIPBOARD_WINDOW_TITLE,  /* Window name */
443*4882a593Smuzhiyun                            WS_OVERLAPPED,       /* Not visible anyway */
444*4882a593Smuzhiyun                            CW_USEDEFAULT,       /* Horizontal position */
445*4882a593Smuzhiyun                            CW_USEDEFAULT,       /* Vertical position */
446*4882a593Smuzhiyun                            CW_USEDEFAULT,       /* Right edge */
447*4882a593Smuzhiyun                            CW_USEDEFAULT,       /* Bottom edge */
448*4882a593Smuzhiyun                            (HWND) NULL, /* No parent or owner window */
449*4882a593Smuzhiyun                            (HMENU) NULL,        /* No menu */
450*4882a593Smuzhiyun                            GetModuleHandle(NULL),       /* Instance handle */
451*4882a593Smuzhiyun                            &cwcp);       /* Creation data */
452*4882a593Smuzhiyun     assert(hwnd != NULL);
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun     /* I'm not sure, but we may need to call this to start message processing */
455*4882a593Smuzhiyun     ShowWindow(hwnd, SW_HIDE);
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun     /* Similarly, we may need a call to this even though we don't paint */
458*4882a593Smuzhiyun     UpdateWindow(hwnd);
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun     return hwnd;
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun /*
464*4882a593Smuzhiyun  * winClipboardErrorHandler - Our application specific error handler
465*4882a593Smuzhiyun  */
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun static int
winClipboardErrorHandler(Display * pDisplay,XErrorEvent * pErr)468*4882a593Smuzhiyun winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun     char pszErrorMsg[100];
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun     XGetErrorText(pDisplay, pErr->error_code, pszErrorMsg, sizeof(pszErrorMsg));
473*4882a593Smuzhiyun     ErrorF("winClipboardErrorHandler - ERROR: \n\t%s\n"
474*4882a593Smuzhiyun            "\tSerial: %lu, Request Code: %d, Minor Code: %d\n",
475*4882a593Smuzhiyun            pszErrorMsg, pErr->serial, pErr->request_code, pErr->minor_code);
476*4882a593Smuzhiyun     return 0;
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun /*
480*4882a593Smuzhiyun  * winClipboardIOErrorHandler - Our application specific IO error handler
481*4882a593Smuzhiyun  */
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun static int
winClipboardIOErrorHandler(Display * pDisplay)484*4882a593Smuzhiyun winClipboardIOErrorHandler(Display * pDisplay)
485*4882a593Smuzhiyun {
486*4882a593Smuzhiyun     ErrorF("winClipboardIOErrorHandler!\n");
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun     if (pthread_equal(pthread_self(), g_winClipboardProcThread)) {
489*4882a593Smuzhiyun         /* Restart at the main entry point */
490*4882a593Smuzhiyun         longjmp(g_jmpEntry, 2);
491*4882a593Smuzhiyun     }
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun     if (g_winClipboardOldIOErrorHandler)
494*4882a593Smuzhiyun         g_winClipboardOldIOErrorHandler(pDisplay);
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun     return 0;
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun void
winClipboardWindowDestroy(void)500*4882a593Smuzhiyun winClipboardWindowDestroy(void)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun   if (g_hwndClipboard) {
503*4882a593Smuzhiyun     SendMessage(g_hwndClipboard, WM_WM_QUIT, 0, 0);
504*4882a593Smuzhiyun   }
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun void
winFixClipboardChain(void)508*4882a593Smuzhiyun winFixClipboardChain(void)
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun   if (g_hwndClipboard) {
511*4882a593Smuzhiyun     PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0);
512*4882a593Smuzhiyun   }
513*4882a593Smuzhiyun }
514