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)", §ion, &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