summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Gottwald <alexander.gottwald@s1999.tu-chemnitz.de>2004-05-09 16:20:13 +0000
committerAlexander Gottwald <alexander.gottwald@s1999.tu-chemnitz.de>2004-05-09 16:20:13 +0000
commit35f4f784c2e6c0bdb3e0c2df9d689efd85d8ac98 (patch)
treea6c1e5e9e4c103b487bfa06510f06667f6492ec5
parent5594a38b9eda09efabd550c530ae4782b33ea32f (diff)
Fix clipboard crashes and silent quits while copying or pasting after using
another Windows application which utilizes the clipboard chain (Dan Wilks)
-rw-r--r--hw/xwin/ChangeLog18
-rw-r--r--hw/xwin/winclipboard.h2
-rw-r--r--hw/xwin/winclipboardinit.c2
-rw-r--r--hw/xwin/winclipboardwndproc.c155
4 files changed, 132 insertions, 45 deletions
diff --git a/hw/xwin/ChangeLog b/hw/xwin/ChangeLog
new file mode 100644
index 000000000..f95e6ea97
--- /dev/null
+++ b/hw/xwin/ChangeLog
@@ -0,0 +1,18 @@
+2004-05-09 Alexander Gottwald <ago@freedesktop.org>
+
+ * Patch by Dan Wilks <Dan_Wilks@intuit.com>
+ * winclipboard.h: Add extern prototypes for winDebug, winErrorFVerb
+ copied from winmsg.h.
+ * winclipboardinit.c (winFixClipboardChain): Post rather than send the
+ reinit message to the clipboard window. Sending the message caused,
+ or possibly just exacerbated an existing, race condition that would
+ cause the X server to hang when coming back from a remote desktop
+ session.
+ * winclipboardwndproc.c (winProcessXEventsTimeout): switch to new
+ logging api's.
+ * winclipboardwindproc.c (winClipboardWindowProc): switch to new
+ logging api's. Add some additional debug logging. Make best effort
+ to prevent our window appearing twice in the clipboard chain. Also
+ detect loops when they occur and try to behave in a reasonable way.
+
+
diff --git a/hw/xwin/winclipboard.h b/hw/xwin/winclipboard.h
index 07cba4854..225f50418 100644
--- a/hw/xwin/winclipboard.h
+++ b/hw/xwin/winclipboard.h
@@ -84,6 +84,8 @@
extern char *display;
extern void ErrorF (const char* /*f*/, ...);
+extern void winDebug (const char *format, ...);
+extern void winErrorFVerb (int verb, const char *format, ...);
/*
diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index a525427b3..01a56cdf0 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -135,6 +135,6 @@ winFixClipboardChain (void)
if (g_fClipboard
&& g_hwndClipboard)
{
- SendMessage (g_hwndClipboard, WM_WM_REINIT, 0, 0);
+ PostMessage (g_hwndClipboard, WM_WM_REINIT, 0, 0);
}
}
diff --git a/hw/xwin/winclipboardwndproc.c b/hw/xwin/winclipboardwndproc.c
index 50efbb141..947db682c 100644
--- a/hw/xwin/winclipboardwndproc.c
+++ b/hw/xwin/winclipboardwndproc.c
@@ -145,9 +145,7 @@ winClipboardWindowProc (HWND hwnd, UINT message,
{
case WM_DESTROY:
{
-#if 0
- ErrorF ("winClipboardWindowProc - WM_DESTROY\n");
-#endif
+ winDebug ("winClipboardWindowProc - WM_DESTROY\n");
/* Remove ourselves from the clipboard chain */
ChangeClipboardChain (hwnd, s_hwndNextViewer);
@@ -161,24 +159,61 @@ winClipboardWindowProc (HWND hwnd, UINT message,
case WM_CREATE:
{
-#if 0
- ErrorF ("winClipboardWindowProc - WM_CREATE\n");
-#endif
+ 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;
+ {
+ 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:
@@ -196,21 +231,58 @@ winClipboardWindowProc (HWND hwnd, UINT message,
* expensive than just putting ourselves back into the chain.
*/
- s_fCBCInitialized = FALSE;
- ChangeClipboardChain (hwnd, s_hwndNextViewer);
- s_hwndNextViewer = NULL;
- s_fCBCInitialized = FALSE;
- s_hwndNextViewer = SetClipboardViewer (hwnd);
+ 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);
@@ -219,6 +291,8 @@ winClipboardWindowProc (HWND hwnd, UINT message,
if (!s_fCBCInitialized)
{
s_fCBCInitialized = TRUE;
+ s_fProcessingDrawClipboard = FALSE;
+ winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
return 0;
}
@@ -233,10 +307,11 @@ winClipboardWindowProc (HWND hwnd, UINT message,
/* Bail when we still own the clipboard */
if (hwnd == GetClipboardOwner ())
{
-#if 0
- ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+
+ winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
"We own the clipboard, returning.\n");
-#endif
+ winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
+ s_fProcessingDrawClipboard = FALSE;
return 0;
}
@@ -248,11 +323,10 @@ winClipboardWindowProc (HWND hwnd, UINT message,
if (!IsClipboardFormatAvailable (CF_TEXT)
&& !IsClipboardFormatAvailable (CF_UNICODETEXT))
{
-#if 0
- ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+
+ winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
"Clipboard does not contain CF_TEXT nor "
"CF_UNICODETEXT.\n");
-#endif
/*
* We need to make sure that the X Server has processed
@@ -264,17 +338,15 @@ winClipboardWindowProc (HWND hwnd, UINT message,
iReturn = XGetSelectionOwner (pDisplay, XA_PRIMARY);
if (iReturn == g_iClipboardWindow)
{
-#if 0
- ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
"PRIMARY selection is owned by us.\n");
-#endif
XSetSelectionOwner (pDisplay,
XA_PRIMARY,
None,
CurrentTime);
}
else if (BadWindow == iReturn || BadAtom == iReturn)
- ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
"XGetSelection failed for PRIMARY: %d\n", iReturn);
/* Release CLIPBOARD selection if owned */
@@ -284,10 +356,8 @@ winClipboardWindowProc (HWND hwnd, UINT message,
False));
if (iReturn == g_iClipboardWindow)
{
-#if 0
- ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
"CLIPBOARD selection is owned by us.\n");
-#endif
XSetSelectionOwner (pDisplay,
XInternAtom (pDisplay,
"CLIPBOARD",
@@ -296,9 +366,11 @@ winClipboardWindowProc (HWND hwnd, UINT message,
CurrentTime);
}
else if (BadWindow == iReturn || BadAtom == iReturn)
- ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
"XGetSelection failed for CLIPBOARD: %d\n", iReturn);
+ winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
+ s_fProcessingDrawClipboard = FALSE;
return 0;
}
@@ -309,16 +381,14 @@ winClipboardWindowProc (HWND hwnd, UINT message,
CurrentTime);
if (iReturn == BadAtom || iReturn == BadWindow)
{
- ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
"Could not reassert ownership of PRIMARY\n");
}
-#if 0
else
{
- ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
"Reasserted ownership of PRIMARY\n");
}
-#endif
/* Reassert ownership of the CLIPBOARD */
iReturn = XSetSelectionOwner (pDisplay,
@@ -329,20 +399,21 @@ winClipboardWindowProc (HWND hwnd, UINT message,
CurrentTime);
if (iReturn == BadAtom || iReturn == BadWindow)
{
- ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
"Could not reassert ownership of CLIPBOARD\n");
}
-#if 0
else
{
- ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+ winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
"Reasserted ownership of CLIPBOARD\n");
}
-#endif
/* Flush the pending SetSelectionOwner event now */
XFlush (pDisplay);
+
+ s_fProcessingDrawClipboard = FALSE;
}
+ winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
return 0;
@@ -368,9 +439,7 @@ winClipboardWindowProc (HWND hwnd, UINT message,
Window iWindow = g_iClipboardWindow;
Bool fConvertToUnicode;
-#if 0
- ErrorF ("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
-#endif
+ winDebug ("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
/* Flag whether to convert to Unicode or not */
if (message == WM_RENDERALLFORMATS)
@@ -389,7 +458,7 @@ winClipboardWindowProc (HWND hwnd, UINT message,
CurrentTime);
if (iReturn == BadAtom || iReturn == BadWindow)
{
- ErrorF ("winClipboardWindowProc - WM_RENDER*FORMAT - "
+ winErrorFVerb (1, "winClipboardWindowProc - WM_RENDER*FORMAT - "
"XConvertSelection () failed\n");
break;
}
@@ -407,7 +476,7 @@ winClipboardWindowProc (HWND hwnd, UINT message,
if (!OpenClipboard (hwnd))
{
- ErrorF ("winClipboardWindowProc - WM_RENDER*FORMATS - "
+ winErrorFVerb (1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
"OpenClipboard () failed: %08x\n",
GetLastError ());
break;
@@ -415,7 +484,7 @@ winClipboardWindowProc (HWND hwnd, UINT message,
if (!EmptyClipboard ())
{
- ErrorF ("winClipboardWindowProc - WM_RENDER*FORMATS - "
+ winErrorFVerb (1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
"EmptyClipboard () failed: %08x\n",
GetLastError ());
break;
@@ -465,16 +534,14 @@ winClipboardWindowProc (HWND hwnd, UINT message,
if (!CloseClipboard ())
{
- ErrorF ("winClipboardWindowProc - WM_RENDERALLFORMATS - "
+ winErrorFVerb (1, "winClipboardWindowProc - WM_RENDERALLFORMATS - "
"CloseClipboard () failed: %08x\n",
GetLastError ());
break;
}
}
-#if 0
- ErrorF ("winClipboardWindowProc - WM_RENDER*FORMAT - Returning.\n");
-#endif
+ winDebug ("winClipboardWindowProc - WM_RENDER*FORMAT - Returning.\n");
return 0;
}
}