user32: Don't regard the clipboard as changed if we don't own it.
I ran into a situation where user32 will call EndClipboardUpdate even though the clipboard hasn't changed. It went something like this: * Program A acquires the clipboard and adds some delay-rendered data. * Program B requests data from the clipboard, causing program A to receive WM_RENDERFORMAT. * Program A calls SetClipboardData to fulfill the request, setting bCBHasChanged to TRUE. * Program C acquires the clipboard. * Program A opens the clipboard to enumerate the formats. When it closes the clipboard, EndClipboardUpdate is called. Signed-off-by: Vincent Povirk <vincent@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1383012395
commit
b68e03f9c9
|
@ -178,6 +178,7 @@ INT WINAPI GetClipboardFormatNameA(UINT wFormat, LPSTR retStr, INT maxlen)
|
||||||
BOOL WINAPI OpenClipboard( HWND hWnd )
|
BOOL WINAPI OpenClipboard( HWND hWnd )
|
||||||
{
|
{
|
||||||
BOOL bRet;
|
BOOL bRet;
|
||||||
|
UINT flags;
|
||||||
|
|
||||||
TRACE("(%p)...\n", hWnd);
|
TRACE("(%p)...\n", hWnd);
|
||||||
|
|
||||||
|
@ -185,10 +186,16 @@ BOOL WINAPI OpenClipboard( HWND hWnd )
|
||||||
{
|
{
|
||||||
req->flags = SET_CB_OPEN;
|
req->flags = SET_CB_OPEN;
|
||||||
req->clipboard = wine_server_user_handle( hWnd );
|
req->clipboard = wine_server_user_handle( hWnd );
|
||||||
bRet = !wine_server_call( req );
|
if ((bRet = !wine_server_call( req )))
|
||||||
|
flags = reply->flags;
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
|
||||||
|
if (bRet && !(flags & CB_PROCESS))
|
||||||
|
{
|
||||||
|
bCBHasChanged = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
TRACE(" returning %i\n", bRet);
|
TRACE(" returning %i\n", bRet);
|
||||||
|
|
||||||
return bRet;
|
return bRet;
|
||||||
|
@ -201,6 +208,7 @@ BOOL WINAPI OpenClipboard( HWND hWnd )
|
||||||
BOOL WINAPI CloseClipboard(void)
|
BOOL WINAPI CloseClipboard(void)
|
||||||
{
|
{
|
||||||
HWND viewer = 0;
|
HWND viewer = 0;
|
||||||
|
UINT flags;
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
|
||||||
TRACE("() Changed=%d\n", bCBHasChanged);
|
TRACE("() Changed=%d\n", bCBHasChanged);
|
||||||
|
@ -210,18 +218,21 @@ BOOL WINAPI CloseClipboard(void)
|
||||||
req->flags = SET_CB_CLOSE;
|
req->flags = SET_CB_CLOSE;
|
||||||
if (bCBHasChanged) req->flags |= SET_CB_SEQNO;
|
if (bCBHasChanged) req->flags |= SET_CB_SEQNO;
|
||||||
if ((ret = !wine_server_call_err( req )))
|
if ((ret = !wine_server_call_err( req )))
|
||||||
|
{
|
||||||
viewer = wine_server_ptr_handle( reply->old_viewer );
|
viewer = wine_server_ptr_handle( reply->old_viewer );
|
||||||
|
flags = reply->flags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
|
||||||
if (!ret) return FALSE;
|
if (!ret) return FALSE;
|
||||||
|
|
||||||
if (bCBHasChanged)
|
if (bCBHasChanged && (flags & CB_PROCESS))
|
||||||
{
|
{
|
||||||
USER_Driver->pEndClipboardUpdate();
|
USER_Driver->pEndClipboardUpdate();
|
||||||
bCBHasChanged = FALSE;
|
|
||||||
if (viewer) SendNotifyMessageW(viewer, WM_DRAWCLIPBOARD, (WPARAM) GetClipboardOwner(), 0);
|
if (viewer) SendNotifyMessageW(viewer, WM_DRAWCLIPBOARD, (WPARAM) GetClipboardOwner(), 0);
|
||||||
}
|
}
|
||||||
|
bCBHasChanged = FALSE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue