winclipboardwndproc.c [plain text]
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
#include <sys/types.h>
#include <sys/time.h>
#include "winclipboard.h"
extern void winFixClipboardChain();
#define WIN_CLIPBOARD_PROP "cyg_clipboard_prop"
#define WIN_POLL_TIMEOUT 1
extern Bool g_fUseUnicode;
extern Bool g_fUnicodeSupport;
extern void *g_pClipboardDisplay;
extern Window g_iClipboardWindow;
extern Atom g_atomLastOwnedSelection;
extern HWND g_hwndClipboard;
static Bool
winProcessXEventsTimeout (HWND hwnd, int iWindow, Display *pDisplay,
Bool fUseUnicode, int iTimeoutSec);
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;
XSync (pDisplay, FALSE);
iConnNumber = ConnectionNumber (pDisplay);
while (1)
{
fd_set fdsRead;
FD_ZERO (&fdsRead);
FD_SET (iConnNumber, &fdsRead);
tv.tv_sec = dwStopTime - (GetTickCount () / 1000);
tv.tv_usec = 0;
if (tv.tv_sec < 0)
return WIN_XEVENTS_SUCCESS;
iReturn = select (iConnNumber + 1,
&fdsRead,
NULL,
NULL,
&tv);
if (iReturn <= 0)
{
ErrorF ("winProcessXEventsTimeout - Call to select () failed: %d. "
"Bailing.\n", iReturn);
break;
}
if (FD_ISSET (iConnNumber, &fdsRead))
{
iReturn = winClipboardFlushXEvents (hwnd,
iWindow,
pDisplay,
fUseUnicode);
if (WIN_XEVENTS_NOTIFY == iReturn
|| WIN_XEVENTS_CONVERT == iReturn)
{
return iReturn;
}
}
}
return WIN_XEVENTS_SUCCESS;
}
#define WM_USER_PASTE_COMPLETE (WM_USER + 1003)
LRESULT CALLBACK
winClipboardWindowProc (HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
static HWND s_hwndNextViewer;
static Bool s_fCBCInitialized;
switch (message)
{
case WM_DESTROY:
{
winDebug ("winClipboardWindowProc - WM_DESTROY\n");
ChangeClipboardChain (hwnd, s_hwndNextViewer);
s_hwndNextViewer = NULL;
PostQuitMessage (0);
}
return 0;
case WM_CREATE:
{
HWND first, next;
DWORD error_code = 0;
winDebug ("winClipboardWindowProc - WM_CREATE\n");
first = GetClipboardViewer();
if (first == hwnd) return 0;
next = SetClipboardViewer (hwnd);
error_code = GetLastError();
if (SUCCEEDED(error_code) && (next == first))
s_hwndNextViewer = next;
else
s_fCBCInitialized = FALSE;
}
return 0;
case WM_CHANGECBCHAIN:
{
winDebug ("winClipboardWindowProc - WM_CHANGECBCHAIN: wParam(%x) "
"lParam(%x) s_hwndNextViewer(%x)\n",
wParam, lParam, s_hwndNextViewer);
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);
}
winDebug ("winClipboardWindowProc - WM_CHANGECBCHAIN: Exit\n");
return 0;
case WM_WM_REINIT:
{
HWND first, next;
DWORD error_code = 0;
winDebug ("winClipboardWindowProc - WM_WM_REINIT: Enter\n");
first = GetClipboardViewer();
if (first == hwnd) return 0;
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");
first = GetClipboardViewer();
if (first == hwnd) return 0;
next = SetClipboardViewer (hwnd);
error_code = GetLastError();
if (SUCCEEDED(error_code) && (next == first))
s_hwndNextViewer = next;
else
s_fCBCInitialized = FALSE;
}
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");
if (! s_fProcessingDrawClipboard)
{
s_fProcessingDrawClipboard = TRUE;
}
else
{
s_fCBCInitialized = FALSE;
ChangeClipboardChain (hwnd, s_hwndNextViewer);
winFixClipboardChain();
winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
"Nested calls detected. Re-initing.\n");
winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
s_fProcessingDrawClipboard = FALSE;
return 0;
}
if (!s_fCBCInitialized)
{
s_fCBCInitialized = TRUE;
s_fProcessingDrawClipboard = FALSE;
winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
return 0;
}
if (hwnd == GetClipboardOwner ())
{
winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
"We own the clipboard, returning.\n");
winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
s_fProcessingDrawClipboard = FALSE;
if (s_hwndNextViewer)
SendMessage (s_hwndNextViewer, message, wParam, lParam);
return 0;
}
if (!IsClipboardFormatAvailable (CF_TEXT)
&& !IsClipboardFormatAvailable (CF_UNICODETEXT))
{
winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
"Clipboard does not contain CF_TEXT nor "
"CF_UNICODETEXT.\n");
XSync (pDisplay, FALSE);
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);
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;
if (s_hwndNextViewer)
SendMessage (s_hwndNextViewer, message, wParam, lParam);
return 0;
}
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");
}
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");
}
XFlush (pDisplay);
s_fProcessingDrawClipboard = FALSE;
}
winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
if (s_hwndNextViewer)
SendMessage (s_hwndNextViewer, message, wParam, lParam);
return 0;
case WM_DESTROYCLIPBOARD:
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");
if (message == WM_RENDERALLFORMATS)
fConvertToUnicode = FALSE;
else
fConvertToUnicode = g_fUnicodeSupport && (CF_UNICODETEXT == wParam);
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;
}
if (message == WM_RENDERALLFORMATS)
{
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;
}
}
iReturn = winProcessXEventsTimeout (hwnd,
iWindow,
pDisplay,
fConvertToUnicode,
WIN_POLL_TIMEOUT);
if (WIN_XEVENTS_CONVERT == iReturn)
{
iReturn = winProcessXEventsTimeout (hwnd,
iWindow,
pDisplay,
fConvertToUnicode,
WIN_POLL_TIMEOUT);
}
if (WIN_XEVENTS_NOTIFY != iReturn)
{
if (g_fUnicodeSupport)
SetClipboardData (CF_UNICODETEXT, NULL);
SetClipboardData (CF_TEXT, NULL);
}
PostMessage(g_hwndClipboard, WM_USER_PASTE_COMPLETE, 0, 0);
if (message == WM_RENDERALLFORMATS)
{
if (!CloseClipboard ())
{
winErrorFVerb (1, "winClipboardWindowProc - WM_RENDERALLFORMATS - "
"CloseClipboard () failed: %08x\n",
GetLastError ());
break;
}
}
winDebug ("winClipboardWindowProc - WM_RENDER*FORMAT - Returning.\n");
return 0;
}
case WM_USER_PASTE_COMPLETE:
{
if (hwnd != GetClipboardOwner ())
return 0;
winDebug ("winClipboardWindowProc - WM_USER_PASTE_COMPLETE\n");
OpenClipboard (g_hwndClipboard);
EmptyClipboard ();
if (g_fUnicodeSupport)
SetClipboardData (CF_UNICODETEXT, NULL);
SetClipboardData (CF_TEXT, NULL);
CloseClipboard ();
}
return 0;
}
return DefWindowProc (hwnd, message, wParam, lParam);
}
BOOL
winClipboardFlushWindowsMessageQueue (HWND hwnd)
{
MSG msg;
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
return FALSE;
else
DispatchMessage (&msg);
}
return TRUE;
}