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
This commit is contained in:
Carlos Garnacho 2020-04-11 17:21:20 +02:00 committed by Robert Mader
parent d2c762cc66
commit 7015bb3efd

View File

@ -203,7 +203,7 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
MetaX11SelectionOutputStreamPrivate *priv = MetaX11SelectionOutputStreamPrivate *priv =
meta_x11_selection_output_stream_get_instance_private (stream); meta_x11_selection_output_stream_get_instance_private (stream);
Display *xdisplay; Display *xdisplay;
size_t element_size, n_elements; size_t element_size, n_elements, max_size;
gboolean first_chunk = FALSE; gboolean first_chunk = FALSE;
int error_code; int error_code;
@ -218,6 +218,7 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
element_size = get_element_size (priv->format); element_size = get_element_size (priv->format);
n_elements = priv->data->len / element_size; n_elements = priv->data->len / element_size;
max_size = get_max_request_size (priv->x11_display);
if (!priv->incr) if (!priv->incr)
first_chunk = TRUE; first_chunk = TRUE;
@ -247,9 +248,13 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
} }
else else
{ {
size_t copy_n_elements;
if (priv->incr && priv->data->len > 0) if (priv->incr && priv->data->len > 0)
priv->delete_pending = TRUE; priv->delete_pending = TRUE;
copy_n_elements = MIN (n_elements, max_size / element_size);
XChangeProperty (xdisplay, XChangeProperty (xdisplay,
priv->xwindow, priv->xwindow,
priv->xproperty, priv->xproperty,
@ -257,8 +262,8 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
priv->format, priv->format,
PropModeReplace, PropModeReplace,
priv->data->data, priv->data->data,
n_elements); copy_n_elements);
g_byte_array_remove_range (priv->data, 0, n_elements * element_size); g_byte_array_remove_range (priv->data, 0, copy_n_elements * element_size);
} }
if (first_chunk) if (first_chunk)