13
0

Fix crash when unpacking or deleting pane

Gtk::Widget_Class::dispose_vfunc_callback calls hide() which invokes
Pane::handle_child_visibility which calls Pane::reallocate which
tries to get the allocation of the widget being destroyed.
This commit is contained in:
Robin Gareus 2016-12-21 17:10:37 +01:00
parent 98c0adda49
commit de04da27ee
2 changed files with 11 additions and 2 deletions

View File

@ -49,6 +49,8 @@ class LIBGTKMM2EXT_API Pane : public Gtk::Container
Pane* pane;
Gtk::Widget* w;
int32_t minsize;
sigc::connection show_con;
sigc::connection hide_con;
Child (Pane* p, Gtk::Widget* widget, uint32_t ms) : pane (p), w (widget), minsize (ms) {}
};

View File

@ -48,6 +48,8 @@ Pane::Pane (bool h)
Pane::~Pane ()
{
for (Children::iterator c = children.begin(); c != children.end(); ++c) {
c->show_con.disconnect ();
c->hide_con.disconnect ();
c->w->remove_destroy_notify_callback (&(*c));
c->w->unparent ();
}
@ -142,6 +144,7 @@ void
Pane::on_add (Widget* w)
{
children.push_back (Child (this, w, 0));
Child& kid = children.back ();
w->set_parent (*this);
/* Gtkmm 2.4 does not correctly arrange for ::on_remove() to be called
@ -150,8 +153,8 @@ Pane::on_add (Widget* w)
*/
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));
kid.show_con = w->signal_show().connect (sigc::mem_fun (*this, &Pane::handle_child_visibility));
kid.hide_con = w->signal_hide().connect (sigc::mem_fun (*this, &Pane::handle_child_visibility));
while (dividers.size() < (children.size() - 1)) {
add_divider ();
@ -170,6 +173,8 @@ Pane::child_destroyed (Gtk::Widget* w)
{
for (Children::iterator c = children.begin(); c != children.end(); ++c) {
if (c->w == w) {
c->show_con.disconnect ();
c->hide_con.disconnect ();
children.erase (c);
break;
}
@ -182,6 +187,8 @@ Pane::on_remove (Widget* w)
{
for (Children::iterator c = children.begin(); c != children.end(); ++c) {
if (c->w == w) {
c->show_con.disconnect ();
c->hide_con.disconnect ();
w->remove_destroy_notify_callback (&(*c));
w->unparent ();
children.erase (c);