[pygobject] Special case signal output arguments which are structs as pass-by-reference
- From: Simon Feltman <sfeltman src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Special case signal output arguments which are structs as pass-by-reference
- Date: Fri, 29 Aug 2014 21:41:40 +0000 (UTC)
commit 28d0337f0e3d4b0e9c4350ce5d6cf0cb68da843f
Author: Simon Feltman <sfeltman src gnome org>
Date: Fri Aug 29 14:18:28 2014 -0700
Special case signal output arguments which are structs as pass-by-reference
Add a special case which avoids copying of struct arguments marked as output
to signals. Since we don't currently support output arguments, users have
come to rely on a pass-by-reference bug which was fixed and caused this to
regress (bug 722899). Add unittest which is currently failing due to a number
of issues with emit() not supporting type annotations or output arguments
(bug 735693).
https://bugzilla.gnome.org/show_bug.cgi?id=735486
gi/pygi-signal-closure.c | 41 +++++++++++++++++++++++++++++++++++------
tests/test_overrides_gtk.py | 24 ++++++++++++++++++++++++
2 files changed, 59 insertions(+), 6 deletions(-)
---
diff --git a/gi/pygi-signal-closure.c b/gi/pygi-signal-closure.c
index 0c6b9b9..3cf8486 100644
--- a/gi/pygi-signal-closure.c
+++ b/gi/pygi-signal-closure.c
@@ -109,16 +109,19 @@ pygi_signal_closure_marshal(GClosure *closure,
} else if (i < sig_info_highest_arg) {
GIArgInfo arg_info;
GITypeInfo type_info;
+ GITypeTag type_tag;
GIArgument arg = { 0, };
PyObject *item = NULL;
gboolean free_array = FALSE;
+ gboolean pass_struct_by_ref = FALSE;
g_callable_info_load_arg(signal_info, i - 1, &arg_info);
g_arg_info_load_type(&arg_info, &type_info);
arg = _pygi_argument_from_g_value(¶m_values[i], &type_info);
-
- if (g_type_info_get_tag (&type_info) == GI_TYPE_TAG_ARRAY) {
+
+ type_tag = g_type_info_get_tag (&type_info);
+ if (type_tag == GI_TYPE_TAG_ARRAY) {
/* Skip the self argument of param_values */
arg.v_pointer = _pygi_argument_to_array (&arg,
_pygi_argument_array_length_marshal,
@@ -127,13 +130,39 @@ pygi_signal_closure_marshal(GClosure *closure,
&type_info,
&free_array);
}
-
- item = _pygi_argument_to_object (&arg, &type_info, GI_TRANSFER_NOTHING);
-
+
+ /* Hack to ensure struct output args are passed-by-reference allowing
+ * callback implementors to modify the struct values. This is needed
+ * for keeping backwards compatibility and should be removed in future
+ * versions which support signal output arguments as return values.
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=735486
+ */
+ if (type_tag == GI_TYPE_TAG_INTERFACE &&
+ g_arg_info_get_direction (&arg_info) == GI_DIRECTION_OUT) {
+ GIBaseInfo *info = g_type_info_get_interface (&type_info);
+ GIInfoType info_type = g_base_info_get_type (info);
+
+ if (info_type == GI_INFO_TYPE_STRUCT) {
+ GType gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *) info);
+ if (g_type_is_a (gtype, G_TYPE_BOXED)) {
+ pass_struct_by_ref = TRUE;
+ }
+ }
+
+ g_base_info_unref (info);
+ }
+
+ if (pass_struct_by_ref) {
+ item = _pygi_argument_to_object (&arg, &type_info, GI_TRANSFER_EVERYTHING);
+ ((PyGBoxed *)item)->free_on_dealloc = FALSE;
+
+ } else {
+ item = _pygi_argument_to_object (&arg, &type_info, GI_TRANSFER_NOTHING);
+ }
+
if (free_array) {
g_array_free (arg.v_pointer, FALSE);
}
-
if (item == NULL) {
goto out;
diff --git a/tests/test_overrides_gtk.py b/tests/test_overrides_gtk.py
index ba90fc3..395b157 100644
--- a/tests/test_overrides_gtk.py
+++ b/tests/test_overrides_gtk.py
@@ -701,6 +701,30 @@ class TestSignals(unittest.TestCase):
self.assertIsInstance(win._alloc_value, Gdk.Rectangle)
self.assertTrue(win._alloc_error is None, win._alloc_error)
+ @unittest.expectedFailure # https://bugzilla.gnome.org/show_bug.cgi?id=735693
+ def test_overlay_child_position(self):
+ def get_child_position(overlay, widget, rect, user_data=None):
+ rect.x = 1
+ rect.y = 2
+ rect.width = 3
+ rect.height = 4
+ return True
+
+ overlay = Gtk.Overlay()
+ overlay.connect('get-child-position', get_child_position)
+
+ rect = Gdk.Rectangle()
+ rect.x = -1
+ rect.y = -1
+ rect.width = -1
+ rect.height = -1
+
+ overlay.emit('get-child-position', None, rect)
+ self.assertEqual(rect.x, 1)
+ self.assertEqual(rect.y, 2)
+ self.assertEqual(rect.width, 3)
+ self.assertEqual(rect.height, 4)
+
@unittest.skipUnless(Gtk, 'Gtk not available')
class TestBuilder(unittest.TestCase):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]