586 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			586 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  *Copyright (C) 2003-2004 Harold L Hunt II 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 HAROLD L HUNT II 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 Harold L Hunt II
 | |
|  *shall not be used in advertising or otherwise to promote the sale, use
 | |
|  *or other dealings in this Software without prior written authorization
 | |
|  *from Harold L Hunt II.
 | |
|  *
 | |
|  * Authors:	Harold L Hunt II
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_XWIN_CONFIG_H
 | |
| #include <xwin-config.h>
 | |
| #endif
 | |
| #include <sys/types.h>
 | |
| #include <sys/time.h>
 | |
| #include "winclipboard.h"
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Constants
 | |
|  */
 | |
| 
 | |
| #define WIN_CLIPBOARD_PROP	"cyg_clipboard_prop"
 | |
| #define WIN_POLL_TIMEOUT	1
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * References to external symbols
 | |
|  */
 | |
| 
 | |
| extern Bool		g_fUseUnicode;
 | |
| extern Bool		g_fUnicodeSupport;
 | |
| extern void		*g_pClipboardDisplay;
 | |
| extern Window		g_iClipboardWindow;
 | |
| extern Atom		g_atomLastOwnedSelection;
 | |
| 
 | |
| 
 | |
| /* 
 | |
|  * Local function prototypes
 | |
|  */
 | |
| 
 | |
| static Bool
 | |
| winProcessXEventsTimeout (HWND hwnd, int iWindow, Display *pDisplay,
 | |
| 			  Bool fUseUnicode, int iTimeoutSec);
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Process X events up to specified timeout
 | |
|  */
 | |
| 
 | |
| static int
 | |
| winProcessXEventsTimeout (HWND hwnd, int iWindow, Display *pDisplay,
 | |
| 			  Bool fUseUnicode, int iTimeoutSec)
 | |
| {
 | |
|   int			iConnNumber;
 | |
|   struct timeval	tv;
 | |
|   int			iReturn;
 | |
|   DWORD			dwStopTime = (GetTickCount () / 1000) + iTimeoutSec;
 | |
| 
 | |
|   /* We need to ensure that all pending events are processed */
 | |
|   XSync (pDisplay, FALSE);
 | |
| 
 | |
|   /* Get our connection number */
 | |
|   iConnNumber = ConnectionNumber (pDisplay);
 | |
| 
 | |
|   /* Loop for X events */
 | |
|   while (1)
 | |
|     {
 | |
|       fd_set		fdsRead;
 | |
| 
 | |
|       /* Setup the file descriptor set */
 | |
|       FD_ZERO (&fdsRead);
 | |
|       FD_SET (iConnNumber, &fdsRead);
 | |
| 
 | |
|       /* Adjust timeout */
 | |
|       tv.tv_sec = dwStopTime - (GetTickCount () / 1000);
 | |
|       tv.tv_usec = 0;
 | |
| 
 | |
|       /* Break out if no time left */
 | |
|       if (tv.tv_sec < 0)
 | |
| 	return WIN_XEVENTS_SUCCESS;
 | |
| 
 | |
|       /* Wait for a Windows event or an X event */
 | |
|       iReturn = select (iConnNumber + 1,/* Highest fds number */
 | |
| 			&fdsRead,	/* Read mask */
 | |
| 			NULL,		/* No write mask */
 | |
| 			NULL,		/* No exception mask */
 | |
| 			&tv);		/* No timeout */
 | |
|       if (iReturn <= 0)
 | |
| 	{
 | |
| 	  ErrorF ("winProcessXEventsTimeout - Call to select () failed: %d.  "
 | |
| 		  "Bailing.\n", iReturn);
 | |
| 	  break;
 | |
| 	}
 | |
| 
 | |
|       /* Branch on which descriptor became active */
 | |
|       if (FD_ISSET (iConnNumber, &fdsRead))
 | |
| 	{
 | |
| 	  /* Process X events */
 | |
| 	  /* Exit when we see that server is shutting down */
 | |
| 	  iReturn = winClipboardFlushXEvents (hwnd,
 | |
| 					      iWindow,
 | |
| 					      pDisplay,
 | |
| 					      fUseUnicode);
 | |
| 	  if (WIN_XEVENTS_NOTIFY == iReturn
 | |
| 	      || WIN_XEVENTS_CONVERT == iReturn)
 | |
| 	    {
 | |
| 	      /* Bail out if convert or notify processed */
 | |
| 	      return iReturn;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   return WIN_XEVENTS_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Process a given Windows message
 | |
|  */
 | |
| 
 | |
| LRESULT CALLBACK
 | |
| winClipboardWindowProc (HWND hwnd, UINT message, 
 | |
| 			WPARAM wParam, LPARAM lParam)
 | |
| {
 | |
|   static HWND		s_hwndNextViewer;
 | |
|   static Bool		s_fCBCInitialized;
 | |
| 
 | |
|   /* Branch on message type */
 | |
|   switch (message)
 | |
|     {
 | |
|     case WM_DESTROY:
 | |
|       {
 | |
| 	winDebug ("winClipboardWindowProc - WM_DESTROY\n");
 | |
| 
 | |
| 	/* Remove ourselves from the clipboard chain */
 | |
| 	ChangeClipboardChain (hwnd, s_hwndNextViewer);
 | |
| 	
 | |
| 	s_hwndNextViewer = NULL;
 | |
| 
 | |
| 	PostQuitMessage (0);
 | |
|       }
 | |
|       return 0;
 | |
| 
 | |
| 
 | |
|     case WM_CREATE:
 | |
|       {
 | |
| 	winDebug ("winClipboardWindowProc - WM_CREATE\n");
 | |
| 	
 | |
| 	/* Add ourselves to the clipboard viewer chain */
 | |
| 	s_hwndNextViewer = SetClipboardViewer (hwnd);
 | |
| 	if (s_hwndNextViewer == hwnd)
 | |
| 	  {
 | |
| 	    s_hwndNextViewer = NULL;
 | |
| 	    winErrorFVerb (1, "winClipboardWindowProc - WM_CREATE: "
 | |
| 			   "attempted to set next window to ourselves.");
 | |
| 	  }
 | |
|       }
 | |
|       return 0;
 | |
| 
 | |
| 
 | |
|     case WM_CHANGECBCHAIN:
 | |
|       {
 | |
| 	static Bool s_fProcessingChangeCBChain = FALSE;
 | |
| 	winDebug ("winClipboardWindowProc - WM_CHANGECBCHAIN: wParam(%x) "
 | |
| 		  "lParam(%x) s_hwndNextViewer(%x)\n", 
 | |
| 		  wParam, lParam, s_hwndNextViewer);
 | |
| 
 | |
| 
 | |
| 	/*
 | |
| 	 * We've occasionally seen a loop in the clipboard chain.  Break
 | |
| 	 * it on the first hint of recursion.
 | |
| 	 */
 | |
| 	if (! s_fProcessingChangeCBChain) 
 | |
| 	  {
 | |
| 	    s_fProcessingChangeCBChain = TRUE;
 | |
| 	  }
 | |
| 	else
 | |
| 	  {
 | |
| 	    winErrorFVerb (1, "winClipboardWindowProc - WM_CHANGECBCHAIN - "
 | |
| 			   "Nested calls detected.  Bailing.\n");
 | |
| 	    winDebug ("winClipboardWindowProc - WM_CHANGECBCHAIN: Exit\n");
 | |
| 	    return 0;
 | |
| 	  }
 | |
| 	
 | |
| 	if ((HWND) wParam == s_hwndNextViewer)
 | |
| 	  {
 | |
| 	    s_hwndNextViewer = (HWND) lParam;
 | |
| 	    if (s_hwndNextViewer == hwnd)
 | |
| 	      {
 | |
| 		s_hwndNextViewer = NULL;
 | |
| 		winErrorFVerb (1, "winClipboardWindowProc - WM_CHANGECBCHAIN: "
 | |
| 			       "attempted to set next window to ourselves.");
 | |
| 	      }
 | |
| 	  }
 | |
| 	else if (s_hwndNextViewer)
 | |
| 	  SendMessage (s_hwndNextViewer, message,
 | |
| 		       wParam, lParam);
 | |
| 
 | |
| 	s_fProcessingChangeCBChain = FALSE;
 | |
|       }
 | |
|       winDebug ("winClipboardWindowProc - WM_CHANGECBCHAIN: Exit\n");
 | |
|       return 0;
 | |
| 
 | |
|     case WM_WM_REINIT:
 | |
|       {
 | |
|         /* Ensure that we're in the clipboard chain.  Some apps,
 | |
|          * WinXP's remote desktop for one, don't play nice with the
 | |
|          * chain.  This message is called whenever we receive a
 | |
|          * WM_ACTIVATEAPP message to ensure that we continue to
 | |
|          * receive clipboard messages.
 | |
| 	 *
 | |
| 	 * It might be possible to detect if we're still in the chain
 | |
| 	 * by calling SendMessage (GetClipboardViewer(),
 | |
| 	 * WM_DRAWCLIPBOARD, 0, 0); and then seeing if we get the
 | |
| 	 * WM_DRAWCLIPBOARD message.  That, however, might be more
 | |
| 	 * expensive than just putting ourselves back into the chain.
 | |
| 	 */
 | |
| 
 | |
| 	winDebug ("winClipboardWindowProc - WM_WM_REINIT: Enter\n");
 | |
| 	if (hwnd != GetClipboardViewer ())
 | |
| 	  {
 | |
| 	    winDebug ("  WM_WM_REINIT: Replacing us(%x) with %x at head "
 | |
| 		      "of chain\n", hwnd, s_hwndNextViewer);
 | |
| 	    s_fCBCInitialized = FALSE;
 | |
| 	    ChangeClipboardChain (hwnd, s_hwndNextViewer);
 | |
| 	    s_hwndNextViewer = NULL;
 | |
| 	    s_fCBCInitialized = FALSE;
 | |
| 	    winDebug ("  WM_WM_REINIT: Putting us back at head of chain.\n");
 | |
| 	    s_hwndNextViewer = SetClipboardViewer (hwnd);
 | |
| 	    if (s_hwndNextViewer == hwnd)
 | |
| 	      {
 | |
| 		s_hwndNextViewer = NULL;
 | |
| 		winErrorFVerb (1, "winClipboardWindowProc - WM_WM_REINIT: "
 | |
| 			       "attempted to set next window to ourselves.\n");
 | |
| 	      }
 | |
| 	  }
 | |
| 	else
 | |
| 	  {
 | |
| 	    winDebug ("  WM_WM_REINIT: already at head of viewer chain.\n");
 | |
| 	  }
 | |
|       }
 | |
|       winDebug ("winClipboardWindowProc - WM_WM_REINIT: Exit\n");
 | |
|       return 0;
 | |
| 
 | |
| 
 | |
|     case WM_DRAWCLIPBOARD:
 | |
|       {
 | |
| 	static Bool s_fProcessingDrawClipboard = FALSE;
 | |
| 	Display	*pDisplay = g_pClipboardDisplay;
 | |
| 	Window	iWindow = g_iClipboardWindow;
 | |
| 	int	iReturn;
 | |
| 
 | |
| 	winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
 | |
| 
 | |
| 	/*
 | |
| 	 * We've occasionally seen a loop in the clipboard chain.  Break
 | |
| 	 * it on the first hint of recursion.
 | |
| 	 */
 | |
| 	if (! s_fProcessingDrawClipboard) 
 | |
| 	  {
 | |
| 	    s_fProcessingDrawClipboard = TRUE;
 | |
| 	  }
 | |
| 	else
 | |
| 	  {
 | |
| 	    winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 | |
| 			   "Nested calls detected.  Bailing.\n");
 | |
| 	    winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
 | |
| 	    return 0;
 | |
| 	  }
 | |
| 
 | |
| 	/* Pass the message on the next window in the clipboard viewer chain */
 | |
| 	if (s_hwndNextViewer)
 | |
| 	  SendMessage (s_hwndNextViewer, message, 0, 0);
 | |
| 	
 | |
| 	/* Bail on first message */
 | |
| 	if (!s_fCBCInitialized)
 | |
| 	  {
 | |
| 	    s_fCBCInitialized = TRUE;
 | |
| 	    s_fProcessingDrawClipboard = FALSE;
 | |
| 	    winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
 | |
| 	    return 0;
 | |
| 	  }
 | |
| 
 | |
| 	/*
 | |
| 	 * NOTE: We cannot bail out when NULL == GetClipboardOwner ()
 | |
| 	 * because some applications deal with the clipboard in a manner
 | |
| 	 * that causes the clipboard owner to be NULL when they are in
 | |
| 	 * fact taking ownership.  One example of this is the Win32
 | |
| 	 * native compile of emacs.
 | |
| 	 */
 | |
| 	
 | |
| 	/* Bail when we still own the clipboard */
 | |
| 	if (hwnd == GetClipboardOwner ())
 | |
| 	  {
 | |
| 
 | |
| 	    winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 | |
| 		    "We own the clipboard, returning.\n");
 | |
| 	    winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
 | |
| 	    s_fProcessingDrawClipboard = FALSE;
 | |
| 	    return 0;
 | |
| 	  }
 | |
| 
 | |
| 	/*
 | |
| 	 * Do not take ownership of the X11 selections when something
 | |
| 	 * other than CF_TEXT or CF_UNICODETEXT has been copied
 | |
| 	 * into the Win32 clipboard.
 | |
| 	 */
 | |
| 	if (!IsClipboardFormatAvailable (CF_TEXT)
 | |
| 	    && !IsClipboardFormatAvailable (CF_UNICODETEXT))
 | |
| 	  {
 | |
| 
 | |
| 	    winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 | |
| 		    "Clipboard does not contain CF_TEXT nor "
 | |
| 		    "CF_UNICODETEXT.\n");
 | |
| 
 | |
| 	    /*
 | |
| 	     * We need to make sure that the X Server has processed
 | |
| 	     * previous XSetSelectionOwner messages.
 | |
| 	     */
 | |
| 	    XSync (pDisplay, FALSE);
 | |
| 
 | |
|             winDebug("winClipboardWindowProc - XSync done.\n");
 | |
| 	    
 | |
| 	    /* Release PRIMARY selection if owned */
 | |
| 	    iReturn = XGetSelectionOwner (pDisplay, XA_PRIMARY);
 | |
| 	    if (iReturn == g_iClipboardWindow)
 | |
| 	      {
 | |
| 		winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 | |
| 			"PRIMARY selection is owned by us.\n");
 | |
| 		XSetSelectionOwner (pDisplay,
 | |
| 				    XA_PRIMARY,
 | |
| 				    None,
 | |
| 				    CurrentTime);
 | |
| 	      }
 | |
| 	    else if (BadWindow == iReturn || BadAtom == iReturn)
 | |
| 	      winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 | |
| 		      "XGetSelection failed for PRIMARY: %d\n", iReturn);
 | |
| 
 | |
| 	    /* Release CLIPBOARD selection if owned */
 | |
| 	    iReturn = XGetSelectionOwner (pDisplay,
 | |
| 					  XInternAtom (pDisplay,
 | |
| 						       "CLIPBOARD",
 | |
| 						       False));
 | |
| 	    if (iReturn == g_iClipboardWindow)
 | |
| 	      {
 | |
| 		winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 | |
| 			"CLIPBOARD selection is owned by us.\n");
 | |
| 		XSetSelectionOwner (pDisplay,
 | |
| 				    XInternAtom (pDisplay,
 | |
| 						 "CLIPBOARD",
 | |
| 						 False),
 | |
| 				    None,
 | |
| 				    CurrentTime);
 | |
| 	      }
 | |
| 	    else if (BadWindow == iReturn || BadAtom == iReturn)
 | |
| 	      winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 | |
| 		      "XGetSelection failed for CLIPBOARD: %d\n", iReturn);
 | |
| 
 | |
| 	    winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
 | |
| 	    s_fProcessingDrawClipboard = FALSE;
 | |
| 	    return 0;
 | |
| 	  }
 | |
| 
 | |
| 	/* Reassert ownership of PRIMARY */	  
 | |
| 	iReturn = XSetSelectionOwner (pDisplay,
 | |
| 				      XA_PRIMARY,
 | |
| 				      iWindow,
 | |
| 				      CurrentTime);
 | |
| 	if (iReturn == BadAtom || iReturn == BadWindow)
 | |
| 	  {
 | |
| 	    winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 | |
| 		    "Could not reassert ownership of PRIMARY\n");
 | |
| 	  }
 | |
| 	else
 | |
| 	  {
 | |
| 	    winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 | |
| 		    "Reasserted ownership of PRIMARY\n");
 | |
| 	  }
 | |
| 	
 | |
| 	/* Reassert ownership of the CLIPBOARD */	  
 | |
| 	iReturn = XSetSelectionOwner (pDisplay,
 | |
| 				      XInternAtom (pDisplay,
 | |
| 						   "CLIPBOARD",
 | |
| 						   False),
 | |
| 				      iWindow,
 | |
| 				      CurrentTime);
 | |
| 	if (iReturn == BadAtom || iReturn == BadWindow)
 | |
| 	  {
 | |
| 	    winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 | |
| 		    "Could not reassert ownership of CLIPBOARD\n");
 | |
| 	  }
 | |
| 	else
 | |
| 	  {
 | |
| 	    winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 | |
| 		    "Reasserted ownership of CLIPBOARD\n");
 | |
| 	  }
 | |
| 	
 | |
| 	/* Flush the pending SetSelectionOwner event now */
 | |
| 	XFlush (pDisplay);
 | |
| 
 | |
| 	s_fProcessingDrawClipboard = FALSE;
 | |
|       }
 | |
|       winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
 | |
|       return 0;
 | |
| 
 | |
| 
 | |
|     case WM_DESTROYCLIPBOARD:
 | |
|       /*
 | |
|        * NOTE: Intentionally do nothing.
 | |
|        * Changes in the Win32 clipboard are handled by WM_DRAWCLIPBOARD
 | |
|        * above.  We only process this message to conform to the specs
 | |
|        * for delayed clipboard rendering in Win32.  You might think
 | |
|        * that we need to release ownership of the X11 selections, but
 | |
|        * we do not, because a WM_DRAWCLIPBOARD message will closely
 | |
|        * follow this message and reassert ownership of the X11
 | |
|        * selections, handling the issue for us.
 | |
|        */
 | |
|       return 0;
 | |
| 
 | |
| 
 | |
|     case WM_RENDERFORMAT:
 | |
|     case WM_RENDERALLFORMATS:
 | |
|       {
 | |
| 	int	iReturn;
 | |
| 	Display *pDisplay = g_pClipboardDisplay;
 | |
| 	Window	iWindow = g_iClipboardWindow;
 | |
| 	Bool	fConvertToUnicode;
 | |
| 
 | |
| 	winDebug ("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
 | |
| 
 | |
| 	/* Flag whether to convert to Unicode or not */
 | |
| 	if (message == WM_RENDERALLFORMATS)
 | |
| 	  fConvertToUnicode = FALSE;
 | |
| 	else
 | |
| 	  fConvertToUnicode = g_fUnicodeSupport && (CF_UNICODETEXT == wParam);
 | |
| 
 | |
| 	/* Request the selection contents */
 | |
| 	iReturn = XConvertSelection (pDisplay,
 | |
| 				     g_atomLastOwnedSelection,
 | |
| 				     XInternAtom (pDisplay,
 | |
| 						  "COMPOUND_TEXT", False),
 | |
| 				     XInternAtom (pDisplay,
 | |
| 						  "CYGX_CUT_BUFFER", False),
 | |
| 				     iWindow,
 | |
| 				     CurrentTime);
 | |
| 	if (iReturn == BadAtom || iReturn == BadWindow)
 | |
| 	  {
 | |
| 	    winErrorFVerb (1, "winClipboardWindowProc - WM_RENDER*FORMAT - "
 | |
| 		    "XConvertSelection () failed\n");
 | |
| 	    break;
 | |
| 	  }
 | |
| 
 | |
| 	/* Special handling for WM_RENDERALLFORMATS */
 | |
| 	if (message == WM_RENDERALLFORMATS)
 | |
| 	  {
 | |
| 	    /* We must open and empty the clipboard */
 | |
| 
 | |
| 	    /* Close clipboard if we have it open already */
 | |
| 	    if (GetOpenClipboardWindow () == hwnd)
 | |
| 	      {
 | |
| 		CloseClipboard ();
 | |
| 	      }	    
 | |
| 
 | |
| 	    if (!OpenClipboard (hwnd))
 | |
| 	      {
 | |
| 		winErrorFVerb (1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
 | |
| 			"OpenClipboard () failed: %08x\n",
 | |
| 			GetLastError ());
 | |
| 		break;
 | |
| 	      }
 | |
| 	    
 | |
| 	    if (!EmptyClipboard ())
 | |
| 	      {
 | |
| 		winErrorFVerb (1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
 | |
| 			"EmptyClipboard () failed: %08x\n",
 | |
| 		      GetLastError ());
 | |
| 		break;
 | |
| 	      }
 | |
| 	  }
 | |
| 
 | |
| 	/* Process the SelectionNotify event */
 | |
| 	iReturn = winProcessXEventsTimeout (hwnd,
 | |
| 					    iWindow,
 | |
| 					    pDisplay,
 | |
| 					    fConvertToUnicode,
 | |
| 					    WIN_POLL_TIMEOUT);
 | |
| 	if (WIN_XEVENTS_CONVERT == iReturn)
 | |
| 	  {
 | |
| 	    /*
 | |
| 	     * The selection was offered for conversion first, so we have
 | |
| 	     * to process a second SelectionNotify event to get the actual
 | |
| 	     * data in the selection.
 | |
| 	     */
 | |
| 	    iReturn = winProcessXEventsTimeout (hwnd,
 | |
| 						iWindow,
 | |
| 						pDisplay,
 | |
| 						fConvertToUnicode,
 | |
| 						WIN_POLL_TIMEOUT);
 | |
| 	  }
 | |
| 	
 | |
| 	/*
 | |
| 	 * The last of the up-to two calls to winProcessXEventsTimeout
 | |
| 	 * from above had better have seen a notify event, or else we
 | |
| 	 * are dealing with a buggy or old X11 app.  In these cases we
 | |
| 	 * have to paste some fake data to the Win32 clipboard to
 | |
| 	 * satisfy the requirement that we write something to it.
 | |
| 	 */
 | |
| 	if (WIN_XEVENTS_NOTIFY != iReturn)
 | |
| 	  {
 | |
| 	    /* Paste no data, to satisfy required call to SetClipboardData */
 | |
| 	    if (g_fUnicodeSupport)
 | |
| 	      SetClipboardData (CF_UNICODETEXT, NULL);
 | |
| 	    SetClipboardData (CF_TEXT, NULL);
 | |
| 	  }
 | |
| 
 | |
| 	/* Special handling for WM_RENDERALLFORMATS */
 | |
| 	if (message == WM_RENDERALLFORMATS)
 | |
| 	  {
 | |
| 	    /* We must close the clipboard */
 | |
| 	    
 | |
| 	    if (!CloseClipboard ())
 | |
| 	      {
 | |
| 	      winErrorFVerb (1, "winClipboardWindowProc - WM_RENDERALLFORMATS - "
 | |
| 		      "CloseClipboard () failed: %08x\n",
 | |
| 		      GetLastError ());
 | |
| 	      break;
 | |
| 	      }
 | |
| 	  }
 | |
| 
 | |
| 	winDebug ("winClipboardWindowProc - WM_RENDER*FORMAT - Returning.\n");
 | |
| 	return 0;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|   /* Let Windows perform default processing for unhandled messages */
 | |
|   return DefWindowProc (hwnd, message, wParam, lParam);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Process any pending Windows messages
 | |
|  */
 | |
| 
 | |
| BOOL
 | |
| winClipboardFlushWindowsMessageQueue (HWND hwnd)
 | |
| {
 | |
|   MSG			msg;
 | |
| 
 | |
|   /* Flush the messaging window queue */
 | |
|   /* NOTE: Do not pass the hwnd of our messaging window to PeekMessage,
 | |
|    * as this will filter out many non-window-specific messages that
 | |
|    * are sent to our thread, such as WM_QUIT.
 | |
|    */
 | |
|   while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
 | |
|     {
 | |
|       /* Dispatch the message if not WM_QUIT */
 | |
|       if (msg.message == WM_QUIT)
 | |
| 	return FALSE;
 | |
|       else
 | |
| 	DispatchMessage (&msg);
 | |
|     }
 | |
|   
 | |
|   return TRUE;
 | |
| }
 |