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>
This commit is contained in:
Alexandre Julliard 2017-05-24 13:03:39 +02:00
parent 4213a83525
commit 719e28bd2c
7 changed files with 47 additions and 20 deletions

View file

@ -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;

View file

@ -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" );
}

View file

@ -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 */

View file

@ -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--;
}

View file

@ -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

View file

@ -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 );

View file

@ -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 );
}