diff options
Diffstat (limited to 'gi/_gobject')
-rw-r--r-- | gi/_gobject/gobjectmodule.c | 10 | ||||
-rw-r--r-- | gi/_gobject/pygobject-private.h | 2 | ||||
-rw-r--r-- | gi/_gobject/pygobject.c | 62 | ||||
-rw-r--r-- | gi/_gobject/pygobject.h | 8 |
4 files changed, 54 insertions, 28 deletions
diff --git a/gi/_gobject/gobjectmodule.c b/gi/_gobject/gobjectmodule.c index 96b5c94..fda21e7 100644 --- a/gi/_gobject/gobjectmodule.c +++ b/gi/_gobject/gobjectmodule.c @@ -996,7 +996,11 @@ pygobject_constructv(PyGObject *self, pygobject_init_wrapper_set((PyObject *) self); obj = g_object_newv(pyg_type_from_object((PyObject *) self), n_parameters, parameters); + + if (g_object_is_floating (obj)) + self->private_flags.flags |= PYGOBJECT_GOBJECT_WAS_FLOATING; pygobject_sink (obj); + pygobject_init_wrapper_set(NULL); if (self->obj == NULL) { self->obj = obj; @@ -1034,7 +1038,9 @@ pygobject__g_instance_init(GTypeInstance *instance, * now */ PyGILState_STATE state; state = pyglib_gil_state_ensure(); - wrapper = pygobject_new_full(object, TRUE, g_class); + wrapper = pygobject_new_full(object, + /*steal=*/ FALSE, + g_class); /* float the wrapper ref here because we are going to orphan it * so we don't destroy the wrapper. The next call to pygobject_new_full @@ -1477,7 +1483,7 @@ pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs) if (obj) { pygobject_sink (obj); - self = (PyGObject *) pygobject_new_full((GObject *)obj, TRUE, NULL); + self = (PyGObject *) pygobject_new((GObject *)obj); g_object_unref(obj); } else self = NULL; diff --git a/gi/_gobject/pygobject-private.h b/gi/_gobject/pygobject-private.h index 1b1d6db..0d1aca0 100644 --- a/gi/_gobject/pygobject-private.h +++ b/gi/_gobject/pygobject-private.h @@ -154,7 +154,7 @@ void pygobject_register_class (PyObject *dict, PyObject *bases); void pygobject_register_wrapper (PyObject *self); PyObject * pygobject_new (GObject *obj); -PyObject * pygobject_new_full (GObject *obj, gboolean sink, gpointer g_class); +PyObject * pygobject_new_full (GObject *obj, gboolean steal, gpointer g_class); void pygobject_sink (GObject *obj); PyTypeObject *pygobject_lookup_class (GType gtype); void pygobject_watch_closure (PyObject *self, GClosure *closure); diff --git a/gi/_gobject/pygobject.c b/gi/_gobject/pygobject.c index a23d469..8673e79 100644 --- a/gi/_gobject/pygobject.c +++ b/gi/_gobject/pygobject.c @@ -951,7 +951,7 @@ pygobject_lookup_class(GType gtype) /** * pygobject_new_full: * @obj: a GObject instance. - * @sink: whether to sink any floating reference found on the GObject. + * @steal: whether to steal a ref from the GObject or add (sink) a new one. * @g_class: the GObjectClass * * This function gets a reference to a wrapper for the given GObject @@ -962,19 +962,30 @@ pygobject_lookup_class(GType gtype) * Returns: a reference to the wrapper for the GObject. */ PyObject * -pygobject_new_full(GObject *obj, gboolean sink, gpointer g_class) +pygobject_new_full(GObject *obj, gboolean steal, gpointer g_class) { PyGObject *self; if (obj == NULL) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } - /* we already have a wrapper for this object -- return it. */ + /* If the GObject already has a PyObject wrapper stashed in its qdata, re-use it. + */ self = (PyGObject *)g_object_get_qdata(obj, pygobject_wrapper_key); if (self != NULL) { - pygobject_ref_sink(self); + /* Note the use of "pygobject_ref_sink" here only deals with PyObject + * wrapper ref counts and has nothing to do with GObject. + */ + pygobject_ref_sink(self); + + /* If steal is true, we also want to decref the incoming GObjects which + * already have a Python wrapper because the wrapper is already holding a + * strong reference. + */ + if (steal) + g_object_unref (obj); + } else { /* create wrapper */ PyGObjectData *inst_data = pyg_object_peek_inst_data(obj); @@ -1000,13 +1011,15 @@ pygobject_new_full(GObject *obj, gboolean sink, gpointer g_class) self->weakreflist = NULL; self->private_flags.flags = 0; self->obj = obj; - /* if we are creating a wrapper around a newly created object, it can have - a floating ref (e.g. for methods like Gtk.Button.new()). Bug 640868 */ - if (sink) - g_object_ref_sink(obj); - else - g_object_ref(obj); - pygobject_register_wrapper((PyObject *)self); + + /* If we are not stealing a ref or the object is floating, + * add a regular ref or sink the object. */ + if (g_object_is_floating (obj)) + self->private_flags.flags |= PYGOBJECT_GOBJECT_WAS_FLOATING; + if (!steal || self->private_flags.flags & PYGOBJECT_GOBJECT_WAS_FLOATING) + g_object_ref_sink (obj); + + pygobject_register_wrapper((PyObject *)self); PyObject_GC_Track((PyObject *)self); } @@ -1017,7 +1030,9 @@ pygobject_new_full(GObject *obj, gboolean sink, gpointer g_class) PyObject * pygobject_new(GObject *obj) { - return pygobject_new_full(obj, TRUE, NULL); + return pygobject_new_full(obj, + /*steal=*/FALSE, + NULL); } static void @@ -1438,14 +1453,17 @@ pygobject_set_properties(PyGObject *self, PyObject *args, PyObject *kwargs) goto exit; } - ret = pygi_set_property_value (self, pspec, value); - if (ret == 0) - goto exit; - else if (PyErr_Occurred()) - goto exit; + ret = pygi_set_property_value (self, pspec, value); + if (ret != 0) { + /* Non-zero return code means that either an error occured ...*/ + if (PyErr_Occurred()) + goto exit; - if (!set_property_from_pspec(G_OBJECT(self->obj), pspec, value)) - goto exit; + /* ... or the property couldn't be found , so let's try the default + * call. */ + if (!set_property_from_pspec(G_OBJECT(self->obj), pspec, value)) + goto exit; + } } result = Py_None; @@ -2343,7 +2361,7 @@ pygobject_weak_ref_call(PyGObjectWeakRef *self, PyObject *args, PyObject *kw) return NULL; if (self->obj) - return pygobject_new_full(self->obj, FALSE, NULL); + return pygobject_new(self->obj); else { Py_INCREF(Py_None); return Py_None; diff --git a/gi/_gobject/pygobject.h b/gi/_gobject/pygobject.h index ba40986..92dc030 100644 --- a/gi/_gobject/pygobject.h +++ b/gi/_gobject/pygobject.h @@ -24,7 +24,8 @@ struct _PyGClosure { typedef enum { PYGOBJECT_USING_TOGGLE_REF = 1 << 0, - PYGOBJECT_IS_FLOATING_REF = 1 << 1 + PYGOBJECT_IS_FLOATING_REF = 1 << 1, + PYGOBJECT_GOBJECT_WAS_FLOATING = 1 << 2, } PyGObjectFlags; /* closures is just an alias for what is found in the @@ -187,8 +188,9 @@ struct _PyGObject_Functions { gpointer data); gboolean (*gerror_exception_check) (GError **error); PyObject* (*option_group_new) (GOptionGroup *group); - GType (* type_from_object_strict) (PyObject *obj, gboolean strict); - PyObject *(* newgobj_full)(GObject *obj, gboolean sink, gpointer g_class); + GType (* type_from_object_strict) (PyObject *obj, gboolean strict); + + PyObject *(* newgobj_full)(GObject *obj, gboolean steal, gpointer g_class); }; #ifndef _INSIDE_PYGOBJECT_ |