summaryrefslogtreecommitdiff
path: root/gi/_gobject
diff options
context:
space:
mode:
Diffstat (limited to 'gi/_gobject')
-rw-r--r--gi/_gobject/gobjectmodule.c10
-rw-r--r--gi/_gobject/pygobject-private.h2
-rw-r--r--gi/_gobject/pygobject.c62
-rw-r--r--gi/_gobject/pygobject.h8
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_