int requestedFormatId;
BYTE* data;
+ BYTE* data_raw;
BOOL data_raw_format;
UINT32 data_format_id;
const char* data_format_name;
int data_length;
+ int data_raw_length;
XEvent* respond;
Window owner;
}
}
+static void xf_cliprdr_clear_cached_data(xfClipboard* clipboard)
+{
+ if (clipboard->data)
+ {
+ free(clipboard->data);
+ clipboard->data = NULL;
+ }
+ clipboard->data_length = 0;
+
+ if (clipboard->data_raw)
+ {
+ free(clipboard->data_raw);
+ clipboard->data_raw = NULL;
+ }
+ clipboard->data_raw_length = 0;
+}
+
static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard,
XEvent* xevent)
{
BYTE* data = NULL;
BOOL delayRespond;
BOOL rawTransfer;
+ BOOL matchingFormat;
unsigned long length;
unsigned long bytes_left;
CLIPRDR_FORMAT* format;
}
}
- if ((clipboard->data != 0) && (formatId == clipboard->data_format_id)
- && (formatName == clipboard->data_format_name))
+ /* We can compare format names by pointer value here as they are both
+ * taken from the same clipboard->serverFormats array */
+ matchingFormat = (formatId == clipboard->data_format_id)
+ && (formatName == clipboard->data_format_name);
+
+ if (matchingFormat && (clipboard->data != 0) && !rawTransfer)
{
- /* Cached clipboard data available. Send it now */
+ /* Cached converted clipboard data available. Send it now */
respond->xselection.property = xevent->xselectionrequest.property;
xf_cliprdr_provide_data(clipboard, respond, clipboard->data,
clipboard->data_length);
}
+ else if (matchingFormat && (clipboard->data_raw != 0) && rawTransfer)
+ {
+ /* Cached raw clipboard data available. Send it now */
+ respond->xselection.property = xevent->xselectionrequest.property;
+ xf_cliprdr_provide_data(clipboard, respond, clipboard->data_raw, clipboard->data_raw_length);
+ }
else if (clipboard->respond)
{
/* duplicate request */
* Send clipboard data request to the server.
* Response will be postponed after receiving the data
*/
- if (clipboard->data)
- {
- free(clipboard->data);
- clipboard->data = NULL;
- }
+ xf_cliprdr_clear_cached_data(clipboard);
respond->xselection.property = xevent->xselectionrequest.property;
clipboard->respond = respond;
xfContext* xfc = clipboard->xfc;
UINT ret;
- if (clipboard->data)
- {
- free(clipboard->data);
- clipboard->data = NULL;
- }
+ xf_cliprdr_clear_cached_data(clipboard);
clipboard->data_format_id = -1;
clipboard->data_format_name = NULL;
if (!clipboard->respond)
return CHANNEL_RC_OK;
- if (clipboard->data)
- {
- free(clipboard->data);
- clipboard->data = NULL;
- }
+ xf_cliprdr_clear_cached_data(clipboard);
pDstData = NULL;
DstSize = 0;
}
}
+ /* Cache converted and original data to avoid doing a possibly costly
+ * conversion again on subsequent requests */
clipboard->data = pDstData;
clipboard->data_length = DstSize;
+
+ /* We have to copy the original data again, as pSrcData is now owned
+ * by clipboard->system. Memory allocation failure is not fatal here
+ * as this is only a cached value. */
+ clipboard->data_raw = (BYTE*) malloc(size);
+ if (clipboard->data_raw)
+ {
+ CopyMemory(clipboard->data_raw, data, size);
+ clipboard->data_raw_length = size;
+ }
+ else
+ {
+ WLog_WARN(TAG, "failed to allocate %"PRIu32" bytes for a copy of raw clipboard data", size);
+ }
+
xf_cliprdr_provide_data(clipboard, clipboard->respond, pDstData, DstSize);
XSendEvent(xfc->display, clipboard->respond->xselection.requestor, 0, 0,
clipboard->respond);
ClipboardDestroy(clipboard->system);
free(clipboard->data);
+ free(clipboard->data_raw);
free(clipboard->respond);
free(clipboard->incr_data);
free(clipboard);