]> Pileus Git - grits/blobdiff - src/grits-viewer.c
Lock draw_queue id to prevent race conditions
[grits] / src / grits-viewer.c
index 52fbaf97a5269d9205e0ece6cbbc7c644e72f98c..86d00c45256751f59d549c35bfa3a55641aff615 100644 (file)
@@ -71,6 +71,16 @@ static void _grits_viewer_fix_rotation(GritsViewer *viewer)
        while (viewer->rotation[2] >  180) viewer->rotation[2] -= 360;
 }
 
+static gboolean _grits_viewer_queue_draw_cb(gpointer _viewer)
+{
+       GritsViewer *viewer = _viewer;
+       g_mutex_lock(&viewer->draw_lock);
+       gtk_widget_queue_draw(GTK_WIDGET(viewer));
+       viewer->draw_source = 0;
+       g_mutex_unlock(&viewer->draw_lock);
+       return FALSE;
+}
+
 /* Signal helpers */
 static void _grits_viewer_emit_location_changed(GritsViewer *viewer)
 {
@@ -187,7 +197,7 @@ static gboolean on_motion_notify(GritsViewer *viewer, GdkEventMotion *event, gpo
 static void on_view_changed(GritsViewer *viewer,
                gdouble _1, gdouble _2, gdouble _3)
 {
-       gtk_widget_queue_draw(GTK_WIDGET(viewer));
+       grits_viewer_queue_draw(viewer);
 }
 
 /***********
@@ -424,6 +434,22 @@ gboolean grits_viewer_get_offline(GritsViewer *viewer)
        return viewer->offline;
 }
 
+/**
+ * grits_viewer_queue_draw:
+ * @viewer: the viewer
+ *
+ * Causes the viewer to redraw the screen. This has the safe effect as
+ * gtk_widget_queue_draw, but is thread safe, and probably faster.
+ */
+void grits_viewer_queue_draw(GritsViewer *viewer)
+{
+       g_mutex_lock(&viewer->draw_lock);
+       if (!viewer->draw_source)
+               viewer->draw_source = g_idle_add_full(G_PRIORITY_HIGH,
+                               _grits_viewer_queue_draw_cb, viewer, NULL);
+       g_mutex_unlock(&viewer->draw_lock);
+}
+
 /***********************************
  * To be implemented by subclasses *
  ***********************************/
@@ -565,7 +591,6 @@ void grits_viewer_add(GritsViewer *viewer, GritsObject *object,
  * @object: the object to remove
  *
  * Remove an object from the viewer.
- * The objects reference count is decremented.
  */
 void grits_viewer_remove(GritsViewer *viewer, GritsObject *object)
 {
@@ -576,7 +601,6 @@ void grits_viewer_remove(GritsViewer *viewer, GritsObject *object)
                g_warning("GritsViewer: remove - Unimplemented");
        object->viewer = NULL;
        klass->remove(viewer, object);
-       g_object_unref(object);
 }
 
 /****************
@@ -595,6 +619,8 @@ static void grits_viewer_init(GritsViewer *viewer)
        viewer->rotation[1] = 0;
        viewer->rotation[2] = 0;
 
+       g_mutex_init(&viewer->draw_lock);
+
        g_object_set(viewer, "can-focus", TRUE, NULL);
        gtk_widget_add_events(GTK_WIDGET(viewer),
                        GDK_BUTTON_PRESS_MASK |
@@ -612,9 +638,21 @@ static void grits_viewer_init(GritsViewer *viewer)
        g_signal_connect(viewer, "location-changed",     G_CALLBACK(on_view_changed),   NULL);
        g_signal_connect(viewer, "rotation-changed",     G_CALLBACK(on_view_changed),   NULL);
 }
+static void grits_viewer_dispose(GObject *gobject)
+{
+       g_debug("GritsViewer: dispose");
+       GritsViewer *viewer = GRITS_VIEWER(gobject);
+       g_mutex_lock(&viewer->draw_lock);
+       if (viewer->draw_source)
+               g_source_remove(viewer->draw_source);
+       g_mutex_unlock(&viewer->draw_lock);
+       G_OBJECT_CLASS(grits_viewer_parent_class)->dispose(gobject);
+}
 static void grits_viewer_finalize(GObject *gobject)
 {
        g_debug("GritsViewer: finalize");
+       GritsViewer *viewer = GRITS_VIEWER(gobject);
+       g_mutex_clear(&viewer->draw_lock);
        G_OBJECT_CLASS(grits_viewer_parent_class)->finalize(gobject);
        g_debug("GritsViewer: finalize - done");
 }
@@ -622,6 +660,7 @@ static void grits_viewer_class_init(GritsViewerClass *klass)
 {
        g_debug("GritsViewer: class_init");
        GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+       gobject_class->dispose      = grits_viewer_dispose;
        gobject_class->finalize     = grits_viewer_finalize;
 
        /**