server: Implement Add/RemoveClipboardFormatListener.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
19d16a7cb1
commit
35537b1d45
|
@ -471,8 +471,15 @@ DWORD WINAPI GetClipboardSequenceNumber(VOID)
|
|||
*/
|
||||
BOOL WINAPI AddClipboardFormatListener(HWND hwnd)
|
||||
{
|
||||
FIXME("%p: stub\n", hwnd);
|
||||
return TRUE;
|
||||
BOOL ret;
|
||||
|
||||
SERVER_START_REQ( add_clipboard_listener )
|
||||
{
|
||||
req->window = wine_server_user_handle( hwnd );
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -480,6 +487,13 @@ BOOL WINAPI AddClipboardFormatListener(HWND hwnd)
|
|||
*/
|
||||
BOOL WINAPI RemoveClipboardFormatListener(HWND hwnd)
|
||||
{
|
||||
FIXME("%p: stub\n", hwnd);
|
||||
return TRUE;
|
||||
BOOL ret;
|
||||
|
||||
SERVER_START_REQ( remove_clipboard_listener )
|
||||
{
|
||||
req->window = wine_server_user_handle( hwnd );
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -598,12 +598,12 @@ static DWORD WINAPI clipboard_thread(void *param)
|
|||
ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
|
||||
SetLastError( 0xdeadbeef );
|
||||
r = pAddClipboardFormatListener( win );
|
||||
todo_wine ok( !r, "AddClipboardFormatListener succeeded\n" );
|
||||
todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
ok( !r, "AddClipboardFormatListener succeeded\n" );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
SetLastError( 0xdeadbeef );
|
||||
r = pAddClipboardFormatListener( (HWND)0xdead );
|
||||
todo_wine ok( !r, "AddClipboardFormatListener succeeded\n" );
|
||||
todo_wine ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
|
||||
ok( !r, "AddClipboardFormatListener succeeded\n" );
|
||||
ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
|
||||
r = pAddClipboardFormatListener( GetDesktopWindow() );
|
||||
ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
|
||||
r = pRemoveClipboardFormatListener( GetDesktopWindow() );
|
||||
|
@ -926,12 +926,12 @@ static DWORD WINAPI clipboard_thread(void *param)
|
|||
ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
|
||||
SetLastError( 0xdeadbeef );
|
||||
r = pRemoveClipboardFormatListener(win);
|
||||
todo_wine ok( !r, "RemoveClipboardFormatListener succeeded\n" );
|
||||
todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
ok( !r, "RemoveClipboardFormatListener succeeded\n" );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
SetLastError( 0xdeadbeef );
|
||||
r = pRemoveClipboardFormatListener( (HWND)0xdead );
|
||||
todo_wine ok( !r, "RemoveClipboardFormatListener succeeded\n" );
|
||||
todo_wine ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
|
||||
ok( !r, "RemoveClipboardFormatListener succeeded\n" );
|
||||
ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -4559,6 +4559,30 @@ struct set_clipboard_viewer_reply
|
|||
|
||||
|
||||
|
||||
struct add_clipboard_listener_request
|
||||
{
|
||||
struct request_header __header;
|
||||
user_handle_t window;
|
||||
};
|
||||
struct add_clipboard_listener_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct remove_clipboard_listener_request
|
||||
{
|
||||
struct request_header __header;
|
||||
user_handle_t window;
|
||||
};
|
||||
struct remove_clipboard_listener_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct open_token_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -5693,6 +5717,8 @@ enum request
|
|||
REQ_empty_clipboard,
|
||||
REQ_get_clipboard_info,
|
||||
REQ_set_clipboard_viewer,
|
||||
REQ_add_clipboard_listener,
|
||||
REQ_remove_clipboard_listener,
|
||||
REQ_open_token,
|
||||
REQ_set_global_windows,
|
||||
REQ_adjust_token_privileges,
|
||||
|
@ -5977,6 +6003,8 @@ union generic_request
|
|||
struct empty_clipboard_request empty_clipboard_request;
|
||||
struct get_clipboard_info_request get_clipboard_info_request;
|
||||
struct set_clipboard_viewer_request set_clipboard_viewer_request;
|
||||
struct add_clipboard_listener_request add_clipboard_listener_request;
|
||||
struct remove_clipboard_listener_request remove_clipboard_listener_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;
|
||||
|
@ -6259,6 +6287,8 @@ union generic_reply
|
|||
struct empty_clipboard_reply empty_clipboard_reply;
|
||||
struct get_clipboard_info_reply get_clipboard_info_reply;
|
||||
struct set_clipboard_viewer_reply set_clipboard_viewer_reply;
|
||||
struct add_clipboard_listener_reply add_clipboard_listener_reply;
|
||||
struct remove_clipboard_listener_reply remove_clipboard_listener_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;
|
||||
|
@ -6318,6 +6348,6 @@ union generic_reply
|
|||
struct terminate_job_reply terminate_job_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 513
|
||||
#define SERVER_PROTOCOL_VERSION 514
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -3307,6 +3307,7 @@ WINUSERAPI BOOL WINAPI UpdateLayeredWindowIndirect(HWND,UPDATELAYEREDWIND
|
|||
#endif /* defined(_WINGDI_) && !defined(NOGDI) */
|
||||
|
||||
WINUSERAPI HKL WINAPI ActivateKeyboardLayout(HKL,UINT);
|
||||
WINUSERAPI BOOL WINAPI AddClipboardFormatListener(HWND);
|
||||
WINUSERAPI BOOL WINAPI AdjustWindowRect(LPRECT,DWORD,BOOL);
|
||||
WINUSERAPI BOOL WINAPI AdjustWindowRectEx(LPRECT,DWORD,BOOL,DWORD);
|
||||
WINUSERAPI BOOL WINAPI AllowSetForegroundWindow(DWORD);
|
||||
|
@ -3901,6 +3902,7 @@ WINUSERAPI UINT WINAPI RegisterWindowMessageW(LPCWSTR);
|
|||
#define RegisterWindowMessage WINELIB_NAME_AW(RegisterWindowMessage)
|
||||
WINUSERAPI BOOL WINAPI ReleaseCapture(void);
|
||||
WINUSERAPI INT WINAPI ReleaseDC(HWND,HDC);
|
||||
WINUSERAPI BOOL WINAPI RemoveClipboardFormatListener(HWND);
|
||||
WINUSERAPI BOOL WINAPI RemoveMenu(HMENU,UINT,UINT);
|
||||
WINUSERAPI HANDLE WINAPI RemovePropA(HWND,LPCSTR);
|
||||
WINUSERAPI HANDLE WINAPI RemovePropW(HWND,LPCWSTR);
|
||||
|
|
|
@ -46,9 +46,13 @@ struct clipboard
|
|||
user_handle_t viewer; /* first window in clipboard viewer list */
|
||||
unsigned int seqno; /* clipboard change sequence number */
|
||||
timeout_t seqno_timestamp; /* time stamp of last seqno increment */
|
||||
unsigned int listen_size; /* size of listeners array */
|
||||
unsigned int listen_count; /* count of listeners */
|
||||
user_handle_t *listeners; /* array of listener windows */
|
||||
};
|
||||
|
||||
static void clipboard_dump( struct object *obj, int verbose );
|
||||
static void clipboard_destroy( struct object *obj );
|
||||
|
||||
static const struct object_ops clipboard_ops =
|
||||
{
|
||||
|
@ -69,7 +73,7 @@ static const struct object_ops clipboard_ops =
|
|||
NULL, /* unlink_name */
|
||||
no_open_file, /* open_file */
|
||||
no_close_handle, /* close_handle */
|
||||
no_destroy /* destroy */
|
||||
clipboard_destroy /* destroy */
|
||||
};
|
||||
|
||||
|
||||
|
@ -85,6 +89,13 @@ static void clipboard_dump( struct object *obj, int verbose )
|
|||
clipboard->owner_win, clipboard->viewer, clipboard->seqno );
|
||||
}
|
||||
|
||||
static void clipboard_destroy( struct object *obj )
|
||||
{
|
||||
struct clipboard *clipboard = (struct clipboard *)obj;
|
||||
|
||||
free( clipboard->listeners );
|
||||
}
|
||||
|
||||
/* retrieve the clipboard info for the current process, allocating it if needed */
|
||||
static struct clipboard *get_process_clipboard(void)
|
||||
{
|
||||
|
@ -104,6 +115,9 @@ static struct clipboard *get_process_clipboard(void)
|
|||
clipboard->viewer = 0;
|
||||
clipboard->seqno = 0;
|
||||
clipboard->seqno_timestamp = 0;
|
||||
clipboard->listen_size = 0;
|
||||
clipboard->listen_count = 0;
|
||||
clipboard->listeners = NULL;
|
||||
winstation->clipboard = clipboard;
|
||||
}
|
||||
}
|
||||
|
@ -111,6 +125,48 @@ static struct clipboard *get_process_clipboard(void)
|
|||
return clipboard;
|
||||
}
|
||||
|
||||
/* add a clipboard listener */
|
||||
static void add_listener( struct clipboard *clipboard, user_handle_t window )
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < clipboard->listen_count; i++)
|
||||
{
|
||||
if (clipboard->listeners[i] != window) continue;
|
||||
set_error( STATUS_INVALID_PARAMETER ); /* already set */
|
||||
return;
|
||||
}
|
||||
if (clipboard->listen_size == clipboard->listen_count)
|
||||
{
|
||||
unsigned int new_size = max( 8, clipboard->listen_size * 2 );
|
||||
user_handle_t *new = realloc( clipboard->listeners, new_size * sizeof(*new) );
|
||||
if (!new)
|
||||
{
|
||||
set_error( STATUS_NO_MEMORY );
|
||||
return;
|
||||
}
|
||||
clipboard->listeners = new;
|
||||
clipboard->listen_size = new_size;
|
||||
}
|
||||
clipboard->listeners[clipboard->listen_count++] = window;
|
||||
}
|
||||
|
||||
/* remove a clipboard listener */
|
||||
static int remove_listener( struct clipboard *clipboard, user_handle_t window )
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < clipboard->listen_count; i++)
|
||||
{
|
||||
if (clipboard->listeners[i] != window) continue;
|
||||
memmove( clipboard->listeners + i, clipboard->listeners + i + 1,
|
||||
(clipboard->listen_count - i - 1) * sizeof(*clipboard->listeners) );
|
||||
clipboard->listen_count--;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cleanup clipboard information upon window destruction */
|
||||
void cleanup_clipboard_window( struct desktop *desktop, user_handle_t window )
|
||||
{
|
||||
|
@ -129,6 +185,7 @@ void cleanup_clipboard_window( struct desktop *desktop, user_handle_t window )
|
|||
clipboard->owner_thread = NULL;
|
||||
}
|
||||
if (clipboard->viewer == window) clipboard->viewer = 0;
|
||||
remove_listener( clipboard, window );
|
||||
}
|
||||
|
||||
/* Called when thread terminates to allow release of clipboard */
|
||||
|
@ -314,3 +371,39 @@ DECL_HANDLER(set_clipboard_viewer)
|
|||
else
|
||||
set_error( STATUS_PENDING ); /* need to send message instead */
|
||||
}
|
||||
|
||||
|
||||
/* add a clipboard listener window */
|
||||
DECL_HANDLER(add_clipboard_listener)
|
||||
{
|
||||
struct clipboard *clipboard = get_process_clipboard();
|
||||
user_handle_t win = req->window;
|
||||
|
||||
if (!clipboard) return;
|
||||
|
||||
if (!get_user_object_handle( &win, USER_WINDOW ))
|
||||
{
|
||||
set_win32_error( ERROR_INVALID_WINDOW_HANDLE );
|
||||
return;
|
||||
}
|
||||
|
||||
add_listener( clipboard, win );
|
||||
}
|
||||
|
||||
|
||||
/* remove a clipboard listener window */
|
||||
DECL_HANDLER(remove_clipboard_listener)
|
||||
{
|
||||
struct clipboard *clipboard = get_process_clipboard();
|
||||
user_handle_t win = req->window;
|
||||
|
||||
if (!clipboard) return;
|
||||
|
||||
if (!get_user_object_handle( &win, USER_WINDOW ))
|
||||
{
|
||||
set_win32_error( ERROR_INVALID_WINDOW_HANDLE );
|
||||
return;
|
||||
}
|
||||
|
||||
if (!remove_listener( clipboard, win )) set_error( STATUS_INVALID_PARAMETER );
|
||||
}
|
||||
|
|
|
@ -3220,6 +3220,18 @@ enum caret_state
|
|||
@END
|
||||
|
||||
|
||||
/* Add a clipboard listener window */
|
||||
@REQ(add_clipboard_listener)
|
||||
user_handle_t window; /* clipboard listener window */
|
||||
@END
|
||||
|
||||
|
||||
/* Remove a clipboard listener window */
|
||||
@REQ(remove_clipboard_listener)
|
||||
user_handle_t window; /* clipboard listener window */
|
||||
@END
|
||||
|
||||
|
||||
/* Open a security token */
|
||||
@REQ(open_token)
|
||||
obj_handle_t handle; /* handle to the thread or process */
|
||||
|
|
|
@ -332,6 +332,8 @@ DECL_HANDLER(set_clipboard_info);
|
|||
DECL_HANDLER(empty_clipboard);
|
||||
DECL_HANDLER(get_clipboard_info);
|
||||
DECL_HANDLER(set_clipboard_viewer);
|
||||
DECL_HANDLER(add_clipboard_listener);
|
||||
DECL_HANDLER(remove_clipboard_listener);
|
||||
DECL_HANDLER(open_token);
|
||||
DECL_HANDLER(set_global_windows);
|
||||
DECL_HANDLER(adjust_token_privileges);
|
||||
|
@ -615,6 +617,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_empty_clipboard,
|
||||
(req_handler)req_get_clipboard_info,
|
||||
(req_handler)req_set_clipboard_viewer,
|
||||
(req_handler)req_add_clipboard_listener,
|
||||
(req_handler)req_remove_clipboard_listener,
|
||||
(req_handler)req_open_token,
|
||||
(req_handler)req_set_global_windows,
|
||||
(req_handler)req_adjust_token_privileges,
|
||||
|
@ -2049,6 +2053,10 @@ 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 add_clipboard_listener_request, window) == 12 );
|
||||
C_ASSERT( sizeof(struct add_clipboard_listener_request) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct remove_clipboard_listener_request, window) == 12 );
|
||||
C_ASSERT( sizeof(struct remove_clipboard_listener_request) == 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 );
|
||||
|
|
|
@ -3798,6 +3798,16 @@ static void dump_set_clipboard_viewer_reply( const struct set_clipboard_viewer_r
|
|||
fprintf( stderr, ", owner=%08x", req->owner );
|
||||
}
|
||||
|
||||
static void dump_add_clipboard_listener_request( const struct add_clipboard_listener_request *req )
|
||||
{
|
||||
fprintf( stderr, " window=%08x", req->window );
|
||||
}
|
||||
|
||||
static void dump_remove_clipboard_listener_request( const struct remove_clipboard_listener_request *req )
|
||||
{
|
||||
fprintf( stderr, " window=%08x", req->window );
|
||||
}
|
||||
|
||||
static void dump_open_token_request( const struct open_token_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
|
@ -4627,6 +4637,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_empty_clipboard_request,
|
||||
(dump_func)dump_get_clipboard_info_request,
|
||||
(dump_func)dump_set_clipboard_viewer_request,
|
||||
(dump_func)dump_add_clipboard_listener_request,
|
||||
(dump_func)dump_remove_clipboard_listener_request,
|
||||
(dump_func)dump_open_token_request,
|
||||
(dump_func)dump_set_global_windows_request,
|
||||
(dump_func)dump_adjust_token_privileges_request,
|
||||
|
@ -4907,6 +4919,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
NULL,
|
||||
(dump_func)dump_get_clipboard_info_reply,
|
||||
(dump_func)dump_set_clipboard_viewer_reply,
|
||||
NULL,
|
||||
NULL,
|
||||
(dump_func)dump_open_token_reply,
|
||||
(dump_func)dump_set_global_windows_reply,
|
||||
(dump_func)dump_adjust_token_privileges_reply,
|
||||
|
@ -5187,6 +5201,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"empty_clipboard",
|
||||
"get_clipboard_info",
|
||||
"set_clipboard_viewer",
|
||||
"add_clipboard_listener",
|
||||
"remove_clipboard_listener",
|
||||
"open_token",
|
||||
"set_global_windows",
|
||||
"adjust_token_privileges",
|
||||
|
|
Loading…
Reference in New Issue