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