rdp: Add clipboard redirection support
Allow clipboard pasting in and out of an RDP session. Co-authored-by: Steve Pronovost <spronovo@microsoft.com> Co-authored-by: Brenton DeGeer <brdegeer@microsoft.com> Signed-off-by: Hideyuki Nagase <hideyukn@microsoft.com> Signed-off-by: Steve Pronovost <spronovo@microsoft.com> Signed-off-by: Brenton DeGeer <brdegeer@microsoft.com>
This commit is contained in:
parent
252771d9aa
commit
297ad403d6
@ -31,6 +31,7 @@ deps_rdp = [
|
||||
]
|
||||
srcs_rdp = [
|
||||
'rdp.c',
|
||||
'rdpclip.c',
|
||||
'rdputil.c',
|
||||
]
|
||||
|
||||
|
@ -555,6 +555,16 @@ rdp_destroy(struct weston_compositor *ec)
|
||||
if (b->listener_events[i])
|
||||
wl_event_source_remove(b->listener_events[i]);
|
||||
|
||||
if (b->clipboard_debug) {
|
||||
weston_log_scope_destroy(b->clipboard_debug);
|
||||
b->clipboard_debug = NULL;
|
||||
}
|
||||
|
||||
if (b->clipboard_verbose) {
|
||||
weston_log_scope_destroy(b->clipboard_verbose);
|
||||
b->clipboard_verbose = NULL;
|
||||
}
|
||||
|
||||
if (b->debug) {
|
||||
weston_log_scope_destroy(b->debug);
|
||||
b->debug = NULL;
|
||||
@ -669,6 +679,8 @@ rdp_peer_context_free(freerdp_peer* client, RdpPeerContext* context)
|
||||
wl_event_source_remove(context->events[i]);
|
||||
}
|
||||
|
||||
rdp_clipboard_destroy(context);
|
||||
|
||||
if (context->vcm)
|
||||
WTSCloseServer(context->vcm);
|
||||
|
||||
@ -924,6 +936,13 @@ xf_peer_activate(freerdp_peer* client)
|
||||
settings->CompressionEnabled = FALSE;
|
||||
}
|
||||
|
||||
if (settings->RedirectClipboard) {
|
||||
if (!peerCtx->vcm) {
|
||||
weston_log("Virtual channel is required for clipboard\n");
|
||||
goto error_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (output->base.width != (int)settings->DesktopWidth ||
|
||||
output->base.height != (int)settings->DesktopHeight)
|
||||
{
|
||||
@ -995,6 +1014,11 @@ xf_peer_activate(freerdp_peer* client)
|
||||
xkb_keymap_unref(keymap);
|
||||
weston_seat_init_pointer(peersItem->seat);
|
||||
|
||||
/* Initialize RDP clipboard after seat is initialized */
|
||||
if (settings->RedirectClipboard)
|
||||
if (rdp_clipboard_init(client) != 0)
|
||||
goto error_exit;
|
||||
|
||||
peersItem->flags |= RDP_PEER_ACTIVATED;
|
||||
|
||||
/* disable pointer on the client side */
|
||||
@ -1014,6 +1038,12 @@ xf_peer_activate(freerdp_peer* client)
|
||||
pixman_region32_fini(&damage);
|
||||
|
||||
return TRUE;
|
||||
|
||||
error_exit:
|
||||
|
||||
rdp_clipboard_destroy(peerCtx);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
@ -1450,6 +1480,7 @@ rdp_peer_init(freerdp_peer *client, struct rdp_backend *b)
|
||||
settings->NSCodec = TRUE;
|
||||
settings->FrameMarkerCommandEnabled = TRUE;
|
||||
settings->SurfaceFrameMarkerEnabled = TRUE;
|
||||
settings->RedirectClipboard = TRUE;
|
||||
settings->HasExtendedMouseEvent = TRUE;
|
||||
settings->HasHorizontalWheel = TRUE;
|
||||
|
||||
@ -1569,6 +1600,15 @@ rdp_backend_create(struct weston_compositor *compositor,
|
||||
b->rdp_monitor_refresh_rate = config->refresh_rate * 1000;
|
||||
rdp_debug(b, "RDP backend: WESTON_RDP_MONITOR_REFRESH_RATE: %d\n", b->rdp_monitor_refresh_rate);
|
||||
|
||||
b->clipboard_debug = weston_log_ctx_add_log_scope(b->compositor->weston_log_ctx,
|
||||
"rdp-backend-clipboard",
|
||||
"Debug messages from RDP backend clipboard\n",
|
||||
NULL, NULL, NULL);
|
||||
b->clipboard_verbose = weston_log_ctx_add_log_scope(b->compositor->weston_log_ctx,
|
||||
"rdp-backend-clipboard-verbose",
|
||||
"Debug messages from RDP backend clipboard\n",
|
||||
NULL, NULL, NULL);
|
||||
|
||||
compositor->backend = &b->base;
|
||||
|
||||
if (config->server_cert && config->server_key) {
|
||||
@ -1660,6 +1700,10 @@ err_compositor:
|
||||
|
||||
weston_compositor_shutdown(compositor);
|
||||
err_free_strings:
|
||||
if (b->clipboard_debug)
|
||||
weston_log_scope_destroy(b->clipboard_debug);
|
||||
if (b->clipboard_verbose)
|
||||
weston_log_scope_destroy(b->clipboard_verbose);
|
||||
if (b->debug)
|
||||
weston_log_scope_destroy(b->debug);
|
||||
if (b->verbose)
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <freerdp/codec/nsc.h>
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
#include <freerdp/channels/wtsvc.h>
|
||||
#include <freerdp/server/cliprdr.h>
|
||||
|
||||
#include <libweston/libweston.h>
|
||||
#include <libweston/backend-rdp.h>
|
||||
@ -78,6 +79,9 @@ struct rdp_backend {
|
||||
struct weston_log_scope *debug;
|
||||
struct weston_log_scope *verbose;
|
||||
|
||||
struct weston_log_scope *clipboard_debug;
|
||||
struct weston_log_scope *clipboard_verbose;
|
||||
|
||||
char *server_cert;
|
||||
char *server_key;
|
||||
char *rdp_key;
|
||||
@ -142,6 +146,13 @@ struct rdp_peer_context {
|
||||
pthread_mutex_t loop_task_list_mutex;
|
||||
struct wl_list loop_task_list; /* struct rdp_loop_task::link */
|
||||
|
||||
/* Clipboard support */
|
||||
CliprdrServerContext *clipboard_server_context;
|
||||
|
||||
struct rdp_clipboard_data_source *clipboard_client_data_source;
|
||||
struct rdp_clipboard_data_source *clipboard_inflight_client_data_source;
|
||||
|
||||
struct wl_listener clipboard_selection_listener;
|
||||
};
|
||||
|
||||
typedef struct rdp_peer_context RdpPeerContext;
|
||||
@ -171,10 +182,22 @@ struct rdp_loop_task {
|
||||
#define rdp_debug_continue(b, ...) \
|
||||
rdp_debug_print(b->debug, true, __VA_ARGS__)
|
||||
|
||||
#define rdp_debug_clipboard_verbose(b, ...) \
|
||||
rdp_debug_print(b->clipboard_verbose, false, __VA_ARGS__)
|
||||
#define rdp_debug_clipboard_verbose_continue(b, ...) \
|
||||
rdp_debug_print(b->clipboard_verbose, true, __VA_ARGS__)
|
||||
#define rdp_debug_clipboard(b, ...) \
|
||||
rdp_debug_print(b->clipboard_debug, false, __VA_ARGS__)
|
||||
#define rdp_debug_clipboard_continue(b, ...) \
|
||||
rdp_debug_print(b->clipboard_debug, true, __VA_ARGS__)
|
||||
|
||||
/* rdputil.c */
|
||||
void
|
||||
rdp_debug_print(struct weston_log_scope *log_scope, bool cont, char *fmt, ...);
|
||||
|
||||
int
|
||||
rdp_wl_array_read_fd(struct wl_array *array, int fd);
|
||||
|
||||
void
|
||||
convert_rdp_keyboard_to_xkb_rule_names(UINT32 KeyboardType, UINT32 KeyboardSubType, UINT32 KeyboardLayout, struct xkb_rule_names *xkbRuleNames);
|
||||
|
||||
@ -204,6 +227,13 @@ rdp_initialize_dispatch_task_event_source(RdpPeerContext *peerCtx);
|
||||
void
|
||||
rdp_destroy_dispatch_task_event_source(RdpPeerContext *peerCtx);
|
||||
|
||||
/* rdpclip.c */
|
||||
int
|
||||
rdp_clipboard_init(freerdp_peer *client);
|
||||
|
||||
void
|
||||
rdp_clipboard_destroy(RdpPeerContext *peerCtx);
|
||||
|
||||
static inline struct rdp_head *
|
||||
to_rdp_head(struct weston_head *base)
|
||||
{
|
||||
|
1744
libweston/backend-rdp/rdpclip.c
Normal file
1744
libweston/backend-rdp/rdpclip.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -226,3 +226,39 @@ rdp_destroy_dispatch_task_event_source(RdpPeerContext *peerCtx)
|
||||
|
||||
pthread_mutex_destroy(&peerCtx->loop_task_list_mutex);
|
||||
}
|
||||
|
||||
/* This is a little tricky - it makes sure there's always at least
|
||||
* one spare byte in the array in case the caller needs to add a
|
||||
* null terminator to it. We can't just null terminate the array
|
||||
* here, because some callers won't want that - and some won't
|
||||
* like having an odd number of bytes.
|
||||
*/
|
||||
int
|
||||
rdp_wl_array_read_fd(struct wl_array *array, int fd)
|
||||
{
|
||||
int len, size;
|
||||
char *data;
|
||||
|
||||
/* Make sure we have at least 1024 bytes of space left */
|
||||
if (array->alloc - array->size < 1024) {
|
||||
if (!wl_array_add(array, 1024)) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
array->size -= 1024;
|
||||
}
|
||||
data = (char *)array->data + array->size;
|
||||
/* Leave one char in case the caller needs space for a
|
||||
* null terminator */
|
||||
size = array->alloc - array->size - 1;
|
||||
do {
|
||||
len = read(fd, data, size);
|
||||
} while (len == -1 && errno == EINTR);
|
||||
|
||||
if (len == -1)
|
||||
return -1;
|
||||
|
||||
array->size += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user