server: Add a request to empty the clipboard.
This commit is contained in:
parent
26bae6d613
commit
3d7aa246d5
|
@ -70,30 +70,6 @@ typedef struct
|
||||||
static BOOL bCBHasChanged = FALSE;
|
static BOOL bCBHasChanged = FALSE;
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
* CLIPBOARD_SetClipboardOwner
|
|
||||||
*
|
|
||||||
* Set the global wineserver clipboard owner. The current process will
|
|
||||||
* be the owner and <hWnd> will get the render notifications.
|
|
||||||
*/
|
|
||||||
static BOOL CLIPBOARD_SetClipboardOwner(HWND hWnd)
|
|
||||||
{
|
|
||||||
BOOL bRet;
|
|
||||||
|
|
||||||
TRACE(" hWnd(%p)\n", hWnd);
|
|
||||||
|
|
||||||
SERVER_START_REQ( set_clipboard_info )
|
|
||||||
{
|
|
||||||
req->flags = SET_CB_OWNER;
|
|
||||||
req->owner = wine_server_user_handle( hWnd );
|
|
||||||
bRet = !wine_server_call_err( req );
|
|
||||||
}
|
|
||||||
SERVER_END_REQ;
|
|
||||||
|
|
||||||
return bRet;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* CLIPBOARD_GetClipboardInfo
|
* CLIPBOARD_GetClipboardInfo
|
||||||
*/
|
*/
|
||||||
|
@ -256,39 +232,25 @@ BOOL WINAPI CloseClipboard(void)
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI EmptyClipboard(void)
|
BOOL WINAPI EmptyClipboard(void)
|
||||||
{
|
{
|
||||||
CLIPBOARDINFO cbinfo;
|
BOOL ret;
|
||||||
|
HWND owner = GetClipboardOwner();
|
||||||
|
|
||||||
TRACE("()\n");
|
TRACE("()\n");
|
||||||
|
|
||||||
if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
|
if (owner) SendMessageTimeoutW( owner, WM_DESTROYCLIPBOARD, 0, 0, SMTO_ABORTIFHUNG, 5000, NULL );
|
||||||
~cbinfo.flags & CB_OPEN)
|
|
||||||
|
SERVER_START_REQ( empty_clipboard )
|
||||||
{
|
{
|
||||||
WARN("Clipboard not opened by calling task!\n");
|
ret = !wine_server_call_err( req );
|
||||||
SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
|
||||||
/* Destroy private objects */
|
if (ret)
|
||||||
if (cbinfo.hWndOwner)
|
{
|
||||||
SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
|
USER_Driver->pEmptyClipboard();
|
||||||
|
bCBHasChanged = TRUE;
|
||||||
/* Tell the driver to acquire the selection. The current owner
|
}
|
||||||
* will be signaled to delete its own cache. */
|
return ret;
|
||||||
|
|
||||||
/* Assign ownership of the clipboard to the current client. We do
|
|
||||||
* this before acquiring the selection so that when we do acquire the
|
|
||||||
* selection and the selection loser gets notified, it can check if
|
|
||||||
* it has lost the Wine clipboard ownership. If it did then it knows
|
|
||||||
* that a WM_DESTROYCLIPBOARD has already been sent. Otherwise it
|
|
||||||
* lost the selection to a X app and it should send the
|
|
||||||
* WM_DESTROYCLIPBOARD itself. */
|
|
||||||
CLIPBOARD_SetClipboardOwner(cbinfo.hWndOpen);
|
|
||||||
|
|
||||||
USER_Driver->pEmptyClipboard();
|
|
||||||
|
|
||||||
bCBHasChanged = TRUE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -408,7 +408,7 @@ static DWORD WINAPI clipboard_thread(void *param)
|
||||||
if (pGetClipboardSequenceNumber)
|
if (pGetClipboardSequenceNumber)
|
||||||
{
|
{
|
||||||
seq = pGetClipboardSequenceNumber();
|
seq = pGetClipboardSequenceNumber();
|
||||||
todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
|
ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
|
||||||
old_seq = seq;
|
old_seq = seq;
|
||||||
}
|
}
|
||||||
count = SendMessageA( win, WM_USER+1, 0, 0 );
|
count = SendMessageA( win, WM_USER+1, 0, 0 );
|
||||||
|
@ -424,7 +424,7 @@ static DWORD WINAPI clipboard_thread(void *param)
|
||||||
if (pGetClipboardSequenceNumber)
|
if (pGetClipboardSequenceNumber)
|
||||||
{
|
{
|
||||||
seq = pGetClipboardSequenceNumber();
|
seq = pGetClipboardSequenceNumber();
|
||||||
todo_wine ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
|
ok( (int)(seq - old_seq) > 0, "sequence unchanged\n" );
|
||||||
old_seq = seq;
|
old_seq = seq;
|
||||||
}
|
}
|
||||||
count = SendMessageA( win, WM_USER+1, 0, 0 );
|
count = SendMessageA( win, WM_USER+1, 0, 0 );
|
||||||
|
|
|
@ -4381,7 +4381,6 @@ struct set_clipboard_info_reply
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SET_CB_OPEN 0x001
|
#define SET_CB_OPEN 0x001
|
||||||
#define SET_CB_OWNER 0x002
|
|
||||||
#define SET_CB_VIEWER 0x004
|
#define SET_CB_VIEWER 0x004
|
||||||
#define SET_CB_SEQNO 0x008
|
#define SET_CB_SEQNO 0x008
|
||||||
#define SET_CB_RELOWNER 0x010
|
#define SET_CB_RELOWNER 0x010
|
||||||
|
@ -4392,6 +4391,18 @@ struct set_clipboard_info_reply
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct empty_clipboard_request
|
||||||
|
{
|
||||||
|
struct request_header __header;
|
||||||
|
char __pad_12[4];
|
||||||
|
};
|
||||||
|
struct empty_clipboard_reply
|
||||||
|
{
|
||||||
|
struct reply_header __header;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct open_token_request
|
struct open_token_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
|
@ -5462,6 +5473,7 @@ enum request
|
||||||
REQ_destroy_class,
|
REQ_destroy_class,
|
||||||
REQ_set_class_info,
|
REQ_set_class_info,
|
||||||
REQ_set_clipboard_info,
|
REQ_set_clipboard_info,
|
||||||
|
REQ_empty_clipboard,
|
||||||
REQ_open_token,
|
REQ_open_token,
|
||||||
REQ_set_global_windows,
|
REQ_set_global_windows,
|
||||||
REQ_adjust_token_privileges,
|
REQ_adjust_token_privileges,
|
||||||
|
@ -5734,6 +5746,7 @@ union generic_request
|
||||||
struct destroy_class_request destroy_class_request;
|
struct destroy_class_request destroy_class_request;
|
||||||
struct set_class_info_request set_class_info_request;
|
struct set_class_info_request set_class_info_request;
|
||||||
struct set_clipboard_info_request set_clipboard_info_request;
|
struct set_clipboard_info_request set_clipboard_info_request;
|
||||||
|
struct empty_clipboard_request empty_clipboard_request;
|
||||||
struct open_token_request open_token_request;
|
struct open_token_request open_token_request;
|
||||||
struct set_global_windows_request set_global_windows_request;
|
struct set_global_windows_request set_global_windows_request;
|
||||||
struct adjust_token_privileges_request adjust_token_privileges_request;
|
struct adjust_token_privileges_request adjust_token_privileges_request;
|
||||||
|
@ -6004,6 +6017,7 @@ union generic_reply
|
||||||
struct destroy_class_reply destroy_class_reply;
|
struct destroy_class_reply destroy_class_reply;
|
||||||
struct set_class_info_reply set_class_info_reply;
|
struct set_class_info_reply set_class_info_reply;
|
||||||
struct set_clipboard_info_reply set_clipboard_info_reply;
|
struct set_clipboard_info_reply set_clipboard_info_reply;
|
||||||
|
struct empty_clipboard_reply empty_clipboard_reply;
|
||||||
struct open_token_reply open_token_reply;
|
struct open_token_reply open_token_reply;
|
||||||
struct set_global_windows_reply set_global_windows_reply;
|
struct set_global_windows_reply set_global_windows_reply;
|
||||||
struct adjust_token_privileges_reply adjust_token_privileges_reply;
|
struct adjust_token_privileges_reply adjust_token_privileges_reply;
|
||||||
|
@ -6059,6 +6073,6 @@ union generic_reply
|
||||||
struct terminate_job_reply terminate_job_reply;
|
struct terminate_job_reply terminate_job_reply;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 475
|
#define SERVER_PROTOCOL_VERSION 476
|
||||||
|
|
||||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
|
@ -160,18 +160,6 @@ static int close_clipboard( struct clipboard *clipboard )
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_clipboard_owner( struct clipboard *clipboard, user_handle_t win )
|
|
||||||
{
|
|
||||||
if (clipboard->open_thread && clipboard->open_thread->process != current->process)
|
|
||||||
{
|
|
||||||
set_error(STATUS_WAS_LOCKED);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
clipboard->owner_win = get_user_full_handle( win );
|
|
||||||
clipboard->owner_thread = current;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int release_clipboard_owner( struct clipboard *clipboard, user_handle_t win )
|
static int release_clipboard_owner( struct clipboard *clipboard, user_handle_t win )
|
||||||
{
|
{
|
||||||
if ((clipboard->open_thread && clipboard->open_thread->process != current->process) ||
|
if ((clipboard->open_thread && clipboard->open_thread->process != current->process) ||
|
||||||
|
@ -216,11 +204,7 @@ DECL_HANDLER(set_clipboard_info)
|
||||||
if (!close_clipboard( clipboard )) return;
|
if (!close_clipboard( clipboard )) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->flags & SET_CB_OWNER)
|
if (req->flags & SET_CB_RELOWNER)
|
||||||
{
|
|
||||||
if (!set_clipboard_owner( clipboard, req->owner )) return;
|
|
||||||
}
|
|
||||||
else if (req->flags & SET_CB_RELOWNER)
|
|
||||||
{
|
{
|
||||||
if (!release_clipboard_owner( clipboard, req->owner )) return;
|
if (!release_clipboard_owner( clipboard, req->owner )) return;
|
||||||
}
|
}
|
||||||
|
@ -236,3 +220,21 @@ DECL_HANDLER(set_clipboard_info)
|
||||||
if (clipboard->owner_thread && clipboard->owner_thread->process == current->process)
|
if (clipboard->owner_thread && clipboard->owner_thread->process == current->process)
|
||||||
reply->flags |= CB_PROCESS;
|
reply->flags |= CB_PROCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* empty the clipboard and grab ownership */
|
||||||
|
DECL_HANDLER(empty_clipboard)
|
||||||
|
{
|
||||||
|
struct clipboard *clipboard = get_process_clipboard();
|
||||||
|
|
||||||
|
if (!clipboard) return;
|
||||||
|
|
||||||
|
if (clipboard->open_thread != current)
|
||||||
|
{
|
||||||
|
set_win32_error( ERROR_CLIPBOARD_NOT_OPEN );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clipboard->owner_win = clipboard->open_win;
|
||||||
|
clipboard->owner_thread = clipboard->open_thread;
|
||||||
|
clipboard->seqno++;
|
||||||
|
}
|
||||||
|
|
|
@ -3087,7 +3087,6 @@ enum coords_relative
|
||||||
@END
|
@END
|
||||||
|
|
||||||
#define SET_CB_OPEN 0x001
|
#define SET_CB_OPEN 0x001
|
||||||
#define SET_CB_OWNER 0x002
|
|
||||||
#define SET_CB_VIEWER 0x004
|
#define SET_CB_VIEWER 0x004
|
||||||
#define SET_CB_SEQNO 0x008
|
#define SET_CB_SEQNO 0x008
|
||||||
#define SET_CB_RELOWNER 0x010
|
#define SET_CB_RELOWNER 0x010
|
||||||
|
@ -3097,6 +3096,11 @@ enum coords_relative
|
||||||
#define CB_PROCESS 0x100
|
#define CB_PROCESS 0x100
|
||||||
|
|
||||||
|
|
||||||
|
/* Empty the clipboard and grab ownership */
|
||||||
|
@REQ(empty_clipboard)
|
||||||
|
@END
|
||||||
|
|
||||||
|
|
||||||
/* Open a security token */
|
/* Open a security token */
|
||||||
@REQ(open_token)
|
@REQ(open_token)
|
||||||
obj_handle_t handle; /* handle to the thread or process */
|
obj_handle_t handle; /* handle to the thread or process */
|
||||||
|
|
|
@ -318,6 +318,7 @@ DECL_HANDLER(create_class);
|
||||||
DECL_HANDLER(destroy_class);
|
DECL_HANDLER(destroy_class);
|
||||||
DECL_HANDLER(set_class_info);
|
DECL_HANDLER(set_class_info);
|
||||||
DECL_HANDLER(set_clipboard_info);
|
DECL_HANDLER(set_clipboard_info);
|
||||||
|
DECL_HANDLER(empty_clipboard);
|
||||||
DECL_HANDLER(open_token);
|
DECL_HANDLER(open_token);
|
||||||
DECL_HANDLER(set_global_windows);
|
DECL_HANDLER(set_global_windows);
|
||||||
DECL_HANDLER(adjust_token_privileges);
|
DECL_HANDLER(adjust_token_privileges);
|
||||||
|
@ -589,6 +590,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
||||||
(req_handler)req_destroy_class,
|
(req_handler)req_destroy_class,
|
||||||
(req_handler)req_set_class_info,
|
(req_handler)req_set_class_info,
|
||||||
(req_handler)req_set_clipboard_info,
|
(req_handler)req_set_clipboard_info,
|
||||||
|
(req_handler)req_empty_clipboard,
|
||||||
(req_handler)req_open_token,
|
(req_handler)req_open_token,
|
||||||
(req_handler)req_set_global_windows,
|
(req_handler)req_set_global_windows,
|
||||||
(req_handler)req_adjust_token_privileges,
|
(req_handler)req_adjust_token_privileges,
|
||||||
|
@ -1989,6 +1991,7 @@ C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_reply, old_owner) == 16 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_reply, old_viewer) == 20 );
|
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( FIELD_OFFSET(struct set_clipboard_info_reply, seqno) == 24 );
|
||||||
C_ASSERT( sizeof(struct set_clipboard_info_reply) == 32 );
|
C_ASSERT( sizeof(struct set_clipboard_info_reply) == 32 );
|
||||||
|
C_ASSERT( sizeof(struct empty_clipboard_request) == 16 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct open_token_request, handle) == 12 );
|
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, access) == 16 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct open_token_request, attributes) == 20 );
|
C_ASSERT( FIELD_OFFSET(struct open_token_request, attributes) == 20 );
|
||||||
|
|
|
@ -3639,6 +3639,10 @@ static void dump_set_clipboard_info_reply( const struct set_clipboard_info_reply
|
||||||
fprintf( stderr, ", seqno=%08x", req->seqno );
|
fprintf( stderr, ", seqno=%08x", req->seqno );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dump_empty_clipboard_request( const struct empty_clipboard_request *req )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static void dump_open_token_request( const struct open_token_request *req )
|
static void dump_open_token_request( const struct open_token_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " handle=%04x", req->handle );
|
fprintf( stderr, " handle=%04x", req->handle );
|
||||||
|
@ -4434,6 +4438,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_destroy_class_request,
|
(dump_func)dump_destroy_class_request,
|
||||||
(dump_func)dump_set_class_info_request,
|
(dump_func)dump_set_class_info_request,
|
||||||
(dump_func)dump_set_clipboard_info_request,
|
(dump_func)dump_set_clipboard_info_request,
|
||||||
|
(dump_func)dump_empty_clipboard_request,
|
||||||
(dump_func)dump_open_token_request,
|
(dump_func)dump_open_token_request,
|
||||||
(dump_func)dump_set_global_windows_request,
|
(dump_func)dump_set_global_windows_request,
|
||||||
(dump_func)dump_adjust_token_privileges_request,
|
(dump_func)dump_adjust_token_privileges_request,
|
||||||
|
@ -4702,6 +4707,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_destroy_class_reply,
|
(dump_func)dump_destroy_class_reply,
|
||||||
(dump_func)dump_set_class_info_reply,
|
(dump_func)dump_set_class_info_reply,
|
||||||
(dump_func)dump_set_clipboard_info_reply,
|
(dump_func)dump_set_clipboard_info_reply,
|
||||||
|
NULL,
|
||||||
(dump_func)dump_open_token_reply,
|
(dump_func)dump_open_token_reply,
|
||||||
(dump_func)dump_set_global_windows_reply,
|
(dump_func)dump_set_global_windows_reply,
|
||||||
(dump_func)dump_adjust_token_privileges_reply,
|
(dump_func)dump_adjust_token_privileges_reply,
|
||||||
|
@ -4970,6 +4976,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||||
"destroy_class",
|
"destroy_class",
|
||||||
"set_class_info",
|
"set_class_info",
|
||||||
"set_clipboard_info",
|
"set_clipboard_info",
|
||||||
|
"empty_clipboard",
|
||||||
"open_token",
|
"open_token",
|
||||||
"set_global_windows",
|
"set_global_windows",
|
||||||
"adjust_token_privileges",
|
"adjust_token_privileges",
|
||||||
|
|
Loading…
Reference in New Issue