Merge pull request #6609 from akallabeth/clip_response
Fixed sending of clipboard format request response
This commit is contained in:
commit
784f445aa1
@ -172,6 +172,9 @@ struct xf_clipboard
|
|||||||
BOOL streams_supported;
|
BOOL streams_supported;
|
||||||
BOOL file_formats_registered;
|
BOOL file_formats_registered;
|
||||||
UINT32 file_capability_flags;
|
UINT32 file_capability_flags;
|
||||||
|
/* last sent data */
|
||||||
|
CLIPRDR_FORMAT* lastSentFormats;
|
||||||
|
UINT32 lastSentNumFormats;
|
||||||
#ifdef WITH_FUSE
|
#ifdef WITH_FUSE
|
||||||
/* FUSE related**/
|
/* FUSE related**/
|
||||||
HANDLE fuse_thread;
|
HANDLE fuse_thread;
|
||||||
@ -343,9 +346,17 @@ static UINT xf_cliprdr_send_data_request(xfClipboard* clipboard, UINT32 formatId
|
|||||||
*
|
*
|
||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT xf_cliprdr_send_data_response(xfClipboard* clipboard, BYTE* data, int size)
|
static UINT xf_cliprdr_send_data_response(xfClipboard* clipboard, const BYTE* data, size_t size)
|
||||||
{
|
{
|
||||||
CLIPRDR_FORMAT_DATA_RESPONSE response = { 0 };
|
CLIPRDR_FORMAT_DATA_RESPONSE response = { 0 };
|
||||||
|
|
||||||
|
/* No request currently pending, do not send a response. */
|
||||||
|
if (clipboard->requestedFormatId < 0)
|
||||||
|
return CHANNEL_RC_OK;
|
||||||
|
|
||||||
|
/* Request handled, reset to invalid */
|
||||||
|
clipboard->requestedFormatId = -1;
|
||||||
|
|
||||||
response.msgFlags = (data) ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
|
response.msgFlags = (data) ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
|
||||||
response.dataLen = size;
|
response.dataLen = size;
|
||||||
response.requestedFormatData = data;
|
response.requestedFormatData = data;
|
||||||
@ -599,17 +610,92 @@ static void xf_cliprdr_provide_server_format_list(xfClipboard* clipboard)
|
|||||||
Stream_Free(formats, TRUE);
|
Stream_Free(formats, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL xf_clipboard_format_equal(const CLIPRDR_FORMAT* a, const CLIPRDR_FORMAT* b)
|
||||||
|
{
|
||||||
|
if (a->formatId != b->formatId)
|
||||||
|
return FALSE;
|
||||||
|
if (!a->formatName && !b->formatName)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return strcmp(a->formatName, b->formatName) == 0;
|
||||||
|
}
|
||||||
|
static BOOL xf_clipboard_changed(xfClipboard* clipboard, const CLIPRDR_FORMAT* formats,
|
||||||
|
UINT32 numFormats)
|
||||||
|
{
|
||||||
|
UINT32 x, y;
|
||||||
|
if (clipboard->lastSentNumFormats != numFormats)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
for (x = 0; x < numFormats; x++)
|
||||||
|
{
|
||||||
|
const CLIPRDR_FORMAT* cur = &clipboard->lastSentFormats[x];
|
||||||
|
BOOL contained = FALSE;
|
||||||
|
for (y = 0; y < numFormats; y++)
|
||||||
|
{
|
||||||
|
if (xf_clipboard_format_equal(cur, &formats[y]))
|
||||||
|
{
|
||||||
|
contained = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!contained)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xf_clipboard_formats_free(xfClipboard* clipboard)
|
||||||
|
{
|
||||||
|
xf_cliprdr_free_formats(clipboard->lastSentFormats, clipboard->lastSentNumFormats);
|
||||||
|
clipboard->lastSentFormats = NULL;
|
||||||
|
clipboard->lastSentNumFormats = 0;
|
||||||
|
}
|
||||||
|
static BOOL xf_clipboard_copy_formats(xfClipboard* clipboard, const CLIPRDR_FORMAT* formats,
|
||||||
|
UINT32 numFormats)
|
||||||
|
{
|
||||||
|
UINT32 x;
|
||||||
|
|
||||||
|
xf_clipboard_formats_free(clipboard);
|
||||||
|
clipboard->lastSentFormats = calloc(numFormats, sizeof(CLIPRDR_FORMAT));
|
||||||
|
if (!clipboard->lastSentFormats)
|
||||||
|
return FALSE;
|
||||||
|
clipboard->lastSentNumFormats = numFormats;
|
||||||
|
for (x = 0; x < numFormats; x++)
|
||||||
|
{
|
||||||
|
CLIPRDR_FORMAT* lcur = &clipboard->lastSentFormats[x];
|
||||||
|
const CLIPRDR_FORMAT* cur = &formats[x];
|
||||||
|
*lcur = *cur;
|
||||||
|
if (cur->formatName)
|
||||||
|
lcur->formatName = _strdup(cur->formatName);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT xf_cliprdr_send_format_list(xfClipboard* clipboard, const CLIPRDR_FORMAT* formats,
|
||||||
|
UINT32 numFormats)
|
||||||
|
{
|
||||||
|
CLIPRDR_FORMAT_LIST formatList = { 0 };
|
||||||
|
formatList.msgFlags = CB_RESPONSE_OK;
|
||||||
|
formatList.numFormats = numFormats;
|
||||||
|
formatList.formats = (CLIPRDR_FORMAT*)formats;
|
||||||
|
formatList.msgType = CB_FORMAT_LIST;
|
||||||
|
|
||||||
|
if (!xf_clipboard_changed(clipboard, formats, numFormats))
|
||||||
|
return CHANNEL_RC_OK;
|
||||||
|
|
||||||
|
xf_clipboard_copy_formats(clipboard, formats, numFormats);
|
||||||
|
/* Ensure all pending requests are answered. */
|
||||||
|
xf_cliprdr_send_data_response(clipboard, NULL, 0);
|
||||||
|
return clipboard->context->ClientFormatList(clipboard->context, &formatList);
|
||||||
|
}
|
||||||
|
|
||||||
static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
|
static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
|
||||||
{
|
{
|
||||||
UINT32 numFormats = 0;
|
UINT32 numFormats = 0;
|
||||||
CLIPRDR_FORMAT* formats = NULL;
|
CLIPRDR_FORMAT* formats = NULL;
|
||||||
CLIPRDR_FORMAT_LIST formatList = { 0 };
|
|
||||||
formats = xf_cliprdr_get_client_formats(clipboard, &numFormats);
|
formats = xf_cliprdr_get_client_formats(clipboard, &numFormats);
|
||||||
formatList.msgFlags = CB_RESPONSE_OK;
|
xf_cliprdr_send_format_list(clipboard, formats, numFormats);
|
||||||
formatList.numFormats = numFormats;
|
|
||||||
formatList.formats = formats;
|
|
||||||
formatList.msgType = CB_FORMAT_LIST;
|
|
||||||
clipboard->context->ClientFormatList(clipboard->context, &formatList);
|
|
||||||
xf_cliprdr_free_formats(formats, numFormats);
|
xf_cliprdr_free_formats(formats, numFormats);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,7 +793,7 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
|
|||||||
free(file_array);
|
free(file_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
xf_cliprdr_send_data_response(clipboard, pDstData, (int)DstSize);
|
xf_cliprdr_send_data_response(clipboard, pDstData, DstSize);
|
||||||
free(pDstData);
|
free(pDstData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -722,6 +808,7 @@ static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target)
|
|||||||
unsigned long bytes_left;
|
unsigned long bytes_left;
|
||||||
xfCliprdrFormat* format;
|
xfCliprdrFormat* format;
|
||||||
xfContext* xfc = clipboard->xfc;
|
xfContext* xfc = clipboard->xfc;
|
||||||
|
|
||||||
format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId);
|
format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId);
|
||||||
|
|
||||||
if (!format || (format->atom != target))
|
if (!format || (format->atom != target))
|
||||||
@ -778,14 +865,16 @@ static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target)
|
|||||||
new_data =
|
new_data =
|
||||||
(BYTE*)realloc(clipboard->incr_data, clipboard->incr_data_length + bytes_left);
|
(BYTE*)realloc(clipboard->incr_data, clipboard->incr_data_length + bytes_left);
|
||||||
|
|
||||||
if (!new_data)
|
if (new_data)
|
||||||
return FALSE;
|
{
|
||||||
|
|
||||||
clipboard->incr_data = new_data;
|
clipboard->incr_data = new_data;
|
||||||
CopyMemory(clipboard->incr_data + clipboard->incr_data_length, data, bytes_left);
|
CopyMemory(clipboard->incr_data + clipboard->incr_data_length, data,
|
||||||
clipboard->incr_data_length += bytes_left;
|
bytes_left);
|
||||||
XFree(data);
|
clipboard->incr_data_length += bytes_left;
|
||||||
data = NULL;
|
XFree(data);
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
has_data = TRUE;
|
has_data = TRUE;
|
||||||
@ -796,7 +885,7 @@ static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target)
|
|||||||
}
|
}
|
||||||
|
|
||||||
XDeleteProperty(xfc->display, xfc->drawable, clipboard->property_atom);
|
XDeleteProperty(xfc->display, xfc->drawable, clipboard->property_atom);
|
||||||
xf_cliprdr_process_requested_data(clipboard, has_data, data, (int)bytes_left);
|
xf_cliprdr_process_requested_data(clipboard, has_data, data, bytes_left);
|
||||||
|
|
||||||
if (data)
|
if (data)
|
||||||
XFree(data);
|
XFree(data);
|
||||||
@ -1204,7 +1293,6 @@ static UINT xf_cliprdr_send_client_format_list(xfClipboard* clipboard)
|
|||||||
{
|
{
|
||||||
UINT32 i, numFormats;
|
UINT32 i, numFormats;
|
||||||
CLIPRDR_FORMAT* formats = NULL;
|
CLIPRDR_FORMAT* formats = NULL;
|
||||||
CLIPRDR_FORMAT_LIST formatList = { 0 };
|
|
||||||
xfContext* xfc = clipboard->xfc;
|
xfContext* xfc = clipboard->xfc;
|
||||||
UINT ret;
|
UINT ret;
|
||||||
numFormats = clipboard->numClientFormats;
|
numFormats = clipboard->numClientFormats;
|
||||||
@ -1224,11 +1312,7 @@ static UINT xf_cliprdr_send_client_format_list(xfClipboard* clipboard)
|
|||||||
formats[i].formatName = clipboard->clientFormats[i].formatName;
|
formats[i].formatName = clipboard->clientFormats[i].formatName;
|
||||||
}
|
}
|
||||||
|
|
||||||
formatList.msgFlags = CB_RESPONSE_OK;
|
ret = xf_cliprdr_send_format_list(clipboard, formats, numFormats);
|
||||||
formatList.numFormats = numFormats;
|
|
||||||
formatList.formats = formats;
|
|
||||||
formatList.msgType = CB_FORMAT_LIST;
|
|
||||||
ret = clipboard->context->ClientFormatList(clipboard->context, &formatList);
|
|
||||||
free(formats);
|
free(formats);
|
||||||
|
|
||||||
if (clipboard->owner && clipboard->owner != xfc->drawable)
|
if (clipboard->owner && clipboard->owner != xfc->drawable)
|
||||||
@ -1501,6 +1585,7 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context,
|
|||||||
xfClipboard* clipboard = (xfClipboard*)context->custom;
|
xfClipboard* clipboard = (xfClipboard*)context->custom;
|
||||||
xfContext* xfc = clipboard->xfc;
|
xfContext* xfc = clipboard->xfc;
|
||||||
UINT ret;
|
UINT ret;
|
||||||
|
xf_clipboard_formats_free(clipboard);
|
||||||
xf_cliprdr_clear_cached_data(clipboard);
|
xf_cliprdr_clear_cached_data(clipboard);
|
||||||
clipboard->data_format_id = -1;
|
clipboard->data_format_id = -1;
|
||||||
clipboard->data_format_name = NULL;
|
clipboard->data_format_name = NULL;
|
||||||
@ -1613,10 +1698,10 @@ xf_cliprdr_server_format_data_request(CliprdrClientContext* context,
|
|||||||
else
|
else
|
||||||
format = xf_cliprdr_get_client_format_by_id(clipboard, formatId);
|
format = xf_cliprdr_get_client_format_by_id(clipboard, formatId);
|
||||||
|
|
||||||
|
clipboard->requestedFormatId = rawTransfer ? CF_RAW : formatId;
|
||||||
if (!format)
|
if (!format)
|
||||||
return xf_cliprdr_send_data_response(clipboard, NULL, 0);
|
return xf_cliprdr_send_data_response(clipboard, NULL, 0);
|
||||||
|
|
||||||
clipboard->requestedFormatId = rawTransfer ? CF_RAW : formatId;
|
|
||||||
XConvertSelection(xfc->display, clipboard->clipboard_atom, format->atom,
|
XConvertSelection(xfc->display, clipboard->clipboard_atom, format->atom,
|
||||||
clipboard->property_atom, xfc->drawable, CurrentTime);
|
clipboard->property_atom, xfc->drawable, CurrentTime);
|
||||||
XFlush(xfc->display);
|
XFlush(xfc->display);
|
||||||
@ -2914,6 +2999,7 @@ void xf_clipboard_free(xfClipboard* clipboard)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
ClipboardDestroy(clipboard->system);
|
ClipboardDestroy(clipboard->system);
|
||||||
|
xf_clipboard_formats_free(clipboard);
|
||||||
free(clipboard->data);
|
free(clipboard->data);
|
||||||
free(clipboard->data_raw);
|
free(clipboard->data_raw);
|
||||||
free(clipboard->respond);
|
free(clipboard->respond);
|
||||||
|
Loading…
Reference in New Issue
Block a user