Gtkmm2ext::Pane: attempt to track child lifetime, since Gtkmm 2.4 doesn't do this...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 20 Jul 2016 03:31:07 +0000 (23:31 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 20 Jul 2016 14:48:07 +0000 (10:48 -0400)
libs/gtkmm2ext/gtkmm2ext/pane.h
libs/gtkmm2ext/pane.cc

index dfe2ef7ffec1a32a7a324219b71e49073c7cf6e1..9612da08d28dd5771a14e2e60e0f4873ab9b9800 100644 (file)
@@ -46,10 +46,11 @@ class LIBGTKMM2EXT_API Pane : public Gtk::Container
   public:
        struct Child
        {
+               Pane* pane;
                Gtk::Widget* w;
                int32_t minsize;
 
-               Child (Gtk::Widget* widget, uint32_t ms) : w (widget), minsize (ms) {}
+               Child (Pane* p, Gtk::Widget* widget, uint32_t ms) : pane (p), w (widget), minsize (ms) {}
        };
 
        typedef std::list<Child> Children;
@@ -108,6 +109,9 @@ class LIBGTKMM2EXT_API Pane : public Gtk::Container
        void add_divider ();
        void handle_child_visibility ();
        bool fract_is_ok (Dividers::size_type, float fract);
+
+       static void* notify_child_destroyed (void*);
+       void* child_destroyed (Gtk::Widget*);
 };
 
 class LIBGTKMM2EXT_API HPane : public Pane
index 867912d540a094a0f56fc1628cac8663ef10346f..3eda140c5705b1c1e05ff7142053f70c87c5807f 100644 (file)
@@ -48,6 +48,7 @@ Pane::Pane (bool h)
 Pane::~Pane ()
 {
        for (Children::iterator c = children.begin(); c != children.end(); ++c) {
+               c->w->remove_destroy_notify_callback (&(*c));
                c->w->unparent ();
        }
 }
@@ -140,9 +141,14 @@ Pane::handle_child_visibility ()
 void
 Pane::on_add (Widget* w)
 {
-       children.push_back (Child (w, 0));
+       children.push_back (Child (this, w, 0));
 
        w->set_parent (*this);
+       /* Gtkmm 2.4 does not correctly arrange for ::on_remove() to be called
+          for custom containers that derive from Gtk::Container. So ... we need
+          to ensure that we hear about child destruction ourselves.
+       */
+       w->add_destroy_notify_callback (&children.back(), &Pane::notify_child_destroyed);
 
        w->signal_show().connect (sigc::mem_fun (*this, &Pane::handle_child_visibility));
        w->signal_hide().connect (sigc::mem_fun (*this, &Pane::handle_child_visibility));
@@ -152,11 +158,31 @@ Pane::on_add (Widget* w)
        }
 }
 
+void*
+Pane::notify_child_destroyed (void* data)
+{
+       Child* child = reinterpret_cast<Child*> (data);
+       return child->pane->child_destroyed (child->w);
+}
+
+void*
+Pane::child_destroyed (Gtk::Widget* w)
+{
+       for (Children::iterator c = children.begin(); c != children.end(); ++c) {
+               if (c->w == w) {
+                       children.erase (c);
+                       break;
+               }
+       }
+       return 0;
+}
+
 void
 Pane::on_remove (Widget* w)
 {
        for (Children::iterator c = children.begin(); c != children.end(); ++c) {
                if (c->w == w) {
+                       w->remove_destroy_notify_callback (&(*c));
                        w->unparent ();
                        children.erase (c);
                        break;