hw/xwin: Remove support for pre-Vista Win32 clipboard API
The original Win32 clipboard API is widely regarded as terrible, since it relies on clients co-operatively managing the clipboard viewer chain, and a single buggy client can break it for all other clients. The last Windows version only supporting that API was Windows XP (5.1), EOLed in 2014. (This requires MinGW-w64 w32api 6.0.0 or later for Add/RemoveClipboardListener correctly exported by the x86_64 user32 implib)
This commit is contained in:
parent
9a4b62798b
commit
9f51dfdec3
|
@ -42,7 +42,6 @@
|
|||
#define WIN_XEVENTS_NOTIFY_DATA 3
|
||||
#define WIN_XEVENTS_NOTIFY_TARGETS 4
|
||||
|
||||
#define WM_WM_REINIT (WM_USER + 1)
|
||||
#define WM_WM_QUIT (WM_USER + 2)
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0]))
|
||||
|
@ -79,14 +78,6 @@ typedef struct
|
|||
Atom atomIncr;
|
||||
} ClipboardAtoms;
|
||||
|
||||
/* Modern clipboard API functions */
|
||||
typedef wBOOL WINAPI (*ADDCLIPBOARDFORMATLISTENERPROC)(HWND hwnd);
|
||||
typedef wBOOL WINAPI (*REMOVECLIPBOARDFORMATLISTENERPROC)(HWND hwnd);
|
||||
|
||||
extern Bool g_fHasModernClipboardApi;
|
||||
extern ADDCLIPBOARDFORMATLISTENERPROC g_fpAddClipboardFormatListener;
|
||||
extern REMOVECLIPBOARDFORMATLISTENERPROC g_fpRemoveClipboardFormatListener;
|
||||
|
||||
/*
|
||||
* winclipboardwndproc.c
|
||||
*/
|
||||
|
|
|
@ -84,10 +84,6 @@ static pthread_t g_winClipboardProcThread;
|
|||
int xfixes_event_base;
|
||||
int xfixes_error_base;
|
||||
|
||||
Bool g_fHasModernClipboardApi = FALSE;
|
||||
ADDCLIPBOARDFORMATLISTENERPROC g_fpAddClipboardFormatListener;
|
||||
REMOVECLIPBOARDFORMATLISTENERPROC g_fpRemoveClipboardFormatListener;
|
||||
|
||||
/*
|
||||
* Local function prototypes
|
||||
*/
|
||||
|
@ -142,11 +138,6 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
|
|||
ErrorF("winClipboardProc - Warning: Locale not supported by X.\n");
|
||||
}
|
||||
|
||||
g_fpAddClipboardFormatListener = (ADDCLIPBOARDFORMATLISTENERPROC)GetProcAddress(GetModuleHandle("user32"),"AddClipboardFormatListener");
|
||||
g_fpRemoveClipboardFormatListener = (REMOVECLIPBOARDFORMATLISTENERPROC)GetProcAddress(GetModuleHandle("user32"),"RemoveClipboardFormatListener");
|
||||
g_fHasModernClipboardApi = g_fpAddClipboardFormatListener && g_fpRemoveClipboardFormatListener;
|
||||
ErrorF("OS maintains clipboard viewer chain: %s\n", g_fHasModernClipboardApi ? "yes" : "no");
|
||||
|
||||
g_winClipboardProcThread = pthread_self();
|
||||
|
||||
/* Set error handler */
|
||||
|
@ -506,11 +497,3 @@ winClipboardWindowDestroy(void)
|
|||
SendMessage(g_hwndClipboard, WM_WM_QUIT, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
winFixClipboardChain(void)
|
||||
{
|
||||
if (g_hwndClipboard) {
|
||||
PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
* Colin Harrison
|
||||
*/
|
||||
|
||||
#define WINVER 0x0600
|
||||
|
||||
#ifdef HAVE_XWIN_CONFIG_H
|
||||
#include <xwin-config.h>
|
||||
#endif
|
||||
|
@ -58,10 +60,6 @@
|
|||
|
||||
#define WIN_POLL_TIMEOUT 1
|
||||
|
||||
#ifndef WM_CLIPBOARDUPDATE
|
||||
#define WM_CLIPBOARDUPDATE 0x031D
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Process X events up to specified timeout
|
||||
*/
|
||||
|
@ -138,8 +136,6 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay,
|
|||
LRESULT CALLBACK
|
||||
winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static HWND s_hwndNextViewer;
|
||||
static Bool s_fCBCInitialized;
|
||||
static Display *pDisplay;
|
||||
static Window iWindow;
|
||||
static ClipboardAtoms *atoms;
|
||||
|
@ -151,18 +147,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
winDebug("winClipboardWindowProc - WM_DESTROY\n");
|
||||
|
||||
if (g_fHasModernClipboardApi)
|
||||
{
|
||||
/* Remove clipboard listener */
|
||||
g_fpRemoveClipboardFormatListener(hwnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove ourselves from the clipboard chain */
|
||||
ChangeClipboardChain(hwnd, s_hwndNextViewer);
|
||||
}
|
||||
|
||||
s_hwndNextViewer = NULL;
|
||||
/* Remove clipboard listener */
|
||||
RemoveClipboardFormatListener(hwnd);
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
@ -185,138 +171,15 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
atoms = cwcp->atoms;
|
||||
fRunning = TRUE;
|
||||
|
||||
if (g_fHasModernClipboardApi)
|
||||
{
|
||||
g_fpAddClipboardFormatListener(hwnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
HWND first, next;
|
||||
DWORD error_code = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
AddClipboardFormatListener(hwnd);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_CHANGECBCHAIN:
|
||||
{
|
||||
winDebug("winClipboardWindowProc - WM_CHANGECBCHAIN: wParam(%p) "
|
||||
"lParam(%p) s_hwndNextViewer(%p)\n",
|
||||
(HWND)wParam, (HWND)lParam, s_hwndNextViewer);
|
||||
|
||||
if ((HWND) wParam == s_hwndNextViewer) {
|
||||
s_hwndNextViewer = (HWND) lParam;
|
||||
if (s_hwndNextViewer == hwnd) {
|
||||
s_hwndNextViewer = NULL;
|
||||
ErrorF("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:
|
||||
{
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
HWND first, next;
|
||||
DWORD error_code = 0;
|
||||
|
||||
winDebug("winClipboardWindowProc - WM_WM_REINIT: Enter\n");
|
||||
|
||||
if (g_fHasModernClipboardApi)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
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(%p) with %p 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;
|
||||
}
|
||||
winDebug("winClipboardWindowProc - WM_WM_REINIT: Exit\n");
|
||||
return 0;
|
||||
|
||||
case WM_DRAWCLIPBOARD:
|
||||
case WM_CLIPBOARDUPDATE:
|
||||
{
|
||||
static Bool s_fProcessingDrawClipboard = FALSE;
|
||||
int iReturn;
|
||||
|
||||
if (message == WM_DRAWCLIPBOARD)
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
|
||||
else
|
||||
winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Enter\n");
|
||||
|
||||
if (!g_fHasModernClipboardApi)
|
||||
{
|
||||
/*
|
||||
* We've occasionally seen a loop in the clipboard chain.
|
||||
* Try and fix it on the first hint of recursion.
|
||||
*/
|
||||
if (!s_fProcessingDrawClipboard) {
|
||||
s_fProcessingDrawClipboard = TRUE;
|
||||
}
|
||||
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();
|
||||
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;
|
||||
}
|
||||
}
|
||||
winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Enter\n");
|
||||
|
||||
/*
|
||||
* NOTE: We cannot bail out when NULL == GetClipboardOwner ()
|
||||
|
@ -329,12 +192,10 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
/* Bail when we still own the clipboard */
|
||||
if (hwnd == GetClipboardOwner()) {
|
||||
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
|
||||
"We own the clipboard, returning.\n");
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
|
||||
s_fProcessingDrawClipboard = FALSE;
|
||||
if (s_hwndNextViewer)
|
||||
SendMessage(s_hwndNextViewer, message, wParam, lParam);
|
||||
winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Exit\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -350,7 +211,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
if (!IsClipboardFormatAvailable(CF_TEXT)
|
||||
&& !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
|
||||
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
|
||||
"Clipboard does not contain CF_TEXT nor "
|
||||
"CF_UNICODETEXT.\n");
|
||||
|
||||
|
@ -365,31 +226,29 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
/* Release PRIMARY selection if owned */
|
||||
iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY);
|
||||
if (iReturn == iWindow) {
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
|
||||
"PRIMARY selection is owned by us.\n");
|
||||
XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime);
|
||||
}
|
||||
else if (BadWindow == iReturn || BadAtom == iReturn)
|
||||
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
ErrorF("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
|
||||
"XGetSelectionOwner failed for PRIMARY: %d\n",
|
||||
iReturn);
|
||||
|
||||
/* Release CLIPBOARD selection if owned */
|
||||
iReturn = XGetSelectionOwner(pDisplay, atoms->atomClipboard);
|
||||
if (iReturn == iWindow) {
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
|
||||
"CLIPBOARD selection is owned by us, releasing\n");
|
||||
XSetSelectionOwner(pDisplay, atoms->atomClipboard, None, CurrentTime);
|
||||
}
|
||||
else if (BadWindow == iReturn || BadAtom == iReturn)
|
||||
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
ErrorF("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
|
||||
"XGetSelectionOwner failed for CLIPBOARD: %d\n",
|
||||
iReturn);
|
||||
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
|
||||
s_fProcessingDrawClipboard = FALSE;
|
||||
if (s_hwndNextViewer)
|
||||
SendMessage(s_hwndNextViewer, message, wParam, lParam);
|
||||
winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Exit\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -398,11 +257,11 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
XA_PRIMARY, iWindow, CurrentTime);
|
||||
if (iReturn == BadAtom || iReturn == BadWindow ||
|
||||
XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
|
||||
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
ErrorF("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
|
||||
"Could not reassert ownership of PRIMARY\n");
|
||||
}
|
||||
else {
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
|
||||
"Reasserted ownership of PRIMARY\n");
|
||||
}
|
||||
|
||||
|
@ -412,33 +271,28 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
if (iReturn == BadAtom || iReturn == BadWindow ||
|
||||
XGetSelectionOwner(pDisplay, atoms->atomClipboard) != iWindow) {
|
||||
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
ErrorF("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
|
||||
"Could not reassert ownership of CLIPBOARD\n");
|
||||
}
|
||||
else {
|
||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||
winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
|
||||
"Reasserted ownership of CLIPBOARD\n");
|
||||
}
|
||||
|
||||
/* 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);
|
||||
winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Exit\n");
|
||||
return 0;
|
||||
|
||||
case WM_DESTROYCLIPBOARD:
|
||||
/*
|
||||
* NOTE: Intentionally do nothing.
|
||||
* Changes in the Win32 clipboard are handled by WM_DRAWCLIPBOARD
|
||||
* Changes in the Win32 clipboard are handled by WM_CLIPBOARDUPDATE
|
||||
* 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
|
||||
* we do not, because a WM_CLIPBOARDUPDATE message will closely
|
||||
* follow this message and reassert ownership of the X11
|
||||
* selections, handling the issue for us.
|
||||
*/
|
||||
|
|
|
@ -1113,9 +1113,6 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
ShowCursor(TRUE);
|
||||
}
|
||||
|
||||
/* Make sure the clipboard chain is ok. */
|
||||
winFixClipboardChain();
|
||||
|
||||
/* Call engine specific screen activation/deactivation function */
|
||||
(*s_pScreenPriv->pwinActivateApp) (s_pScreen);
|
||||
|
||||
|
|
Loading…
Reference in New Issue