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

Ken Thomases ken at
Thu Feb 2 14:51:45 CST 2017

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 at>
 dlls/winemac.drv/clipboard.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/dlls/winemac.drv/clipboard.c b/dlls/winemac.drv/clipboard.c
index 7115c3b..53f01d5 100644
--- a/dlls/winemac.drv/clipboard.c
+++ b/dlls/winemac.drv/clipboard.c
@@ -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;
             if (is_clipboard_owner) break;  /* ignore our own changes */
+            if ((LONG)(GetClipboardSequenceNumber() - last_get_seqno) <= 0) break;
         case WM_RENDERFORMAT:
@@ -2220,6 +2222,8 @@ BOOL query_pasteboard_data(HWND hwnd, CFStringRef type)
+    last_get_seqno = GetClipboardSequenceNumber();
     return ret;

More information about the wine-patches mailing list