Fix make rpm errors due to ibus-dconf and pygobject override
[platform/upstream/ibus.git] / src / ibusconfig.c
1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 /* vim:set et sts=4: */
3 /* ibus - The Input Bus
4  * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
5  * Copyright (C) 2008-2010 Red Hat, Inc.
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 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 Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22 #include "ibusinternal.h"
23 #include "ibusmarshalers.h"
24 #include "ibusshare.h"
25 #include "ibusconfig.h"
26 #include "ibusbus.h"
27 #include "ibuserror.h"
28
29 #define IBUS_CONFIG_GET_PRIVATE(o)  \
30    (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_CONFIG, IBusConfigPrivate))
31
32 enum {
33     VALUE_CHANGED,
34     LAST_SIGNAL,
35 };
36
37
38 /* IBusConfigPriv */
39 struct _IBusConfigPrivate {
40     GArray *watch_rules;
41     guint watch_config_signal_id;
42 };
43
44 static guint    config_signals[LAST_SIGNAL] = { 0 };
45
46 static void      ibus_config_class_init     (IBusConfigClass    *class);
47 static void      ibus_config_init           (IBusConfig         *config);
48 static void      ibus_config_real_destroy   (IBusProxy          *proxy);
49
50 static void      ibus_config_g_signal       (GDBusProxy         *proxy,
51                                              const gchar        *sender_name,
52                                              const gchar        *signal_name,
53                                              GVariant           *parameters);
54
55 static void      initable_iface_init        (GInitableIface     *initable_iface);
56 static void      async_initable_iface_init  (GAsyncInitableIface
57                                                                 *async_initable_iface);
58
59 static gchar    *_make_match_rule           (const gchar        *section,
60                                              const gchar        *name);
61 static guint     _signal_subscribe          (GDBusProxy         *proxy);
62 static void      _signal_unsubscribe        (GDBusProxy         *proxy,
63                                              guint               signal_id);
64
65 static void      _remove_all_match_rules    (IBusConfig         *config);
66
67 G_DEFINE_TYPE_WITH_CODE (IBusConfig, ibus_config, IBUS_TYPE_PROXY,
68                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
69                          G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
70                          );
71
72 static void
73 ibus_config_class_init (IBusConfigClass *class)
74 {
75     GDBusProxyClass *dbus_proxy_class = G_DBUS_PROXY_CLASS (class);
76     IBusProxyClass *proxy_class = IBUS_PROXY_CLASS (class);
77
78     g_type_class_add_private (class, sizeof (IBusConfigPrivate));
79
80     dbus_proxy_class->g_signal = ibus_config_g_signal;
81     proxy_class->destroy = ibus_config_real_destroy;
82
83
84     /* install signals */
85     /**
86      * IBusConfig::value-changed:
87      * @config: An IBusConfig.
88      * @section: Section name.
89      * @name: Name of the property.
90      * @value: Value.
91      *
92      * Emitted when configuration value is changed.
93      * <note><para>Argument @user_data is ignored in this function.</para></note>
94      */
95     config_signals[VALUE_CHANGED] =
96         g_signal_new (I_("value-changed"),
97             G_TYPE_FROM_CLASS (class),
98             G_SIGNAL_RUN_LAST,
99             0,
100             NULL, NULL,
101             _ibus_marshal_VOID__STRING_STRING_VARIANT,
102             G_TYPE_NONE,
103             3,
104             G_TYPE_STRING,
105             G_TYPE_STRING,
106             G_TYPE_VARIANT | G_SIGNAL_TYPE_STATIC_SCOPE);
107 }
108
109 static void
110 ibus_config_init (IBusConfig *config)
111 {
112     config->priv = IBUS_CONFIG_GET_PRIVATE (config);
113     config->priv->watch_rules = g_array_new (FALSE, FALSE, sizeof (gchar *));
114 }
115
116 static void
117 ibus_config_real_destroy (IBusProxy *proxy)
118 {
119     IBusConfigPrivate *priv = IBUS_CONFIG_GET_PRIVATE (proxy);
120
121     _signal_unsubscribe (G_DBUS_PROXY (proxy), priv->watch_config_signal_id);
122     _remove_all_match_rules (IBUS_CONFIG (proxy));
123     g_array_free (priv->watch_rules, FALSE);
124
125     IBUS_PROXY_CLASS(ibus_config_parent_class)->destroy (proxy);
126 }
127
128
129 static void
130 ibus_config_g_signal (GDBusProxy  *proxy,
131                       const gchar *sender_name,
132                       const gchar *signal_name,
133                       GVariant    *parameters)
134 {
135     if (g_strcmp0 (signal_name, "ValueChanged") == 0) {
136         const gchar *section = NULL;
137         const gchar *name = NULL;
138         GVariant *value = NULL;
139
140         g_variant_get (parameters, "(&s&sv)", &section, &name, &value);
141
142         g_signal_emit (proxy,
143                        config_signals[VALUE_CHANGED],
144                        0,
145                        section,
146                        name,
147                        value);
148         g_variant_unref (value);
149         return;
150     }
151
152     g_return_if_reached ();
153 }
154
155 static void
156 _connection_signal_cb (GDBusConnection *connection,
157                        const gchar     *sender_name,
158                        const gchar     *object_path,
159                        const gchar     *interface_name,
160                        const gchar     *signal_name,
161                        GVariant        *parameters,
162                        IBusConfig      *config)
163 {
164     g_return_if_fail (IBUS_IS_CONFIG (config));
165
166     ibus_config_g_signal (G_DBUS_PROXY (config),
167                           sender_name,
168                           signal_name,
169                           parameters);
170 }
171
172 static gchar *
173 _make_match_rule (const gchar *section,
174                   const gchar *name)
175 {
176     GString *str = g_string_new ("type='signal',"
177                                  "interface='" IBUS_INTERFACE_CONFIG "',"
178                                  "path='" IBUS_PATH_CONFIG "',"
179                                  "member='ValueChanged'");
180     if (section != NULL) {
181         g_string_append_printf (str, ",arg0='%s'", section);
182         if (name != NULL)
183             g_string_append_printf (str, ",arg1='%s'", name);
184     }
185     return g_string_free (str, FALSE);
186 }
187
188 static void
189 _remove_all_match_rules (IBusConfig *config)
190 {
191     gint i;
192
193     for (i = 0; i < config->priv->watch_rules->len; i++) {
194         IBusBus *bus = ibus_bus_new ();
195         gchar *rule = g_array_index (config->priv->watch_rules, gchar *, i);
196         ibus_bus_remove_match (bus, rule);
197         g_object_unref (bus);
198         g_free (rule);
199     }
200     g_array_set_size (config->priv->watch_rules, 0);
201 }
202
203 gboolean
204 ibus_config_watch (IBusConfig  *config,
205                    const gchar *section,
206                    const gchar *name)
207 {
208     g_return_val_if_fail (IBUS_IS_CONFIG (config), FALSE);
209     g_assert ((section != NULL) || (section == NULL && name == NULL));
210
211     IBusBus *bus = ibus_bus_new ();
212     gchar *rule;
213     gboolean retval;
214
215     if (section == NULL && name == NULL) {
216         _remove_all_match_rules (config);
217
218         rule = _make_match_rule (NULL, NULL);
219         retval = ibus_bus_add_match (bus, rule);
220         g_object_unref (bus);
221         g_free (rule);
222
223         return retval;
224     }
225
226     if (config->priv->watch_rules->len == 0) {
227         rule = _make_match_rule (NULL, NULL);
228         retval = ibus_bus_remove_match (bus, rule);
229         g_free (rule);
230         if (!retval) {
231             g_object_unref (bus);
232             return FALSE;
233         }
234     }
235
236     rule = _make_match_rule (section, name);
237     retval = ibus_bus_add_match (bus, rule);
238     g_object_unref (bus);
239     if (!retval) {
240         g_free (rule);
241         return FALSE;
242     }
243
244     g_array_append_val (config->priv->watch_rules, rule);
245     return TRUE;
246 }
247
248 gboolean
249 ibus_config_unwatch (IBusConfig  *config,
250                      const gchar *section,
251                      const gchar *name)
252 {
253     g_return_val_if_fail (IBUS_IS_CONFIG (config), FALSE);
254     g_assert ((section != NULL) || (section == NULL && name == NULL));
255
256     IBusBus *bus = ibus_bus_new ();
257     gchar *rule = _make_match_rule (section, name);
258     gboolean retval;
259
260     retval = ibus_bus_remove_match (bus, rule);
261     g_object_unref (bus);
262     if (retval && (section != NULL || name != NULL)) {
263         /* Remove the previously registered match rule from
264            config->priv->watch_rules. */
265         gint i;
266         for (i = 0; i < config->priv->watch_rules->len; i++) {
267             gchar *_rule = g_array_index (config->priv->watch_rules, gchar *,
268                                           i);
269             if (g_strcmp0 (_rule, rule) == 0) {
270                 config->priv->watch_rules =
271                     g_array_remove_index_fast (config->priv->watch_rules, i);
272                 g_free (_rule);
273                 break;
274             }
275         }
276     }
277     g_free (rule);
278
279     return TRUE;
280 }
281
282 IBusConfig *
283 ibus_config_new (GDBusConnection  *connection,
284                  GCancellable     *cancellable,
285                  GError          **error)
286 {
287     g_assert (G_IS_DBUS_CONNECTION (connection));
288
289     GInitable *initable;
290
291     GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
292                             G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
293                             G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS;
294
295     initable = g_initable_new (IBUS_TYPE_CONFIG,
296                                cancellable,
297                                error,
298                                "g-connection",      connection,
299                                "g-flags",           flags,
300                                "g-name",            IBUS_SERVICE_CONFIG,
301                                "g-interface-name",  IBUS_INTERFACE_CONFIG,
302                                "g-object-path",     IBUS_PATH_CONFIG,
303                                "g-default-timeout", ibus_get_timeout (),
304                                NULL);
305     if (initable == NULL)
306         return NULL;
307
308     if (g_dbus_proxy_get_name_owner (G_DBUS_PROXY (initable)) == NULL) {
309         /* The configuration daemon, which is usually ibus-gconf, is not started yet. */
310         g_set_error (error,
311                      IBUS_ERROR,
312                      IBUS_ERROR_NO_CONFIG,
313                      "Configuration daemon is not running.");
314         g_object_unref (initable);
315         return NULL;
316     }
317
318     /* clients should not destroy the config service. */
319     IBUS_PROXY (initable)->own = FALSE;
320
321     return IBUS_CONFIG (initable);
322 }
323
324 void
325 ibus_config_new_async (GDBusConnection     *connection,
326                        GCancellable        *cancellable,
327                        GAsyncReadyCallback  callback,
328                        gpointer             user_data)
329 {
330     g_assert (G_IS_DBUS_CONNECTION (connection));
331     g_assert (callback != NULL);
332
333     GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
334                             G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
335                             G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS;
336
337     g_async_initable_new_async (IBUS_TYPE_CONFIG,
338                                 G_PRIORITY_DEFAULT,
339                                 cancellable,
340                                 callback,
341                                 user_data,
342                                 "g-connection",      connection,
343                                 "g-flags",           flags,
344                                 "g-name",            IBUS_SERVICE_CONFIG,
345                                 "g-interface-name",  IBUS_INTERFACE_CONFIG,
346                                 "g-object-path",     IBUS_PATH_CONFIG,
347                                 "g-default-timeout", ibus_get_timeout (),
348                                 NULL);
349 }
350
351 IBusConfig *
352 ibus_config_new_async_finish (GAsyncResult  *res,
353                               GError       **error)
354 {
355     g_assert (G_IS_ASYNC_RESULT (res));
356     g_assert (error == NULL || *error == NULL);
357
358     GObject *object = NULL;
359     GObject *source_object = NULL;
360
361     source_object = g_async_result_get_source_object (res);
362     g_assert (source_object != NULL);
363
364     object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
365                                           res,
366                                           error);
367     g_object_unref (source_object);
368
369     if (object != NULL) {
370         if (g_dbus_proxy_get_name_owner (G_DBUS_PROXY (object)) == NULL) {
371             /* The configuration daemon, which is usually ibus-gconf, 
372              * is not started yet. */
373             g_set_error (error,
374                          IBUS_ERROR,
375                          IBUS_ERROR_NO_CONFIG,
376                          "Configuration daemon is not running.");
377             g_object_unref (object);
378             return NULL;
379         }
380         /* clients should not destroy the config service. */
381         IBUS_PROXY (object)->own = FALSE;
382         return IBUS_CONFIG (object);
383     }
384     else {
385         return NULL;
386     }
387 }
388
389 GVariant *
390 ibus_config_get_value (IBusConfig  *config,
391                        const gchar *section,
392                        const gchar *name)
393 {
394     g_assert (IBUS_IS_CONFIG (config));
395     g_assert (section != NULL);
396     g_assert (name != NULL);
397
398     GError *error = NULL;
399     GVariant *result;
400     result = g_dbus_proxy_call_sync ((GDBusProxy *) config,
401                                      "GetValue",                /* method_name */
402                                      g_variant_new ("(ss)",
403                                         section, name),         /* parameters */
404                                      G_DBUS_CALL_FLAGS_NONE,    /* flags */
405                                      -1,                        /* timeout */
406                                      NULL,                      /* cancellable */
407                                      &error                     /* error */
408                                      );
409     if (result == NULL) {
410         g_warning ("%s.GetValue: %s", IBUS_INTERFACE_CONFIG, error->message);
411         g_error_free (error);
412         return NULL;
413     }
414
415     GVariant *value = NULL;
416     g_variant_get (result, "(v)", &value);
417     g_variant_unref (result);
418
419     return value;
420 }
421
422 void
423 ibus_config_get_value_async (IBusConfig         *config,
424                              const gchar        *section,
425                              const gchar        *name,
426                              gint                timeout_ms,
427                              GCancellable       *cancellable,
428                              GAsyncReadyCallback callback,
429                              gpointer            user_data)
430 {
431     g_assert (IBUS_IS_CONFIG (config));
432     g_assert (section != NULL);
433     g_assert (name != NULL);
434
435     g_dbus_proxy_call ((GDBusProxy *)config,
436                        "GetValue",
437                        g_variant_new ("(ss)", section, name),
438                        G_DBUS_CALL_FLAGS_NONE,
439                        timeout_ms,
440                        cancellable,
441                        callback,
442                        user_data);
443 }
444
445 GVariant *
446 ibus_config_get_value_async_finish (IBusConfig    *config,
447                                     GAsyncResult  *result,
448                                     GError       **error)
449 {
450     g_assert (IBUS_IS_CONFIG (config));
451     g_assert (G_IS_ASYNC_RESULT (result));
452     g_assert (error == NULL || *error == NULL);
453
454     GVariant *value = NULL;
455     GVariant *retval = g_dbus_proxy_call_finish ((GDBusProxy *)config,
456                                                  result,
457                                                  error);
458     if (retval != NULL) {
459         g_variant_get (retval, "(v)", &value);
460         g_variant_unref (retval);
461     }
462
463     return value;
464 }
465
466 GVariant *
467 ibus_config_get_values (IBusConfig  *config,
468                         const gchar *section)
469 {
470     g_assert (IBUS_IS_CONFIG (config));
471     g_assert (section != NULL);
472
473     GError *error = NULL;
474     GVariant *result;
475     result = g_dbus_proxy_call_sync ((GDBusProxy *) config,
476                                      "GetValues",
477                                      g_variant_new ("(s)", section),
478                                      G_DBUS_CALL_FLAGS_NONE,
479                                      -1,
480                                      NULL,
481                                      &error);
482     if (result == NULL) {
483         g_warning ("%s.GetValues: %s", IBUS_INTERFACE_CONFIG, error->message);
484         g_error_free (error);
485         return NULL;
486     }
487
488     GVariant *value = NULL;
489     g_variant_get (result, "(@a{sv})", &value);
490     g_variant_unref (result);
491
492     return value;
493 }
494
495 void
496 ibus_config_get_values_async (IBusConfig         *config,
497                               const gchar        *section,
498                               gint                timeout_ms,
499                               GCancellable       *cancellable,
500                               GAsyncReadyCallback callback,
501                               gpointer            user_data)
502 {
503     g_assert (IBUS_IS_CONFIG (config));
504     g_assert (section != NULL);
505
506     g_dbus_proxy_call ((GDBusProxy *)config,
507                        "GetValues",
508                        g_variant_new ("(s)", section),
509                        G_DBUS_CALL_FLAGS_NONE,
510                        timeout_ms,
511                        cancellable,
512                        callback,
513                        user_data);
514 }
515
516 GVariant *
517 ibus_config_get_values_async_finish (IBusConfig    *config,
518                                      GAsyncResult  *result,
519                                      GError       **error)
520 {
521     g_assert (IBUS_IS_CONFIG (config));
522     g_assert (G_IS_ASYNC_RESULT (result));
523     g_assert (error == NULL || *error == NULL);
524
525     GVariant *value = NULL;
526     GVariant *retval = g_dbus_proxy_call_finish ((GDBusProxy *)config,
527                                                  result,
528                                                  error);
529     if (retval != NULL) {
530         g_variant_get (retval, "(@a{sv})", &value);
531         g_variant_unref (retval);
532     }
533
534     return value;
535 }
536     
537 gboolean
538 ibus_config_set_value (IBusConfig   *config,
539                        const gchar  *section,
540                        const gchar  *name,
541                        GVariant     *value)
542 {
543     g_assert (IBUS_IS_CONFIG (config));
544     g_assert (section != NULL);
545     g_assert (name != NULL);
546     g_assert (value != NULL);
547
548     GError *error = NULL;
549     GVariant *result;
550     result = g_dbus_proxy_call_sync ((GDBusProxy *) config,
551                                      "SetValue",                /* method_name */
552                                      g_variant_new ("(ssv)",
553                                         section, name, value),  /* parameters */
554                                      G_DBUS_CALL_FLAGS_NONE,    /* flags */
555                                      -1,                        /* timeout */
556                                      NULL,                      /* cancellable */
557                                      &error                     /* error */
558                                      );
559     if (result == NULL) {
560         g_warning ("%s.SetValue: %s", IBUS_INTERFACE_CONFIG, error->message);
561         g_error_free (error);
562         return FALSE;
563     }
564     g_variant_unref (result);
565     return TRUE;
566 }
567
568 void
569 ibus_config_set_value_async (IBusConfig         *config,
570                              const gchar        *section,
571                              const gchar        *name,
572                              GVariant           *value,
573                              gint                timeout_ms,
574                              GCancellable       *cancellable,
575                              GAsyncReadyCallback callback,
576                              gpointer            user_data)
577 {
578     g_assert (IBUS_IS_CONFIG (config));
579     g_assert (section != NULL);
580     g_assert (name != NULL);
581     g_assert (value != NULL);
582
583     g_dbus_proxy_call ((GDBusProxy *) config,
584                        "SetValue",                /* method_name */
585                        g_variant_new ("(ssv)",
586                                       section, name, value),  /* parameters */
587                        G_DBUS_CALL_FLAGS_NONE,    /* flags */
588                        timeout_ms,
589                        cancellable,
590                        callback,
591                        user_data);
592 }
593
594 gboolean
595 ibus_config_set_value_async_finish (IBusConfig         *config,
596                                     GAsyncResult       *result,
597                                     GError            **error)
598 {
599     g_assert (IBUS_IS_CONFIG (config));
600     g_assert (G_IS_ASYNC_RESULT (result));
601     g_assert (error == NULL || *error == NULL);
602
603     GVariant *retval = g_dbus_proxy_call_finish ((GDBusProxy *)config,
604                                                  result,
605                                                  error);
606     if (retval != NULL) {
607         g_variant_unref (retval);
608         return TRUE;
609     }
610
611     return FALSE;
612 }
613
614 gboolean
615 ibus_config_unset (IBusConfig   *config,
616                    const gchar  *section,
617                    const gchar  *name)
618 {
619     g_assert (IBUS_IS_CONFIG (config));
620     g_assert (section != NULL);
621     g_assert (name != NULL);
622
623     GError *error = NULL;
624     GVariant *result;
625     result = g_dbus_proxy_call_sync ((GDBusProxy *) config,
626                                      "UnsetValue",              /* method_name */
627                                      g_variant_new ("(ss)",
628                                         section, name),         /* parameters */
629                                      G_DBUS_CALL_FLAGS_NONE,    /* flags */
630                                      -1,                        /* timeout */
631                                      NULL,                      /* cancellable */
632                                      &error                     /* error */
633                                      );
634     if (result == NULL) {
635         g_warning ("%s.UnsetValue: %s", IBUS_INTERFACE_CONFIG, error->message);
636         g_error_free (error);
637         return FALSE;
638     }
639     g_variant_unref (result);
640     return TRUE;
641 }
642
643 static guint
644 _signal_subscribe (GDBusProxy *proxy)
645 {
646     GDBusConnection *connection = g_dbus_proxy_get_connection (proxy);
647     return g_dbus_connection_signal_subscribe (connection,
648                                                NULL,
649                                                IBUS_INTERFACE_CONFIG,
650                                                NULL,
651                                                NULL,
652                                                NULL,
653                                                G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
654                                                (GDBusSignalCallback) _connection_signal_cb,
655                                                g_object_ref (proxy),
656                                                (GDestroyNotify) g_object_unref);
657 }
658
659 static void
660 _signal_unsubscribe (GDBusProxy *proxy, guint signal_id)
661 {
662     GDBusConnection *connection = g_dbus_proxy_get_connection (proxy);
663     g_dbus_connection_signal_unsubscribe (connection, signal_id);
664 }
665
666 static GInitableIface *initable_iface_parent = NULL;
667
668 static gboolean
669 initable_init (GInitable     *initable,
670                GCancellable  *cancellable,
671                GError       **error)
672 {
673     if (!initable_iface_parent->init (initable, cancellable, error))
674         return FALSE;
675
676     IBusConfig *config = IBUS_CONFIG (initable);
677     config->priv->watch_config_signal_id =
678         _signal_subscribe (G_DBUS_PROXY (initable));
679
680     gboolean retval = ibus_config_watch (config, NULL, NULL);
681     if (!retval)
682         g_set_error (error,
683                      IBUS_ERROR,
684                      IBUS_ERROR_FAILED,
685                      "Cannot watch configuration change.");
686     return retval;
687 }
688
689 static void
690 initable_iface_init (GInitableIface *initable_iface)
691 {
692     initable_iface_parent = g_type_interface_peek_parent (initable_iface);
693     initable_iface->init = initable_init;
694 }
695
696 static GAsyncInitableIface *async_initable_iface_parent = NULL;
697
698 static void
699 async_initable_init_async (GAsyncInitable      *initable,
700                            gint                 io_priority,
701                            GCancellable        *cancellable,
702                            GAsyncReadyCallback  callback,
703                            gpointer             user_data)
704 {
705     async_initable_iface_parent->init_async (initable,
706                                              io_priority,
707                                              cancellable,
708                                              callback,
709                                              user_data);
710 }
711
712 static gboolean
713 async_initable_init_finish (GAsyncInitable  *initable,
714                             GAsyncResult    *res,
715                             GError         **error)
716 {
717     if (!async_initable_iface_parent->init_finish (initable, res, error))
718         return FALSE;
719
720     IBusConfig *config = IBUS_CONFIG (initable);
721     config->priv->watch_config_signal_id =
722         _signal_subscribe (G_DBUS_PROXY (initable));
723     return ibus_config_watch (config, NULL, NULL);
724 }
725
726 static void
727 async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
728 {
729     async_initable_iface_parent =
730         g_type_interface_peek_parent (async_initable_iface);
731     async_initable_iface->init_async = async_initable_init_async;
732     async_initable_iface->init_finish = async_initable_init_finish;
733 }