Add thread safe grits_viewer_queue_draw function
authorAndy Spencer <andy753421@gmail.com>
Thu, 27 Dec 2012 09:26:28 +0000 (09:26 +0000)
committerAndy Spencer <andy753421@gmail.com>
Thu, 27 Dec 2012 10:03:32 +0000 (10:03 +0000)
This should be used by threads when they finish loading something. Any
additional loading which must be done by the main thread will ideally be
done during the next draw.

src/grits-opengl.c
src/grits-viewer.c
src/grits-viewer.h
src/objects/grits-object.c

index 90e830b..0e803ba 100644 (file)
@@ -290,7 +290,7 @@ static gboolean run_mouse_move(GritsOpenGL *opengl, GdkEventMotion *event)
 static gboolean on_motion_notify(GritsOpenGL *opengl, GdkEventMotion *event, gpointer _)
 {
        opengl->mouse_queue = *event;
-       gtk_widget_queue_draw(GTK_WIDGET(opengl));
+       grits_viewer_queue_draw(GRITS_VIEWER(opengl));
        return FALSE;
 }
 
@@ -402,18 +402,18 @@ static gboolean on_key_press(GritsOpenGL *opengl, GdkEventKey *event, gpointer _
        /* Testing */
        if (kv == GDK_w) {
                opengl->wireframe = !opengl->wireframe;
-               gtk_widget_queue_draw(GTK_WIDGET(opengl));
+               grits_viewer_queue_draw(GRITS_VIEWER(opengl));
        }
        if (kv == GDK_p) {
                opengl->pickmode = !opengl->pickmode;
-               gtk_widget_queue_draw(GTK_WIDGET(opengl));
+               grits_viewer_queue_draw(GRITS_VIEWER(opengl));
        }
 #ifdef ROAM_DEBUG
        else if (kv == GDK_n) roam_sphere_split_one(opengl->sphere);
        else if (kv == GDK_p) roam_sphere_merge_one(opengl->sphere);
        else if (kv == GDK_r) roam_sphere_split_merge(opengl->sphere);
        else if (kv == GDK_u) roam_sphere_update_errors(opengl->sphere);
-       gtk_widget_queue_draw(GTK_WIDGET(opengl));
+       grits_viewer_queue_draw(GRITS_VIEWER(opengl));
 #endif
        return FALSE;
 }
index aa5c3a5..67d25fb 100644 (file)
@@ -71,6 +71,14 @@ 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;
+       gtk_widget_queue_draw(GTK_WIDGET(viewer));
+       viewer->draw_source = 0;
+       return FALSE;
+}
+
 /* Signal helpers */
 static void _grits_viewer_emit_location_changed(GritsViewer *viewer)
 {
@@ -187,7 +195,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 +432,20 @@ 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)
+{
+       if (!viewer->draw_source)
+               viewer->draw_source = g_idle_add_full(G_PRIORITY_HIGH,
+                               _grits_viewer_queue_draw_cb, viewer, NULL);
+}
+
 /***********************************
  * To be implemented by subclasses *
  ***********************************/
@@ -610,6 +632,14 @@ 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);
+       if (viewer->draw_source)
+               g_source_remove(viewer->draw_source);
+       G_OBJECT_CLASS(grits_viewer_parent_class)->dispose(gobject);
+}
 static void grits_viewer_finalize(GObject *gobject)
 {
        g_debug("GritsViewer: finalize");
@@ -620,6 +650,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;
 
        /**
index 4b04e3f..fa9fc07 100644 (file)
@@ -119,6 +119,9 @@ struct _GritsViewer {
        /* For dragging */
        gint    drag_mode;
        gdouble drag_x, drag_y;
+
+       /* For queue_draw */
+       guint   draw_source;
 };
 
 struct _GritsViewerClass {
@@ -187,4 +190,6 @@ void grits_viewer_add(GritsViewer *viewer, GritsObject *object,
                gint level, gboolean sort);
 void grits_viewer_remove(GritsViewer *viewer, GritsObject *object);
 
+void grits_viewer_queue_draw(GritsViewer *viewer);
+
 #endif
index 4674e8a..2eb6b5c 100644 (file)
@@ -163,7 +163,7 @@ void grits_object_hide(GritsObject *object, gboolean hidden)
 void grits_object_queue_draw(GritsObject *object)
 {
        if (object->viewer)
-               gtk_widget_queue_draw(GTK_WIDGET(object->viewer));
+               grits_viewer_queue_draw(object->viewer);
 }
 
 void grits_object_set_cursor(GritsObject *object, GdkCursorType cursor)