From 107bb3d9c2b3b11d8d529fa59358263d43dbd59c Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Sat, 11 Apr 2020 17:21:20 +0200 Subject: [PATCH] x11: Don't exceed transfer size in INCR chunks The stream automatically flushes after data size exceeds the size we deem for INCR chunks, but we still try to copy it all. Actually limit the data we copy, and leave the rest for future INCR chunks. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198 (cherry picked from commit 7015bb3efd5e588e50be9948f32ee04fa4bd8319) --- src/x11/meta-x11-selection-output-stream.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/x11/meta-x11-selection-output-stream.c b/src/x11/meta-x11-selection-output-stream.c index 4cdde8ab3..7179074e9 100644 --- a/src/x11/meta-x11-selection-output-stream.c +++ b/src/x11/meta-x11-selection-output-stream.c @@ -203,7 +203,7 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st MetaX11SelectionOutputStreamPrivate *priv = meta_x11_selection_output_stream_get_instance_private (stream); Display *xdisplay; - size_t element_size, n_elements; + size_t element_size, n_elements, max_size; gboolean first_chunk = FALSE; int error_code; @@ -218,6 +218,7 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st element_size = get_element_size (priv->format); n_elements = priv->data->len / element_size; + max_size = get_max_request_size (priv->x11_display); if (!priv->incr) first_chunk = TRUE; @@ -247,9 +248,13 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st } else { + size_t copy_n_elements; + if (priv->incr && priv->data->len > 0) priv->delete_pending = TRUE; + copy_n_elements = MIN (n_elements, max_size / element_size); + XChangeProperty (xdisplay, priv->xwindow, priv->xproperty, @@ -257,8 +262,8 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st priv->format, PropModeReplace, priv->data->data, - n_elements); - g_byte_array_remove_range (priv->data, 0, n_elements * element_size); + copy_n_elements); + g_byte_array_remove_range (priv->data, 0, copy_n_elements * element_size); } if (first_chunk)