Index: gobject/gobjectmodule.c
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gobject/gobjectmodule.c,v
retrieving revision 1.169
diff -u -3 -p -r1.169 gobjectmodule.c
--- gobject/gobjectmodule.c	22 May 2005 23:01:36 -0000	1.169
+++ gobject/gobjectmodule.c	27 May 2005 11:23:16 -0000
@@ -409,11 +409,82 @@ pyg_object_get_property (GObject *object
     pyg_gil_state_release(state);
 }
 
+/* see gobject-private.h for details about this */
+GStaticPrivate __pygobject_caller = G_STATIC_PRIVATE_INIT;
+
+static GObject *
+pyg_object_class_constructor (GType type, guint n_construct_properties, 
+			      GObjectConstructParam *construct_properties)
+{
+    PyGObjectCaller caller = pyg_object_get_caller();
+    GObject *ret;
+  
+    pyg_object_set_caller(PYG_OBJECT_CALLER_EXTERN);
+    switch (caller) {
+	case PYG_OBJECT_CALLER_PYTHON:
+	/* FIXME: This will cause issues if you inherit from a Python object 
+	 * in C and inherit from that object in C again. When that happens 
+	 * we'll need to add some type data to point to the real constructor 
+	 * or so.
+	 */
+	    {
+		GObjectClass *parent = g_type_class_peek(g_type_parent(type));
+		while (parent->constructor == pyg_object_class_constructor)
+		    parent = g_type_class_peek_parent(parent);
+		return parent->constructor(type, n_construct_properties, construct_properties);
+	    }
+	case PYG_OBJECT_CALLER_GOBJECT:
+	    g_warning("according to the caller variable, we called ourself."
+		      " This indicates something bad.");
+	    /* fall through for now */
+	default:
+	    {
+		PyObject *args, *kwargs, *pyobject;
+		PyTypeObject *typeobject = pygobject_lookup_class (type);
+		guint i;
+
+		if (!typeobject) 
+		    g_error("No Python type, type %s is improperly registered",
+				  g_type_name (type));
+		if (n_construct_properties > 0) {
+		    kwargs = PyDict_New();
+		    for (i = 0; i < n_construct_properties; i++) {
+			PyObject *valobj = pyg_param_gvalue_as_pyobject(construct_properties[i].value,
+									FALSE, 
+									construct_properties[i].pspec);
+			if (!valobj || PyDict_SetItemString(kwargs, 
+							    construct_properties[i].pspec->name, 
+							    valobj) != 0)
+			    g_warning("could not add property %s to construct properties", 
+				      construct_properties[i].pspec->name);
+			}
+		} else {
+		    kwargs = NULL;
+		}
+		args = (PyObject *) PyTuple_New (0);
+		pyg_object_set_caller (PYG_OBJECT_CALLER_GOBJECT);
+		pyobject = PyObject_Call ((PyObject *) typeobject, args, NULL);
+		if (pyobject == NULL) { 
+		    PyErr_Print ();
+		    g_error("object creation for type %s failed", g_type_name (type));
+		}
+		Py_DECREF (args);
+		Py_XDECREF (kwargs);
+		Py_DECREF (pyobject); /* reference is held by the GObject's qdata */
+		ret = pygobject_get (pyobject);
+		/* weird behaviour expected from constructors */
+		g_object_freeze_notify (ret);
+		return ret;
+	    }
+    }
+}
+
 static void
 pyg_object_class_init(GObjectClass *class, PyObject *py_class)
 {
     class->set_property = pyg_object_set_property;
     class->get_property = pyg_object_get_property;
+    class->constructor = pyg_object_class_constructor;
 }
 
 static gboolean
Index: gobject/pygobject-private.h
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gobject/pygobject-private.h,v
retrieving revision 1.31
diff -u -3 -p -r1.31 pygobject-private.h
--- gobject/pygobject-private.h	22 May 2005 22:38:55 -0000	1.31
+++ gobject/pygobject-private.h	27 May 2005 11:23:16 -0000
@@ -38,6 +38,30 @@ extern struct _PyGObject_Functions pygob
             PyEval_RestoreThread(_save);                \
     } G_STMT_END
 
+/* The following code is used in constructors to track who initiated the 
+ * construction of an object. You can think of it as an extra argument passed
+ * to the creation of objects. Constructors inside PyGTK need to take special
+ * code paths when called from PyGTK code to ensure object creation.
+ * Since this is a thread-global variable and there are reentrancy issues 
+ * during object creation, the time window where this variable is set needs
+ * to be kept as small as possible. Because of it, this variable is set by the 
+ * function calling the constructor directly before it calls it and immediately
+ * cleared by the constructor that was called.
+ */
+typedef enum {
+    /* Defaut. Indicates that the construction of this object was initiated
+     * from outside of PyGTK. */
+    PYG_OBJECT_CALLER_EXTERN = 0,
+    /* Indicates that a GObject is created from the PygObject init function. */
+    PYG_OBJECT_CALLER_PYTHON,
+    /* Indicates that a PyObject is created from the GObject constructor. */
+    PYG_OBJECT_CALLER_GOBJECT
+} PyGObjectCaller;
+extern GStaticPrivate __pygobject_caller;
+#define pyg_object_set_caller(caller) \
+    g_static_private_set (&__pygobject_caller, GINT_TO_POINTER (caller), NULL)
+#define pyg_object_get_caller() \
+    GPOINTER_TO_INT (g_static_private_get (&__pygobject_caller))
 
 extern GType PY_TYPE_OBJECT;
 
Index: gobject/pygobject.c
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gobject/pygobject.c,v
retrieving revision 1.42
diff -u -3 -p -r1.42 pygobject.c
--- gobject/pygobject.c	22 May 2005 22:38:55 -0000	1.42
+++ gobject/pygobject.c	27 May 2005 11:23:17 -0000
@@ -565,7 +565,9 @@ pygobject_init(PyGObject *self, PyObject
     guint n_params = 0, i;
     GParameter *params = NULL;
     GObjectClass *class;
-
+    PyGObjectCaller caller = pyg_object_get_caller();
+  
+    pyg_object_set_caller(PYG_OBJECT_CALLER_EXTERN);
     if (!PyArg_ParseTuple(args, ":GObject.__init__", &object_type))
 	return -1;
 
@@ -615,10 +617,27 @@ pygobject_init(PyGObject *self, PyObject
 	}
     }
 
+    /* FIXME: It would be nicer if we only set this when we know that we have
+     * a Python subclasses object to avoid screwups.
+     * That requires a gboolean pygtk_gtype_created_in_python (GType) though
+     */
+    pyg_object_set_caller(PYG_OBJECT_CALLER_PYTHON);
     self->obj = g_object_newv(object_type, n_params, params);
-    if (self->obj)
-	pygobject_register_wrapper((PyObject *)self);
-    else
+    pyg_object_set_caller(PYG_OBJECT_CALLER_EXTERN);
+    if (self->obj) {
+	/* this is basically the same as pygobject_register_wrapper */
+	if (!pygobject_wrapper_key)
+	    pygobject_wrapper_key=g_quark_from_static_string(pygobject_wrapper_id);
+
+	Py_INCREF(self);
+	g_object_set_qdata_full(self->obj, pygobject_wrapper_key, self,
+				pyg_destroy_notify);
+	/* only sink the object if it's ours. C code wants the floating ref */
+	if (caller == PYG_OBJECT_CALLER_GOBJECT)
+	    sink_object (self->obj);
+	else
+	    g_object_ref (self->obj);
+    } else
 	PyErr_SetString (PyExc_RuntimeError, "could not create object");
 	   
  cleanup:
