[mutter/wip/carlosg/incr-is-fubar: 2/2] core: Cater for reading selection in chunks



commit ac9d75fb7171086b288a45fd738267b17c531246
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue Apr 14 14:01:40 2020 +0200

    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);
     }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]