From 4bdf9a1e70e8aef0066fb3af72ad580069b02fa1 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Tue, 14 Apr 2020 14:01:40 +0200 Subject: [PATCH] core: Cater for reading selection in chunks For the cases where we read a fixed size from the selection (eg. imposing limits for the clipboard manager), g_input_stream_read_bytes_async() might not read up to this given size if the other side is spoonfeeding it content. Cater for multiple read/write cycles here, until (maximum) transfer size is reached. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1198 --- src/core/meta-selection.c | 54 +++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/src/core/meta-selection.c b/src/core/meta-selection.c index 818c22687..4e42e59a9 100644 --- a/src/core/meta-selection.c +++ b/src/core/meta-selection.c @@ -51,6 +51,9 @@ static guint signals[N_SIGNALS] = { 0 }; G_DEFINE_TYPE (MetaSelection, meta_selection, G_TYPE_OBJECT) +static void read_selection_source_async (GTask *task, + TransferRequest *request); + static void meta_selection_dispose (GObject *object) { @@ -217,6 +220,7 @@ write_cb (GOutputStream *stream, GAsyncResult *result, GTask *task) { + TransferRequest *request; GError *error = NULL; g_output_stream_write_bytes_finish (stream, result, &error); @@ -227,8 +231,17 @@ write_cb (GOutputStream *stream, return; } - g_task_return_boolean (task, TRUE); - g_object_unref (task); + request = g_task_get_task_data (task); + + if (request->len > 0) + { + read_selection_source_async (task, request); + } + else + { + g_task_return_boolean (task, TRUE); + g_object_unref (task); + } } static void @@ -247,8 +260,26 @@ read_cb (GInputStream *stream, g_object_unref (task); return; } + else if (g_bytes_get_size (bytes) == 0) + { + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } request = g_task_get_task_data (task); + + if (request->len < g_bytes_get_size (bytes)) + { + GBytes *copy; + + /* Trim content */ + copy = g_bytes_new_from_bytes (bytes, 0, request->len); + g_bytes_unref (bytes); + bytes = copy; + } + + request->len -= g_bytes_get_size (bytes); g_output_stream_write_bytes_async (request->ostream, bytes, G_PRIORITY_DEFAULT, @@ -258,6 +289,18 @@ read_cb (GInputStream *stream, g_bytes_unref (bytes); } +static void +read_selection_source_async (GTask *task, + TransferRequest *request) +{ + g_input_stream_read_bytes_async (request->istream, + (gsize) request->len, + G_PRIORITY_DEFAULT, + g_task_get_cancellable (task), + (GAsyncReadyCallback) read_cb, + task); +} + static void source_read_cb (MetaSelectionSource *source, GAsyncResult *result, @@ -291,12 +334,7 @@ source_read_cb (MetaSelectionSource *source, } else { - g_input_stream_read_bytes_async (request->istream, - (gsize) request->len, - G_PRIORITY_DEFAULT, - g_task_get_cancellable (task), - (GAsyncReadyCallback) read_cb, - task); + read_selection_source_async (task, request); } }