winemac: Ignore clipboard updates provoked by our own call to GetClipboardData().

During a call to GetClipboardData(), the app may be asked to render the data
for a promised format.  This will cause us to receive WM_CLIPBOARDUPDATE.

Almost always, the app will have just rendered the requested format and not
made any other changes.  Therefore, we don't need to rebuild the Mac pasteboard
from the Win32 clipboard.  Doing so can cause a race with the other Mac app
which is querying the pasteboard (for a paste operation, for example).  We
basically delete the data we _just_ added and rebuild the list of available
types.  The symptom is that the other Mac app sees the available types change
and maybe be incomplete.

In theory, the Windows app could make other changes to the clipboard and this
change would cause us to fail to convey them to the Mac pasteboard.  I consider
that very unlikely and the tradeoff to improve the common case is worth it.

Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
oldstable
Ken Thomases 2017-02-02 14:51:45 -06:00 committed by Alexandre Julliard
parent 39ed0c0ca1
commit c95d2de3dd
1 changed files with 4 additions and 0 deletions

View File

@ -200,6 +200,7 @@ static BOOL is_clipboard_owner;
static macdrv_window clipboard_cocoa_window;
static UINT rendered_formats;
static ULONG64 last_clipboard_update;
static DWORD last_get_seqno;
static WINE_CLIPFORMAT **current_mac_formats;
static unsigned int nb_current_mac_formats;
static WCHAR clipboard_pipe_name[256];
@ -1819,6 +1820,7 @@ static LRESULT CALLBACK clipboard_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM
return TRUE;
case WM_CLIPBOARDUPDATE:
if (is_clipboard_owner) break; /* ignore our own changes */
if ((LONG)(GetClipboardSequenceNumber() - last_get_seqno) <= 0) break;
set_mac_pasteboard_types_from_win32_clipboard();
break;
case WM_RENDERFORMAT:
@ -2220,6 +2222,8 @@ BOOL query_pasteboard_data(HWND hwnd, CFStringRef type)
}
}
last_get_seqno = GetClipboardSequenceNumber();
CloseClipboard();
return ret;