[PATCH] Fix for a GtkMenu crash and leak



Hi

Here is a fix for a bug in GtkMenu that I ran into.

The sequence of:

activating a menu item
removing the menu item
destroying it
adding a new menu item
activating the new menu item 

causes a leak in the better case and a crash in the worse case.

GtkMenu keeps a cached old_active_menu_item that continues to point to a
menu item even after it has been removed from the menu and destroyed. If
a new menu item aliases to the old address, gets added and activated, it
gets an extra unref that it shouldn't get.

The fix clears out the cached value and properly does an unref on the
item when it's being removed from the menu.

I found this in Gtk+ 1.2, as far as I can tell the same applies for
HEAD.

If it's OK, I can check in into both.

Pavel

Index: gtk/gtkmenu.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenu.c,v
retrieving revision 1.41.2.4
diff -p -u -r1.41.2.4 gtkmenu.c
--- gtk/gtkmenu.c	2000/09/08 01:50:35	1.41.2.4
+++ gtk/gtkmenu.c	2000/12/31 01:57:34
@@ -94,6 +94,8 @@ static void gtk_menu_position       (Gtk
 static void gtk_menu_reparent       (GtkMenu           *menu, 
 				     GtkWidget         *new_parent, 
 				     gboolean           unrealize);
+static void gtk_menu_remove         (GtkContainer      *menu,
+				     GtkWidget         *widget);
 
 static GtkMenuShellClass *parent_class = NULL;
 static const gchar	 *attach_data_key = "gtk-menu-attach-data";
@@ -159,6 +161,8 @@ gtk_menu_class_init (GtkMenuClass *class
   widget_class->hide_all = gtk_menu_hide_all;
   widget_class->enter_notify_event = gtk_menu_enter_notify;
   widget_class->leave_notify_event = gtk_menu_leave_notify;
+
+  container_class->remove = gtk_menu_remove;
   
   menu_shell_class->submenu_placement = GTK_LEFT_RIGHT;
   menu_shell_class->deactivate = gtk_menu_deactivate;
@@ -393,6 +397,28 @@ gtk_menu_insert (GtkMenu   *menu,
 {
   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), child, position);
 }
+
+void 
+gtk_menu_remove(GtkContainer *container,
+	        GtkWidget    *widget)
+{
+  GtkMenu *menu;
+  g_return_if_fail (GTK_IS_MENU (container));
+  g_return_if_fail (GTK_IS_MENU_ITEM (widget));
+
+  menu = GTK_MENU (container);
+
+  /* Clear out old_active_menu_item if it matches the item we are
removing
+   */
+  if (menu->old_active_menu_item == widget)
+    {
+      gtk_widget_unref (menu->old_active_menu_item);
+      menu->old_active_menu_item = NULL;
+    }
+
+  GTK_CONTAINER_CLASS (parent_class)->remove (container, widget);
+}
+
 
 static void
 gtk_menu_tearoff_bg_copy (GtkMenu *menu)




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