diff options
Diffstat (limited to 'libs/gtkmm2/gtk/gtkmm/object.cc')
-rw-r--r-- | libs/gtkmm2/gtk/gtkmm/object.cc | 407 |
1 files changed, 407 insertions, 0 deletions
diff --git a/libs/gtkmm2/gtk/gtkmm/object.cc b/libs/gtkmm2/gtk/gtkmm/object.cc new file mode 100644 index 0000000000..b61a028949 --- /dev/null +++ b/libs/gtkmm2/gtk/gtkmm/object.cc @@ -0,0 +1,407 @@ +// Generated by gtkmmproc -- DO NOT MODIFY! + +#include <gtkmm/object.h> +#include <gtkmm/private/object_p.h> + +/* $Id$ */ + +/* Copyright 1998-2002 The gtkmm Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <glibmm/quark.h> +#include <gtk/gtkobject.h> + + +namespace Gtk +{ + +Object::Object(const Glib::ConstructParams& construct_params) +: + Glib::Object(construct_params) +{ + gobject_disposed_ = false; + + _init_unmanage(); //We don't like the GTK+ default memory management - we want to be in control._) +} + +Object::Object(GtkObject* castitem) +: + Glib::Object((GObject*) castitem) +{ + gobject_disposed_ = false; + + _init_unmanage(); //We don't like the GTK+ default memory management - we want to be in control. +} + +void Object::_init_unmanage(bool /* is_toplevel = false */) +{ + //GTKMM_LIFECYCLE + + if(gobject_) + { + //Glib::Object::Object has already stored a pointer to this C++ instance in the underlying C instance, + //and connected a callback which will, in turn, call our destroy_notify_(), + //so will will know if GTK+ disposes of the underlying instance. + + // Most GTK+ objects are floating, by default. This means that the container widget controls their lifetime. + // 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. + { + GLIBMM_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() ), + + #ifdef GLIBMM_DEBUG_REFCOUNTING + 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. + //GLIBMM_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. + } + } +} + +void Object::_destroy_c_instance() +{ + #ifdef GLIBMM_DEBUG_REFCOUNTING + g_warning("Gtk::Object::_destroy_c_instance() this=%10X, gobject_=%10X\n", this, gobject_); + if(gobject_) + g_warning(" gtypename: %s\n", G_OBJECT_TYPE_NAME(gobject_)); + #endif + + cpp_destruction_in_progress_ = true; + + // 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. + //If this is a problem, then you'll have to use a managed() object, which will die only upon GTK+'s request. + + //We can't do anything with the gobject_ if it's already been disposed. + //This prevents us from unref-ing it again, or destroying it again after GTK+ has told us that it has been disposed. + if (!gobject_disposed_) + { + if(referenced_) + { + //It's not manage()ed so we just unref to destroy it + #ifdef GLIBMM_DEBUG_REFCOUNTING + g_warning("final unref: gtypename: %s, refcount: %d\n", G_OBJECT_TYPE_NAME(object), ((GObject*)object)->ref_count); + #endif + + //Because we called disconnect_cpp_wrapper() our dispose callback will not be called, because the qdata has been removed. + //So we'll connect a callback again, just so that gobject_disposed_ gets set for use later in this same method. + gulong connection_id_destroy = g_signal_connect (object, "destroy", G_CALLBACK (&callback_destroy_), this); + + GLIBMM_DEBUG_UNREFERENCE(this, object); + g_object_unref(object); + + if(!gobject_disposed_) //or if(g_signal_handler_is_connected(object, connection_id_destroy)) + g_signal_handler_disconnect(object, connection_id_destroy); + + //destroy_notify() should have been called after the final g_object_unref() or gtk_object_destroy(), so gobject_disposed_ should now be true. + + //If the C instance still isn't dead then insist, by calling gtk_object_destroy(). + //This is necessary because even a manage()d widget is refed when added to a container. + // <danielk> That's simply not true. But references might be taken elsewhere, + // and gtk_object_destroy() just tells everyone "drop your refs, please!". + if (!gobject_disposed_) + { + #ifdef GLIBMM_DEBUG_REFCOUNTING + g_warning("Gtk::Object::_destroy_c_instance(): Calling gtk_object_destroy(): gobject_=%10X, gtypename=%s\n", object, G_OBJECT_TYPE_NAME(object)); + #endif + + g_assert(GTK_IS_OBJECT(object)); + gtk_object_destroy(object); //Container widgets can respond to this. + } + } + else + { + //It's manag()ed, but the coder decided to delete it before deleting its parent. + //That should be OK because the Container can respond to that. + #ifdef GLIBMM_DEBUG_REFCOUNTING + g_warning("Gtk::Object::_destroy_c_instance(): Calling gtk_object_destroy(): gobject_=%10X\n", gobject_); + #endif + + if (!gobject_disposed_) + { + g_assert(GTK_IS_OBJECT(object)); + gtk_object_destroy(object); + } + } + } + + //Glib::Object::~Object() will not g_object_unref() it too. because gobject_ is now 0. + } +} + +Object::~Object() +{ + #ifdef GLIBMM_DEBUG_REFCOUNTING + g_warning("Gtk::Object::~Object() gobject_=%10X\n", gobject_); + #endif + + //This has probably been called already from Gtk::Object::_destroy(), which is called from derived destructors. + _destroy_c_instance(); +} + +void Object::disconnect_cpp_wrapper() +{ + //GTKMM_LIFECYCLE: + + #ifdef GLIBMM_DEBUG_REFCOUNTING + g_warning("Gtk::Object::disconnect_cpp_wrapper() this=%10X, gobject_=%10X\n", this, gobject_); + if(gobject_) + g_warning(" gtypename: %s\n", G_OBJECT_TYPE_NAME(gobject_)); + #endif + + if(gobj()) + { + //Prevent gtk vfuncs and default signal handlers from calling our instance methods: + g_object_steal_qdata((GObject*)gobj(), Glib::quark_); //It will no longer be possible to get the C++ instance from the C instance. + + //Allow us to prevent generation of a new C++ wrapper during destruction: + g_object_set_qdata((GObject*)gobj(), Glib::quark_cpp_wrapper_deleted_, (gpointer)true); + + //Prevent C++ instance from using GTK+ object: + gobject_ = 0; + + //TODO: Disconnect any signals, using gtk methods. + //We'll have to keep a record of all the connections. + } +} + +void Object::destroy_notify_() +{ + //Overriden. + //GTKMM_LIFECYCLE + + #ifdef GLIBMM_DEBUG_REFCOUNTING + g_warning("Gtk::Object::destroy_notify_: this=%10X, gobject_=%10X\n", this, gobject_); + if(gobject_) + g_warning(" gtypename=%s\n", G_OBJECT_TYPE_NAME(gobject_)); + #endif + + //Remember that it's been disposed (which only happens once): + //This also stops us from destroying it again in the destructor when it calls destroy_(). + gobject_disposed_ = true; + + if(!cpp_destruction_in_progress_) //This function might have been called as a side-effect of destroy() when it called gtk_object_destroy(). + { + if (!referenced_) //If it's manage()ed. + { + #ifdef GLIBMM_DEBUG_REFCOUNTING + g_warning("Gtk::Object::destroy_notify_: before delete this.\n"); + #endif + delete this; //Free the C++ instance. + } + else //It's not managed, but the C gobject_ just died before the C++ instance.. + { + #ifdef GLIBMM_DEBUG_REFCOUNTING + g_warning("Gtk::Object::destroy_notify_: setting gobject_ to 0\n"); + #endif + gobject_ = 0; + } + } + +} + +void Object::destroy_() +{ + //Called from destructors. + //GTKMM_LIFECYCLE + + #ifdef GLIBMM_DEBUG_REFCOUNTING + g_warning("Gtk::Object::destroy_(): gobject_: %10X\n", gobject_); + if(gobject_) + g_warning(" gtypename: %s\n", G_OBJECT_TYPE_NAME(gobject_)); + #endif + + if ( !cpp_destruction_in_progress_ ) //see comment below. + { + //Prevent destroy_notify_() from running as a possible side-effect of gtk_object_destroy. + //We can't predict whether destroy_notify_() will really be run, so we'll disconnect the C++ instance here. + cpp_destruction_in_progress_ = true; + + //destroy the C instance: + _destroy_c_instance(); + } + + //The C++ destructor will be reached later. This function was called by a destructor. +} + +void Object::set_manage() +{ + //GTKMM_LIFECYCLE + //This object will not be unref()ed by gtkmm, though it could be destroyed if the coder deletes the C++ instance early. + //This method is overriden in Gtk::Window because they can not be manage()ed. + + if (!referenced_) return; //It's already managed. + + // remove our reference + if (gobject_->ref_count >= 1) //This should only happen just after creation. We don't use "==1" because GtkButton starts with a refcount of 2 when using a mnemonic. + { + //g_warning("Object::set_manage(), making object floating: %s\n", G_OBJECT_TYPE_NAME(gobject_)); + + // Cowardly refuse to remove last reference make floating instead. //TODO: What does that comment mean? + #ifdef GLIBMM_DEBUG_REFCOUNTING + g_warning("Object::set_manage(): setting GTK_FLOATING: gobject_ = %p", (void*) gobj()); + g_warning(" gtypename=%s\n", G_OBJECT_TYPE_NAME(gobj())); + #endif + GTK_OBJECT_SET_FLAGS(gobj(), GTK_FLOATING); + } + else + { + g_warning("Object::set_manage(). Refcount seems to be 0. %s\n", G_OBJECT_TYPE_NAME(gobject_)); + + //DEF_GLIBMM_DEBUG_UNREF(this, gobj()) + //g_object_unref(gobj()); + } + + //g_warning("Object::set_manage(): end: %s", G_OBJECT_TYPE_NAME(gobject_)); + //g_warning(" refcount=%d", G_OBJECT(gobj())->ref_count); + + referenced_ = false; +} + +void Object::callback_destroy_(GObject*, void* data) //static +{ + //This is only used for a short time, then disconnected. + + Object* cppObject = static_cast<Object*>(data); + if(cppObject) //This will be 0 if the C++ destructor has already run. + { + cppObject->gobject_disposed_ = true; + } +} + +bool Object::is_managed_() const +{ + return !referenced_; +} + +} // namespace Gtk + + +namespace +{ +} // anonymous namespace + + +namespace Glib +{ + +Gtk::Object* wrap(GtkObject* object, bool take_copy) +{ + return dynamic_cast<Gtk::Object *> (Glib::wrap_auto ((GObject*)(object), take_copy)); +} + +} /* namespace Glib */ + +namespace Gtk +{ + + +/* The *_Class implementation: */ + +const Glib::Class& Object_Class::init() +{ + if(!gtype_) // create the GType if necessary + { + // Glib::Class has to know the class init function to clone custom types. + class_init_func_ = &Object_Class::class_init_function; + + // This is actually just optimized away, apparently with no harm. + // Make sure that the parent type has been created. + //CppClassParent::CppObjectType::get_type(); + + // Create the wrapper type, with the same class/instance size as the base type. + register_derived_type(gtk_object_get_type()); + + // Add derived versions of interfaces, if the C type implements any interfaces: + } + + return *this; +} + +void Object_Class::class_init_function(void* g_class, void* class_data) +{ + BaseClassType *const klass = static_cast<BaseClassType*>(g_class); + CppClassParent::class_init_function(klass, class_data); + +} + + +Glib::ObjectBase* Object_Class::wrap_new(GObject* o) +{ + return manage(new Object((GtkObject*)(o))); + +} + + +/* The implementation: */ + +Object::CppClassType Object::object_class_; // initialize static member + +GType Object::get_type() +{ + return object_class_.init().get_type(); +} + +GType Object::get_base_type() +{ + return gtk_object_get_type(); +} + + +Glib::PropertyProxy<void*> Object::property_user_data() +{ + return Glib::PropertyProxy<void*>(this, "user-data"); +} + +Glib::PropertyProxy_ReadOnly<void*> Object::property_user_data() const +{ + return Glib::PropertyProxy_ReadOnly<void*>(this, "user-data"); +} + + +} // namespace Gtk + + |