client/X11: transfer raw clipboard format data

The second step of raw transfer is to transfer the format data itself.
This has been already implemented in XFreeRDP before, but several
tweaks are required for it to work correctly.

The idea of raw data transfer is to request for _FREERDP_RAW clipboard
format while putting the actual formatId into _FREERDP_CLIPRDR property
where the requested data is expected to arrive to. Then the clipboard
owner will check for the real formatId and deliver the expected data.

This stays true, but the check is performed in a more straightforward
way, and CF_RAW format (numerically equal to zero) is not considered
an unknown destination format when performing (identity) conversions
with wClipboard. This is not an issue because wClipboard will allow
only identity conversion for CF_RAW, it will fail if something else
is going to be converted into CF_RAW.
This commit is contained in:
ilammy 2015-08-19 10:25:59 +03:00
parent 391ed0d91d
commit 7bce7ef372

View File

@ -79,6 +79,7 @@ struct xf_clipboard
int requestedFormatId; int requestedFormatId;
BYTE* data; BYTE* data;
BOOL data_raw_format;
UINT32 data_format_id; UINT32 data_format_id;
const char* data_format_name; const char* data_format_name;
int data_length; int data_length;
@ -554,6 +555,10 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
switch (format->formatId) switch (format->formatId)
{ {
case CF_RAW:
srcFormatId = CF_RAW;
break;
case CF_TEXT: case CF_TEXT:
case CF_OEMTEXT: case CF_OEMTEXT:
case CF_UNICODETEXT: case CF_UNICODETEXT:
@ -593,7 +598,7 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
dstFormatId = format->formatId; dstFormatId = format->formatId;
} }
if (bSuccess && dstFormatId) if (bSuccess)
{ {
DstSize = 0; DstSize = 0;
pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize); pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize);
@ -774,6 +779,7 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent*
XEvent* respond; XEvent* respond;
BYTE* data = NULL; BYTE* data = NULL;
BOOL delayRespond; BOOL delayRespond;
BOOL rawTransfer;
unsigned long length; unsigned long length;
unsigned long bytes_left; unsigned long bytes_left;
CLIPRDR_FORMAT* format; CLIPRDR_FORMAT* format;
@ -816,6 +822,7 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent*
{ {
formatId = format->formatId; formatId = format->formatId;
formatName = format->formatName; formatName = format->formatName;
rawTransfer = FALSE;
if (formatId == CF_RAW) if (formatId == CF_RAW)
{ {
@ -828,6 +835,7 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent*
if (data) if (data)
{ {
rawTransfer = TRUE;
CopyMemory(&formatId, data, 4); CopyMemory(&formatId, data, 4);
XFree(data); XFree(data);
} }
@ -859,6 +867,7 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent*
clipboard->respond = respond; clipboard->respond = respond;
clipboard->data_format_id = formatId; clipboard->data_format_id = formatId;
clipboard->data_format_name = formatName; clipboard->data_format_name = formatName;
clipboard->data_raw_format = rawTransfer;
delayRespond = TRUE; delayRespond = TRUE;
xf_cliprdr_send_data_request(clipboard, formatId); xf_cliprdr_send_data_request(clipboard, formatId);
@ -1204,12 +1213,15 @@ static UINT xf_cliprdr_server_format_list_response(CliprdrClientContext* context
*/ */
static UINT xf_cliprdr_server_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) static UINT xf_cliprdr_server_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
{ {
BOOL rawTransfer;
xfCliprdrFormat* format = NULL; xfCliprdrFormat* format = NULL;
UINT32 formatId = formatDataRequest->requestedFormatId; UINT32 formatId = formatDataRequest->requestedFormatId;
xfClipboard* clipboard = (xfClipboard*) context->custom; xfClipboard* clipboard = (xfClipboard*) context->custom;
xfContext* xfc = clipboard->xfc; xfContext* xfc = clipboard->xfc;
if (xf_cliprdr_is_raw_transfer_available(clipboard)) rawTransfer = xf_cliprdr_is_raw_transfer_available(clipboard);
if (rawTransfer)
{ {
format = xf_cliprdr_get_client_format_by_id(clipboard, CF_RAW); format = xf_cliprdr_get_client_format_by_id(clipboard, CF_RAW);
@ -1222,7 +1234,7 @@ static UINT xf_cliprdr_server_format_data_request(CliprdrClientContext* context,
if (!format) if (!format)
return xf_cliprdr_send_data_response(clipboard, NULL, 0); return xf_cliprdr_send_data_response(clipboard, NULL, 0);
clipboard->requestedFormatId = formatId; clipboard->requestedFormatId = rawTransfer ? CF_RAW : formatId;
XConvertSelection(xfc->display, clipboard->clipboard_atom, XConvertSelection(xfc->display, clipboard->clipboard_atom,
format->atom, clipboard->property_atom, xfc->drawable, CurrentTime); format->atom, clipboard->property_atom, xfc->drawable, CurrentTime);
@ -1269,7 +1281,12 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context
srcFormatId = 0; srcFormatId = 0;
dstFormatId = 0; dstFormatId = 0;
if (clipboard->data_format_name) if (clipboard->data_raw_format)
{
srcFormatId = CF_RAW;
dstFormatId = CF_RAW;
}
else if (clipboard->data_format_name)
{ {
if (strcmp(clipboard->data_format_name, "HTML Format") == 0) if (strcmp(clipboard->data_format_name, "HTML Format") == 0)
{ {
@ -1320,7 +1337,7 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context
if (!bSuccess) if (!bSuccess)
free (pSrcData); free (pSrcData);
if (bSuccess && dstFormatId) if (bSuccess)
{ {
DstSize = 0; DstSize = 0;
pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize); pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize);