diff options
Diffstat (limited to 'xorg-server/hw/xwin/winclipboardwndproc.c')
-rw-r--r-- | xorg-server/hw/xwin/winclipboardwndproc.c | 337 |
1 files changed, 137 insertions, 200 deletions
diff --git a/xorg-server/hw/xwin/winclipboardwndproc.c b/xorg-server/hw/xwin/winclipboardwndproc.c index 9394b04db..1dbee9b6f 100644 --- a/xorg-server/hw/xwin/winclipboardwndproc.c +++ b/xorg-server/hw/xwin/winclipboardwndproc.c @@ -37,15 +37,17 @@ #include <sys/time.h> #include "winclipboard.h" #include "misc.h" +#include "winmsg.h" +#include "objbase.h" +#include "ddraw.h" +#include "winwindow.h" /* * Constants */ -#define WIN_CLIPBOARD_PROP "cyg_clipboard_prop" #define WIN_POLL_TIMEOUT 1 - /* * References to external symbols */ @@ -55,9 +57,10 @@ extern Bool g_fUnicodeSupport; extern void *g_pClipboardDisplay; extern Window g_iClipboardWindow; extern Atom g_atomLastOwnedSelection; - +extern Bool g_fClipboardStarted; /* BPS - g_hwndClipboard needed for X app->Windows paste fix */ extern HWND g_hwndClipboard; +extern Bool g_fClipboardPrimary; /* * Local function prototypes @@ -81,8 +84,17 @@ winProcessXEventsTimeout (HWND hwnd, int iWindow, Display *pDisplay, int iReturn; DWORD dwStopTime = (GetTickCount () / 1000) + iTimeoutSec; - /* We need to ensure that all pending events are processed */ - XSync (pDisplay, FALSE); + /* Make sure the output messages are sent before waiting on a response. */ + iReturn = winClipboardFlushXEvents (hwnd, + iWindow, + pDisplay, + fUseUnicode, + TRUE); + if (WIN_XEVENTS_NOTIFY == iReturn) + { + /* Bail out if notify processed */ + return iReturn; + } /* Get our connection number */ iConnNumber = ConnectionNumber (pDisplay); @@ -112,8 +124,8 @@ winProcessXEventsTimeout (HWND hwnd, int iWindow, Display *pDisplay, &tv); /* No timeout */ if (iReturn < 0) { - ErrorF ("winProcessXEventsTimeout - Call to select () failed: %d. " - "Bailing.\n", iReturn); + ErrorF ("winProcessXEventsTimeout - Call to select () failed: %d (%x). " + "Bailing.\n", iReturn, WSAGetLastError()); break; } @@ -125,7 +137,8 @@ winProcessXEventsTimeout (HWND hwnd, int iWindow, Display *pDisplay, iReturn = winClipboardFlushXEvents (hwnd, iWindow, pDisplay, - fUseUnicode); + fUseUnicode, + TRUE); if (WIN_XEVENTS_NOTIFY == iReturn || WIN_XEVENTS_CONVERT == iReturn) { @@ -138,23 +151,15 @@ winProcessXEventsTimeout (HWND hwnd, int iWindow, Display *pDisplay, return WIN_XEVENTS_SUCCESS; } - /* * Process a given Windows message */ -/* BPS - Define our own message, which we'll post to ourselves to facilitate - * resetting the delayed rendering mechanism after each paste from X app to - * Windows app. TODO - Perhaps move to win.h with the other WM_USER messages. - */ -#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; /* Branch on message type */ switch (message) @@ -167,7 +172,7 @@ winClipboardWindowProc (HWND hwnd, UINT message, ChangeClipboardChain (hwnd, s_hwndNextViewer); s_hwndNextViewer = NULL; - + g_hwndClipboard = NULL; PostQuitMessage (0); } return 0; @@ -179,15 +184,16 @@ winClipboardWindowProc (HWND hwnd, UINT message, DWORD error_code = 0; winDebug ("winClipboardWindowProc - WM_CREATE\n"); - first = GetClipboardViewer(); /* Get handle to first viewer in chain. */ - if (first == hwnd) return 0; /* Make sure it's not us! */ /* Add ourselves to the clipboard viewer chain */ - next = SetClipboardViewer (hwnd); - error_code = GetLastError(); - if (SUCCEEDED(error_code) && (next == first)) /* SetClipboardViewer must have succeeded, and the handle */ - s_hwndNextViewer = next; /* it returned must have been the first window in the chain */ - else - s_fCBCInitialized = FALSE; + s_hwndNextViewer = SetClipboardViewer (hwnd); + #ifdef _DEBUG + if (s_hwndNextViewer== hwnd) + { + ErrorF("WM_CREATE: SetClipboardViewer returned own window. This causes an endless loop, so reset s_hwndNextViewer. "); + s_hwndNextViewer=NULL; + } + #endif + } return 0; @@ -202,11 +208,10 @@ winClipboardWindowProc (HWND hwnd, UINT message, { s_hwndNextViewer = (HWND) lParam; if (s_hwndNextViewer == hwnd) - { - s_hwndNextViewer = NULL; - winErrorFVerb (1, "winClipboardWindowProc - WM_CHANGECBCHAIN: " - "attempted to set next window to ourselves."); - } + { + winDebug("WM_CHANGECBCHAIN: trying to set s_hwndNextViewer to own window. Resetting it back to NULL. "); + s_hwndNextViewer=NULL; /* This would cause an endless loop, so break it by ending the loop here. I have seen this happening, why??? */ + } } else if (s_hwndNextViewer) SendMessage (s_hwndNextViewer, message, @@ -233,27 +238,28 @@ winClipboardWindowProc (HWND hwnd, UINT message, HWND first, next; DWORD error_code = 0; + if (!g_hwndClipboard) + return 0; winDebug ("winClipboardWindowProc - WM_WM_REINIT: Enter\n"); first = GetClipboardViewer(); /* Get handle to first viewer in chain. */ - if (first == hwnd) return 0; /* Make sure it's not us! */ - 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(); /* Get handle to first viewer in chain. */ - if (first == hwnd) return 0; /* Make sure it's not us! */ - next = SetClipboardViewer (hwnd); - error_code = GetLastError(); - if (SUCCEEDED(error_code) && (next == first)) /* SetClipboardViewer must have succeeded, and the handle */ - s_hwndNextViewer = next; /* it returned must have been the first window in the chain */ - else - s_fCBCInitialized = FALSE; + if (first != hwnd) + { + winDebug (" WM_WM_REINIT: Replacing us(%x) with %x at head " + "of chain\n", hwnd, s_hwndNextViewer); + if (!wParam) ChangeClipboardChain (hwnd, s_hwndNextViewer); /* When wParam is set, the window was already removed from the chain */ + winDebug (" WM_WM_REINIT: Putting us back at head of chain.\n"); + s_hwndNextViewer = SetClipboardViewer (hwnd); + #ifdef _DEBUG + if (s_hwndNextViewer== hwnd) + { + ErrorF("WM_WM_REINIT: SetClipboardViewer returned own window. This causes an endless loop, so reset s_hwndNextViewer. "); + s_hwndNextViewer=NULL; + } + #endif + } + winDebug ("winClipboardWindowProc - WM_WM_REINIT: Exit\n"); } - winDebug ("winClipboardWindowProc - WM_WM_REINIT: Exit\n"); return 0; @@ -266,7 +272,15 @@ winClipboardWindowProc (HWND hwnd, UINT message, Window iWindow = g_iClipboardWindow; int iReturn; - winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n"); + winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD 0x%x 0x%x 0x%x: Enter\n",hwnd,wParam,lParam); + + if (!g_fClipboardStarted) + { + winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit with no processing\n"); + if (s_hwndNextViewer) + SendMessage (s_hwndNextViewer, message, wParam, lParam); + return 0; + } if (generation != serverGeneration) { @@ -285,46 +299,15 @@ winClipboardWindowProc (HWND hwnd, UINT message, else { /* Attempt to break the nesting by getting out of the chain, twice?, and then fix and bail */ - s_fCBCInitialized = FALSE; ChangeClipboardChain (hwnd, s_hwndNextViewer); - winFixClipboardChain(); - winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - " + winFixClipboardChain(1); + ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - " "Nested calls detected. Re-initing.\n"); winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n"); s_fProcessingDrawClipboard = FALSE; return 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; - if (s_hwndNextViewer) - SendMessage (s_hwndNextViewer, message, wParam, lParam); - return 0; - } - /* * Do not take ownership of the X11 selections when something * other than CF_TEXT or CF_UNICODETEXT has been copied @@ -344,21 +327,23 @@ winClipboardWindowProc (HWND hwnd, UINT message, */ XSync (pDisplay, FALSE); - /* 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); - + if (g_fClipboardPrimary) + { + /* 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) + ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - " + "XGetSelection failed for PRIMARY: %d\n", iReturn); + } /* Release CLIPBOARD selection if owned */ iReturn = XGetSelectionOwner (pDisplay, atomClipboard); @@ -372,7 +357,7 @@ winClipboardWindowProc (HWND hwnd, UINT message, CurrentTime); } else if (BadWindow == iReturn || BadAtom == iReturn) - winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - " + ErrorF ("winClipboardWindowProc - WM_DRAWCLIPBOARD - " "XGetSelection failed for CLIPBOARD: %d\n", iReturn); winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n"); @@ -381,53 +366,58 @@ winClipboardWindowProc (HWND hwnd, UINT message, SendMessage (s_hwndNextViewer, message, wParam, lParam); return 0; } - - /* Reassert ownership of PRIMARY */ - iReturn = XSetSelectionOwner (pDisplay, - XA_PRIMARY, - iWindow, - CurrentTime); - if (iReturn == BadAtom || iReturn == BadWindow || - XGetSelectionOwner (pDisplay, XA_PRIMARY) != iWindow) - { - 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, - atomClipboard, - iWindow, - CurrentTime); - - if (iReturn == BadAtom || iReturn == BadWindow || - XGetSelectionOwner (pDisplay, atomClipboard) != iWindow) - { - winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - " - "Could not reassert ownership of CLIPBOARD\n"); - } - else + /* Only reassert ownership when we did not change the clipboard ourselves */ + if (hwnd!=(HWND)wParam) + { + if (g_fClipboardPrimary) { - winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - " - "Reasserted ownership of CLIPBOARD\n"); + /* Reassert ownership of PRIMARY */ + iReturn = XSetSelectionOwner (pDisplay, + XA_PRIMARY, + iWindow, + CurrentTime); + if (iReturn == BadAtom || iReturn == BadWindow || + XGetSelectionOwner (pDisplay, XA_PRIMARY) != iWindow) + { + ErrorF ("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, + atomClipboard, + iWindow, + CurrentTime); + + if (iReturn == BadAtom || iReturn == BadWindow || + XGetSelectionOwner (pDisplay, atomClipboard) != iWindow) + { + ErrorF ("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; - } + /* Flush the pending SetSelectionOwner event now */ + XFlush (pDisplay); + } + + s_fProcessingDrawClipboard = FALSE; winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n"); /* Pass the message on the next window in the clipboard viewer chain */ if (s_hwndNextViewer) SendMessage (s_hwndNextViewer, message, wParam, lParam); return 0; + } case WM_DESTROYCLIPBOARD: /* @@ -465,12 +455,12 @@ winClipboardWindowProc (HWND hwnd, UINT message, XInternAtom (pDisplay, "COMPOUND_TEXT", False), XInternAtom (pDisplay, - "CYGX_CUT_BUFFER", False), + WIN_LOCAL_PROPERTY, False), iWindow, CurrentTime); if (iReturn == BadAtom || iReturn == BadWindow) { - winErrorFVerb (1, "winClipboardWindowProc - WM_RENDER*FORMAT - " + ErrorF ("winClipboardWindowProc - WM_RENDER*FORMAT - " "XConvertSelection () failed\n"); break; } @@ -479,16 +469,9 @@ winClipboardWindowProc (HWND hwnd, UINT message, 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 - " + ErrorF ("winClipboardWindowProc - WM_RENDER*FORMATS - " "OpenClipboard () failed: %08x\n", GetLastError ()); break; @@ -496,35 +479,26 @@ winClipboardWindowProc (HWND hwnd, UINT message, if (!EmptyClipboard ()) { - winErrorFVerb (1, "winClipboardWindowProc - WM_RENDER*FORMATS - " + ErrorF ("winClipboardWindowProc - WM_RENDER*FORMATS - " "EmptyClipboard () failed: %08x\n", GetLastError ()); + CloseClipboard (); break; } } /* Process the SelectionNotify event */ - iReturn = winProcessXEventsTimeout (hwnd, + do { + 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); - } + } while (WIN_XEVENTS_CONVERT == iReturn); + /* - * The last of the up-to two calls to winProcessXEventsTimeout + * The last call 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 @@ -532,6 +506,7 @@ winClipboardWindowProc (HWND hwnd, UINT message, */ if (WIN_XEVENTS_NOTIFY != iReturn) { + ErrorF("winClipboardWindowProc - winProcessXEventsTimeout should have returned WIN_XEVENTS_NOTIFY was %d\n",iReturn); /* Paste no data, to satisfy required call to SetClipboardData */ if (g_fUnicodeSupport) SetClipboardData (CF_UNICODETEXT, NULL); @@ -540,13 +515,6 @@ winClipboardWindowProc (HWND hwnd, UINT message, ErrorF("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY\n"); } - /* BPS - Post ourselves a user message whose handler will reset the - * delayed rendering mechanism after the paste is complete. This is - * necessary because calling SetClipboardData() with a NULL argument - * here will cause the data we just put on the clipboard to be lost! - */ - PostMessage(g_hwndClipboard, WM_USER_PASTE_COMPLETE, 0, 0); - /* Special handling for WM_RENDERALLFORMATS */ if (message == WM_RENDERALLFORMATS) { @@ -554,7 +522,7 @@ winClipboardWindowProc (HWND hwnd, UINT message, if (!CloseClipboard ()) { - winErrorFVerb (1, "winClipboardWindowProc - WM_RENDERALLFORMATS - " + ErrorF ("winClipboardWindowProc - WM_RENDERALLFORMATS - " "CloseClipboard () failed: %08x\n", GetLastError ()); break; @@ -564,37 +532,6 @@ winClipboardWindowProc (HWND hwnd, UINT message, winDebug ("winClipboardWindowProc - WM_RENDER*FORMAT - Returning.\n"); return 0; } - /* BPS - This WM_USER message is posted by us. It gives us the opportunity - * to reset the delayed rendering mechanism after each and every paste - * from an X app to a Windows app. Without such a mechanism, subsequent - * changes of selection in the X app owning the selection are not - * reflected in pastes into Windows apps, since Windows won't send us the - * WM_RENDERFORMAT message unless someone has set changed data (or NULL) - * on the clipboard. */ - case WM_USER_PASTE_COMPLETE: - { - if (hwnd != GetClipboardOwner ()) - /* In case we've lost the selection since posting the message */ - return 0; - winDebug ("winClipboardWindowProc - WM_USER_PASTE_COMPLETE\n"); - - /* Set up for another delayed rendering callback */ - OpenClipboard (g_hwndClipboard); - - /* Take ownership of the Windows clipboard */ - EmptyClipboard (); - - /* Advertise Unicode if we support it */ - if (g_fUnicodeSupport) - SetClipboardData (CF_UNICODETEXT, NULL); - - /* Always advertise regular text */ - SetClipboardData (CF_TEXT, NULL); - - /* Release the clipboard */ - CloseClipboard (); - } - return 0; } /* Let Windows perform default processing for unhandled messages */ |