Coverage Report

Created: 2025-11-16 06:56

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