xwin: Use WM_CLIPBOARDUPDATE clipboard API
Windows Vista and later have a saner clipboard API where the clipboard viewer linked list is no longer maintained by applications. Use it where available. Signed-off-by: Jon Turney <jon.turney@dronecode.org.uk> Reviewed-by: Colin Harrison <colin.harrison@virgin.net>
This commit is contained in:
parent
de7f1fd6f8
commit
008efebda8
|
@ -77,6 +77,14 @@ typedef struct
|
||||||
Atom atomTargets;
|
Atom atomTargets;
|
||||||
} ClipboardAtoms;
|
} 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
|
* winclipboardwndproc.c
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -84,6 +84,10 @@ static pthread_t g_winClipboardProcThread;
|
||||||
int xfixes_event_base;
|
int xfixes_event_base;
|
||||||
int xfixes_error_base;
|
int xfixes_error_base;
|
||||||
|
|
||||||
|
Bool g_fHasModernClipboardApi = FALSE;
|
||||||
|
ADDCLIPBOARDFORMATLISTENERPROC g_fpAddClipboardFormatListener;
|
||||||
|
REMOVECLIPBOARDFORMATLISTENERPROC g_fpRemoveClipboardFormatListener;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local function prototypes
|
* Local function prototypes
|
||||||
*/
|
*/
|
||||||
|
@ -138,6 +142,11 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
|
||||||
ErrorF("winClipboardProc - Warning: Locale not supported by X.\n");
|
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();
|
g_winClipboardProcThread = pthread_self();
|
||||||
|
|
||||||
/* Set error handler */
|
/* Set error handler */
|
||||||
|
|
|
@ -58,6 +58,9 @@
|
||||||
|
|
||||||
#define WIN_POLL_TIMEOUT 1
|
#define WIN_POLL_TIMEOUT 1
|
||||||
|
|
||||||
|
#ifndef WM_CLIPBOARDUPDATE
|
||||||
|
#define WM_CLIPBOARDUPDATE 0x031D
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process X events up to specified timeout
|
* Process X events up to specified timeout
|
||||||
|
@ -151,8 +154,16 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
winDebug("winClipboardWindowProc - WM_DESTROY\n");
|
winDebug("winClipboardWindowProc - WM_DESTROY\n");
|
||||||
|
|
||||||
/* Remove ourselves from the clipboard chain */
|
if (g_fHasModernClipboardApi)
|
||||||
ChangeClipboardChain(hwnd, s_hwndNextViewer);
|
{
|
||||||
|
/* Remove clipboard listener */
|
||||||
|
g_fpRemoveClipboardFormatListener(hwnd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Remove ourselves from the clipboard chain */
|
||||||
|
ChangeClipboardChain(hwnd, s_hwndNextViewer);
|
||||||
|
}
|
||||||
|
|
||||||
s_hwndNextViewer = NULL;
|
s_hwndNextViewer = NULL;
|
||||||
}
|
}
|
||||||
|
@ -168,8 +179,6 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
|
||||||
case WM_CREATE:
|
case WM_CREATE:
|
||||||
{
|
{
|
||||||
HWND first, next;
|
|
||||||
DWORD error_code = 0;
|
|
||||||
ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams;
|
ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams;
|
||||||
|
|
||||||
winDebug("winClipboardWindowProc - WM_CREATE\n");
|
winDebug("winClipboardWindowProc - WM_CREATE\n");
|
||||||
|
@ -179,16 +188,26 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
atoms = cwcp->atoms;
|
atoms = cwcp->atoms;
|
||||||
fRunning = TRUE;
|
fRunning = TRUE;
|
||||||
|
|
||||||
first = GetClipboardViewer(); /* Get handle to first viewer in chain. */
|
if (g_fHasModernClipboardApi)
|
||||||
if (first == hwnd)
|
{
|
||||||
return 0; /* Make sure it's not us! */
|
g_fpAddClipboardFormatListener(hwnd);
|
||||||
/* 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
|
else
|
||||||
s_fCBCInitialized = FALSE;
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -233,6 +252,11 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
|
||||||
winDebug("winClipboardWindowProc - WM_WM_REINIT: Enter\n");
|
winDebug("winClipboardWindowProc - WM_WM_REINIT: Enter\n");
|
||||||
|
|
||||||
|
if (g_fHasModernClipboardApi)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
first = GetClipboardViewer(); /* Get handle to first viewer in chain. */
|
first = GetClipboardViewer(); /* Get handle to first viewer in chain. */
|
||||||
if (first == hwnd)
|
if (first == hwnd)
|
||||||
return 0; /* Make sure it's not us! */
|
return 0; /* Make sure it's not us! */
|
||||||
|
@ -257,38 +281,45 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case WM_DRAWCLIPBOARD:
|
case WM_DRAWCLIPBOARD:
|
||||||
|
case WM_CLIPBOARDUPDATE:
|
||||||
{
|
{
|
||||||
static Bool s_fProcessingDrawClipboard = FALSE;
|
static Bool s_fProcessingDrawClipboard = FALSE;
|
||||||
int iReturn;
|
int iReturn;
|
||||||
|
|
||||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
|
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.
|
/*
|
||||||
*/
|
* We've occasionally seen a loop in the clipboard chain.
|
||||||
if (!s_fProcessingDrawClipboard) {
|
* Try and fix it on the first hint of recursion.
|
||||||
s_fProcessingDrawClipboard = TRUE;
|
*/
|
||||||
}
|
if (!s_fProcessingDrawClipboard) {
|
||||||
else {
|
s_fProcessingDrawClipboard = TRUE;
|
||||||
/* Attempt to break the nesting by getting out of the chain, twice?, and then fix and bail */
|
}
|
||||||
s_fCBCInitialized = FALSE;
|
else {
|
||||||
ChangeClipboardChain(hwnd, s_hwndNextViewer);
|
/* Attempt to break the nesting by getting out of the chain, twice?, and then fix and bail */
|
||||||
winFixClipboardChain();
|
s_fCBCInitialized = FALSE;
|
||||||
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
ChangeClipboardChain(hwnd, s_hwndNextViewer);
|
||||||
"Nested calls detected. Re-initing.\n");
|
winFixClipboardChain();
|
||||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
|
ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
|
||||||
s_fProcessingDrawClipboard = FALSE;
|
"Nested calls detected. Re-initing.\n");
|
||||||
return 0;
|
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
|
||||||
}
|
s_fProcessingDrawClipboard = FALSE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Bail on first message */
|
/* Bail on first message */
|
||||||
if (!s_fCBCInitialized) {
|
if (!s_fCBCInitialized) {
|
||||||
s_fCBCInitialized = TRUE;
|
s_fCBCInitialized = TRUE;
|
||||||
s_fProcessingDrawClipboard = FALSE;
|
s_fProcessingDrawClipboard = FALSE;
|
||||||
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
|
winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: We cannot bail out when NULL == GetClipboardOwner ()
|
* NOTE: We cannot bail out when NULL == GetClipboardOwner ()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user