Module: wine Branch: master Commit: 719e28bd2c8393e5940df11894ea3e03ce35e2f3 URL: http://source.winehq.org/git/wine.git/?a=commit;h=719e28bd2c8393e5940df11894...
Author: Alexandre Julliard julliard@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@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 ); }