xfreerdp: partially migrate to cliprdr callback interface

This commit is contained in:
Marc-André Moreau 2014-10-15 17:42:55 -04:00
parent 7a5d45ed34
commit 4ba0010294
1 changed files with 270 additions and 66 deletions

View File

@ -253,18 +253,43 @@ static xfCliprdrFormat* xf_cliprdr_get_format_by_atom(xfClipboard* clipboard, At
static void xf_cliprdr_send_supported_format_list(xfClipboard* clipboard)
{
int i;
RDP_CB_FORMAT_LIST_EVENT* event;
event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
if (!clipboard->context)
{
RDP_CB_FORMAT_LIST_EVENT* event;
event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_FormatList, NULL, NULL);
event->formats = (UINT32*) malloc(sizeof(UINT32) * clipboard->numClientFormats);
event->num_formats = clipboard->numClientFormats;
event->formats = (UINT32*) malloc(sizeof(UINT32) * clipboard->numClientFormats);
event->num_formats = clipboard->numClientFormats;
for (i = 0; i < clipboard->numClientFormats; i++)
event->formats[i] = clipboard->clientFormats[i].formatId;
for (i = 0; i < clipboard->numClientFormats; i++)
{
event->formats[i] = clipboard->clientFormats[i].formatId;
}
freerdp_channels_send_event(clipboard->channels, (wMessage*) event);
freerdp_channels_send_event(clipboard->channels, (wMessage*) event);
}
else
{
CLIPRDR_FORMAT* formats;
CLIPRDR_FORMAT_LIST formatList;
ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST));
formatList.cFormats = clipboard->numClientFormats;
formats = (CLIPRDR_FORMAT*) calloc(formatList.cFormats, sizeof(CLIPRDR_FORMAT));
formatList.formats = formats;
for (i = 0; i < clipboard->numClientFormats; i++)
{
formats->formatId = clipboard->clientFormats[i].formatId;
formats->formatName = NULL;
}
clipboard->context->ClientFormatList(clipboard->context, &formatList);
}
}
static void xf_cliprdr_send_format_list(xfClipboard* clipboard)
@ -274,43 +299,79 @@ static void xf_cliprdr_send_format_list(xfClipboard* clipboard)
if (xf_cliprdr_is_self_owned(clipboard))
{
Atom type;
int result;
BYTE* format_data;
int format, result;
unsigned long length, bytes_left;
RDP_CB_FORMAT_LIST_EVENT* event;
xfContext* xfc = clipboard->xfc;
int format_property;
unsigned long length;
unsigned long bytes_left;
result = XGetWindowProperty(xfc->display, clipboard->root_window,
clipboard->property_atom, 0, 3600, 0, XA_STRING,
&type, &format, &length, &bytes_left, (BYTE**) &format_data);
&type, &format_property, &length, &bytes_left, (BYTE**) &format_data);
if (result != Success)
{
WLog_ERR(TAG, "XGetWindowProperty failed");
return;
}
DEBUG_X11_CLIPRDR("format=%d len=%d bytes_left=%d", format, (int) length, (int) bytes_left);
event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_FormatList, NULL, NULL);
if (!clipboard->context)
{
RDP_CB_FORMAT_LIST_EVENT* event;
event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_FormatList, NULL, NULL);
event->raw_format_data = (BYTE *) malloc(length);
CopyMemory(event->raw_format_data, format_data, length);
event->raw_format_data_size = length;
freerdp_channels_send_event(clipboard->channels, (wMessage*) event);
}
else
{
CLIPRDR_FORMAT_LIST formatList;
ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST));
/**
* TODO: handle (raw?) format data
* The original code appears to be sending back the original,
* unmodified server format list here.
*/
formatList.cFormats = clipboard->numServerFormats;
formatList.formats = clipboard->serverFormats;
clipboard->context->ClientFormatList(clipboard->context, &formatList);
}
event->raw_format_data = (BYTE*) malloc(length);
CopyMemory(event->raw_format_data, format_data, length);
event->raw_format_data_size = length;
XFree(format_data);
freerdp_channels_send_event(clipboard->channels, (wMessage*) event);
}
else if (clipboard->owner == None)
{
RDP_CB_FORMAT_LIST_EVENT* event;
if (!clipboard->context)
{
RDP_CB_FORMAT_LIST_EVENT *event;
event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_FormatList, NULL, NULL);
event = (RDP_CB_FORMAT_LIST_EVENT *) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_FormatList, NULL, NULL);
event->num_formats = 0;
event->num_formats = 0;
freerdp_channels_send_event(clipboard->channels, (wMessage*) event);
freerdp_channels_send_event(clipboard->channels, (wMessage *) event);
}
else
{
CLIPRDR_FORMAT_LIST formatList;
ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST));
formatList.cFormats = 0;
formatList.formats = NULL;
clipboard->context->ClientFormatList(clipboard->context, &formatList);
}
}
else if (clipboard->owner != xfc->drawable)
{
@ -320,29 +381,56 @@ static void xf_cliprdr_send_format_list(xfClipboard* clipboard)
}
}
static void xf_cliprdr_send_data_request(xfClipboard* clipboard, UINT32 format)
static void xf_cliprdr_send_data_request(xfClipboard* clipboard, UINT32 formatId)
{
RDP_CB_DATA_REQUEST_EVENT* event;
if (!clipboard->context)
{
RDP_CB_DATA_REQUEST_EVENT* event;
event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_DataRequest, NULL, NULL);
event->format = format;
event->format = formatId;
freerdp_channels_send_event(clipboard->channels, (wMessage*) event);
freerdp_channels_send_event(clipboard->channels, (wMessage *) event);
}
else
{
CLIPRDR_FORMAT_DATA_REQUEST request;
ZeroMemory(&request, sizeof(CLIPRDR_FORMAT_DATA_REQUEST));
request.requestedFormatId = formatId;
clipboard->context->ClientFormatDataRequest(clipboard->context, &request);
}
}
static void xf_cliprdr_send_data_response(xfClipboard* clipboard, BYTE* data, int size)
{
RDP_CB_DATA_RESPONSE_EVENT* event;
if (!clipboard->context)
{
RDP_CB_DATA_RESPONSE_EVENT *event;
event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class,
event = (RDP_CB_DATA_RESPONSE_EVENT *) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_DataResponse, NULL, NULL);
event->data = data;
event->size = size;
event->data = data;
event->size = size;
freerdp_channels_send_event(clipboard->channels, (wMessage*) event);
freerdp_channels_send_event(clipboard->channels, (wMessage *) event);
}
else
{
CLIPRDR_FORMAT_DATA_RESPONSE response;
ZeroMemory(&response, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE));
response.dataLen = size;
response.requestedFormatData = data;
clipboard->context->ClientFormatDataResponse(clipboard->context, &response);
}
}
static void xf_cliprdr_process_cb_monitor_ready_event(xfClipboard* clipboard)
@ -387,56 +475,65 @@ static void xf_cliprdr_process_cb_data_request_event(xfClipboard* clipboard, RDP
static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
{
int num;
int i, j;
int i;
Atom atom;
int format;
BYTE* data = NULL;
unsigned long length, bytes_left;
int format_property;
unsigned long length;
unsigned long bytes_left;
UINT32 numFormats = 0;
xfCliprdrFormat* format = NULL;
CLIPRDR_FORMAT* formats = NULL;
RDP_CB_FORMAT_LIST_EVENT* event;
xfContext* xfc = clipboard->xfc;
XGetWindowProperty(xfc->display, xfc->drawable, clipboard->property_atom,
0, 200, 0, XA_ATOM, &atom, &format, &length, &bytes_left, &data);
0, 200, 0, XA_ATOM, &atom, &format_property, &length, &bytes_left, &data);
if (length > 0)
formats = (CLIPRDR_FORMAT*) calloc(length, sizeof(CLIPRDR_FORMAT));
for (i = 0; i < length; i++)
{
event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_FormatList, NULL, NULL);
atom = ((Atom*) data)[i];
event->formats = (UINT32*) malloc(sizeof(UINT32) * clipboard->numClientFormats);
num = 0;
format = xf_cliprdr_get_format_by_atom(clipboard, atom);
for (i = 0; i < length; i++)
if (format)
{
atom = ((Atom*) data)[i];
for (j = 0; j < clipboard->numClientFormats; j++)
{
if (clipboard->clientFormats[j].atom == atom)
{
event->formats[num++] = clipboard->clientFormats[j].formatId;
break;
}
}
formats[numFormats].formatId = format->formatId;
formats[numFormats].formatName = NULL;
numFormats++;
}
event->num_formats = num;
XFree(data);
freerdp_channels_send_event(clipboard->channels, (wMessage*) event);
}
else
{
if (data)
XFree(data);
XFree(data);
if (!clipboard->context)
{
event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
CliprdrChannel_FormatList, NULL, NULL);
event->num_formats = 0;
event->num_formats = numFormats;
event->formats = (UINT32*) calloc(numFormats, sizeof(UINT32));
freerdp_channels_send_event(clipboard->channels, (wMessage*) event);
for (i = 0; i < numFormats; i++)
{
event->formats[i] = formats[i].formatId;
}
freerdp_channels_send_event(clipboard->channels, (wMessage *) event);
}
else
{
CLIPRDR_FORMAT_LIST formatList;
ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST));
formatList.cFormats = numFormats;
formatList.formats = formats;
clipboard->context->ClientFormatList(clipboard->context, &formatList);
}
}
@ -800,6 +897,7 @@ static void xf_cliprdr_process_cb_format_list_event(xfClipboard* clipboard, RDP_
if (event->raw_format_data)
{
/* this appears to store the raw format list in an X11 atom */
XChangeProperty(xfc->display, clipboard->root_window, clipboard->property_atom,
XA_STRING, 8, PropModeReplace, event->raw_format_data, event->raw_format_data_size);
}
@ -1248,6 +1346,9 @@ int xf_cliprdr_send_client_format_list(xfClipboard* clipboard)
CLIPRDR_FORMAT* formats;
CLIPRDR_FORMAT_LIST formatList;
xf_cliprdr_send_format_list(clipboard);
return 1;
formatList.cFormats = 3;
formats = (CLIPRDR_FORMAT*) calloc(formatList.cFormats, sizeof(CLIPRDR_FORMAT));
@ -1371,6 +1472,7 @@ static int xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR_
int i, j;
CLIPRDR_FORMAT* format;
xfClipboard* clipboard = (xfClipboard*) context->custom;
xfContext* xfc = clipboard->xfc;
if (clipboard->data)
{
@ -1412,6 +1514,12 @@ static int xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR_
}
}
XSetSelectionOwner(xfc->display, clipboard->clipboard_atom, xfc->drawable, CurrentTime);
XFlush(xfc->display);
return 1;
xf_cliprdr_send_client_format_list_response(clipboard, TRUE);
for (i = 0; i < formatList->cFormats; i++)
@ -1436,7 +1544,39 @@ static int xf_cliprdr_server_format_list_response(CliprdrClientContext* context,
static int xf_cliprdr_server_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
{
xfCliprdrFormat* format = NULL;
UINT32 formatId = formatDataRequest->requestedFormatId;
xfClipboard* clipboard = (xfClipboard*) context->custom;
xfContext* xfc = clipboard->xfc;
if (xf_cliprdr_is_self_owned(clipboard))
{
format = xf_cliprdr_get_format_by_id(clipboard, CLIPRDR_FORMAT_RAW);
XChangeProperty(xfc->display, xfc->drawable, clipboard->property_atom,
XA_INTEGER, 32, PropModeReplace, (BYTE*) &formatId, 1);
}
else
{
format = xf_cliprdr_get_format_by_id(clipboard, formatId);
}
if (!format)
{
xf_cliprdr_send_data_response(clipboard, NULL, 0);
return 1;
}
clipboard->requestedFormatId = formatId;
XConvertSelection(xfc->display, clipboard->clipboard_atom,
format->atom, clipboard->property_atom, xfc->drawable, CurrentTime);
XFlush(xfc->display);
/* After this point, we expect a SelectionNotify event from the clipboard owner. */
return 1;
xf_cliprdr_send_client_format_data_response(clipboard, formatDataRequest->requestedFormatId);
@ -1445,7 +1585,68 @@ static int xf_cliprdr_server_format_data_request(CliprdrClientContext* context,
static int xf_cliprdr_server_format_data_response(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
{
UINT32 size = formatDataResponse->dataLen;
BYTE* data = formatDataResponse->requestedFormatData;
xfClipboard* clipboard = (xfClipboard*) context->custom;
xfContext* xfc = clipboard->xfc;
if (!clipboard->respond)
return 1;
if (size < 1)
{
clipboard->respond->xselection.property = None;
}
else
{
if (clipboard->data)
{
free(clipboard->data);
clipboard->data = NULL;
}
switch (clipboard->data_format)
{
case CLIPRDR_FORMAT_RAW:
case CB_FORMAT_PNG:
case CB_FORMAT_JPEG:
case CB_FORMAT_GIF:
clipboard->data = data;
clipboard->data_length = size;
data = NULL;
size = 0;
break;
case CLIPRDR_FORMAT_TEXT:
xf_cliprdr_process_text(clipboard, data, size);
break;
case CLIPRDR_FORMAT_UNICODETEXT:
xf_cliprdr_process_unicodetext(clipboard, data, size);
break;
case CLIPRDR_FORMAT_DIB:
xf_cliprdr_process_dib(clipboard, data, size);
break;
case CB_FORMAT_HTML:
xf_cliprdr_process_html(clipboard, data, size);
break;
default:
clipboard->respond->xselection.property = None;
break;
}
xf_cliprdr_provide_data(clipboard, clipboard->respond);
}
XSendEvent(xfc->display, clipboard->respond->xselection.requestor, 0, 0, clipboard->respond);
XFlush(xfc->display);
free(clipboard->respond);
clipboard->respond = NULL;
return 1;
xf_cliprdr_recv_server_format_data_response(clipboard, clipboard->requestedFormatId,
formatDataResponse->requestedFormatData, formatDataResponse->dataLen);
@ -1589,4 +1790,7 @@ void xf_cliprdr_uninit(xfContext* xfc, CliprdrClientContext* cliprdr)
{
xfc->cliprdr = NULL;
cliprdr->custom = NULL;
if (xfc->clipboard)
xfc->clipboard->context = NULL;
}