[perl-Gtk2] Document cirular reference in Gtk2::AcelLabel



commit b6cfeb99ef5f6364ee9fdbd5f0232dc000e5df08
Author: Kevin Ryde <user42 zip com au>
Date:   Mon Mar 29 15:47:32 2010 +0200

    Document cirular reference in Gtk2::AcelLabel
    
    Gtk2::AcelLabel's accel-widget property can create a circular reference.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=592391

 t/GtkMenuItem.t     |   48 ++++++++++++++++++++++++++++++++++++++++++++++--
 xs/GtkAccelLabel.xs |   13 +++++++++++++
 xs/GtkMenuItem.xs   |   21 ++++++++++++++++++++-
 3 files changed, 79 insertions(+), 3 deletions(-)
---
diff --git a/t/GtkMenuItem.t b/t/GtkMenuItem.t
index 588b939..5235ddd 100644
--- a/t/GtkMenuItem.t
+++ b/t/GtkMenuItem.t
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -w
 use strict;
-use Gtk2::TestHelper tests => 14;
+use Gtk2::TestHelper tests => 18;
 
 # $Id$
 
@@ -66,7 +66,51 @@ SKIP: {
   is ($item -> get_accel_path(), '<bla>/bla/bla');
 }
 
+#-----------------------------------------------------------------------------
+# circular ref between MenuItem and child AccelLabel
+#
+# These tests verify what's described in the pod of Gtk2::MenuItem->new,
+# ->new_with_label and ->new_with_mnemonic, namely that circa Gtk 2.18 an
+# item created with a label gets a circular reference up from the child
+# AccelLabel "accel-widget" property and thus needs ->destroy or similar.
+#
+# If the MenuItems here are in fact destroyed by weakening then that'd be
+# fine for the code, but the docs would be wrong, for some or other Gtk
+# version.
+#
+require Scalar::Util;
+{
+  my $item = Gtk2::MenuItem->new("foo");
+  Scalar::Util::weaken ($item);
+  ok ($item, 'new("foo") not destroyed by weakening (correctness of the docs)');
+  if ($item) { $item->destroy; }
+}
+{
+  my $item = Gtk2::MenuItem->new_with_label("foo");
+  Scalar::Util::weaken ($item);
+  ok ($item, 'new_with_label("foo") not destroyed by weakening (correctness of the docs)');
+  if ($item) { $item->destroy; }
+}
+{
+  my $item = Gtk2::MenuItem->new_with_mnemonic("foo");
+  Scalar::Util::weaken ($item);
+  ok ($item, 'new_with_mnemonic("foo") not destroyed by weakening (correctness of the docs)');
+  if ($item) { $item->destroy; }
+}
+
+SKIP: {
+  # "label" property new in Gtk 2.16
+  skip 'new 2.16 stuff', 1
+    unless Gtk2->CHECK_VERSION(2, 16, 0);
+
+  my $item = Gtk2::MenuItem->new;
+  $item->set (label => "foo");
+  Scalar::Util::weaken ($item);
+  ok ($item, 'set(label=>"foo") not destroyed by weakening (correctness of the docs)');
+  if ($item) { $item->destroy; }
+}
+
 __END__
 
-Copyright (C) 2003 by the gtk2-perl team (see the file AUTHORS for the
+Copyright (C) 2003, 2010 by the gtk2-perl team (see the file AUTHORS for the
 full list).  See LICENSE for more information.
diff --git a/xs/GtkAccelLabel.xs b/xs/GtkAccelLabel.xs
index bdc4e43..25348d5 100644
--- a/xs/GtkAccelLabel.xs
+++ b/xs/GtkAccelLabel.xs
@@ -23,6 +23,19 @@
 
 MODULE = Gtk2::AccelLabel	PACKAGE = Gtk2::AccelLabel	PREFIX = gtk_accel_label_
 
+=for position DESCRIPTION
+
+=head1 DESCRIPTION
+
+Note that the C<accel-widget> property is a hard reference to the
+target widget.  If it's a container parent of the AccelLabel then it
+will be a circular reference and will have to be unset by an explicit
+C<destroy> when no longer wanted, as usual for such things.  See
+L<Gtk2::MenuItem> for how this affects the common case of a MenuItem
+containing a AccelLabel.
+
+=cut
+
 ## GtkWidget* gtk_accel_label_new (const gchar *string)
 GtkWidget *
 gtk_accel_label_new (class, string)
diff --git a/xs/GtkMenuItem.xs b/xs/GtkMenuItem.xs
index 2177154..262a593 100644
--- a/xs/GtkMenuItem.xs
+++ b/xs/GtkMenuItem.xs
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 by the gtk2-perl team (see the file AUTHORS)
+ * Copyright (c) 2003, 2010 by the gtk2-perl team (see the file AUTHORS)
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -78,6 +78,25 @@ gtk2perl_menu_item_toggle_size_request_marshal (GClosure * closure,
 
 MODULE = Gtk2::MenuItem	PACKAGE = Gtk2::MenuItem	PREFIX = gtk_menu_item_
 
+=for position DESCRIPTION
+
+=head1 DESCRIPTION
+
+If a MenuItem is created with a C<$label> string, or if the C<label>
+property is set later, then it should be destroyed with
+C<< $item->destroy >>.  Just dropping the last Perl ref is not enough
+because (as of Gtk through to 2.18) there's a circular reference from
+the child C<Gtk2::AccelLabel> back up to the item (the C<accel-widget>
+property).
+
+When a MenuItem is in a C<Gtk2::Menu> a C<destroy> happens
+automatically.  Dropping the last ref to a Menu calls C<destroy> on
+its children, as usual for a container.  But if you remove a MenuItem
+with a label from a menu (or never add it to one) then be sure to
+C<< $item->destroy >> explicitly.
+
+=cut
+
 BOOT:
 	gperl_signal_set_marshaller_for (GTK_TYPE_MENU_ITEM, "toggle_size_request",
 	                                 gtk2perl_menu_item_toggle_size_request_marshal);



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