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