Alexandre Julliard : server: Don' t increment the clipboard sequence number for delayed rendering or synthesized formats.

Alexandre Julliard julliard at winehq.org
Wed May 24 17:17:33 CDT 2017


Module: wine
Branch: master
Commit: 719e28bd2c8393e5940df11894ea3e03ce35e2f3
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=719e28bd2c8393e5940df11894ea3e03ce35e2f3

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed May 24 13:03:39 2017 +0200

server: Don't increment the clipboard sequence number for delayed rendering or synthesized formats.

Based on a patch by Piotr Caban.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/user32/clipboard.c        |  9 +++++++--
 dlls/user32/tests/clipboard.c  | 15 +++++++--------
 include/wine/server_protocol.h |  4 +++-
 server/clipboard.c             | 30 ++++++++++++++++++++++++------
 server/protocol.def            |  1 +
 server/request.h               |  7 ++++---
 server/trace.c                 |  1 +
 7 files changed, 47 insertions(+), 20 deletions(-)

diff --git a/dlls/user32/clipboard.c b/dlls/user32/clipboard.c
index d33459c..2fc5c76 100644
--- a/dlls/user32/clipboard.c
+++ b/dlls/user32/clipboard.c
@@ -1047,6 +1047,7 @@ HANDLE WINAPI GetClipboardData( UINT format )
         SERVER_START_REQ( get_clipboard_data )
         {
             req->format = format;
+            req->render = render;
             if (cache)
             {
                 req->cached = 1;
@@ -1081,13 +1082,17 @@ HANDLE WINAPI GetClipboardData( UINT format )
         if (render)  /* try rendering it */
         {
             render = FALSE;
-            if (owner)
+            if (from)
+            {
+                render_synthesized_format( format, from );
+                continue;
+            }
+            else if (owner)
             {
                 TRACE( "%s sending WM_RENDERFORMAT to %p\n", debugstr_format( format ), owner );
                 SendMessageW( owner, WM_RENDERFORMAT, format, 0 );
                 continue;
             }
-            if (from) return render_synthesized_format( format, from );
         }
         TRACE( "%s returning 0\n", debugstr_format( format ));
         return 0;
diff --git a/dlls/user32/tests/clipboard.c b/dlls/user32/tests/clipboard.c
index 434a325..f0a24cb 100644
--- a/dlls/user32/tests/clipboard.c
+++ b/dlls/user32/tests/clipboard.c
@@ -768,8 +768,7 @@ static void test_synthesized(void)
                broken( tests[i].format == CF_DIBV5 && cf == CF_DIB ), /* >= Vista */
                "%u: couldn't get data, cf %04x err %d\n", i, cf, GetLastError());
             seq = GetClipboardSequenceNumber();
-            todo_wine_if(cf != tests[i].format && cf != CF_LOCALE)
-                ok(seq == old_seq, "sequence changed (test %d %d)\n", i, cf);
+            ok(seq == old_seq, "sequence changed (test %d %d)\n", i, cf);
             switch (cf)
             {
             case CF_LOCALE:
@@ -935,7 +934,7 @@ static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARA
             handle = SetClipboardData( CF_TEXT, create_textA() );
             ok( handle != 0, "SetClipboardData failed: %d\n", GetLastError() );
             seq = GetClipboardSequenceNumber();
-            todo_wine ok( seq == old_seq, "sequence changed\n" );
+            ok( seq == old_seq, "sequence changed\n" );
             old_seq = seq;
 
             handle = CreateThread( NULL, 0, clipboard_render_data_thread, NULL, 0, NULL );
@@ -943,7 +942,7 @@ static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARA
             ok( WaitForSingleObject(handle, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
             CloseHandle( handle );
             seq = GetClipboardSequenceNumber();
-            todo_wine ok( seq == old_seq, "sequence changed\n" );
+            ok( seq == old_seq, "sequence changed\n" );
         }
 
         break;
@@ -1250,7 +1249,7 @@ static DWORD WINAPI clipboard_thread(void *param)
 
     SetClipboardData( CF_WAVE, 0 );
     seq = GetClipboardSequenceNumber();
-    todo_wine ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
+    ok( (int)(seq - old_seq) == 1, "sequence diff %d\n", seq - old_seq );
     old_seq = seq;
     if (!cross_thread)
     {
@@ -1521,13 +1520,13 @@ static DWORD WINAPI clipboard_thread(void *param)
         old_seq = GetClipboardSequenceNumber();
         run_process( "get_clipboard_data" );
         seq = GetClipboardSequenceNumber();
-        todo_wine ok( seq == old_seq, "sequence changed\n" );
+        ok( seq == old_seq, "sequence changed\n" );
         do_render_format = FALSE;
 
         count = SendMessageA( win, WM_USER+1, 0, 0 );
-        todo_wine ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
+        ok( count == 1, "WM_DRAWCLIPBOARD not received\n" );
         count = SendMessageA( win, WM_USER+2, 0, 0 );
-        todo_wine ok( count == 1 || broken(!pAddClipboardFormatListener) /* < Vista */, "WM_CLIPBOARDUPDATE not received\n" );
+        ok( count == 1 || broken(!pAddClipboardFormatListener) /* < Vista */, "WM_CLIPBOARDUPDATE not received\n" );
         fmt = SendMessageA( win, WM_USER+4, 0, 0 );
         ok( fmt == CF_TEXT, "WM_RENDERFORMAT received\n" );
     }
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index cee0f57..0d7a7cd 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -4522,8 +4522,10 @@ struct get_clipboard_data_request
 {
     struct request_header __header;
     unsigned int   format;
+    int            render;
     int            cached;
     unsigned int   seqno;
+    char __pad_28[4];
 };
 struct get_clipboard_data_reply
 {
@@ -6416,6 +6418,6 @@ union generic_reply
     struct terminate_job_reply terminate_job_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 531
+#define SERVER_PROTOCOL_VERSION 532
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/clipboard.c b/server/clipboard.c
index a93319a..160eb46 100644
--- a/server/clipboard.c
+++ b/server/clipboard.c
@@ -57,6 +57,7 @@ struct clipboard
     unsigned int   lcid;             /* locale id to use for synthesizing text formats */
     unsigned int   seqno;            /* clipboard change sequence number */
     unsigned int   open_seqno;       /* sequence number at open time */
+    unsigned int   rendering;        /* format rendering recursion counter */
     struct list    formats;          /* list of data formats */
     unsigned int   format_count;     /* count of data formats */
     unsigned int   format_map;       /* existence bitmap for formats < CF_MAX */
@@ -366,6 +367,7 @@ DECL_HANDLER(open_clipboard)
     }
 
     if (!clipboard->open_thread) clipboard->open_seqno = clipboard->seqno; /* first open */
+    if (clipboard->open_thread != current) clipboard->rendering = 0;
     clipboard->open_win = win;
     clipboard->open_thread = current;
 
@@ -418,9 +420,10 @@ DECL_HANDLER(set_clipboard_data)
 
     free( format->data );
     format->from   = 0;
-    format->seqno  = clipboard->seqno++;
+    format->seqno  = clipboard->seqno;
     format->size   = get_req_data_size();
     format->data   = data;
+    if (!clipboard->rendering) clipboard->seqno++;
 
     if (req->format == CF_TEXT || req->format == CF_OEMTEXT || req->format == CF_UNICODETEXT)
         clipboard->lcid = req->lcid;
@@ -445,15 +448,30 @@ DECL_HANDLER(get_clipboard_data)
     if (!(format = get_format( clipboard, req->format )))
     {
         set_error( STATUS_OBJECT_NAME_NOT_FOUND );
-        return;
+        goto done;
     }
     reply->from   = format->from;
     reply->total  = format->size;
     reply->seqno  = format->seqno;
-    if (!format->data && !format->from) reply->owner = clipboard->owner;
-    if (req->cached && req->seqno == format->seqno) return;  /* client-side cache still valid */
-    if (format->size <= get_reply_max_size()) set_reply_data( format->data, format->size );
-    else set_error( STATUS_BUFFER_OVERFLOW );
+    reply->owner  = clipboard->owner;
+
+    if (!format->data && req->render)  /* try rendering it client-side */
+    {
+        if (format->from || clipboard->owner) clipboard->rendering++;
+        return;
+    }
+
+    if (req->cached && req->seqno == format->seqno) goto done;  /* client-side cache still valid */
+
+    if (format->size > get_reply_max_size())
+    {
+        set_error( STATUS_BUFFER_OVERFLOW );
+        return;
+    }
+    set_reply_data( format->data, format->size );
+
+done:
+    if (!req->render) clipboard->rendering--;
 }
 
 
diff --git a/server/protocol.def b/server/protocol.def
index 6cafa70..7eaaec2 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3184,6 +3184,7 @@ enum caret_state
 /* Fetch a data format from the clipboard */
 @REQ(get_clipboard_data)
     unsigned int   format;         /* clipboard format of the data */
+    int            render;         /* will we try to render it if missing? */
     int            cached;         /* do we already have it in the client-side cache? */
     unsigned int   seqno;          /* sequence number for the data in the cache */
 @REPLY
diff --git a/server/request.h b/server/request.h
index 8b9d9b6..ad89f30 100644
--- a/server/request.h
+++ b/server/request.h
@@ -2040,9 +2040,10 @@ C_ASSERT( sizeof(struct set_clipboard_data_request) == 24 );
 C_ASSERT( FIELD_OFFSET(struct set_clipboard_data_reply, seqno) == 8 );
 C_ASSERT( sizeof(struct set_clipboard_data_reply) == 16 );
 C_ASSERT( FIELD_OFFSET(struct get_clipboard_data_request, format) == 12 );
-C_ASSERT( FIELD_OFFSET(struct get_clipboard_data_request, cached) == 16 );
-C_ASSERT( FIELD_OFFSET(struct get_clipboard_data_request, seqno) == 20 );
-C_ASSERT( sizeof(struct get_clipboard_data_request) == 24 );
+C_ASSERT( FIELD_OFFSET(struct get_clipboard_data_request, render) == 16 );
+C_ASSERT( FIELD_OFFSET(struct get_clipboard_data_request, cached) == 20 );
+C_ASSERT( FIELD_OFFSET(struct get_clipboard_data_request, seqno) == 24 );
+C_ASSERT( sizeof(struct get_clipboard_data_request) == 32 );
 C_ASSERT( FIELD_OFFSET(struct get_clipboard_data_reply, from) == 8 );
 C_ASSERT( FIELD_OFFSET(struct get_clipboard_data_reply, owner) == 12 );
 C_ASSERT( FIELD_OFFSET(struct get_clipboard_data_reply, seqno) == 16 );
diff --git a/server/trace.c b/server/trace.c
index 7b33043..6e23184 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -3775,6 +3775,7 @@ static void dump_set_clipboard_data_reply( const struct set_clipboard_data_reply
 static void dump_get_clipboard_data_request( const struct get_clipboard_data_request *req )
 {
     fprintf( stderr, " format=%08x", req->format );
+    fprintf( stderr, ", render=%d", req->render );
     fprintf( stderr, ", cached=%d", req->cached );
     fprintf( stderr, ", seqno=%08x", req->seqno );
 }




More information about the wine-cvs mailing list