From 98b24dcb5059e471673ece96eb33b31052d29867 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard <julliard@winehq.org> Date: Mon, 22 Aug 2016 19:26:55 +0900 Subject: [PATCH] server: Add a separate request to set the clipboard viewer. Signed-off-by: Alexandre Julliard <julliard@winehq.org> --- dlls/user32/clipboard.c | 68 ++++++++++++++++------------------ dlls/user32/tests/msg.c | 2 +- include/wine/server_protocol.h | 24 ++++++++++-- server/clipboard.c | 19 +++++++++- server/protocol.def | 12 +++++- server/request.h | 9 ++++- server/trace.c | 16 +++++++- 7 files changed, 104 insertions(+), 46 deletions(-) diff --git a/dlls/user32/clipboard.c b/dlls/user32/clipboard.c index 915c370ea62..dcb317210a9 100644 --- a/dlls/user32/clipboard.c +++ b/dlls/user32/clipboard.c @@ -109,25 +109,6 @@ void CLIPBOARD_ReleaseOwner( HWND hwnd ) } -/************************************************************************** - * CLIPBOARD_SetClipboardViewer - */ -static HWND CLIPBOARD_SetClipboardViewer( HWND hWnd ) -{ - HWND hwndPrev = 0; - - SERVER_START_REQ( set_clipboard_info ) - { - req->flags = SET_CB_VIEWER; - req->viewer = wine_server_user_handle( hWnd ); - if (!wine_server_call_err( req )) - hwndPrev = wine_server_ptr_handle( reply->old_viewer ); - } - SERVER_END_REQ; - - return hwndPrev; -} - /************************************************************************** * WIN32 Clipboard implementation **************************************************************************/ @@ -298,15 +279,25 @@ HWND WINAPI GetOpenClipboardWindow(void) /************************************************************************** * SetClipboardViewer (USER32.@) */ -HWND WINAPI SetClipboardViewer( HWND hWnd ) +HWND WINAPI SetClipboardViewer( HWND hwnd ) { - HWND hwndPrev = CLIPBOARD_SetClipboardViewer(hWnd); + HWND prev = 0, owner = 0; - if (hWnd) - SendNotifyMessageW(hWnd, WM_DRAWCLIPBOARD, (WPARAM) GetClipboardOwner(), 0); - TRACE("(%p): returning %p\n", hWnd, hwndPrev); + SERVER_START_REQ( set_clipboard_viewer ) + { + req->viewer = wine_server_user_handle( hwnd ); + if (!wine_server_call_err( req )) + { + prev = wine_server_ptr_handle( reply->old_viewer ); + owner = wine_server_ptr_handle( reply->owner ); + } + } + SERVER_END_REQ; - return hwndPrev; + if (hwnd) SendNotifyMessageW( hwnd, WM_DRAWCLIPBOARD, (WPARAM)owner, 0 ); + + TRACE( "(%p): returning %p\n", hwnd, prev ); + return prev; } @@ -333,22 +324,27 @@ HWND WINAPI GetClipboardViewer(void) /************************************************************************** * ChangeClipboardChain (USER32.@) */ -BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext) +BOOL WINAPI ChangeClipboardChain( HWND hwnd, HWND next ) { - BOOL bRet = TRUE; - HWND hWndViewer = GetClipboardViewer(); + NTSTATUS status; + HWND viewer; + + if (!hwnd) return FALSE; - if (hWndViewer) + SERVER_START_REQ( set_clipboard_viewer ) { - if (WIN_GetFullHandle(hWnd) == hWndViewer) - CLIPBOARD_SetClipboardViewer(WIN_GetFullHandle(hWndNext)); - else - bRet = !SendMessageW(hWndViewer, WM_CHANGECBCHAIN, (WPARAM)hWnd, (LPARAM)hWndNext); + req->viewer = wine_server_user_handle( next ); + req->previous = wine_server_user_handle( hwnd ); + status = wine_server_call( req ); + viewer = wine_server_ptr_handle( reply->old_viewer ); } - else - ERR("hWndViewer is lost\n"); + SERVER_END_REQ; - return bRet; + if (status == STATUS_PENDING) + return !SendMessageW( viewer, WM_CHANGECBCHAIN, (WPARAM)hwnd, (LPARAM)next ); + + if (status) SetLastError( RtlNtStatusToDosError( status )); + return !status; } diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 07d10b4e29a..61980dfb81b 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -14027,7 +14027,7 @@ static void test_clipboard_viewers(void) expect_HWND(hWnd1, GetClipboardViewer()); ChangeClipboardChain(NULL, hWnd2); - ok_sequence(WmEmptySeq, "change chain (viewer=1, remove=NULL, next=2)", TRUE); + ok_sequence(WmEmptySeq, "change chain (viewer=1, remove=NULL, next=2)", FALSE); expect_HWND(hWnd1, GetClipboardViewer()); /* Actually change clipboard viewer with ChangeClipboardChain. */ diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 6576eb901c9..c865bb8c1c3 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -4493,7 +4493,7 @@ struct set_clipboard_info_request struct request_header __header; unsigned int flags; user_handle_t owner; - user_handle_t viewer; + char __pad_20[4]; }; struct set_clipboard_info_reply { @@ -4506,7 +4506,6 @@ struct set_clipboard_info_reply char __pad_28[4]; }; -#define SET_CB_VIEWER 0x004 #define SET_CB_SEQNO 0x008 #define SET_CB_RELOWNER 0x010 #define CB_OPEN 0x040 @@ -4527,6 +4526,22 @@ struct empty_clipboard_reply +struct set_clipboard_viewer_request +{ + struct request_header __header; + user_handle_t viewer; + user_handle_t previous; + char __pad_20[4]; +}; +struct set_clipboard_viewer_reply +{ + struct reply_header __header; + user_handle_t old_viewer; + user_handle_t owner; +}; + + + struct open_token_request { struct request_header __header; @@ -5659,6 +5674,7 @@ enum request REQ_close_clipboard, REQ_set_clipboard_info, REQ_empty_clipboard, + REQ_set_clipboard_viewer, REQ_open_token, REQ_set_global_windows, REQ_adjust_token_privileges, @@ -5941,6 +5957,7 @@ union generic_request struct close_clipboard_request close_clipboard_request; struct set_clipboard_info_request set_clipboard_info_request; struct empty_clipboard_request empty_clipboard_request; + struct set_clipboard_viewer_request set_clipboard_viewer_request; struct open_token_request open_token_request; struct set_global_windows_request set_global_windows_request; struct adjust_token_privileges_request adjust_token_privileges_request; @@ -6221,6 +6238,7 @@ union generic_reply struct close_clipboard_reply close_clipboard_reply; struct set_clipboard_info_reply set_clipboard_info_reply; struct empty_clipboard_reply empty_clipboard_reply; + struct set_clipboard_viewer_reply set_clipboard_viewer_reply; struct open_token_reply open_token_reply; struct set_global_windows_reply set_global_windows_reply; struct adjust_token_privileges_reply adjust_token_privileges_reply; @@ -6280,6 +6298,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; }; -#define SERVER_PROTOCOL_VERSION 510 +#define SERVER_PROTOCOL_VERSION 511 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/clipboard.c b/server/clipboard.c index 423892531c6..c906e702324 100644 --- a/server/clipboard.c +++ b/server/clipboard.c @@ -219,8 +219,6 @@ DECL_HANDLER(set_clipboard_info) if (!release_clipboard_owner( clipboard, req->owner )) return; } - if (req->flags & SET_CB_VIEWER) clipboard->viewer = get_user_full_handle( req->viewer ); - if (req->flags & SET_CB_SEQNO) clipboard->seqno++; reply->seqno = get_seqno( clipboard ); @@ -248,3 +246,20 @@ DECL_HANDLER(empty_clipboard) clipboard->owner_thread = clipboard->open_thread; clipboard->seqno++; } + + +/* set the clipboard viewer window */ +DECL_HANDLER(set_clipboard_viewer) +{ + struct clipboard *clipboard = get_process_clipboard(); + + if (!clipboard) return; + + reply->old_viewer = clipboard->viewer; + reply->owner = clipboard->owner_win; + + if (!req->previous || clipboard->viewer == get_user_full_handle( req->previous )) + clipboard->viewer = get_user_full_handle( req->viewer ); + else + set_error( STATUS_PENDING ); /* need to send message instead */ +} diff --git a/server/protocol.def b/server/protocol.def index 4b800de59f7..56145469c8a 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3179,7 +3179,6 @@ enum caret_state @REQ(set_clipboard_info) unsigned int flags; /* flags for fields to set (see below) */ user_handle_t owner; /* clipboard owner */ - user_handle_t viewer; /* first clipboard viewer */ @REPLY unsigned int flags; /* status flags (see below) */ user_handle_t old_clipboard; /* old clipboard window */ @@ -3188,7 +3187,6 @@ enum caret_state unsigned int seqno; /* current sequence number */ @END -#define SET_CB_VIEWER 0x004 #define SET_CB_SEQNO 0x008 #define SET_CB_RELOWNER 0x010 #define CB_OPEN 0x040 @@ -3201,6 +3199,16 @@ enum caret_state @END +/* Set the clipboard viewer window */ +@REQ(set_clipboard_viewer) + user_handle_t viewer; /* clipboard viewer */ + user_handle_t previous; /* if non-zero, check that this was the previous viewer */ +@REPLY + user_handle_t old_viewer; /* previous clipboard viewer */ + user_handle_t owner; /* clipboard owner */ +@END + + /* Open a security token */ @REQ(open_token) obj_handle_t handle; /* handle to the thread or process */ diff --git a/server/request.h b/server/request.h index 4f0055c26f4..b4f25a7513d 100644 --- a/server/request.h +++ b/server/request.h @@ -330,6 +330,7 @@ DECL_HANDLER(open_clipboard); DECL_HANDLER(close_clipboard); DECL_HANDLER(set_clipboard_info); DECL_HANDLER(empty_clipboard); +DECL_HANDLER(set_clipboard_viewer); DECL_HANDLER(open_token); DECL_HANDLER(set_global_windows); DECL_HANDLER(adjust_token_privileges); @@ -611,6 +612,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_close_clipboard, (req_handler)req_set_clipboard_info, (req_handler)req_empty_clipboard, + (req_handler)req_set_clipboard_viewer, (req_handler)req_open_token, (req_handler)req_set_global_windows, (req_handler)req_adjust_token_privileges, @@ -2025,7 +2027,6 @@ C_ASSERT( FIELD_OFFSET(struct close_clipboard_reply, owner) == 12 ); C_ASSERT( sizeof(struct close_clipboard_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, flags) == 12 ); C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, owner) == 16 ); -C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, viewer) == 20 ); C_ASSERT( sizeof(struct set_clipboard_info_request) == 24 ); C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_reply, flags) == 8 ); C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_reply, old_clipboard) == 12 ); @@ -2034,6 +2035,12 @@ C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_reply, old_viewer) == 20 ); C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_reply, seqno) == 24 ); C_ASSERT( sizeof(struct set_clipboard_info_reply) == 32 ); C_ASSERT( sizeof(struct empty_clipboard_request) == 16 ); +C_ASSERT( FIELD_OFFSET(struct set_clipboard_viewer_request, viewer) == 12 ); +C_ASSERT( FIELD_OFFSET(struct set_clipboard_viewer_request, previous) == 16 ); +C_ASSERT( sizeof(struct set_clipboard_viewer_request) == 24 ); +C_ASSERT( FIELD_OFFSET(struct set_clipboard_viewer_reply, old_viewer) == 8 ); +C_ASSERT( FIELD_OFFSET(struct set_clipboard_viewer_reply, owner) == 12 ); +C_ASSERT( sizeof(struct set_clipboard_viewer_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct open_token_request, handle) == 12 ); C_ASSERT( FIELD_OFFSET(struct open_token_request, access) == 16 ); C_ASSERT( FIELD_OFFSET(struct open_token_request, attributes) == 20 ); diff --git a/server/trace.c b/server/trace.c index dea9dce2f12..b3b6793aaae 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3759,7 +3759,6 @@ static void dump_set_clipboard_info_request( const struct set_clipboard_info_req { fprintf( stderr, " flags=%08x", req->flags ); fprintf( stderr, ", owner=%08x", req->owner ); - fprintf( stderr, ", viewer=%08x", req->viewer ); } static void dump_set_clipboard_info_reply( const struct set_clipboard_info_reply *req ) @@ -3775,6 +3774,18 @@ static void dump_empty_clipboard_request( const struct empty_clipboard_request * { } +static void dump_set_clipboard_viewer_request( const struct set_clipboard_viewer_request *req ) +{ + fprintf( stderr, " viewer=%08x", req->viewer ); + fprintf( stderr, ", previous=%08x", req->previous ); +} + +static void dump_set_clipboard_viewer_reply( const struct set_clipboard_viewer_reply *req ) +{ + fprintf( stderr, " old_viewer=%08x", req->old_viewer ); + fprintf( stderr, ", owner=%08x", req->owner ); +} + static void dump_open_token_request( const struct open_token_request *req ) { fprintf( stderr, " handle=%04x", req->handle ); @@ -4602,6 +4613,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_close_clipboard_request, (dump_func)dump_set_clipboard_info_request, (dump_func)dump_empty_clipboard_request, + (dump_func)dump_set_clipboard_viewer_request, (dump_func)dump_open_token_request, (dump_func)dump_set_global_windows_request, (dump_func)dump_adjust_token_privileges_request, @@ -4880,6 +4892,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_close_clipboard_reply, (dump_func)dump_set_clipboard_info_reply, NULL, + (dump_func)dump_set_clipboard_viewer_reply, (dump_func)dump_open_token_reply, (dump_func)dump_set_global_windows_reply, (dump_func)dump_adjust_token_privileges_reply, @@ -5158,6 +5171,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "close_clipboard", "set_clipboard_info", "empty_clipboard", + "set_clipboard_viewer", "open_token", "set_global_windows", "adjust_token_privileges", -- GitLab