[gtkmm] Gtk::Widget: Don't call signal_hide handlers on a widget being deleted.
- From: Kjell Ahlstedt <kjellahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtkmm] Gtk::Widget: Don't call signal_hide handlers on a widget being deleted.
- Date: Mon, 29 Apr 2013 11:27:18 +0000 (UTC)
commit d51d12e6084ad70f89bcc68b970426b7a13ec899
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date: Mon Apr 29 13:12:35 2013 +0200
Gtk::Widget: Don't call signal_hide handlers on a widget being deleted.
* gtk/src/widget.[hg|ccg]: Add custom C callbacks for signal_hide. Don't
call signal_hide handlers or an on_hide() override on a widget while it is
being deleted. This requires the latest glibmm from git master, where a bug
in _WRAP_SIGNAL(..., custom_c_callback) has been fixed. Bug #605728.
ChangeLog | 9 ++++++
gtk/src/widget.ccg | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++
gtk/src/widget.hg | 2 +-
3 files changed, 83 insertions(+), 1 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index b3dc589..bd5e078 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-04-29 Kjell Ahlstedt <kjell ahlstedt bredband net>
+
+ Gtk::Widget: Don't call signal_hide handlers on a widget being deleted.
+
+ * gtk/src/widget.[hg|ccg]: Add custom C callbacks for signal_hide. Don't
+ call signal_hide handlers or an on_hide() override on a widget while it is
+ being deleted. This requires the latest glibmm from git master, where a bug
+ in _WRAP_SIGNAL(..., custom_c_callback) has been fixed. Bug #605728.
+
3.8.0:
2013-04-05 Murray Cumming <murrayc murrayc com>
diff --git a/gtk/src/widget.ccg b/gtk/src/widget.ccg
index ccf1d47..6299779 100644
--- a/gtk/src/widget.ccg
+++ b/gtk/src/widget.ccg
@@ -31,6 +31,31 @@
namespace //anonymous
{
+// This signal callback is custom implemented, so that we can refrain from calling
+// the signal handler if the C++ wrapper is being deleted.
+// https://bugzilla.gnome.org/show_bug.cgi?id=605728#c5
+void Widget_signal_hide_callback(GObject* self, void* data)
+{
+ const Glib::ObjectBase* const obj = Glib::ObjectBase::_get_current_wrapper(self);
+
+ // Do not try to call a signal on a disassociated wrapper.
+ // This function might be invoked recursively if the signal_hide() handler
+ // deletes the object.
+ // Therefore we have to test for cpp_destruction_in_progress_ at this point.
+ if(obj && !obj->_cpp_destruction_is_in_progress())
+ {
+ try
+ {
+ if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data))
+ (*static_cast<sigc::slot<void>*>(slot))();
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+ }
+}
+
//These signal callbacks are custom implemented, so that we can create a temporary SelectionData instance.
//To do this, we used the optional custom_c_callback paramater to _WRAP_SIGNAL() in the .hg file.
static void Widget_signal_drag_data_get_callback(GtkWidget* self, GdkDragContext* p0,GtkSelectionData*
p1,guint p2,guint p3,void* data)
@@ -85,6 +110,54 @@ static void Widget_signal_selection_get_callback(GtkWidget* self, GtkSelectionDa
namespace Gtk
{
+// This default handler callback is custom implemented, so that we can refrain
+// from calling an on_hide() override, if the C++ wrapper is being deleted.
+void Widget_Class::hide_callback(GtkWidget* self)
+{
+ Glib::ObjectBase *const obj_base = static_cast<Glib::ObjectBase*>(
+ Glib::ObjectBase::_get_current_wrapper((GObject*)self));
+
+ // Non-gtkmmproc-generated custom classes implicitly call the default
+ // Glib::ObjectBase constructor, which sets is_derived_. But gtkmmproc-
+ // generated classes can use this optimisation, which avoids the unnecessary
+ // parameter conversions if there is no possibility of the virtual function
+ // being overridden:
+ // This function might be invoked recursively if an on_hide() override
+ // deletes the object.
+ // Therefore we test for cpp_destruction_in_progress_ at this point.
+ // (Not sure if it's necessary, but it feels safer. Perhaps the following
+ // dynamic_cast catches all dangerous cases. /Kjell Ahlstedt)
+ if(obj_base && obj_base->is_derived_() && !obj_base->_cpp_destruction_is_in_progress())
+ {
+ CppObjectType *const obj = dynamic_cast<CppObjectType* const>(obj_base);
+ if(obj) // This can be NULL during destruction.
+ {
+ #ifdef GLIBMM_EXCEPTIONS_ENABLED
+ try // Trap C++ exceptions which would normally be lost because this is a C callback.
+ {
+ #endif //GLIBMM_EXCEPTIONS_ENABLED
+ // Call the virtual member method, which derived classes might override.
+ obj->on_hide();
+ return;
+ #ifdef GLIBMM_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+ #endif //GLIBMM_EXCEPTIONS_ENABLED
+ }
+ }
+
+ BaseClassType *const base = static_cast<BaseClassType*>(
+ g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The
original underlying C class).
+ );
+
+ // Call the original underlying C function:
+ if(base && base->hide)
+ (*base->hide)(self);
+}
+
//These default handler callbacks are custom implemented, so that we can create a temporary SelectionData
instance.
//To do this, we used the optional custom_c_callback paramater to _WRAP_SIGNAL() in the .hg file.
void Widget_Class::selection_get_callback(GtkWidget* self, GtkSelectionData* p0, guint p1, guint p2)
diff --git a/gtk/src/widget.hg b/gtk/src/widget.hg
index 0fd441d..1fb2d16 100644
--- a/gtk/src/widget.hg
+++ b/gtk/src/widget.hg
@@ -559,7 +559,7 @@ public:
_WRAP_SIGNAL(void show(),"show")
- _WRAP_SIGNAL(void hide(),"hide")
+ _WRAP_SIGNAL(void hide(),"hide", custom_c_callback)
/// Emitted on mapping of a widget to the screen.
//- See {flags.mapped}.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]