--- libgnomecanvas-2.3.0/libgnomecanvas/gnome-canvas.c	Thu Mar 27 12:35:21 2003
+++ libgnomecanvas/libgnomecanvas/gnome-canvas.c	Mon Apr  7 10:51:43 2003
@@ -206,6 +206,37 @@
 	return item;
 }
 
+/**
+ * Called when the parent gets destroyed.
+ */
+static void
+parent_destroyed (gpointer data,  GObject *where_the_object_was)
+{
+	GnomeCanvasItem *item = data;
+	g_assert (item->parent == (GnomeCanvasItem*) where_the_object_was);
+
+	group_remove (GNOME_CANVAS_GROUP (where_the_object_was), data);
+}
+
+/* Set the parent for a canvas item. This also adds weak references, so
+ * items get removed properly.
+ * FixMe: how should this behave for a @group with no canvas?
+ */
+static void
+item_set_parent (GnomeCanvasItem *item, GnomeCanvasGroup *group)
+{
+	item->parent = GNOME_CANVAS_ITEM (group);
+	g_object_weak_ref (G_OBJECT (group), parent_destroyed, item);
+	/* Do not add the canvas more than once: */
+	if (!item->canvas) {
+		item->canvas = item->parent->canvas;
+		if (item->canvas)
+			g_object_add_weak_pointer (G_OBJECT (item->canvas),
+						   (gpointer) &item->canvas);
+		else
+			g_warning ("Added canvas item to canvas group with no canvas");
+	}
+}
 
 /* Performs post-creation operations on a canvas item (adding it to its parent
  * group, etc.)
@@ -240,8 +271,7 @@
 		    g_warning ("Cannot set `parent' argument after item has "
 			       "already been constructed.");
 		} else if (g_value_get_object (value)) {
-			item->parent = GNOME_CANVAS_ITEM (g_value_get_object (value));
-			item->canvas = item->parent->canvas;
+			item_set_parent (item, GNOME_CANVAS_GROUP (g_value_get_object (value)));
 			item_post_create_setup (item);
 		}
 		break;
@@ -289,8 +319,7 @@
 	g_return_if_fail (GNOME_IS_CANVAS_GROUP (parent));
 	g_return_if_fail (GNOME_IS_CANVAS_ITEM (item));
 
-	item->parent = GNOME_CANVAS_ITEM (parent);
-	item->canvas = item->parent->canvas;
+	item_set_parent (item, parent);
 
 	g_object_set_valist (G_OBJECT (item), first_arg_name, args);
 
@@ -349,6 +378,12 @@
 	if (item->parent)
 		group_remove (GNOME_CANVAS_GROUP (item->parent), item);
 
+	if (item->canvas) {
+		g_object_remove_weak_pointer (G_OBJECT (item->canvas),
+					      (gpointer) &item->canvas);
+		item->canvas = NULL;
+	}
+
 	g_free (item->xform);
 	item->xform = NULL;
 
@@ -1123,7 +1158,8 @@
 	redraw_if_visible (item);
 
 	group_remove (GNOME_CANVAS_GROUP (item->parent), item);
-	item->parent = GNOME_CANVAS_ITEM (new_group);
+	//item->parent = GNOME_CANVAS_ITEM (new_group);
+	item_set_parent (item, new_group);
 	group_add (new_group, item);
 
 	/* Redraw and repick */
@@ -1859,7 +1895,7 @@
 		(* GNOME_CANVAS_ITEM_GET_CLASS (item)->map) (item);
 }
 
-/* Removes an item from a group */
+/* Removes an item from a group, canvas is not reset, though */
 static void
 group_remove (GnomeCanvasGroup *group, GnomeCanvasItem *item)
 {
@@ -1878,6 +1914,8 @@
 
 			/* Unparent the child */
 
+			g_object_weak_unref (G_OBJECT (item->parent),
+					     parent_destroyed, item);
 			item->parent = NULL;
 			g_object_unref (G_OBJECT (item));
 
@@ -2122,6 +2160,8 @@
 
 	canvas->root = GNOME_CANVAS_ITEM (g_object_new (gnome_canvas_group_get_type (), NULL));
 	canvas->root->canvas = canvas;
+	g_object_add_weak_pointer (G_OBJECT (canvas),
+				   (gpointer) &canvas->root->canvas);
 
 	g_object_ref (canvas->root);
 	gtk_object_sink (GTK_OBJECT (canvas->root));
