cliprdr: integrate with xfreerdp.

This commit is contained in:
Vic Lee 2011-09-23 11:37:17 +08:00
parent 68d0e7db6a
commit 783681664a
12 changed files with 1440 additions and 104 deletions

View File

@ -38,44 +38,52 @@
void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, RDP_CB_FORMAT_LIST_EVENT* cb_event)
{
STREAM* data_out;
STREAM* s;
int i;
data_out = cliprdr_packet_new(CB_FORMAT_LIST, 0, 36 * cb_event->num_formats);
if (cb_event->raw_format_data)
{
s = cliprdr_packet_new(CB_FORMAT_LIST, 0, cb_event->raw_format_data_size);
stream_write(s, cb_event->raw_format_data, cb_event->raw_format_data_size);
}
else
{
s = cliprdr_packet_new(CB_FORMAT_LIST, 0, 36 * cb_event->num_formats);
for (i = 0; i < cb_event->num_formats; i++)
{
stream_write_uint32(data_out, cb_event->formats[i]);
stream_write_uint32(s, cb_event->formats[i]);
switch (cb_event->formats[i])
{
case CB_FORMAT_HTML:
memcpy(stream_get_tail(data_out), CFSTR_HTML, sizeof(CFSTR_HTML));
memcpy(stream_get_tail(s), CFSTR_HTML, sizeof(CFSTR_HTML));
break;
case CB_FORMAT_PNG:
memcpy(stream_get_tail(data_out), CFSTR_PNG, sizeof(CFSTR_PNG));
memcpy(stream_get_tail(s), CFSTR_PNG, sizeof(CFSTR_PNG));
break;
case CB_FORMAT_JPEG:
memcpy(stream_get_tail(data_out), CFSTR_JPEG, sizeof(CFSTR_JPEG));
memcpy(stream_get_tail(s), CFSTR_JPEG, sizeof(CFSTR_JPEG));
break;
case CB_FORMAT_GIF:
memcpy(stream_get_tail(data_out), CFSTR_GIF, sizeof(CFSTR_GIF));
memcpy(stream_get_tail(s), CFSTR_GIF, sizeof(CFSTR_GIF));
break;
}
stream_seek(data_out, 32);
stream_seek(s, 32);
}
}
cliprdr_packet_send(cliprdr, data_out);
cliprdr_packet_send(cliprdr, s);
}
static void cliprdr_send_format_list_response(cliprdrPlugin* cliprdr)
{
STREAM* data_out;
STREAM* s;
data_out = cliprdr_packet_new(CB_FORMAT_LIST_RESPONSE, CB_RESPONSE_OK, 0);
cliprdr_packet_send(cliprdr, data_out);
s = cliprdr_packet_new(CB_FORMAT_LIST_RESPONSE, CB_RESPONSE_OK, 0);
cliprdr_packet_send(cliprdr, s);
}
void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* data_in, uint32 dataLen)
void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* s, uint32 dataLen)
{
RDP_CB_FORMAT_LIST_EVENT* cb_event;
uint32 format;
@ -85,14 +93,23 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* data_in, uint32
cb_event = (RDP_CB_FORMAT_LIST_EVENT*)freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR,
RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL);
num_formats = dataLen / 36;
cb_event->formats = (uint32*)xmalloc(sizeof(uint32) * num_formats);
cb_event->num_formats = 0;
if (dataLen > 0)
{
cb_event->raw_format_data = (uint8*) xmalloc(dataLen);
memcpy(cb_event->raw_format_data, stream_get_tail(s), dataLen);
cb_event->raw_format_data_size = dataLen;
}
if (num_formats * 36 != dataLen)
DEBUG_WARN("dataLen %d not devided by 36!", dataLen);
for (i = 0; i < num_formats; i++)
{
stream_read_uint32(data_in, format);
stream_read_uint32(s, format);
supported = 1;
switch (format)
{
@ -102,22 +119,22 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* data_in, uint32
break;
default:
if (memcmp(stream_get_tail(data_in), CFSTR_HTML, sizeof(CFSTR_HTML)) == 0)
if (memcmp(stream_get_tail(s), CFSTR_HTML, sizeof(CFSTR_HTML)) == 0)
{
format = CB_FORMAT_HTML;
break;
}
if (memcmp(stream_get_tail(data_in), CFSTR_PNG, sizeof(CFSTR_PNG)) == 0)
if (memcmp(stream_get_tail(s), CFSTR_PNG, sizeof(CFSTR_PNG)) == 0)
{
format = CB_FORMAT_PNG;
break;
}
if (memcmp(stream_get_tail(data_in), CFSTR_JPEG, sizeof(CFSTR_JPEG)) == 0)
if (memcmp(stream_get_tail(s), CFSTR_JPEG, sizeof(CFSTR_JPEG)) == 0)
{
format = CB_FORMAT_JPEG;
break;
}
if (memcmp(stream_get_tail(data_in), CFSTR_GIF, sizeof(CFSTR_GIF)) == 0)
if (memcmp(stream_get_tail(s), CFSTR_GIF, sizeof(CFSTR_GIF)) == 0)
{
format = CB_FORMAT_GIF;
break;
@ -125,7 +142,7 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* data_in, uint32
supported = 0;
break;
}
stream_seek(data_in, 32);
stream_seek(s, 32);
if (supported)
cb_event->formats[cb_event->num_formats++] = format;
@ -135,42 +152,65 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* data_in, uint32
cliprdr_send_format_list_response(cliprdr);
}
void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, STREAM* data_in)
void cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, uint16 msgFlags)
{
RDP_EVENT* event;
if ((msgFlags & CB_RESPONSE_FAIL) != 0)
{
event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_SYNC, NULL, NULL);
svc_plugin_send_event((rdpSvcPlugin*)cliprdr, event);
}
}
void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, STREAM* s)
{
RDP_CB_DATA_REQUEST_EVENT* cb_event;
cb_event = (RDP_CB_DATA_REQUEST_EVENT*)freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR,
RDP_EVENT_TYPE_CB_DATA_REQUEST, NULL, NULL);
stream_read_uint32(data_in, cb_event->format);
stream_read_uint32(s, cb_event->format);
svc_plugin_send_event((rdpSvcPlugin*)cliprdr, (RDP_EVENT*)cb_event);
}
void cliprdr_process_format_data_response_event(cliprdrPlugin* cliprdr, RDP_CB_DATA_RESPONSE_EVENT* cb_event)
{
STREAM* data_out;
STREAM* s;
data_out = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, CB_RESPONSE_OK, cb_event->size);
stream_write(data_out, cb_event->data, cb_event->size);
cliprdr_packet_send(cliprdr, data_out);
if (cb_event->size > 0)
{
s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, CB_RESPONSE_OK, cb_event->size);
stream_write(s, cb_event->data, cb_event->size);
}
else
{
s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, CB_RESPONSE_FAIL, 0);
}
cliprdr_packet_send(cliprdr, s);
}
void cliprdr_process_format_data_request_event(cliprdrPlugin* cliprdr, RDP_CB_DATA_REQUEST_EVENT* cb_event)
{
STREAM* data_out;
STREAM* s;
data_out = cliprdr_packet_new(CB_FORMAT_DATA_REQUEST, 0, 4);
stream_write_uint32(data_out, cb_event->format);
cliprdr_packet_send(cliprdr, data_out);
s = cliprdr_packet_new(CB_FORMAT_DATA_REQUEST, 0, 4);
stream_write_uint32(s, cb_event->format);
cliprdr_packet_send(cliprdr, s);
}
void cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, STREAM* data_in, uint32 dataLen)
void cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, STREAM* s, uint32 dataLen)
{
RDP_CB_DATA_RESPONSE_EVENT* cb_event;
cb_event = (RDP_CB_DATA_RESPONSE_EVENT*)freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR,
RDP_EVENT_TYPE_CB_DATA_RESPONSE, NULL, NULL);
if (dataLen > 0)
{
cb_event->size = dataLen;
cb_event->data = (uint8*)xmalloc(dataLen);
memcpy(cb_event->data, stream_get_tail(data_in), dataLen);
memcpy(cb_event->data, stream_get_tail(s), dataLen);
}
svc_plugin_send_event((rdpSvcPlugin*)cliprdr, (RDP_EVENT*)cb_event);
}

View File

@ -23,6 +23,7 @@
void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, RDP_CB_FORMAT_LIST_EVENT* cb_event);
void cliprdr_process_format_list(cliprdrPlugin* cliprdr, STREAM* data_in, uint32 dataLen);
void cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, uint16 msgFlags);
void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, STREAM* data_in);
void cliprdr_process_format_data_response_event(cliprdrPlugin* cliprdr, RDP_CB_DATA_RESPONSE_EVENT* cb_event);

View File

@ -33,29 +33,29 @@
STREAM* cliprdr_packet_new(uint16 msgType, uint16 msgFlags, uint32 dataLen)
{
STREAM* data_out;
STREAM* s;
data_out = stream_new(dataLen + 8);
stream_write_uint16(data_out, msgType);
stream_write_uint16(data_out, msgFlags);
s = stream_new(dataLen + 8);
stream_write_uint16(s, msgType);
stream_write_uint16(s, msgFlags);
/* Write actual length after the entire packet has been constructed. */
stream_seek(data_out, 4);
stream_seek(s, 4);
return data_out;
return s;
}
void cliprdr_packet_send(cliprdrPlugin* cliprdr, STREAM* data_out)
void cliprdr_packet_send(cliprdrPlugin* cliprdr, STREAM* s)
{
int pos;
uint32 dataLen;
pos = stream_get_pos(data_out);
pos = stream_get_pos(s);
dataLen = pos - 8;
stream_set_pos(data_out, 4);
stream_write_uint32(data_out, dataLen);
stream_set_pos(data_out, pos);
stream_set_pos(s, 4);
stream_write_uint32(s, dataLen);
stream_set_pos(s, pos);
svc_plugin_send((rdpSvcPlugin*)cliprdr, data_out);
svc_plugin_send((rdpSvcPlugin*)cliprdr, s);
}
static void cliprdr_process_connect(rdpSvcPlugin* plugin)
@ -63,28 +63,28 @@ static void cliprdr_process_connect(rdpSvcPlugin* plugin)
DEBUG_SVC("connecting");
}
static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, STREAM* data_in)
static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, STREAM* s)
{
uint16 cCapabilitiesSets;
stream_read_uint16(data_in, cCapabilitiesSets);
stream_read_uint16(s, cCapabilitiesSets);
DEBUG_SVC("cCapabilitiesSets %d", cCapabilitiesSets);
}
static void cliprdr_send_clip_caps(cliprdrPlugin* cliprdr)
{
STREAM* data_out;
STREAM* s;
data_out = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN);
s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN);
stream_write_uint16(data_out, 1); /* cCapabilitiesSets */
stream_write_uint16(data_out, 0); /* pad1 */
stream_write_uint16(data_out, CB_CAPSTYPE_GENERAL); /* capabilitySetType */
stream_write_uint16(data_out, CB_CAPSTYPE_GENERAL_LEN); /* lengthCapability */
stream_write_uint32(data_out, CB_CAPS_VERSION_2); /* version */
stream_write_uint32(data_out, 0); /* generalFlags */
stream_write_uint16(s, 1); /* cCapabilitiesSets */
stream_write_uint16(s, 0); /* pad1 */
stream_write_uint16(s, CB_CAPSTYPE_GENERAL); /* capabilitySetType */
stream_write_uint16(s, CB_CAPSTYPE_GENERAL_LEN); /* lengthCapability */
stream_write_uint32(s, CB_CAPS_VERSION_2); /* version */
stream_write_uint32(s, 0); /* generalFlags */
cliprdr_packet_send(cliprdr, data_out);
cliprdr_packet_send(cliprdr, s);
}
static void cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr)
@ -97,23 +97,23 @@ static void cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr)
svc_plugin_send_event((rdpSvcPlugin*)cliprdr, event);
}
static void cliprdr_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
static void cliprdr_process_receive(rdpSvcPlugin* plugin, STREAM* s)
{
cliprdrPlugin* cliprdr = (cliprdrPlugin*)plugin;
uint16 msgType;
uint16 msgFlags;
uint32 dataLen;
stream_read_uint16(data_in, msgType);
stream_read_uint16(data_in, msgFlags);
stream_read_uint32(data_in, dataLen);
stream_read_uint16(s, msgType);
stream_read_uint16(s, msgFlags);
stream_read_uint32(s, dataLen);
DEBUG_SVC("msgType %d msgFlags %d dataLen %d", msgType, msgFlags, dataLen);
switch (msgType)
{
case CB_CLIP_CAPS:
cliprdr_process_clip_caps(cliprdr, data_in);
cliprdr_process_clip_caps(cliprdr, s);
break;
case CB_MONITOR_READY:
@ -121,18 +121,19 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
break;
case CB_FORMAT_LIST:
cliprdr_process_format_list(cliprdr, data_in, dataLen);
cliprdr_process_format_list(cliprdr, s, dataLen);
break;
case CB_FORMAT_LIST_RESPONSE:
cliprdr_process_format_list_response(cliprdr, msgFlags);
break;
case CB_FORMAT_DATA_REQUEST:
cliprdr_process_format_data_request(cliprdr, data_in);
cliprdr_process_format_data_request(cliprdr, s);
break;
case CB_FORMAT_DATA_RESPONSE:
cliprdr_process_format_data_response(cliprdr, data_in, dataLen);
cliprdr_process_format_data_response(cliprdr, s, dataLen);
break;
default:
@ -140,7 +141,7 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
break;
}
stream_free(data_in);
stream_free(s);
}
static void cliprdr_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event)

View File

@ -27,6 +27,8 @@ add_executable(xfreerdp
xf_rail.h
xf_tsmf.c
xf_tsmf.h
xf_cliprdr.c
xf_cliprdr.h
xf_event.c
xf_event.h
xf_keyboard.c

1225
client/X11/xf_cliprdr.c Normal file

File diff suppressed because it is too large Load Diff

34
client/X11/xf_cliprdr.h Normal file
View File

@ -0,0 +1,34 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* X11 Clipboard Redirection
*
* Copyright 2010-2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __XF_CLIPRDR_H
#define __XF_CLIPRDR_H
#include "xfreerdp.h"
void xf_cliprdr_init(xfInfo* xfi, rdpChanMan* chanman);
void xf_cliprdr_uninit(xfInfo* xfi);
void xf_process_cliprdr_event(xfInfo* xfi, RDP_EVENT* event);
boolean xf_cliprdr_process_selection_notify(xfInfo* xfi, XEvent* xevent);
boolean xf_cliprdr_process_selection_request(xfInfo* xfi, XEvent* xevent);
boolean xf_cliprdr_process_selection_clear(xfInfo* xfi, XEvent* xevent);
boolean xf_cliprdr_process_property_notify(xfInfo* xfi, XEvent* xevent);
void xf_cliprdr_check_owner(xfInfo* xfi);
#endif /* __XF_CLIPRDR_H */

View File

@ -21,6 +21,7 @@
#include <freerdp/kbd/vkcodes.h>
#include "xf_rail.h"
#include "xf_cliprdr.h"
#include "xf_event.h"
@ -347,6 +348,8 @@ boolean xf_event_FocusIn(xfInfo* xfi, XEvent* event, boolean app)
//xf_rail_send_activate(xfi, event->xany.window, True);
xf_kbd_focus_in(xfi);
xf_cliprdr_check_owner(xfi);
return True;
}
@ -499,6 +502,38 @@ boolean xf_event_MapNotify(xfInfo* xfi, XEvent* event, boolean app)
return True;
}
boolean xf_event_SelectionNotify(xfInfo* xfi, XEvent* event, boolean app)
{
if (xf_cliprdr_process_selection_notify(xfi, event))
return True;
return True;
}
boolean xf_event_SelectionRequest(xfInfo* xfi, XEvent* event, boolean app)
{
if (xf_cliprdr_process_selection_request(xfi, event))
return True;
return True;
}
boolean xf_event_SelectionClear(xfInfo* xfi, XEvent* event, boolean app)
{
if (xf_cliprdr_process_selection_clear(xfi, event))
return True;
return True;
}
boolean xf_event_PropertyNotify(xfInfo* xfi, XEvent* event, boolean app)
{
if (xf_cliprdr_process_property_notify(xfi, event))
return True;
return True;
}
boolean xf_event_process(freerdp* instance, XEvent* event)
{
boolean app = False;
@ -590,6 +625,22 @@ boolean xf_event_process(freerdp* instance, XEvent* event)
status = xf_event_ClientMessage(xfi, event, app);
break;
case SelectionNotify:
status = xf_event_SelectionNotify(xfi, event, app);
break;
case SelectionRequest:
status = xf_event_SelectionRequest(xfi, event, app);
break;
case SelectionClear:
status = xf_event_SelectionClear(xfi, event, app);
break;
case PropertyNotify:
status = xf_event_PropertyNotify(xfi, event, app);
break;
default:
DEBUG_X11("xf_event_process unknown event %d", event->type);
break;

View File

@ -226,7 +226,8 @@ xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height)
input_mask =
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
VisibilityChangeMask | FocusChangeMask | StructureNotifyMask |
PointerMotionMask | ExposureMask | EnterWindowMask | LeaveWindowMask;
PointerMotionMask | ExposureMask | EnterWindowMask | LeaveWindowMask |
PropertyChangeMask;
XSelectInput(xfi->display, window->handle, input_mask);
XMapWindow(xfi->display, window->handle);

View File

@ -48,6 +48,7 @@
#include "xf_rail.h"
#include "xf_tsmf.h"
#include "xf_event.h"
#include "xf_cliprdr.h"
#include "xf_monitor.h"
#include "xf_keyboard.h"
@ -466,6 +467,7 @@ boolean xf_post_connect(freerdp* instance)
freerdp_chanman_post_connect(GET_CHANMAN(instance), instance);
xf_tsmf_init(xfi, xv_port);
xf_cliprdr_init(xfi, GET_CHANMAN(instance));
return True;
}
@ -523,32 +525,6 @@ int xf_receive_channel_data(freerdp* instance, int channelId, uint8* data, int s
return freerdp_chanman_data(instance, channelId, data, size, flags, total_size);
}
void xf_process_cb_sync_event(xfInfo* xfi, rdpChanMan* chanman)
{
RDP_EVENT* event;
RDP_CB_FORMAT_LIST_EVENT* format_list_event;
event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL);
format_list_event = (RDP_CB_FORMAT_LIST_EVENT*) event;
format_list_event->num_formats = 0;
freerdp_chanman_send_event(chanman, event);
}
void xf_process_cliprdr_event(xfInfo* xfi, rdpChanMan* chanman, RDP_EVENT* event)
{
switch (event->event_type)
{
case RDP_EVENT_TYPE_CB_SYNC:
xf_process_cb_sync_event(xfi, chanman);
break;
default:
break;
}
}
void xf_process_channel_event(rdpChanMan* chanman, freerdp* instance)
{
xfInfo* xfi;
@ -571,7 +547,7 @@ void xf_process_channel_event(rdpChanMan* chanman, freerdp* instance)
break;
case RDP_EVENT_CLASS_CLIPRDR:
xf_process_cliprdr_event(xfi, chanman, event);
xf_process_cliprdr_event(xfi, event);
break;
default:
@ -616,6 +592,7 @@ void xf_window_free(xfInfo* xfi)
rail_free(xfi->rail);
xf_tsmf_uninit(xfi);
xf_cliprdr_uninit(xfi);
}
void xf_free(xfInfo* xfi)

View File

@ -94,6 +94,7 @@ struct xf_info
uint8* bmp_codec_none;
void* rfx_context;
void* xv_context;
void* clipboard_context;
Atom _NET_WM_ICON;
Atom _MOTIF_WM_HINTS;

View File

@ -56,6 +56,8 @@ struct _RDP_CB_FORMAT_LIST_EVENT
RDP_EVENT event;
uint32* formats;
uint16 num_formats;
uint8* raw_format_data;
uint32 raw_format_data_size;
};
typedef struct _RDP_CB_FORMAT_LIST_EVENT RDP_CB_FORMAT_LIST_EVENT;

View File

@ -113,6 +113,7 @@ static void freerdp_cliprdr_event_free(RDP_EVENT* event)
{
RDP_CB_FORMAT_LIST_EVENT* cb_event = (RDP_CB_FORMAT_LIST_EVENT*)event;
xfree(cb_event->formats);
xfree(cb_event->raw_format_data);
}
break;
case RDP_EVENT_TYPE_CB_DATA_RESPONSE: