[gtk/async-highlight: 4/4] wip: towards async fontify




commit ad09e0b82bc0bc2b35933894350546530585b30d
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Aug 13 00:45:52 2020 -0400

    wip: towards async fontify
    
    This works fine for most demos, but mysteriously
    breaks in the one demo where it is needed: cursors.
    
    The subprocess just seems to peter out, I end up
    in a situation where the main thread is blocked in write()
    and some other thread is in the unix signal source
    trying to process a SIGCHLD.
    
    The difference between the cursors demos and the others
    is that the input is much larger here: 170k vs the
    usual 4k to 10k in the other demos.

 demos/gtk-demo/main.c | 165 +++++++++++++++++++++++++++-----------------------
 1 file changed, 90 insertions(+), 75 deletions(-)
---
diff --git a/demos/gtk-demo/main.c b/demos/gtk-demo/main.c
index 551fb034ab..49502e1ab2 100644
--- a/demos/gtk-demo/main.c
+++ b/demos/gtk-demo/main.c
@@ -234,20 +234,85 @@ activate_run (GSimpleAction *action,
   gtk_demo_run (demo, window);
 }
 
-static GBytes *
-fontify_text (const char *format,
-              const char *text)
+static void
+fontify_finish (GObject *source,
+                GAsyncResult *result,
+                gpointer data)
 {
-  GSubprocess *subprocess;
-  GBytes *stdin_buf;
+  GSubprocess *subprocess = G_SUBPROCESS (source);
+  GtkTextBuffer *buffer = data;
   GBytes *stdout_buf = NULL;
   GBytes *stderr_buf = NULL;
   GError *error = NULL;
+  char *p;
+  GtkTextIter start, end;
+
+  if (!g_subprocess_communicate_finish (subprocess,
+                                        result,
+                                        &stdout_buf,
+                                        &stderr_buf,
+                                        &error))
+    {
+      g_clear_pointer (&stdout_buf, g_bytes_unref);
+      g_clear_pointer (&stderr_buf, g_bytes_unref);
+
+      g_warning ("%s", error->message);
+      g_clear_error (&error);
+
+#if 0
+      gtk_text_buffer_get_bounds (buffer, &start, &end);
+      gtk_text_buffer_delete (buffer, &start, &end);
+      gtk_text_buffer_insert (buffer, &start, text, len);
+#endif
+      g_object_unref (subprocess);
+      g_object_unref (buffer);
+      return;
+    }
+
+  if (g_subprocess_get_exit_status (subprocess) != 0)
+    {
+      if (stderr_buf)
+        g_warning ("%s", (char *)g_bytes_get_data (stderr_buf, NULL));
+      g_clear_pointer (&stderr_buf, g_bytes_unref);
+    }
+
+  g_object_unref (subprocess);
+
+  g_clear_pointer (&stderr_buf, g_bytes_unref);
+
+  if (stdout_buf)
+    {
+      char *markup;
+      gsize len;
+
+      /* highlight puts a span with font and size around its output,
+       * which we don't want.
+       */
+      markup = g_bytes_unref_to_data (stdout_buf, &len);
+      for (p = markup + strlen ("<span "); *p != '>'; p++) *p = ' ';
+      gtk_text_buffer_get_bounds (buffer, &start, &end);
+      gtk_text_buffer_delete (buffer, &start, &end);
+      gtk_text_buffer_insert_markup (buffer, &start, markup, len);
+   }
+
+  g_object_unref (buffer);
+}
+
+void
+fontify (const char    *format,
+         GtkTextBuffer *source_buffer,
+         GBytes        *stdin_buf)
+{
+  GSubprocess *subprocess;
   char *format_arg;
   GtkSettings *settings;
   char *theme;
   gboolean prefer_dark;
   const char *style_arg;
+  const char *text;
+  gsize len;
+  GtkTextIter start, end;
+  GError *error = NULL;
 
   settings = gtk_settings_get_default ();
   g_object_get (settings,
@@ -291,74 +356,18 @@ fontify_text (const char *format,
 
       g_clear_error (&error);
 
-      return NULL;
-    }
-
-  stdin_buf = g_bytes_new_static (text, strlen (text));
-
-  if (!g_subprocess_communicate (subprocess,
-                                 stdin_buf,
-                                 NULL,
-                                 &stdout_buf,
-                                 &stderr_buf,
-                                 &error))
-    {
-      g_clear_pointer (&stdin_buf, g_bytes_unref);
-      g_clear_pointer (&stdout_buf, g_bytes_unref);
-      g_clear_pointer (&stderr_buf, g_bytes_unref);
-
-      g_warning ("%s", error->message);
-      g_clear_error (&error);
-
-      return NULL;
-    }
-
-  g_bytes_unref (stdin_buf);
-
-  if (g_subprocess_get_exit_status (subprocess) != 0)
-    {
-      if (stderr_buf)
-        g_warning ("%s", (char *)g_bytes_get_data (stderr_buf, NULL));
-
-      g_clear_pointer (&stdout_buf, g_bytes_unref);
-    }
-
-  g_clear_pointer (&stderr_buf, g_bytes_unref);
-
-  g_object_unref (subprocess);
-
-  return stdout_buf;
-}
-
-void
-fontify (const char    *format,
-         GtkTextBuffer *source_buffer)
-{
-  GtkTextIter start, end;
-  char *text;
-  GBytes *bytes;
-
-  gtk_text_buffer_get_bounds (source_buffer, &start, &end);
-  text = gtk_text_buffer_get_text (source_buffer, &start, &end, TRUE);
-
-  bytes = fontify_text (format, text);
-  if (bytes)
-    {
-      char *markup;
-      gsize len;
-      char *p;
-
-      markup = g_bytes_unref_to_data (bytes, &len);
-      /* highlight puts a span with font and size around its output,
-       * which we don't want.
-       */
-      for (p = markup + strlen ("<span "); *p != '>'; p++) *p = ' ';
+      gtk_text_buffer_get_bounds (source_buffer, &start, &end);
       gtk_text_buffer_delete (source_buffer, &start, &end);
-      gtk_text_buffer_insert_markup (source_buffer, &start, markup, len);
-      g_free (markup);
+      text = g_bytes_get_data (stdin_buf, &len);
+      gtk_text_buffer_insert (source_buffer, &start, text, len);
+      return;
     }
 
-  g_free (text);
+  g_subprocess_communicate_async (subprocess,
+                                  stdin_buf,
+                                  NULL,
+                                  fontify_finish,
+                                  g_object_ref (source_buffer));
 }
 
 static GtkWidget *
@@ -454,13 +463,12 @@ display_text (const char  *format,
   gtk_text_view_set_monospace (GTK_TEXT_VIEW (textview), TRUE);
 
   buffer = gtk_text_buffer_new (NULL);
-  gtk_text_buffer_set_text (buffer, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes));
-
-  if (format)
-    fontify (format, buffer);
 
   gtk_text_view_set_buffer (GTK_TEXT_VIEW (textview), buffer);
 
+  if (format)
+    fontify (format, buffer, bytes);
+
   g_bytes_unref (bytes);
 
   sw = gtk_scrolled_window_new ();
@@ -593,6 +601,7 @@ load_file (const char *demoname,
   char **lines;
   GBytes *bytes;
   int i;
+  char *text;
 
   if (!g_strcmp0 (current_file, filename))
     return;
@@ -748,7 +757,13 @@ load_file (const char *demoname,
 
   g_strfreev (lines);
 
-  fontify ("c", source_buffer);
+  gtk_text_buffer_get_bounds (source_buffer, &start, &end);
+  text = gtk_text_buffer_get_text (source_buffer, &start, &end, TRUE);
+  bytes = g_bytes_new_static (text, strlen (text));
+
+  fontify ("c", source_buffer, bytes);
+
+  g_bytes_unref (bytes);
 
   gtk_text_buffer_end_irreversible_action (source_buffer);
   gtk_text_view_set_buffer (GTK_TEXT_VIEW (source_view), source_buffer);


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