[gimp] app: make the airbrush tool thread-safe w.r.t. paint thread



commit ddfc7715cbcd8d165520902bc0abfff3c09b88f4
Author: Ell <ell_se yahoo com>
Date:   Mon Apr 16 09:49:15 2018 -0400

    app: make the airbrush tool thread-safe w.r.t. paint thread
    
    GimpAirbrush currently performs painting and flushes the image on
    its own during the airbrush timeout.  This is unsafe w.r.t. the
    paint thread, since the timeout is run on the main thread, while
    paint commands should run on the paint thread.
    
    Add a "timeout" signal to GimpAirbrush, and simply emit this signal
    during the airbrush timeout, rather than actually painting.
    
    Connect to this signal in GimpAirbrushTool, and use
    gimppaintool-paint to perform the actual painting, in a thread-safe
    manner (see the previous commit.)

 app/paint/gimpairbrush.c     |   37 ++++++++++++++++++++-----------------
 app/paint/gimpairbrush.h     |   11 +++++------
 app/tools/gimpairbrushtool.c |   33 ++++++++++++++++++++++++++++++++-
 3 files changed, 57 insertions(+), 24 deletions(-)
---
diff --git a/app/paint/gimpairbrush.c b/app/paint/gimpairbrush.c
index 8ba5e97..042cb2b 100644
--- a/app/paint/gimpairbrush.c
+++ b/app/paint/gimpairbrush.c
@@ -36,6 +36,13 @@
 #include "gimp-intl.h"
 
 
+enum
+{
+  TIMEOUT,
+  LAST_SIGNAL
+};
+
+
 static void       gimp_airbrush_finalize (GObject          *object);
 
 static void       gimp_airbrush_paint    (GimpPaintCore    *paint_core,
@@ -56,6 +63,8 @@ G_DEFINE_TYPE (GimpAirbrush, gimp_airbrush, GIMP_TYPE_PAINTBRUSH)
 
 #define parent_class gimp_airbrush_parent_class
 
+static guint airbrush_signals[LAST_SIGNAL] = { 0 };
+
 
 void
 gimp_airbrush_register (Gimp                      *gimp,
@@ -78,6 +87,15 @@ gimp_airbrush_class_init (GimpAirbrushClass *klass)
   object_class->finalize  = gimp_airbrush_finalize;
 
   paint_core_class->paint = gimp_airbrush_paint;
+
+  airbrush_signals[TIMEOUT] =
+    g_signal_new ("timeout",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (GimpAirbrushClass, timeout),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
 }
 
 static void
@@ -96,8 +114,6 @@ gimp_airbrush_finalize (GObject *object)
       airbrush->timeout_id = 0;
     }
 
-  g_clear_object (&airbrush->sym);
-
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -142,13 +158,6 @@ gimp_airbrush_paint (GimpPaintCore    *paint_core,
           fade_point = gimp_paint_options_get_fade (paint_options, image,
                                                     paint_core->pixel_dist);
 
-          airbrush->drawable      = drawable;
-          airbrush->paint_options = paint_options;
-
-          if (airbrush->sym)
-            g_object_unref (airbrush->sym);
-          airbrush->sym = g_object_ref (sym);
-
           /* Base our timeout on the original stroke. */
           coords = gimp_symmetry_get_origin (sym);
 
@@ -171,8 +180,6 @@ gimp_airbrush_paint (GimpPaintCore    *paint_core,
                                                    paint_options,
                                                    sym,
                                                    paint_state, time);
-
-      g_clear_object (&airbrush->sym);
       break;
     }
 }
@@ -212,13 +219,9 @@ gimp_airbrush_timeout (gpointer data)
 {
   GimpAirbrush *airbrush = GIMP_AIRBRUSH (data);
 
-  gimp_airbrush_paint (GIMP_PAINT_CORE (airbrush),
-                       airbrush->drawable,
-                       airbrush->paint_options,
-                       airbrush->sym,
-                       GIMP_PAINT_STATE_MOTION, 0);
+  airbrush->timeout_id = 0;
 
-  gimp_image_flush (gimp_item_get_image (GIMP_ITEM (airbrush->drawable)));
+  g_signal_emit (airbrush, airbrush_signals[TIMEOUT], 0);
 
   return G_SOURCE_REMOVE;
 }
diff --git a/app/paint/gimpairbrush.h b/app/paint/gimpairbrush.h
index a3f9a8a..7aa802c 100644
--- a/app/paint/gimpairbrush.h
+++ b/app/paint/gimpairbrush.h
@@ -34,18 +34,17 @@ typedef struct _GimpAirbrushClass GimpAirbrushClass;
 
 struct _GimpAirbrush
 {
-  GimpPaintbrush    parent_instance;
+  GimpPaintbrush  parent_instance;
 
-  guint             timeout_id;
-
-  GimpSymmetry     *sym;
-  GimpDrawable     *drawable;
-  GimpPaintOptions *paint_options;
+  guint           timeout_id;
 };
 
 struct _GimpAirbrushClass
 {
   GimpPaintbrushClass  parent_class;
+
+  /*  signals  */
+  void (* timeout) (GimpAirbrush *airbrush);
 };
 
 
diff --git a/app/tools/gimpairbrushtool.c b/app/tools/gimpairbrushtool.c
index 62796a7..2374a37 100644
--- a/app/tools/gimpairbrushtool.c
+++ b/app/tools/gimpairbrushtool.c
@@ -31,16 +31,24 @@
 
 #include "gimpairbrushtool.h"
 #include "gimppaintoptions-gui.h"
+#include "gimppainttool-paint.h"
 #include "gimptoolcontrol.h"
 
 #include "gimp-intl.h"
 
 
-static GtkWidget * gimp_airbrush_options_gui (GimpToolOptions *tool_options);
+static void        gimp_airbrush_tool_constructed      (GObject          *object);
+
+static void        gimp_airbrush_tool_airbrush_timeout (GimpAirbrush     *airbrush,
+                                                        GimpAirbrushTool *airbrush_tool);
+
+static GtkWidget * gimp_airbrush_options_gui           (GimpToolOptions  *tool_options);
 
 
 G_DEFINE_TYPE (GimpAirbrushTool, gimp_airbrush_tool, GIMP_TYPE_PAINTBRUSH_TOOL)
 
+#define parent_class gimp_airbrush_tool_parent_class
+
 
 void
 gimp_airbrush_tool_register (GimpToolRegisterCallback  callback,
@@ -63,6 +71,9 @@ gimp_airbrush_tool_register (GimpToolRegisterCallback  callback,
 static void
 gimp_airbrush_tool_class_init (GimpAirbrushToolClass *klass)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed = gimp_airbrush_tool_constructed;
 }
 
 static void
@@ -73,6 +84,26 @@ gimp_airbrush_tool_init (GimpAirbrushTool *airbrush)
   gimp_tool_control_set_tool_cursor (tool->control, GIMP_TOOL_CURSOR_AIRBRUSH);
 }
 
+static void
+gimp_airbrush_tool_constructed (GObject *object)
+{
+  GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (object);
+
+  G_OBJECT_CLASS (parent_class)->constructed (object);
+
+  g_signal_connect_object (paint_tool->core, "timeout",
+                           G_CALLBACK (gimp_airbrush_tool_airbrush_timeout),
+                           object, 0);
+}
+
+static void
+gimp_airbrush_tool_airbrush_timeout (GimpAirbrush     *airbrush,
+                                     GimpAirbrushTool *airbrush_tool)
+{
+  gimp_paint_tool_paint_core_paint (GIMP_PAINT_TOOL (airbrush_tool),
+                                    GIMP_PAINT_STATE_MOTION, 0);
+}
+
 
 /*  tool options stuff  */
 


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