[perl-Gtk2] Gtk2::Menu: free the detach func earlier



commit eaa7a8893c568fcafe8a0ba5f01a12528f9dad25
Author: Kevin Ryde <user42 zip com au>
Date:   Sun Apr 18 07:43:58 2010 +1000

    Gtk2::Menu: free the detach func earlier
    
    Free the detach func passed to attach_to_widget() after it has been called.  It
    will only be called once, so this safely frees memory earlier than previously.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=616061

 t/GtkMenu.t   |   17 ++++++++++++++++-
 xs/GtkMenu.xs |   23 +++++++++++++++++++----
 2 files changed, 35 insertions(+), 5 deletions(-)
---
diff --git a/t/GtkMenu.t b/t/GtkMenu.t
index 4a50835..27b4cd7 100644
--- a/t/GtkMenu.t
+++ b/t/GtkMenu.t
@@ -8,7 +8,7 @@
 # 	- rm
 #########################
 
-use Gtk2::TestHelper tests => 62;
+use Gtk2::TestHelper tests => 64;
 
 ok( my $menubar = Gtk2::MenuBar->new );
 
@@ -156,6 +156,21 @@ unless ($i_know_you) {
 	}
 }
 
+{
+  my $item = Gtk2::MenuItem->new;
+  my $menu = Gtk2::Menu->new;
+  my $detach_args;
+  my $detach_func = sub { $detach_args = \ _; };
+  $menu->attach_to_widget ($item, $detach_func);
+  $menu->detach;
+  is_deeply ($detach_args, [ $item, $menu ], 'detach callback args');
+
+  # crib note: $detach_func must be a closure referring to a variable
+  # outside itself to weaken away like this
+  Scalar::Util::weaken ($detach_func);
+  is ($detach_func, undef, 'detach callback func freed after called');
+}
+
 SKIP: {
 	skip 'new 2.14 stuff', 2
 		unless Gtk2->CHECK_VERSION(2, 14, 0);
diff --git a/xs/GtkMenu.xs b/xs/GtkMenu.xs
index db16e81..283e39b 100644
--- a/xs/GtkMenu.xs
+++ b/xs/GtkMenu.xs
@@ -100,8 +100,13 @@ gtk2perl_menu_detach_func (GtkWidget *attach_widget,
 	callback = g_object_get_data (G_OBJECT (attach_widget),
 	                              "__gtk2perl_menu_detach_func__");
 
-	if (callback)
+	if (callback) {
 		gperl_callback_invoke (callback, NULL, attach_widget, menu);
+
+		/* free the handler after it's been called */
+		g_object_set_data (G_OBJECT (attach_widget),
+				   "__gtk2perl_menu_detach_func__", NULL);
+	}
 }
 
 MODULE = Gtk2::Menu	PACKAGE = Gtk2::Menu	PREFIX = gtk_menu_
@@ -195,15 +200,25 @@ gtk_menu_set_accel_path (menu, accel_path)
 	GtkMenu *menu
 	const gchar *accel_path
 
+=for apidoc
+Attach C<$menu> to C<$attach_widget>.  C<$menu> must not be currently
+attached to any other widget, including not a submenu of a
+C<Gtk2::MenuItem>.
+
+If C<$menu> is later detached from the widget with
+C<< $menu->detach >> then the C<$detach_func> is called as
+
+    &$detach_func ($attach_widget, $menu)
+=cut
 void
-gtk_menu_attach_to_widget (menu, attach_widget, detacher)
+gtk_menu_attach_to_widget (menu, attach_widget, detach_func)
 	GtkMenu *menu
 	GtkWidget *attach_widget
-	SV *detacher
+	SV *detach_func
     PREINIT:
 	GPerlCallback *callback;
     CODE:
-	callback = gtk2perl_menu_detach_func_create (detacher, NULL);
+	callback = gtk2perl_menu_detach_func_create (detach_func, NULL);
 
 	g_object_set_data_full (G_OBJECT (attach_widget),
 	                        "__gtk2perl_menu_detach_func__",



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