[goffice] Canvas: avoid anted cursor crash in Gnumeric.



commit 6b5d824784090931ad63eede1e9042df325257ff
Author: Morten Welinder <terra gnome org>
Date:   Sat Dec 6 16:13:15 2014 -0500

    Canvas: avoid anted cursor crash in Gnumeric.
    
    With this patch we will be more careful in removing items from a canvas.
    The canvas stores direct pointers to some items and we now clear them
    consistently.

 ChangeLog                   |   15 +++++++++++++++
 NEWS                        |    1 +
 goffice/canvas/goc-canvas.c |   32 +++++++++++++++++++++++++++++---
 goffice/canvas/goc-canvas.h |    2 ++
 goffice/canvas/goc-group.c  |    6 ++++--
 goffice/canvas/goc-item.c   |    4 ----
 6 files changed, 51 insertions(+), 9 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index bf6e4cb..e5e9955 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2014-12-06  Morten Welinder  <terra gnome org>
+
+       * goffice/canvas/goc-canvas.c (goc_canvas_draw): Plug leak.
+       (_goc_canvas_remove_item): New function.  Use of this fixes
+       several crashes.
+
+       * goffice/canvas/goc-group.c (goc_group_remove_child): Don't mess
+       directly with the canvas' members here.  Tell the canvas that
+       child is gone.
+       (goc_group_add_child): If the canvas changes, tell the old canvas
+       that child is gone.
+
+       * goffice/canvas/goc-item.c (goc_item_dispose): Don't mess
+       directly with the canvas' members here.
+
 2014-11-26  Jean Brefort  <jean brefort normalesup org>
 
        reviewed by: <delete if not using a buddy>
diff --git a/NEWS b/NEWS
index 91e409e..1521bf6 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,7 @@ Jean:
 
 Morten:
        * Dead kitten salvage.
+       * Fix canvas issues when removing items.
 
 --------------------------------------------------------------------------
 goffice 0.10.18:
diff --git a/goffice/canvas/goc-canvas.c b/goffice/canvas/goc-canvas.c
index 03acc86..ea9f85b 100644
--- a/goffice/canvas/goc-canvas.c
+++ b/goffice/canvas/goc-canvas.c
@@ -87,9 +87,12 @@ goc_canvas_draw (GtkWidget *widget, cairo_t *cr)
                        }
                        return TRUE;
                }
+
+               cairo_region_destroy (region);
        }
+
        goc_item_get_bounds (GOC_ITEM (canvas->root),&x0, &y0, &x1, &y1);
-    for (i= 0; i  < l->num_rectangles; i++) {
+       for (i= 0; i  < l->num_rectangles; i++) {
                clip_x1 = l->rectangles[i].x;
                clip_y1 = l->rectangles[i].y;
                clip_x2 = clip_x1 + l->rectangles[i].width;
@@ -292,8 +295,6 @@ goc_canvas_finalize (GObject *obj)
        GocCanvas *canvas = GOC_CANVAS (obj);
        GocCanvasPrivate *priv = (GocCanvasPrivate *) canvas->priv;
        g_object_unref (canvas->root);
-       if (priv->invalid_region != NULL)
-               cairo_region_destroy (priv->invalid_region);
        g_free (canvas->priv);
        parent_klass->finalize (obj);
 }
@@ -768,3 +769,28 @@ goc_canvas_get_bounds (GocCanvas *canvas, double *x0, double *y0, double *x1, do
        goc_item_get_bounds (GOC_ITEM (canvas->root), x0, y0, x1, y1);
 }
 
+/*
+ * Item is leaving this canvas.  Get rid of direct pointers.
+ */
+void
+_goc_canvas_remove_item (GocCanvas *canvas, GocItem *item)
+{
+       GocCanvasPrivate *priv;
+
+       g_return_if_fail (GOC_IS_CANVAS (canvas));
+       g_return_if_fail (GOC_IS_ITEM (item));
+
+       priv = (GocCanvasPrivate *) canvas->priv;
+
+       if (canvas->last_item == item)
+               canvas->last_item = NULL;
+       if (canvas->grabbed_item == item)
+               canvas->grabbed_item = NULL;
+       if (priv->invalidated_item == item) {
+               if (priv->invalid_region != NULL) {
+                       cairo_region_destroy (priv->invalid_region);
+                       priv->invalid_region = NULL;
+               }
+               priv->invalidated_item = NULL;
+       }
+}
diff --git a/goffice/canvas/goc-canvas.h b/goffice/canvas/goc-canvas.h
index 41f205e..f55b951 100644
--- a/goffice/canvas/goc-canvas.h
+++ b/goffice/canvas/goc-canvas.h
@@ -93,6 +93,8 @@ void           goc_canvas_c2w (GocCanvas *canvas, double x, double y, int *x_, int *y_);
 void            goc_canvas_render (GocCanvas *canvas, cairo_t *cr, double x0, double y0, double x1, double 
y1);
 void            goc_canvas_get_bounds (GocCanvas *canvas, double *x0, double *y0, double *x1, double *y1);
 
+void _goc_canvas_remove_item (GocCanvas *canvas, GocItem *item);
+
 G_END_DECLS
 
 #endif  /* GOC_CANVAS_H */
diff --git a/goffice/canvas/goc-group.c b/goffice/canvas/goc-group.c
index 389f1cb..24bf144 100644
--- a/goffice/canvas/goc-group.c
+++ b/goffice/canvas/goc-group.c
@@ -354,6 +354,8 @@ goc_group_add_child (GocGroup *parent, GocItem *item)
        item->canvas = parent->base.canvas;
 
        /* Notify of changes.  */
+       if (old_canvas && item->canvas != old_canvas)
+               _goc_canvas_remove_item (old_canvas, item);
        g_object_notify (G_OBJECT (item), "parent");
        if (item->canvas != old_canvas)
                g_object_notify (G_OBJECT (item), "canvas");
@@ -377,8 +379,8 @@ goc_group_remove_child (GocGroup *parent, GocItem *item)
        g_return_if_fail (GOC_IS_GROUP (parent));
        g_return_if_fail (GOC_IS_ITEM (item));
        g_return_if_fail (item->parent == parent);
-       if (item->canvas && item->canvas->last_item == item)
-               item->canvas->last_item = NULL;
+       if (item->canvas)
+               _goc_canvas_remove_item (item->canvas, item);
        if (GOC_ITEM (parent)->realized)
                _goc_item_unrealize (item);
        parent->children = g_list_remove (parent->children, item);
diff --git a/goffice/canvas/goc-item.c b/goffice/canvas/goc-item.c
index e04c240..3e2aa2c 100644
--- a/goffice/canvas/goc-item.c
+++ b/goffice/canvas/goc-item.c
@@ -221,10 +221,6 @@ goc_item_dispose (GObject *object)
        GtkStyleContext *context;
 
        if (item->canvas) {
-               if (item->canvas->last_item == item)
-                       item->canvas->last_item = NULL;
-               if (item->canvas->grabbed_item == item)
-                       item->canvas->grabbed_item = NULL;
                item->cached_bounds = TRUE; /* avoids a call to update_bounds */
                goc_item_invalidate (item);
        }


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