diff options
author | Alexander Gottwald <alexander.gottwald@s1999.tu-chemnitz.de> | 2004-05-09 16:20:13 +0000 |
---|---|---|
committer | Alexander Gottwald <alexander.gottwald@s1999.tu-chemnitz.de> | 2004-05-09 16:20:13 +0000 |
commit | 35f4f784c2e6c0bdb3e0c2df9d689efd85d8ac98 (patch) | |
tree | a6c1e5e9e4c103b487bfa06510f06667f6492ec5 | |
parent | 5594a38b9eda09efabd550c530ae4782b33ea32f (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/ChangeLog | 18 | ||||
-rw-r--r-- | hw/xwin/winclipboard.h | 2 | ||||
-rw-r--r-- | hw/xwin/winclipboardinit.c | 2 | ||||
-rw-r--r-- | hw/xwin/winclipboardwndproc.c | 155 |
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; } } |