? gtkmm2.kdevprj
? gtkmm2.kdevses
? gtkmm_leakfix.patch
? temp.patch
? temp_debug.patch
? temp_debug2.patch
? docs/internal/lifecycle.txt
? examples/base/a.out
? examples/book/helloworld/a.out
? examples/book/helloworld/temp.txt
? examples/book/idle/Makefile
? examples/book/idle/Makefile.in
? examples/book/idle/idle
? tests/wrap_existing/stack_trace.txt
? tests/wrap_existing/temp.txt
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtkmm-root/base/ChangeLog,v
retrieving revision 1.788
diff -u -p -r1.788 ChangeLog
--- ChangeLog	3 Jul 2003 10:42:02 -0000	1.788
+++ ChangeLog	10 Jul 2003 16:06:07 -0000
@@ -1,3 +1,20 @@
+2003-07-05  Murray Cumming  <murrayc@usa.net>
+
+	* gtk/src/object.ccg Object::_init_unmanage(): 
+	Don't g_object_ref() objects that are already not managed, such as 
+	stuff used with Glib::Wrap() which is already in a container 
+	(Containers sink (unfloat) child widgets after they are added). Also, 
+	don't mark it as not manage()d, (!referenced_) of course. This was 
+	doing one-too-many refs, so sometimes the objects would not be 
+	finalized even if they were destroyed. Daniel Elstner found this 
+	potential problem months ago and I should have listened to him.
+	This seems to fix the lifetime bug shown in tests/wrap_existing. I think this
+  fixes the get_toplevel_windows() leak shown in tests/refcount_dialog also.
+  Thanks to Harold Hopfes for doing _lots_ of investigation work on this bug.
+	* gtk/src/window.ccg: Window::_destroy_c_instance():
+	Remove the g_object_unref() that was a window-specific fix for the
+	extra g_object_ref() in gtk/src/object.ccg above.
+
 2003-07-03  Murray Cumming  <murrayc@usa.net>
 
 	* Used %p and (void*) cast with various g_warning()s used when
Index: NEWS
===================================================================
RCS file: /cvs/gnome/gtkmm-root/base/NEWS,v
retrieving revision 1.73
diff -u -p -r1.73 NEWS
--- NEWS	21 May 2003 05:17:18 -0000	1.73
+++ NEWS	10 Jul 2003 16:06:08 -0000
@@ -1,3 +1,16 @@
+2.2.4:
+
+* Fixed memory leak of C++ instances when using Glib::wrap() on existing child
+  widgets, for instance inside Dialog::get_vbox(). (Murray Cumming, Harold Hopfes).
+* TreeView: Correctly declared generate_cellrenderer() template specializations.
+  gcc 3.2.3 and gcc 3.3.0 on Debian Linux, and gcc on Win32, were not picking these
+  up, causing automatic-selection of CellRenderers (e.g. check boxes for bools)
+  to fail. (Cedric Gustin).
+
+2.2.3:
+
+* Just rebuilt tarball due to some generated libtool file problems.
+
 2.2.2:
 
 * OptionMenu: Fixed segfault when Menu remembers destroyed OptionMenu.
Index: glib/glibmm/objectbase.cc
===================================================================
RCS file: /cvs/gnome/gtkmm-root/glib-src/objectbase.cc,v
retrieving revision 1.12
diff -u -p -r1.12 objectbase.cc
--- glib/glibmm/objectbase.cc	3 Jul 2003 10:09:23 -0000	1.12
+++ glib/glibmm/objectbase.cc	10 Jul 2003 16:06:10 -0000
@@ -239,6 +239,12 @@ void ObjectBase::set_manage()
           "only Gtk::Object instances can be managed");
 }
 
+bool ObjectBase::_cpp_destruction_is_in_progress() const
+{
+  return cpp_destruction_in_progress_;
+}
+
+
 bool _gobject_cppinstance_already_deleted(GObject* gobject)
 {
   //This function is used to prevent calling wrap() on a GTK+ instance whose gtkmm instance has been deleted.
Index: glib/glibmm/objectbase.h
===================================================================
RCS file: /cvs/gnome/gtkmm-root/glib-src/objectbase.h,v
retrieving revision 1.9
diff -u -p -r1.9 objectbase.h
--- glib/glibmm/objectbase.h	11 Oct 2002 18:05:43 -0000	1.9
+++ glib/glibmm/objectbase.h	10 Jul 2003 16:06:10 -0000
@@ -88,6 +88,7 @@ public:
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
   static ObjectBase* _get_current_wrapper(GObject* object);
+  bool _cpp_destruction_is_in_progress() const;
 #endif
 
 protected:
Index: gtk/src/object.ccg
===================================================================
RCS file: /cvs/gnome/gtkmm-root/gtk-src/object.ccg,v
retrieving revision 1.37
diff -u -p -r1.37 object.ccg
--- gtk/src/object.ccg	3 Jul 2003 10:09:24 -0000	1.37
+++ gtk/src/object.ccg	10 Jul 2003 16:06:16 -0000
@@ -46,9 +46,6 @@ void Object::_init_unmanage(bool /* is_t
 {
   //GTKMM_LIFECYCLE
 
-  //g_warning("Object::_init_unmanage(): %s\n", G_OBJECT_TYPE_NAME(gobject_));
-  referenced_ = true; //Not managed.
-  
   if(gobject_)
   {
     //Glib::Object::Object has already stored a pointer to this C++ instance in the underlying C instance,
@@ -59,8 +56,6 @@ void Object::_init_unmanage(bool /* is_t
     // We'll change this:
     if(GTK_OBJECT_FLOATING (gobject_)) //Top-level Windows and Dialogs can not be manag()ed, so there is no need to do this.
     {
-      //g_warning("Object::_init_unmanage(), object was floating: %s\n", G_OBJECT_TYPE_NAME(gobject_));
-
       GTKMM_DEBUG_REFERENCE(this, gobject_);
       g_object_ref(gobject_);  //Increase ref by 1 so that it doesn't get deleted when we sink() it (sink()ing does an unref)
       gtk_object_sink((GtkObject*)gobject_); //Stops it from being floating - we will make this optional ( see Gtk::manage() ),
@@ -69,17 +64,21 @@ void Object::_init_unmanage(bool /* is_t
       g_warning("gtkmm after sink: C++ instance: %p, C instance: %p, refcount=%d\n", (void*)(Glib::ObjectBase*)this, (void*)gobject_, G_OBJECT(gobject_)->ref_count);
       g_warning("    c instance gtype: %s\n", G_OBJECT_TYPE_NAME(gobject_));
       #endif
+
+      referenced_ = true; //Not managed.
     }
     else
     {
        //This widget is already not floating. It's probably already been added to a GTK+ container, and has just had Glib::wrap() called on it.
        //It's not floating because containers call gtk_object_sink() on child widgets to take control of them.
        //We just ref() it so that we can unref it later.
-       GTKMM_DEBUG_REFERENCE(this, gobject_);
-       g_object_ref(gobject_);
+       //GTKMM_DEBUG_REFERENCE(this, gobject_);
+       //g_object_ref(gobject_);
     
        //Alternatively, it might be a top-level window (e.g. a Dialog). We would then be doing one too-many refs(),
        //We do an extra unref() in Window::_destroy_c_instance() to take care of that.
+
+       referenced_ = false; //Managed. We should not try to unfloat GtkObjects that we did not instantiate.
     }
   }
 }
@@ -96,14 +95,16 @@ void Object::_destroy_c_instance()
 
   // remove our hook.
   GtkObject* object = gobj();
+
   if (object)
-  {
+  { 
     g_assert(GTK_IS_OBJECT(object));
 
     disconnect_cpp_wrapper();
     //Unfortunately this means that our dispose callback will not be called, because the qdata has been removed.
     //So we'll connect the callback again, just so that gobject_disposed_ gets set for use later in this same method.
     //See below:
+   
 
     //This probably isn't a problem now:
     //If we are killing the C++ instance before the C instance, then this might lead to strange behaviour.
@@ -163,7 +164,7 @@ void Object::_destroy_c_instance()
     }
 
     //Glib::Object::~Object() will not g_object_unref() it too. because gobject_ is now 0.
-  }
+  }  
 }
 
 Object::~Object()
@@ -299,7 +300,7 @@ void Object::set_manage() 
 }
 
 void Object::callback_destroy_(GObject*, void* data) //static
-{
+{ 
   //This is only used for a short time, then disconnected.
 
   Object* cppObject = static_cast<Object*>(data);
Index: gtk/src/widget.ccg
===================================================================
RCS file: /cvs/gnome/gtkmm-root/gtk-src/widget.ccg,v
retrieving revision 1.40
diff -u -p -r1.40 widget.ccg
--- gtk/src/widget.ccg	3 Jul 2003 10:09:24 -0000	1.40
+++ gtk/src/widget.ccg	10 Jul 2003 16:06:17 -0000
@@ -244,6 +244,8 @@ void Widget_Class::parent_set_callback_c
 
 void Widget_Class::dispose_vfunc_callback(GObject* self)
 {
+  //Avoid disposal. See also Window_Class::dispose_vfunc_callback().
+  
   #ifdef GTKMM_DEBUG_REFCOUNTING
   g_warning("Widget_Class::dispose_vfunc_callback(): gobject_: %p\n", (void*)self);
   //if(self)
@@ -257,19 +259,17 @@ void Widget_Class::dispose_vfunc_callbac
   // several signal emissions, particularly signal_hide().  Therefore we
   // have to test for cpp_destruction_in_progress_ at this point.
 
-  if(obj && !obj->cpp_destruction_in_progress_)
-  {
+  if(obj && !obj->_cpp_destruction_is_in_progress()) //When it should really be destroyed, we zero gobj_.
+  { 
     GtkWidget *const pWidget = obj->gobj();
     g_return_if_fail(pWidget == GTK_WIDGET(self));
 
     // Abort dispose if the widget isn't managed, in order to prevent
-    // the nasty self-destroying behaviour of GTK+.  This applies to:
-    //
-    // - GtkWindow, if it received "delete_event"
-    // - GtkDialog, which destroys on "response" by default
-    // - any widget inside a GtkContainer on gtk_container_destroy()
+    // the nasty self-destroying behaviour of GTK+.  This applies to
+    // any widget inside a GtkContainer on gtk_container_destroy()
+    // See also Window_Class::dispose_vfunc_callback().
 
-    if(obj->referenced_)
+    if(obj->referenced_) //Not managed
     {
       // GTKMM_LIFECYCLE
       // Remove the widget from its parent container so that it
@@ -281,28 +281,60 @@ void Widget_Class::dispose_vfunc_callbac
         // non-managed objects here, the container just releases the
         // reference it has acquired before in gtk_container_add().
 
+        #ifdef GTKMM_DEBUG_REFCOUNTING
+        g_warning("Widget_Class::dispose_vfunc_callback(): removing gobject_: %p from parent: %p", (void*)self, (void*)pWidget->parent);
+        #endif
+  
         gtk_container_remove(GTK_CONTAINER(pWidget->parent), pWidget);
+
+        #ifdef GTKMM_DEBUG_REFCOUNTING
+        g_warning("Widget_Class::dispose_vfunc_callback(): after removing from parent.");
+        #endif
       }
 
+      #ifdef GTKMM_DEBUG_REFCOUNTING
+      g_warning("Widget_Class::dispose_vfunc_callback(): before gtk_widget_hide().");
+      #endif
+        
       // Now hide the widget.  The C++ object must _not_ be accessed anymore
       // after this call, because a signal_hide() handler might delete it.
       gtk_widget_hide(pWidget);
 
+      #ifdef GTKMM_DEBUG_REFCOUNTING
+      g_warning("Widget_Class::dispose_vfunc_callback(): after gtk_widget_hide().");
+      #endif
+      
       // GTKMM_LIFECYCLE
       return; // Prevent calling of normal C dispose vfunc (see below)
     }
 
+    #ifdef GTKMM_DEBUG_REFCOUNTING
+    g_warning("Widget_Class::dispose_vfunc_callback(): unreferenced: before gtk_widget_hide().");
+    #endif
+    
     // Always hide widgets on gtk_object_destroy(), regardless of whether
     // the widget is managed or not.  This is done for consistency so that
     // connecting to signal_hide() is guaranteed to work.
     gtk_widget_hide(pWidget);
+
+    #ifdef GTKMM_DEBUG_REFCOUNTING
+    g_warning("Widget_Class::dispose_vfunc_callback(): unreferenced:  after gtk_widget_hide().");
+    #endif
   }
 
   GObjectClass *const base = static_cast<GObjectClass*>(
       g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)));
 
+  #ifdef GTKMM_DEBUG_REFCOUNTING
+  g_warning("Widget_Class::dispose_vfunc_callback(): before calling base->dispose.");
+  #endif
+        
   if(base->dispose)
     (*base->dispose)(self);
+
+  #ifdef GTKMM_DEBUG_REFCOUNTING
+  g_warning("Widget_Class::dispose_vfunc_callback(): after calling base->dispose.");
+  #endif
 }
 
 } // namespace Gtk
Index: gtk/src/window.ccg
===================================================================
RCS file: /cvs/gnome/gtkmm-root/gtk-src/window.ccg,v
retrieving revision 1.31
diff -u -p -r1.31 window.ccg
--- gtk/src/window.ccg	3 Jul 2003 10:09:24 -0000	1.31
+++ gtk/src/window.ccg	10 Jul 2003 16:06:17 -0000
@@ -112,16 +112,83 @@ void Window::_destroy_c_instance()
     if (!gobject_disposed_)
     {
         //Windows can not be unrefed. They are "self-owning".
-        #ifdef GTKMM_DEBUG_REFCOUNTING
-        g_warning("Gtk::Window::_destroy_c_instance(): Calling gtk_object_destroy(): gobject_=%p\n", (void*)object);
-        #endif
-        g_object_unref(object); //We ref()ed it one too many times to simplify our _init_unmanage() code.
-
-        if(!gobject_disposed_) //Just in case that unref() really destroyed it, in which case our dispose callack would have just been called.
-          gtk_object_destroy(object);
+        gtk_object_destroy(object);
       }
 
     //Glib::Object::~Object() will not g_object_unref() it too. because gobject_ is now 0.
+  }
+}
+
+
+void Window_Class::dispose_vfunc_callback(GObject* self)
+{
+  //Avoid disposal of Windows on delete_event (window close) signal.
+  
+  #ifdef GTKMM_DEBUG_REFCOUNTING
+  g_warning("Window_Class::dispose_vfunc_callback(): gobject_: %p\n", (void*)self);
+  #endif
+
+  Widget *const obj = dynamic_cast<Widget*>(
+      Glib::ObjectBase::_get_current_wrapper(self));
+
+  // This function might be invoked recursively because we're triggering
+  // several signal emissions, particularly signal_hide().  Therefore we
+  // have to test for cpp_destruction_in_progress_ at this point.
+
+  if(obj && !obj->_cpp_destruction_is_in_progress()) //When it should really be destroyed, we zero gobj_.
+  {
+    GtkWidget* const pWidget = obj->gobj();
+    g_return_if_fail(pWidget == GTK_WIDGET(self));
+
+    // Abort dispose if the widget isn't managed, in order to prevent
+    // the nasty self-destroying behaviour of GTK+.  This applies to:
+    //
+    // - GtkWindow, if it received "delete_event"
+    // - GtkDialog, which destroys on "response" by default
+
+    #ifdef GTKMM_DEBUG_REFCOUNTING
+    g_warning("Window_Class::dispose_vfunc_callback(): before gtk_widget_hide().");
+    #endif
+
+    // Now hide the widget.  The C++ object must _not_ be accessed anymore
+    // after this call, because a signal_hide() handler might delete it.
+    gtk_widget_hide(pWidget);
+
+    #ifdef GTKMM_DEBUG_REFCOUNTING
+    g_warning("Window_Class::dispose_vfunc_callback(): after gtk_widget_hide().");
+    #endif
+
+    // GTKMM_LIFECYCLE
+    return; // Prevent calling of normal C dispose vfunc (see below)
+  }
+  else
+  {
+    #ifdef GTKMM_DEBUG_REFCOUNTING
+    //g_warning("Window_Class::dispose_vfunc_callback(): unreferenced: before gtk_widget_hide().");
+    #endif
+
+    // Always hide widgets on gtk_object_destroy(), regardless of whether
+    // the widget is managed or not.  This is done for consistency so that
+    // connecting to signal_hide() is guaranteed to work.
+    //gtk_widget_hide(pWidget);
+
+    #ifdef GTKMM_DEBUG_REFCOUNTING
+    //g_warning("Window_Class::dispose_vfunc_callback(): unreferenced:  after gtk_widget_hide().");
+    #endif
+  
+    GObjectClass *const base = static_cast<GObjectClass*>(
+        g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)));
+
+    #ifdef GTKMM_DEBUG_REFCOUNTING
+    g_warning("Window_Class::dispose_vfunc_callback(): before calling base->dispose.");
+    #endif
+
+    if(base->dispose)
+      (*base->dispose)(self);
+
+    #ifdef GTKMM_DEBUG_REFCOUNTING
+    g_warning("Window_Class::dispose_vfunc_callback(): after calling base->dispose.");
+    #endif
   }
 }
 
Index: gtk/src/window.hg
===================================================================
RCS file: /cvs/gnome/gtkmm-root/gtk-src/window.hg,v
retrieving revision 1.57
diff -u -p -r1.57 window.hg
--- gtk/src/window.hg	7 Mar 2003 07:47:08 -0000	1.57
+++ gtk/src/window.hg	10 Jul 2003 16:06:20 -0000
@@ -81,6 +81,19 @@ public:
   _WRAP_SIGNAL(void activate_default(), "activate_default")
   _WRAP_SIGNAL(void move_focus(DirectionType direction), "move_focus")
 
+  #m4begin
+dnl// Hook in special code to catch explicit uses of gtk_object_destroy() by
+dnl// GTK+ code, e.g. when receiving the GDK_DELETE event.  For details, look
+dnl// at Gtk::Window_Class::dispose_vfunc_callback() in window.ccg.
+dnl
+  _PUSH(SECTION_PCC_CLASS_INIT_VFUNCS)
+    reinterpret_cast<GObjectClass*>(klass)->dispose = &dispose_vfunc_callback;
+  _SECTION(SECTION_PH_VFUNCS)
+    static void dispose_vfunc_callback(GObject* self);
+  _POP()
+#m4end
+
+
   _WRAP_METHOD(void set_title(const Glib::ustring& title),
                gtk_window_set_title)
 
Index: tests/wrap_existing/main.cc
===================================================================
RCS file: /cvs/gnome/gtkmm-root/base/tests/wrap_existing/main.cc,v
retrieving revision 1.1
diff -u -p -r1.1 main.cc
--- tests/wrap_existing/main.cc	3 Jul 2003 10:09:26 -0000	1.1
+++ tests/wrap_existing/main.cc	10 Jul 2003 16:06:20 -0000
@@ -28,17 +28,11 @@ int main(int argc, char**argv)
   //Set a quark and a callback:
   initialize_quark();
   int a = 0; // (This doesn't work unless we have a non-null value for the 3rd parameter.)
-  g_object_set_qdata_full((GObject*)pBox->gobj(), quark_test, &a, &on_object_qdata_destroyed);
- 
+  g_object_set_qdata_full((GObject*)pBox->gobj(), quark_test, &a, &on_object_qdata_destroyed); 
 
   g_warning("vbox refcount=%d", G_OBJECT(pBox->gobj())->ref_count);
 
-  //g_object_unref(G_OBJECT(pBox->gobj()));
-
-  //g_warning("vbox refcount=%d", G_OBJECT(pBox->gobj())->ref_count);
-
   delete pDialog;
 
-  //g_warning("after delete");
-
+  g_warning("after delete");
 }
