Fixed sending of clipboard format request response
authorakallabeth <akallabeth@posteo.net>
Thu, 26 Nov 2020 15:34:28 +0000 (16:34 +0100)
committerakallabeth <akallabeth@users.noreply.github.com>
Thu, 25 Feb 2021 08:51:41 +0000 (09:51 +0100)
If a request was pending and new formats were announced the response
to a ServerFormatDataRequest was never sent.

(cherry picked from commit 2efb7d92745614a92c66b721205689a433248d31)

client/X11/xf_cliprdr.c

index 77288a0..d297d21 100644 (file)
@@ -268,9 +268,17 @@ static UINT xf_cliprdr_send_data_request(xfClipboard* clipboard, UINT32 formatId
  *
  * @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 };
+
+       /* 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.dataLen = size;
        response.requestedFormatData = data;
@@ -524,17 +532,26 @@ static void xf_cliprdr_provide_server_format_list(xfClipboard* clipboard)
        Stream_Free(formats, TRUE);
 }
 
-static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
+static UINT xf_cliprdr_send_format_list(xfClipboard* clipboard, const CLIPRDR_FORMAT* formats,
+                                        UINT32 numFormats)
 {
-       UINT32 numFormats = 0;
-       CLIPRDR_FORMAT* formats = NULL;
        CLIPRDR_FORMAT_LIST formatList = { 0 };
-       formats = xf_cliprdr_get_client_formats(clipboard, &numFormats);
        formatList.msgFlags = CB_RESPONSE_OK;
        formatList.numFormats = numFormats;
        formatList.formats = formats;
        formatList.msgType = CB_FORMAT_LIST;
-       clipboard->context->ClientFormatList(clipboard->context, &formatList);
+
+       /* 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)
+{
+       UINT32 numFormats = 0;
+       CLIPRDR_FORMAT* formats = NULL;
+       formats = xf_cliprdr_get_client_formats(clipboard, &numFormats);
+       xf_cliprdr_send_format_list(clipboard, formats, numFormats);
        xf_cliprdr_free_formats(formats, numFormats);
 }
 
@@ -631,7 +648,7 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
                free(file_array);
        }
 
-       xf_cliprdr_send_data_response(clipboard, pDstData, (int)DstSize);
+       xf_cliprdr_send_data_response(clipboard, pDstData, DstSize);
        free(pDstData);
 }
 
@@ -646,6 +663,7 @@ static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target)
        unsigned long bytes_left;
        xfCliprdrFormat* format;
        xfContext* xfc = clipboard->xfc;
+
        format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId);
 
        if (!format || (format->atom != target))
@@ -1079,7 +1097,6 @@ static UINT xf_cliprdr_send_client_format_list(xfClipboard* clipboard)
 {
        UINT32 i, numFormats;
        CLIPRDR_FORMAT* formats = NULL;
-       CLIPRDR_FORMAT_LIST formatList = { 0 };
        xfContext* xfc = clipboard->xfc;
        UINT ret;
        numFormats = clipboard->numClientFormats;
@@ -1099,11 +1116,7 @@ static UINT xf_cliprdr_send_client_format_list(xfClipboard* clipboard)
                formats[i].formatName = clipboard->clientFormats[i].formatName;
        }
 
-       formatList.msgFlags = CB_RESPONSE_OK;
-       formatList.numFormats = numFormats;
-       formatList.formats = formats;
-       formatList.msgType = CB_FORMAT_LIST;
-       ret = clipboard->context->ClientFormatList(clipboard->context, &formatList);
+       ret = xf_cliprdr_send_format_list(clipboard, formats, numFormats);
        free(formats);
 
        if (clipboard->owner && clipboard->owner != xfc->drawable)
@@ -1314,10 +1327,10 @@ xf_cliprdr_server_format_data_request(CliprdrClientContext* context,
        else
                format = xf_cliprdr_get_client_format_by_id(clipboard, formatId);
 
+       clipboard->requestedFormatId = rawTransfer ? CF_RAW : formatId;
        if (!format)
                return xf_cliprdr_send_data_response(clipboard, NULL, 0);
 
-       clipboard->requestedFormatId = rawTransfer ? CF_RAW : formatId;
        XConvertSelection(xfc->display, clipboard->clipboard_atom, format->atom,
                          clipboard->property_atom, xfc->drawable, CurrentTime);
        XFlush(xfc->display);