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