1 /* gbinding.c: Binding for object properties
2 *
3 * Copyright (C) 2010 Intel Corp.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 *
18 * Author: Emmanuele Bassi <ebassi@linux.intel.com>
19 */
20
21 /**
22 * SECTION:gbinding
23 * @Title: GBinding
24 * @Short_Description: Bind two object properties
25 *
26 * #GBinding is the representation of a binding between a property on a
27 * #GObject instance (or source) and another property on another #GObject
28 * instance (or target). Whenever the source property changes, the same
29 * value is applied to the target property; for instance, the following
30 * binding:
31 *
32 * |[<!-- language="C" -->
33 * g_object_bind_property (object1, "property-a",
34 * object2, "property-b",
35 * G_BINDING_DEFAULT);
36 * ]|
37 *
38 * will cause the property named "property-b" of @object2 to be updated
39 * every time g_object_set() or the specific accessor changes the value of
40 * the property "property-a" of @object1.
41 *
42 * It is possible to create a bidirectional binding between two properties
43 * of two #GObject instances, so that if either property changes, the
44 * other is updated as well, for instance:
45 *
46 * |[<!-- language="C" -->
47 * g_object_bind_property (object1, "property-a",
48 * object2, "property-b",
49 * G_BINDING_BIDIRECTIONAL);
50 * ]|
51 *
52 * will keep the two properties in sync.
53 *
54 * It is also possible to set a custom transformation function (in both
55 * directions, in case of a bidirectional binding) to apply a custom
56 * transformation from the source value to the target value before
57 * applying it; for instance, the following binding:
58 *
59 * |[<!-- language="C" -->
60 * g_object_bind_property_full (adjustment1, "value",
61 * adjustment2, "value",
62 * G_BINDING_BIDIRECTIONAL,
63 * celsius_to_fahrenheit,
64 * fahrenheit_to_celsius,
65 * NULL, NULL);
66 * ]|
67 *
68 * will keep the "value" property of the two adjustments in sync; the
69 * @celsius_to_fahrenheit function will be called whenever the "value"
70 * property of @adjustment1 changes and will transform the current value
71 * of the property before applying it to the "value" property of @adjustment2.
72 *
73 * Vice versa, the @fahrenheit_to_celsius function will be called whenever
74 * the "value" property of @adjustment2 changes, and will transform the
75 * current value of the property before applying it to the "value" property
76 * of @adjustment1.
77 *
78 * Note that #GBinding does not resolve cycles by itself; a cycle like
79 *
80 * |[
81 * object1:propertyA -> object2:propertyB
82 * object2:propertyB -> object3:propertyC
83 * object3:propertyC -> object1:propertyA
84 * ]|
85 *
86 * might lead to an infinite loop. The loop, in this particular case,
87 * can be avoided if the objects emit the #GObject::notify signal only
88 * if the value has effectively been changed. A binding is implemented
89 * using the #GObject::notify signal, so it is susceptible to all the
90 * various ways of blocking a signal emission, like g_signal_stop_emission()
91 * or g_signal_handler_block().
92 *
93 * A binding will be severed, and the resources it allocates freed, whenever
94 * either one of the #GObject instances it refers to are finalized, or when
95 * the #GBinding instance loses its last reference.
96 *
97 * Bindings for languages with garbage collection can use
98 * g_binding_unbind() to explicitly release a binding between the source
99 * and target properties, instead of relying on the last reference on the
100 * binding, source, and target instances to drop.
101 *
102 * #GBinding is available since GObject 2.26
103 */
104
105 #include "config.h"
106
107 #include <string.h>
108
109 #include "gbinding.h"
110 #include "genums.h"
111 #include "gmarshal.h"
112 #include "gobject.h"
113 #include "gsignal.h"
114 #include "gparamspecs.h"
115 #include "gvaluetypes.h"
116
117 #include "glibintl.h"
118
119
120 GType
g_binding_flags_get_type(void)121 g_binding_flags_get_type (void)
122 {
123 static gsize static_g_define_type_id = 0;
124
125 if (g_once_init_enter (&static_g_define_type_id))
126 {
127 static const GFlagsValue values[] = {
128 { G_BINDING_DEFAULT, "G_BINDING_DEFAULT", "default" },
129 { G_BINDING_BIDIRECTIONAL, "G_BINDING_BIDIRECTIONAL", "bidirectional" },
130 { G_BINDING_SYNC_CREATE, "G_BINDING_SYNC_CREATE", "sync-create" },
131 { G_BINDING_INVERT_BOOLEAN, "G_BINDING_INVERT_BOOLEAN", "invert-boolean" },
132 { 0, NULL, NULL }
133 };
134 GType g_define_type_id =
135 g_flags_register_static (g_intern_static_string ("GBindingFlags"), values);
136 g_once_init_leave (&static_g_define_type_id, g_define_type_id);
137 }
138
139 return static_g_define_type_id;
140 }
141
142 /* Reference counted helper struct that is passed to all callbacks to ensure
143 * that they never work with already freed objects without having to store
144 * strong references for them.
145 *
146 * Using strong references anywhere is not possible because of the API
147 * requirements of GBinding, specifically that the initial reference of the
148 * GBinding is owned by the source/target and the caller and can be released
149 * either by the source/target being finalized or calling g_binding_unbind().
150 *
151 * As such, the only strong reference has to be owned by both weak notifies of
152 * the source and target and the first to be called has to release it.
153 */
154 typedef struct {
155 GWeakRef binding;
156 GWeakRef source;
157 GWeakRef target;
158 gboolean binding_removed;
159 } BindingContext;
160
161 static BindingContext *
binding_context_ref(BindingContext * context)162 binding_context_ref (BindingContext *context)
163 {
164 return g_atomic_rc_box_acquire (context);
165 }
166
167 static void
binding_context_clear(BindingContext * context)168 binding_context_clear (BindingContext *context)
169 {
170 g_weak_ref_clear (&context->binding);
171 g_weak_ref_clear (&context->source);
172 g_weak_ref_clear (&context->target);
173 }
174
175 static void
binding_context_unref(BindingContext * context)176 binding_context_unref (BindingContext *context)
177 {
178 g_atomic_rc_box_release_full (context, (GDestroyNotify) binding_context_clear);
179 }
180
181 /* Reference counting for the transform functions to ensure that they're always
182 * valid while making use of them in the property notify callbacks.
183 *
184 * The transform functions are released when unbinding but unbinding can happen
185 * while the transform functions are currently in use inside the notify callbacks.
186 */
187 typedef struct {
188 GBindingTransformFunc transform_s2t;
189 GBindingTransformFunc transform_t2s;
190
191 gpointer transform_data;
192 GDestroyNotify destroy_notify;
193 } TransformFunc;
194
195 static TransformFunc *
transform_func_new(GBindingTransformFunc transform_s2t,GBindingTransformFunc transform_t2s,gpointer transform_data,GDestroyNotify destroy_notify)196 transform_func_new (GBindingTransformFunc transform_s2t,
197 GBindingTransformFunc transform_t2s,
198 gpointer transform_data,
199 GDestroyNotify destroy_notify)
200 {
201 TransformFunc *func = g_atomic_rc_box_new0 (TransformFunc);
202
203 func->transform_s2t = transform_s2t;
204 func->transform_t2s = transform_t2s;
205 func->transform_data = transform_data;
206 func->destroy_notify = destroy_notify;
207
208 return func;
209 }
210
211 static TransformFunc *
transform_func_ref(TransformFunc * func)212 transform_func_ref (TransformFunc *func)
213 {
214 return g_atomic_rc_box_acquire (func);
215 }
216
217 static void
transform_func_clear(TransformFunc * func)218 transform_func_clear (TransformFunc *func)
219 {
220 if (func->destroy_notify)
221 func->destroy_notify (func->transform_data);
222 }
223
224 static void
transform_func_unref(TransformFunc * func)225 transform_func_unref (TransformFunc *func)
226 {
227 g_atomic_rc_box_release_full (func, (GDestroyNotify) transform_func_clear);
228 }
229
230 #define G_BINDING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_BINDING, GBindingClass))
231 #define G_IS_BINDING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_BINDING))
232 #define G_BINDING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_BINDING, GBindingClass))
233
234 typedef struct _GBindingClass GBindingClass;
235
236 struct _GBinding
237 {
238 GObject parent_instance;
239
240 /* no reference is held on the objects, to avoid cycles */
241 BindingContext *context;
242
243 /* protects transform_func, source, target property notify and
244 * target_weak_notify_installed for unbinding */
245 GMutex unbind_lock;
246
247 /* transform functions, only NULL after unbinding */
248 TransformFunc *transform_func; /* LOCK: unbind_lock */
249
250 /* the property names are interned, so they should not be freed */
251 const gchar *source_property;
252 const gchar *target_property;
253
254 GParamSpec *source_pspec;
255 GParamSpec *target_pspec;
256
257 GBindingFlags flags;
258
259 guint source_notify; /* LOCK: unbind_lock */
260 guint target_notify; /* LOCK: unbind_lock */
261 gboolean target_weak_notify_installed; /* LOCK: unbind_lock */
262
263 /* a guard, to avoid loops */
264 guint is_frozen : 1;
265 };
266
267 struct _GBindingClass
268 {
269 GObjectClass parent_class;
270 };
271
272 enum
273 {
274 PROP_0,
275
276 PROP_SOURCE,
277 PROP_TARGET,
278 PROP_SOURCE_PROPERTY,
279 PROP_TARGET_PROPERTY,
280 PROP_FLAGS
281 };
282
283 static guint gobject_notify_signal_id;
284
285 G_DEFINE_TYPE (GBinding, g_binding, G_TYPE_OBJECT)
286
287 static void weak_unbind (gpointer user_data, GObject *where_the_object_was);
288
289 /* Must be called with the unbind lock held, context/binding != NULL and strong
290 * references to source/target or NULL.
291 * Return TRUE if the binding was actually removed and FALSE if it was already
292 * removed before. */
293 static gboolean
unbind_internal_locked(BindingContext * context,GBinding * binding,GObject * source,GObject * target)294 unbind_internal_locked (BindingContext *context, GBinding *binding, GObject *source, GObject *target)
295 {
296 gboolean binding_was_removed = FALSE;
297
298 g_assert (context != NULL);
299 g_assert (binding != NULL);
300
301 /* If the target went away we still have a strong reference to the source
302 * here and can clear it from the binding. Otherwise if the source went away
303 * we can clear the target from the binding. Finalizing an object clears its
304 * signal handlers and all weak references pointing to it before calling
305 * weak notify callbacks.
306 *
307 * If both still exist we clean up everything set up by the binding.
308 */
309 if (source)
310 {
311 /* We always add/remove the source property notify and the weak notify
312 * of the source at the same time, and should only ever do that once. */
313 if (binding->source_notify != 0)
314 {
315 g_signal_handler_disconnect (source, binding->source_notify);
316
317 g_object_weak_unref (source, weak_unbind, context);
318 binding_context_unref (context);
319
320 binding->source_notify = 0;
321 }
322 g_weak_ref_set (&context->source, NULL);
323 }
324
325 /* As above, but with the target. If source==target then no weak notify was
326 * installed for the target, which is why that is stored as a separate
327 * boolean inside the binding. */
328 if (target)
329 {
330 /* There might be a target property notify without a weak notify on the
331 * target or the other way around, so these have to be handled
332 * independently here unlike for the source. */
333 if (binding->target_notify != 0)
334 {
335 g_signal_handler_disconnect (target, binding->target_notify);
336
337 binding->target_notify = 0;
338 }
339 g_weak_ref_set (&context->target, NULL);
340
341 /* Remove the weak notify from the target, at most once */
342 if (binding->target_weak_notify_installed)
343 {
344 g_object_weak_unref (target, weak_unbind, context);
345 binding_context_unref (context);
346 binding->target_weak_notify_installed = FALSE;
347 }
348 }
349
350 /* Make sure to remove the binding only once and return to the caller that
351 * this was the call that actually removed it. */
352 if (!context->binding_removed)
353 {
354 context->binding_removed = TRUE;
355 binding_was_removed = TRUE;
356 }
357
358 return binding_was_removed;
359 }
360
361 /* the basic assumption is that if either the source or the target
362 * goes away then the binding does not exist any more and it should
363 * be reaped as well. Each weak notify owns a strong reference to the
364 * binding that should be dropped here. */
365 static void
weak_unbind(gpointer user_data,GObject * where_the_object_was)366 weak_unbind (gpointer user_data,
367 GObject *where_the_object_was)
368 {
369 BindingContext *context = user_data;
370 GBinding *binding;
371 GObject *source, *target;
372 gboolean binding_was_removed = FALSE;
373 TransformFunc *transform_func;
374
375 binding = g_weak_ref_get (&context->binding);
376 if (!binding)
377 {
378 /* The binding was already destroyed before so there's nothing to do */
379 binding_context_unref (context);
380 return;
381 }
382
383 g_mutex_lock (&binding->unbind_lock);
384
385 transform_func = g_steal_pointer (&binding->transform_func);
386
387 source = g_weak_ref_get (&context->source);
388 target = g_weak_ref_get (&context->target);
389
390 /* If this is called then either the source or target or both must be in the
391 * process of being disposed. If this happens as part of g_object_unref()
392 * then the weak references are actually cleared, otherwise if disposing
393 * happens as part of g_object_run_dispose() then they would still point to
394 * the disposed object.
395 *
396 * If the object this is being called for is either the source or the target
397 * and we actually got a strong reference to it nonetheless (see above),
398 * then signal handlers and weak notifies for it are already disconnected
399 * and they must not be disconnected a second time. Instead simply clear the
400 * weak reference and be done with it.
401 *
402 * See https://gitlab.gnome.org/GNOME/glib/-/issues/2266 */
403
404 if (source == where_the_object_was)
405 {
406 g_weak_ref_set (&context->source, NULL);
407 g_clear_object (&source);
408 }
409
410 if (target == where_the_object_was)
411 {
412 g_weak_ref_set (&context->target, NULL);
413 g_clear_object (&target);
414 }
415
416 binding_was_removed = unbind_internal_locked (context, binding, source, target);
417
418 g_mutex_unlock (&binding->unbind_lock);
419
420 /* Unref source, target and transform_func after the mutex is unlocked as it
421 * might release the last reference, which then accesses the mutex again */
422 g_clear_object (&target);
423 g_clear_object (&source);
424
425 g_clear_pointer (&transform_func, transform_func_unref);
426
427 /* This releases the strong reference we got from the weak ref above */
428 g_object_unref (binding);
429
430 /* This will take care of the binding itself. */
431 if (binding_was_removed)
432 g_object_unref (binding);
433
434 /* Each weak notify owns a reference to the binding context. */
435 binding_context_unref (context);
436 }
437
438 static gboolean
default_transform(GBinding * binding,const GValue * value_a,GValue * value_b,gpointer user_data G_GNUC_UNUSED)439 default_transform (GBinding *binding,
440 const GValue *value_a,
441 GValue *value_b,
442 gpointer user_data G_GNUC_UNUSED)
443 {
444 /* if it's not the same type, try to convert it using the GValue
445 * transformation API; otherwise just copy it
446 */
447 if (!g_type_is_a (G_VALUE_TYPE (value_a), G_VALUE_TYPE (value_b)))
448 {
449 /* are these two types compatible (can be directly copied)? */
450 if (g_value_type_compatible (G_VALUE_TYPE (value_a),
451 G_VALUE_TYPE (value_b)))
452 {
453 g_value_copy (value_a, value_b);
454 return TRUE;
455 }
456
457 if (g_value_type_transformable (G_VALUE_TYPE (value_a),
458 G_VALUE_TYPE (value_b)))
459 {
460 if (g_value_transform (value_a, value_b))
461 return TRUE;
462 }
463
464 g_warning ("%s: Unable to convert a value of type %s to a "
465 "value of type %s",
466 G_STRLOC,
467 g_type_name (G_VALUE_TYPE (value_a)),
468 g_type_name (G_VALUE_TYPE (value_b)));
469
470 return FALSE;
471 }
472
473 g_value_copy (value_a, value_b);
474 return TRUE;
475 }
476
477 static gboolean
default_invert_boolean_transform(GBinding * binding,const GValue * value_a,GValue * value_b,gpointer user_data G_GNUC_UNUSED)478 default_invert_boolean_transform (GBinding *binding,
479 const GValue *value_a,
480 GValue *value_b,
481 gpointer user_data G_GNUC_UNUSED)
482 {
483 gboolean value;
484
485 g_assert (G_VALUE_HOLDS_BOOLEAN (value_a));
486 g_assert (G_VALUE_HOLDS_BOOLEAN (value_b));
487
488 value = g_value_get_boolean (value_a);
489 value = !value;
490
491 g_value_set_boolean (value_b, value);
492
493 return TRUE;
494 }
495
496 static void
on_source_notify(GObject * source,GParamSpec * pspec,BindingContext * context)497 on_source_notify (GObject *source,
498 GParamSpec *pspec,
499 BindingContext *context)
500 {
501 GBinding *binding;
502 GObject *target;
503 TransformFunc *transform_func;
504 GValue from_value = G_VALUE_INIT;
505 GValue to_value = G_VALUE_INIT;
506 gboolean res;
507
508 binding = g_weak_ref_get (&context->binding);
509 if (!binding)
510 return;
511
512 if (binding->is_frozen)
513 {
514 g_object_unref (binding);
515 return;
516 }
517
518 target = g_weak_ref_get (&context->target);
519 if (!target)
520 {
521 g_object_unref (binding);
522 return;
523 }
524
525 /* Get the transform function safely */
526 g_mutex_lock (&binding->unbind_lock);
527 if (!binding->transform_func)
528 {
529 /* it was released already during unbinding, nothing to do here */
530 g_mutex_unlock (&binding->unbind_lock);
531 return;
532 }
533 transform_func = transform_func_ref (binding->transform_func);
534 g_mutex_unlock (&binding->unbind_lock);
535
536 g_value_init (&from_value, G_PARAM_SPEC_VALUE_TYPE (binding->source_pspec));
537 g_value_init (&to_value, G_PARAM_SPEC_VALUE_TYPE (binding->target_pspec));
538
539 g_object_get_property (source, binding->source_pspec->name, &from_value);
540
541 res = transform_func->transform_s2t (binding,
542 &from_value,
543 &to_value,
544 transform_func->transform_data);
545
546 transform_func_unref (transform_func);
547
548 if (res)
549 {
550 binding->is_frozen = TRUE;
551
552 g_param_value_validate (binding->target_pspec, &to_value);
553 g_object_set_property (target, binding->target_pspec->name, &to_value);
554
555 binding->is_frozen = FALSE;
556 }
557
558 g_value_unset (&from_value);
559 g_value_unset (&to_value);
560
561 g_object_unref (target);
562 g_object_unref (binding);
563 }
564
565 static void
on_target_notify(GObject * target,GParamSpec * pspec,BindingContext * context)566 on_target_notify (GObject *target,
567 GParamSpec *pspec,
568 BindingContext *context)
569 {
570 GBinding *binding;
571 GObject *source;
572 TransformFunc *transform_func;
573 GValue from_value = G_VALUE_INIT;
574 GValue to_value = G_VALUE_INIT;
575 gboolean res;
576
577 binding = g_weak_ref_get (&context->binding);
578 if (!binding)
579 return;
580
581 if (binding->is_frozen)
582 {
583 g_object_unref (binding);
584 return;
585 }
586
587 source = g_weak_ref_get (&context->source);
588 if (!source)
589 {
590 g_object_unref (binding);
591 return;
592 }
593
594 /* Get the transform function safely */
595 g_mutex_lock (&binding->unbind_lock);
596 if (!binding->transform_func)
597 {
598 /* it was released already during unbinding, nothing to do here */
599 g_mutex_unlock (&binding->unbind_lock);
600 return;
601 }
602 transform_func = transform_func_ref (binding->transform_func);
603 g_mutex_unlock (&binding->unbind_lock);
604
605 g_value_init (&from_value, G_PARAM_SPEC_VALUE_TYPE (binding->target_pspec));
606 g_value_init (&to_value, G_PARAM_SPEC_VALUE_TYPE (binding->source_pspec));
607
608 g_object_get_property (target, binding->target_pspec->name, &from_value);
609
610 res = transform_func->transform_t2s (binding,
611 &from_value,
612 &to_value,
613 transform_func->transform_data);
614 transform_func_unref (transform_func);
615
616 if (res)
617 {
618 binding->is_frozen = TRUE;
619
620 g_param_value_validate (binding->source_pspec, &to_value);
621 g_object_set_property (source, binding->source_pspec->name, &to_value);
622
623 binding->is_frozen = FALSE;
624 }
625
626 g_value_unset (&from_value);
627 g_value_unset (&to_value);
628
629 g_object_unref (source);
630 g_object_unref (binding);
631 }
632
633 static inline void
g_binding_unbind_internal(GBinding * binding,gboolean unref_binding)634 g_binding_unbind_internal (GBinding *binding,
635 gboolean unref_binding)
636 {
637 BindingContext *context = binding->context;
638 GObject *source, *target;
639 gboolean binding_was_removed = FALSE;
640 TransformFunc *transform_func;
641
642 g_mutex_lock (&binding->unbind_lock);
643
644 transform_func = g_steal_pointer (&binding->transform_func);
645
646 source = g_weak_ref_get (&context->source);
647 target = g_weak_ref_get (&context->target);
648
649 binding_was_removed = unbind_internal_locked (context, binding, source, target);
650
651 g_mutex_unlock (&binding->unbind_lock);
652
653 /* Unref source, target and transform_func after the mutex is unlocked as it
654 * might release the last reference, which then accesses the mutex again */
655 g_clear_object (&target);
656 g_clear_object (&source);
657
658 g_clear_pointer (&transform_func, transform_func_unref);
659
660 if (binding_was_removed && unref_binding)
661 g_object_unref (binding);
662 }
663
664 static void
g_binding_finalize(GObject * gobject)665 g_binding_finalize (GObject *gobject)
666 {
667 GBinding *binding = G_BINDING (gobject);
668
669 g_binding_unbind_internal (binding, FALSE);
670
671 binding_context_unref (binding->context);
672
673 g_mutex_clear (&binding->unbind_lock);
674
675 G_OBJECT_CLASS (g_binding_parent_class)->finalize (gobject);
676 }
677
678 /* @key must have already been validated with is_valid()
679 * Modifies @key in place. */
680 static void
canonicalize_key(gchar * key)681 canonicalize_key (gchar *key)
682 {
683 gchar *p;
684
685 for (p = key; *p != 0; p++)
686 {
687 gchar c = *p;
688
689 if (c == '_')
690 *p = '-';
691 }
692 }
693
694 /* @key must have already been validated with is_valid() */
695 static gboolean
is_canonical(const gchar * key)696 is_canonical (const gchar *key)
697 {
698 return (strchr (key, '_') == NULL);
699 }
700
701 static gboolean
is_valid_property_name(const gchar * key)702 is_valid_property_name (const gchar *key)
703 {
704 const gchar *p;
705
706 /* First character must be a letter. */
707 if ((key[0] < 'A' || key[0] > 'Z') &&
708 (key[0] < 'a' || key[0] > 'z'))
709 return FALSE;
710
711 for (p = key; *p != 0; p++)
712 {
713 const gchar c = *p;
714
715 if (c != '-' && c != '_' &&
716 (c < '0' || c > '9') &&
717 (c < 'A' || c > 'Z') &&
718 (c < 'a' || c > 'z'))
719 return FALSE;
720 }
721
722 return TRUE;
723 }
724
725 static void
g_binding_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * pspec)726 g_binding_set_property (GObject *gobject,
727 guint prop_id,
728 const GValue *value,
729 GParamSpec *pspec)
730 {
731 GBinding *binding = G_BINDING (gobject);
732
733 switch (prop_id)
734 {
735 case PROP_SOURCE:
736 g_weak_ref_set (&binding->context->source, g_value_get_object (value));
737 break;
738
739 case PROP_TARGET:
740 g_weak_ref_set (&binding->context->target, g_value_get_object (value));
741 break;
742
743 case PROP_SOURCE_PROPERTY:
744 case PROP_TARGET_PROPERTY:
745 {
746 gchar *name_copy = NULL;
747 const gchar *name = g_value_get_string (value);
748 const gchar **dest;
749
750 /* Ensure the name we intern is canonical. */
751 if (!is_canonical (name))
752 {
753 name_copy = g_value_dup_string (value);
754 canonicalize_key (name_copy);
755 name = name_copy;
756 }
757
758 if (prop_id == PROP_SOURCE_PROPERTY)
759 dest = &binding->source_property;
760 else
761 dest = &binding->target_property;
762
763 *dest = g_intern_string (name);
764
765 g_free (name_copy);
766 break;
767 }
768
769 case PROP_FLAGS:
770 binding->flags = g_value_get_flags (value);
771 break;
772
773 default:
774 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
775 break;
776 }
777 }
778
779 static void
g_binding_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * pspec)780 g_binding_get_property (GObject *gobject,
781 guint prop_id,
782 GValue *value,
783 GParamSpec *pspec)
784 {
785 GBinding *binding = G_BINDING (gobject);
786
787 switch (prop_id)
788 {
789 case PROP_SOURCE:
790 g_value_take_object (value, g_weak_ref_get (&binding->context->source));
791 break;
792
793 case PROP_SOURCE_PROPERTY:
794 /* @source_property is interned, so we don’t need to take a copy */
795 g_value_set_interned_string (value, binding->source_property);
796 break;
797
798 case PROP_TARGET:
799 g_value_take_object (value, g_weak_ref_get (&binding->context->target));
800 break;
801
802 case PROP_TARGET_PROPERTY:
803 /* @target_property is interned, so we don’t need to take a copy */
804 g_value_set_interned_string (value, binding->target_property);
805 break;
806
807 case PROP_FLAGS:
808 g_value_set_flags (value, binding->flags);
809 break;
810
811 default:
812 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
813 break;
814 }
815 }
816
817 static void
g_binding_constructed(GObject * gobject)818 g_binding_constructed (GObject *gobject)
819 {
820 GBinding *binding = G_BINDING (gobject);
821 GBindingTransformFunc transform_func = default_transform;
822 GObject *source, *target;
823 GQuark source_property_detail;
824 GClosure *source_notify_closure;
825
826 /* assert that we were constructed correctly */
827 source = g_weak_ref_get (&binding->context->source);
828 target = g_weak_ref_get (&binding->context->target);
829 g_assert (source != NULL);
830 g_assert (target != NULL);
831 g_assert (binding->source_property != NULL);
832 g_assert (binding->target_property != NULL);
833
834 /* we assume a check was performed prior to construction - since
835 * g_object_bind_property_full() does it; we cannot fail construction
836 * anyway, so it would be hard for use to properly warn here
837 */
838 binding->source_pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (source), binding->source_property);
839 binding->target_pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (target), binding->target_property);
840 g_assert (binding->source_pspec != NULL);
841 g_assert (binding->target_pspec != NULL);
842
843 /* switch to the invert boolean transform if needed */
844 if (binding->flags & G_BINDING_INVERT_BOOLEAN)
845 transform_func = default_invert_boolean_transform;
846
847 /* set the default transformation functions here */
848 binding->transform_func = transform_func_new (transform_func, transform_func, NULL, NULL);
849
850 source_property_detail = g_quark_from_string (binding->source_property);
851 source_notify_closure = g_cclosure_new (G_CALLBACK (on_source_notify),
852 binding_context_ref (binding->context),
853 (GClosureNotify) binding_context_unref);
854 binding->source_notify = g_signal_connect_closure_by_id (source,
855 gobject_notify_signal_id,
856 source_property_detail,
857 source_notify_closure,
858 FALSE);
859
860 g_object_weak_ref (source, weak_unbind, binding_context_ref (binding->context));
861
862 if (binding->flags & G_BINDING_BIDIRECTIONAL)
863 {
864 GQuark target_property_detail;
865 GClosure *target_notify_closure;
866
867 target_property_detail = g_quark_from_string (binding->target_property);
868 target_notify_closure = g_cclosure_new (G_CALLBACK (on_target_notify),
869 binding_context_ref (binding->context),
870 (GClosureNotify) binding_context_unref);
871 binding->target_notify = g_signal_connect_closure_by_id (target,
872 gobject_notify_signal_id,
873 target_property_detail,
874 target_notify_closure,
875 FALSE);
876 }
877
878 if (target != source)
879 {
880 g_object_weak_ref (target, weak_unbind, binding_context_ref (binding->context));
881
882 /* Need to remember separately if a target weak notify was installed as
883 * unlike for the source it can exist independently of the property
884 * notification callback */
885 binding->target_weak_notify_installed = TRUE;
886 }
887
888 g_object_unref (source);
889 g_object_unref (target);
890 }
891
892 static void
g_binding_class_init(GBindingClass * klass)893 g_binding_class_init (GBindingClass *klass)
894 {
895 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
896
897 gobject_notify_signal_id = g_signal_lookup ("notify", G_TYPE_OBJECT);
898 g_assert (gobject_notify_signal_id != 0);
899
900 gobject_class->constructed = g_binding_constructed;
901 gobject_class->set_property = g_binding_set_property;
902 gobject_class->get_property = g_binding_get_property;
903 gobject_class->finalize = g_binding_finalize;
904
905 /**
906 * GBinding:source:
907 *
908 * The #GObject that should be used as the source of the binding
909 *
910 * Since: 2.26
911 */
912 g_object_class_install_property (gobject_class, PROP_SOURCE,
913 g_param_spec_object ("source",
914 P_("Source"),
915 P_("The source of the binding"),
916 G_TYPE_OBJECT,
917 G_PARAM_CONSTRUCT_ONLY |
918 G_PARAM_READWRITE |
919 G_PARAM_STATIC_STRINGS));
920 /**
921 * GBinding:target:
922 *
923 * The #GObject that should be used as the target of the binding
924 *
925 * Since: 2.26
926 */
927 g_object_class_install_property (gobject_class, PROP_TARGET,
928 g_param_spec_object ("target",
929 P_("Target"),
930 P_("The target of the binding"),
931 G_TYPE_OBJECT,
932 G_PARAM_CONSTRUCT_ONLY |
933 G_PARAM_READWRITE |
934 G_PARAM_STATIC_STRINGS));
935 /**
936 * GBinding:source-property:
937 *
938 * The name of the property of #GBinding:source that should be used
939 * as the source of the binding.
940 *
941 * This should be in [canonical form][canonical-parameter-names] to get the
942 * best performance.
943 *
944 * Since: 2.26
945 */
946 g_object_class_install_property (gobject_class, PROP_SOURCE_PROPERTY,
947 g_param_spec_string ("source-property",
948 P_("Source Property"),
949 P_("The property on the source to bind"),
950 NULL,
951 G_PARAM_CONSTRUCT_ONLY |
952 G_PARAM_READWRITE |
953 G_PARAM_STATIC_STRINGS));
954 /**
955 * GBinding:target-property:
956 *
957 * The name of the property of #GBinding:target that should be used
958 * as the target of the binding.
959 *
960 * This should be in [canonical form][canonical-parameter-names] to get the
961 * best performance.
962 *
963 * Since: 2.26
964 */
965 g_object_class_install_property (gobject_class, PROP_TARGET_PROPERTY,
966 g_param_spec_string ("target-property",
967 P_("Target Property"),
968 P_("The property on the target to bind"),
969 NULL,
970 G_PARAM_CONSTRUCT_ONLY |
971 G_PARAM_READWRITE |
972 G_PARAM_STATIC_STRINGS));
973 /**
974 * GBinding:flags:
975 *
976 * Flags to be used to control the #GBinding
977 *
978 * Since: 2.26
979 */
980 g_object_class_install_property (gobject_class, PROP_FLAGS,
981 g_param_spec_flags ("flags",
982 P_("Flags"),
983 P_("The binding flags"),
984 G_TYPE_BINDING_FLAGS,
985 G_BINDING_DEFAULT,
986 G_PARAM_CONSTRUCT_ONLY |
987 G_PARAM_READWRITE |
988 G_PARAM_STATIC_STRINGS));
989 }
990
991 static void
g_binding_init(GBinding * binding)992 g_binding_init (GBinding *binding)
993 {
994 g_mutex_init (&binding->unbind_lock);
995
996 binding->context = g_atomic_rc_box_new0 (BindingContext);
997 g_weak_ref_init (&binding->context->binding, binding);
998 g_weak_ref_init (&binding->context->source, NULL);
999 g_weak_ref_init (&binding->context->target, NULL);
1000 }
1001
1002 /**
1003 * g_binding_get_flags:
1004 * @binding: a #GBinding
1005 *
1006 * Retrieves the flags passed when constructing the #GBinding.
1007 *
1008 * Returns: the #GBindingFlags used by the #GBinding
1009 *
1010 * Since: 2.26
1011 */
1012 GBindingFlags
g_binding_get_flags(GBinding * binding)1013 g_binding_get_flags (GBinding *binding)
1014 {
1015 g_return_val_if_fail (G_IS_BINDING (binding), G_BINDING_DEFAULT);
1016
1017 return binding->flags;
1018 }
1019
1020 /**
1021 * g_binding_get_source:
1022 * @binding: a #GBinding
1023 *
1024 * Retrieves the #GObject instance used as the source of the binding.
1025 *
1026 * A #GBinding can outlive the source #GObject as the binding does not hold a
1027 * strong reference to the source. If the source is destroyed before the
1028 * binding then this function will return %NULL.
1029 *
1030 * Use g_binding_dup_source() if the source or binding are used from different
1031 * threads as otherwise the pointer returned from this function might become
1032 * invalid if the source is finalized from another thread in the meantime.
1033 *
1034 * Returns: (transfer none) (nullable): the source #GObject, or %NULL if the
1035 * source does not exist any more.
1036 *
1037 * Deprecated: 2.68: Use g_binding_dup_source() for a safer version of this
1038 * function.
1039 *
1040 * Since: 2.26
1041 */
1042 GObject *
g_binding_get_source(GBinding * binding)1043 g_binding_get_source (GBinding *binding)
1044 {
1045 GObject *source;
1046
1047 g_return_val_if_fail (G_IS_BINDING (binding), NULL);
1048
1049 source = g_weak_ref_get (&binding->context->source);
1050 /* Unref here, this API is not thread-safe
1051 * FIXME: Remove this API when we next break API */
1052 if (source)
1053 g_object_unref (source);
1054
1055 return source;
1056 }
1057
1058 /**
1059 * g_binding_dup_source:
1060 * @binding: a #GBinding
1061 *
1062 * Retrieves the #GObject instance used as the source of the binding.
1063 *
1064 * A #GBinding can outlive the source #GObject as the binding does not hold a
1065 * strong reference to the source. If the source is destroyed before the
1066 * binding then this function will return %NULL.
1067 *
1068 * Returns: (transfer full) (nullable): the source #GObject, or %NULL if the
1069 * source does not exist any more.
1070 *
1071 * Since: 2.68
1072 */
1073 GObject *
g_binding_dup_source(GBinding * binding)1074 g_binding_dup_source (GBinding *binding)
1075 {
1076 g_return_val_if_fail (G_IS_BINDING (binding), NULL);
1077
1078 return g_weak_ref_get (&binding->context->source);
1079 }
1080
1081 /**
1082 * g_binding_get_target:
1083 * @binding: a #GBinding
1084 *
1085 * Retrieves the #GObject instance used as the target of the binding.
1086 *
1087 * A #GBinding can outlive the target #GObject as the binding does not hold a
1088 * strong reference to the target. If the target is destroyed before the
1089 * binding then this function will return %NULL.
1090 *
1091 * Use g_binding_dup_target() if the target or binding are used from different
1092 * threads as otherwise the pointer returned from this function might become
1093 * invalid if the target is finalized from another thread in the meantime.
1094 *
1095 * Returns: (transfer none) (nullable): the target #GObject, or %NULL if the
1096 * target does not exist any more.
1097 *
1098 * Deprecated: 2.68: Use g_binding_dup_target() for a safer version of this
1099 * function.
1100 *
1101 * Since: 2.26
1102 */
1103 GObject *
g_binding_get_target(GBinding * binding)1104 g_binding_get_target (GBinding *binding)
1105 {
1106 GObject *target;
1107
1108 g_return_val_if_fail (G_IS_BINDING (binding), NULL);
1109
1110 target = g_weak_ref_get (&binding->context->target);
1111 /* Unref here, this API is not thread-safe
1112 * FIXME: Remove this API when we next break API */
1113 if (target)
1114 g_object_unref (target);
1115
1116 return target;
1117 }
1118
1119 /**
1120 * g_binding_dup_target:
1121 * @binding: a #GBinding
1122 *
1123 * Retrieves the #GObject instance used as the target of the binding.
1124 *
1125 * A #GBinding can outlive the target #GObject as the binding does not hold a
1126 * strong reference to the target. If the target is destroyed before the
1127 * binding then this function will return %NULL.
1128 *
1129 * Returns: (transfer full) (nullable): the target #GObject, or %NULL if the
1130 * target does not exist any more.
1131 *
1132 * Since: 2.68
1133 */
1134 GObject *
g_binding_dup_target(GBinding * binding)1135 g_binding_dup_target (GBinding *binding)
1136 {
1137 g_return_val_if_fail (G_IS_BINDING (binding), NULL);
1138
1139 return g_weak_ref_get (&binding->context->target);
1140 }
1141
1142 /**
1143 * g_binding_get_source_property:
1144 * @binding: a #GBinding
1145 *
1146 * Retrieves the name of the property of #GBinding:source used as the source
1147 * of the binding.
1148 *
1149 * Returns: the name of the source property
1150 *
1151 * Since: 2.26
1152 */
1153 const gchar *
g_binding_get_source_property(GBinding * binding)1154 g_binding_get_source_property (GBinding *binding)
1155 {
1156 g_return_val_if_fail (G_IS_BINDING (binding), NULL);
1157
1158 return binding->source_property;
1159 }
1160
1161 /**
1162 * g_binding_get_target_property:
1163 * @binding: a #GBinding
1164 *
1165 * Retrieves the name of the property of #GBinding:target used as the target
1166 * of the binding.
1167 *
1168 * Returns: the name of the target property
1169 *
1170 * Since: 2.26
1171 */
1172 const gchar *
g_binding_get_target_property(GBinding * binding)1173 g_binding_get_target_property (GBinding *binding)
1174 {
1175 g_return_val_if_fail (G_IS_BINDING (binding), NULL);
1176
1177 return binding->target_property;
1178 }
1179
1180 /**
1181 * g_binding_unbind:
1182 * @binding: a #GBinding
1183 *
1184 * Explicitly releases the binding between the source and the target
1185 * property expressed by @binding.
1186 *
1187 * This function will release the reference that is being held on
1188 * the @binding instance if the binding is still bound; if you want to hold on
1189 * to the #GBinding instance after calling g_binding_unbind(), you will need
1190 * to hold a reference to it.
1191 *
1192 * Note however that this function does not take ownership of @binding, it
1193 * only unrefs the reference that was initially created by
1194 * g_object_bind_property() and is owned by the binding.
1195 *
1196 * Since: 2.38
1197 */
1198 void
g_binding_unbind(GBinding * binding)1199 g_binding_unbind (GBinding *binding)
1200 {
1201 g_return_if_fail (G_IS_BINDING (binding));
1202
1203 g_binding_unbind_internal (binding, TRUE);
1204 }
1205
1206 /**
1207 * g_object_bind_property_full:
1208 * @source: (type GObject.Object): the source #GObject
1209 * @source_property: the property on @source to bind
1210 * @target: (type GObject.Object): the target #GObject
1211 * @target_property: the property on @target to bind
1212 * @flags: flags to pass to #GBinding
1213 * @transform_to: (scope notified) (nullable): the transformation function
1214 * from the @source to the @target, or %NULL to use the default
1215 * @transform_from: (scope notified) (nullable): the transformation function
1216 * from the @target to the @source, or %NULL to use the default
1217 * @user_data: custom data to be passed to the transformation functions,
1218 * or %NULL
1219 * @notify: (nullable): a function to call when disposing the binding, to free
1220 * resources used by the transformation functions, or %NULL if not required
1221 *
1222 * Complete version of g_object_bind_property().
1223 *
1224 * Creates a binding between @source_property on @source and @target_property
1225 * on @target, allowing you to set the transformation functions to be used by
1226 * the binding.
1227 *
1228 * If @flags contains %G_BINDING_BIDIRECTIONAL then the binding will be mutual:
1229 * if @target_property on @target changes then the @source_property on @source
1230 * will be updated as well. The @transform_from function is only used in case
1231 * of bidirectional bindings, otherwise it will be ignored
1232 *
1233 * The binding will automatically be removed when either the @source or the
1234 * @target instances are finalized. This will release the reference that is
1235 * being held on the #GBinding instance; if you want to hold on to the
1236 * #GBinding instance, you will need to hold a reference to it.
1237 *
1238 * To remove the binding, call g_binding_unbind().
1239 *
1240 * A #GObject can have multiple bindings.
1241 *
1242 * The same @user_data parameter will be used for both @transform_to
1243 * and @transform_from transformation functions; the @notify function will
1244 * be called once, when the binding is removed. If you need different data
1245 * for each transformation function, please use
1246 * g_object_bind_property_with_closures() instead.
1247 *
1248 * Returns: (transfer none): the #GBinding instance representing the
1249 * binding between the two #GObject instances. The binding is released
1250 * whenever the #GBinding reference count reaches zero.
1251 *
1252 * Since: 2.26
1253 */
1254 GBinding *
g_object_bind_property_full(gpointer source,const gchar * source_property,gpointer target,const gchar * target_property,GBindingFlags flags,GBindingTransformFunc transform_to,GBindingTransformFunc transform_from,gpointer user_data,GDestroyNotify notify)1255 g_object_bind_property_full (gpointer source,
1256 const gchar *source_property,
1257 gpointer target,
1258 const gchar *target_property,
1259 GBindingFlags flags,
1260 GBindingTransformFunc transform_to,
1261 GBindingTransformFunc transform_from,
1262 gpointer user_data,
1263 GDestroyNotify notify)
1264 {
1265 GParamSpec *pspec;
1266 GBinding *binding;
1267
1268 g_return_val_if_fail (G_IS_OBJECT (source), NULL);
1269 g_return_val_if_fail (source_property != NULL, NULL);
1270 g_return_val_if_fail (is_valid_property_name (source_property), NULL);
1271 g_return_val_if_fail (G_IS_OBJECT (target), NULL);
1272 g_return_val_if_fail (target_property != NULL, NULL);
1273 g_return_val_if_fail (is_valid_property_name (target_property), NULL);
1274
1275 if (source == target && g_strcmp0 (source_property, target_property) == 0)
1276 {
1277 g_warning ("Unable to bind the same property on the same instance");
1278 return NULL;
1279 }
1280
1281 /* remove the G_BINDING_INVERT_BOOLEAN flag in case we have
1282 * custom transformation functions
1283 */
1284 if ((flags & G_BINDING_INVERT_BOOLEAN) &&
1285 (transform_to != NULL || transform_from != NULL))
1286 {
1287 flags &= ~G_BINDING_INVERT_BOOLEAN;
1288 }
1289
1290 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (source), source_property);
1291 if (pspec == NULL)
1292 {
1293 g_warning ("%s: The source object of type %s has no property called '%s'",
1294 G_STRLOC,
1295 G_OBJECT_TYPE_NAME (source),
1296 source_property);
1297 return NULL;
1298 }
1299
1300 if (!(pspec->flags & G_PARAM_READABLE))
1301 {
1302 g_warning ("%s: The source object of type %s has no readable property called '%s'",
1303 G_STRLOC,
1304 G_OBJECT_TYPE_NAME (source),
1305 source_property);
1306 return NULL;
1307 }
1308
1309 if ((flags & G_BINDING_BIDIRECTIONAL) &&
1310 ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) || !(pspec->flags & G_PARAM_WRITABLE)))
1311 {
1312 g_warning ("%s: The source object of type %s has no writable property called '%s'",
1313 G_STRLOC,
1314 G_OBJECT_TYPE_NAME (source),
1315 source_property);
1316 return NULL;
1317 }
1318
1319 if ((flags & G_BINDING_INVERT_BOOLEAN) &&
1320 !(G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_BOOLEAN))
1321 {
1322 g_warning ("%s: The G_BINDING_INVERT_BOOLEAN flag can only be used "
1323 "when binding boolean properties; the source property '%s' "
1324 "is of type '%s'",
1325 G_STRLOC,
1326 source_property,
1327 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
1328 return NULL;
1329 }
1330
1331 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (target), target_property);
1332 if (pspec == NULL)
1333 {
1334 g_warning ("%s: The target object of type %s has no property called '%s'",
1335 G_STRLOC,
1336 G_OBJECT_TYPE_NAME (target),
1337 target_property);
1338 return NULL;
1339 }
1340
1341 if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) || !(pspec->flags & G_PARAM_WRITABLE))
1342 {
1343 g_warning ("%s: The target object of type %s has no writable property called '%s'",
1344 G_STRLOC,
1345 G_OBJECT_TYPE_NAME (target),
1346 target_property);
1347 return NULL;
1348 }
1349
1350 if ((flags & G_BINDING_BIDIRECTIONAL) &&
1351 !(pspec->flags & G_PARAM_READABLE))
1352 {
1353 g_warning ("%s: The target object of type %s has no readable property called '%s'",
1354 G_STRLOC,
1355 G_OBJECT_TYPE_NAME (target),
1356 target_property);
1357 return NULL;
1358 }
1359
1360 if ((flags & G_BINDING_INVERT_BOOLEAN) &&
1361 !(G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_BOOLEAN))
1362 {
1363 g_warning ("%s: The G_BINDING_INVERT_BOOLEAN flag can only be used "
1364 "when binding boolean properties; the target property '%s' "
1365 "is of type '%s'",
1366 G_STRLOC,
1367 target_property,
1368 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
1369 return NULL;
1370 }
1371
1372 binding = g_object_new (G_TYPE_BINDING,
1373 "source", source,
1374 "source-property", source_property,
1375 "target", target,
1376 "target-property", target_property,
1377 "flags", flags,
1378 NULL);
1379
1380 g_assert (binding->transform_func != NULL);
1381
1382 /* Use default functions if not provided here */
1383 if (transform_to == NULL)
1384 transform_to = binding->transform_func->transform_s2t;
1385
1386 if (transform_from == NULL)
1387 transform_from = binding->transform_func->transform_t2s;
1388
1389 g_clear_pointer (&binding->transform_func, transform_func_unref);
1390 binding->transform_func = transform_func_new (transform_to, transform_from, user_data, notify);
1391
1392 /* synchronize the target with the source by faking an emission of
1393 * the ::notify signal for the source property; this will also take
1394 * care of the bidirectional binding case because the eventual change
1395 * will emit a notification on the target
1396 */
1397 if (flags & G_BINDING_SYNC_CREATE)
1398 on_source_notify (source, binding->source_pspec, binding->context);
1399
1400 return binding;
1401 }
1402
1403 /**
1404 * g_object_bind_property:
1405 * @source: (type GObject.Object): the source #GObject
1406 * @source_property: the property on @source to bind
1407 * @target: (type GObject.Object): the target #GObject
1408 * @target_property: the property on @target to bind
1409 * @flags: flags to pass to #GBinding
1410 *
1411 * Creates a binding between @source_property on @source and @target_property
1412 * on @target. Whenever the @source_property is changed the @target_property is
1413 * updated using the same value. For instance:
1414 *
1415 * |[
1416 * g_object_bind_property (action, "active", widget, "sensitive", 0);
1417 * ]|
1418 *
1419 * Will result in the "sensitive" property of the widget #GObject instance to be
1420 * updated with the same value of the "active" property of the action #GObject
1421 * instance.
1422 *
1423 * If @flags contains %G_BINDING_BIDIRECTIONAL then the binding will be mutual:
1424 * if @target_property on @target changes then the @source_property on @source
1425 * will be updated as well.
1426 *
1427 * The binding will automatically be removed when either the @source or the
1428 * @target instances are finalized. To remove the binding without affecting the
1429 * @source and the @target you can just call g_object_unref() on the returned
1430 * #GBinding instance.
1431 *
1432 * Removing the binding by calling g_object_unref() on it must only be done if
1433 * the binding, @source and @target are only used from a single thread and it
1434 * is clear that both @source and @target outlive the binding. Especially it
1435 * is not safe to rely on this if the binding, @source or @target can be
1436 * finalized from different threads. Keep another reference to the binding and
1437 * use g_binding_unbind() instead to be on the safe side.
1438 *
1439 * A #GObject can have multiple bindings.
1440 *
1441 * Returns: (transfer none): the #GBinding instance representing the
1442 * binding between the two #GObject instances. The binding is released
1443 * whenever the #GBinding reference count reaches zero.
1444 *
1445 * Since: 2.26
1446 */
1447 GBinding *
g_object_bind_property(gpointer source,const gchar * source_property,gpointer target,const gchar * target_property,GBindingFlags flags)1448 g_object_bind_property (gpointer source,
1449 const gchar *source_property,
1450 gpointer target,
1451 const gchar *target_property,
1452 GBindingFlags flags)
1453 {
1454 /* type checking is done in g_object_bind_property_full() */
1455
1456 return g_object_bind_property_full (source, source_property,
1457 target, target_property,
1458 flags,
1459 NULL,
1460 NULL,
1461 NULL, NULL);
1462 }
1463
1464 typedef struct _TransformData
1465 {
1466 GClosure *transform_to_closure;
1467 GClosure *transform_from_closure;
1468 } TransformData;
1469
1470 static gboolean
bind_with_closures_transform_to(GBinding * binding,const GValue * source,GValue * target,gpointer data)1471 bind_with_closures_transform_to (GBinding *binding,
1472 const GValue *source,
1473 GValue *target,
1474 gpointer data)
1475 {
1476 TransformData *t_data = data;
1477 GValue params[3] = { G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT };
1478 GValue retval = G_VALUE_INIT;
1479 gboolean res;
1480
1481 g_value_init (¶ms[0], G_TYPE_BINDING);
1482 g_value_set_object (¶ms[0], binding);
1483
1484 g_value_init (¶ms[1], G_TYPE_VALUE);
1485 g_value_set_boxed (¶ms[1], source);
1486
1487 g_value_init (¶ms[2], G_TYPE_VALUE);
1488 g_value_set_boxed (¶ms[2], target);
1489
1490 g_value_init (&retval, G_TYPE_BOOLEAN);
1491 g_value_set_boolean (&retval, FALSE);
1492
1493 g_closure_invoke (t_data->transform_to_closure, &retval, 3, params, NULL);
1494
1495 res = g_value_get_boolean (&retval);
1496 if (res)
1497 {
1498 const GValue *out_value = g_value_get_boxed (¶ms[2]);
1499
1500 g_assert (out_value != NULL);
1501
1502 g_value_copy (out_value, target);
1503 }
1504
1505 g_value_unset (¶ms[0]);
1506 g_value_unset (¶ms[1]);
1507 g_value_unset (¶ms[2]);
1508 g_value_unset (&retval);
1509
1510 return res;
1511 }
1512
1513 static gboolean
bind_with_closures_transform_from(GBinding * binding,const GValue * source,GValue * target,gpointer data)1514 bind_with_closures_transform_from (GBinding *binding,
1515 const GValue *source,
1516 GValue *target,
1517 gpointer data)
1518 {
1519 TransformData *t_data = data;
1520 GValue params[3] = { G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT };
1521 GValue retval = G_VALUE_INIT;
1522 gboolean res;
1523
1524 g_value_init (¶ms[0], G_TYPE_BINDING);
1525 g_value_set_object (¶ms[0], binding);
1526
1527 g_value_init (¶ms[1], G_TYPE_VALUE);
1528 g_value_set_boxed (¶ms[1], source);
1529
1530 g_value_init (¶ms[2], G_TYPE_VALUE);
1531 g_value_set_boxed (¶ms[2], target);
1532
1533 g_value_init (&retval, G_TYPE_BOOLEAN);
1534 g_value_set_boolean (&retval, FALSE);
1535
1536 g_closure_invoke (t_data->transform_from_closure, &retval, 3, params, NULL);
1537
1538 res = g_value_get_boolean (&retval);
1539 if (res)
1540 {
1541 const GValue *out_value = g_value_get_boxed (¶ms[2]);
1542
1543 g_assert (out_value != NULL);
1544
1545 g_value_copy (out_value, target);
1546 }
1547
1548 g_value_unset (¶ms[0]);
1549 g_value_unset (¶ms[1]);
1550 g_value_unset (¶ms[2]);
1551 g_value_unset (&retval);
1552
1553 return res;
1554 }
1555
1556 static void
bind_with_closures_free_func(gpointer data)1557 bind_with_closures_free_func (gpointer data)
1558 {
1559 TransformData *t_data = data;
1560
1561 if (t_data->transform_to_closure != NULL)
1562 g_closure_unref (t_data->transform_to_closure);
1563
1564 if (t_data->transform_from_closure != NULL)
1565 g_closure_unref (t_data->transform_from_closure);
1566
1567 g_slice_free (TransformData, t_data);
1568 }
1569
1570 /**
1571 * g_object_bind_property_with_closures: (rename-to g_object_bind_property_full)
1572 * @source: (type GObject.Object): the source #GObject
1573 * @source_property: the property on @source to bind
1574 * @target: (type GObject.Object): the target #GObject
1575 * @target_property: the property on @target to bind
1576 * @flags: flags to pass to #GBinding
1577 * @transform_to: a #GClosure wrapping the transformation function
1578 * from the @source to the @target, or %NULL to use the default
1579 * @transform_from: a #GClosure wrapping the transformation function
1580 * from the @target to the @source, or %NULL to use the default
1581 *
1582 * Creates a binding between @source_property on @source and @target_property
1583 * on @target, allowing you to set the transformation functions to be used by
1584 * the binding.
1585 *
1586 * This function is the language bindings friendly version of
1587 * g_object_bind_property_full(), using #GClosures instead of
1588 * function pointers.
1589 *
1590 * Returns: (transfer none): the #GBinding instance representing the
1591 * binding between the two #GObject instances. The binding is released
1592 * whenever the #GBinding reference count reaches zero.
1593 *
1594 * Since: 2.26
1595 */
1596 GBinding *
g_object_bind_property_with_closures(gpointer source,const gchar * source_property,gpointer target,const gchar * target_property,GBindingFlags flags,GClosure * transform_to,GClosure * transform_from)1597 g_object_bind_property_with_closures (gpointer source,
1598 const gchar *source_property,
1599 gpointer target,
1600 const gchar *target_property,
1601 GBindingFlags flags,
1602 GClosure *transform_to,
1603 GClosure *transform_from)
1604 {
1605 TransformData *data;
1606
1607 data = g_slice_new0 (TransformData);
1608
1609 if (transform_to != NULL)
1610 {
1611 if (G_CLOSURE_NEEDS_MARSHAL (transform_to))
1612 g_closure_set_marshal (transform_to, g_cclosure_marshal_BOOLEAN__BOXED_BOXED);
1613
1614 data->transform_to_closure = g_closure_ref (transform_to);
1615 g_closure_sink (data->transform_to_closure);
1616 }
1617
1618 if (transform_from != NULL)
1619 {
1620 if (G_CLOSURE_NEEDS_MARSHAL (transform_from))
1621 g_closure_set_marshal (transform_from, g_cclosure_marshal_BOOLEAN__BOXED_BOXED);
1622
1623 data->transform_from_closure = g_closure_ref (transform_from);
1624 g_closure_sink (data->transform_from_closure);
1625 }
1626
1627 return g_object_bind_property_full (source, source_property,
1628 target, target_property,
1629 flags,
1630 transform_to != NULL ? bind_with_closures_transform_to : NULL,
1631 transform_from != NULL ? bind_with_closures_transform_from : NULL,
1632 data,
1633 bind_with_closures_free_func);
1634 }
1635