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-2015 Peng Huang <shawn.p.huang@gmail.com>
5  * Copyright (C) 2015-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
6  * Copyright (C) 2008-2016 Red Hat, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
21  * USA
22  */
23 
24 #include "ibusbus.h"
25 #include <errno.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <glib/gstdio.h>
30 #include <gio/gio.h>
31 #include "ibusmarshalers.h"
32 #include "ibusinternal.h"
33 #include "ibusshare.h"
34 #include "ibusenginedesc.h"
35 #include "ibusserializable.h"
36 #include "ibusconfig.h"
37 
38 #define IBUS_BUS_GET_PRIVATE(o)  \
39    ((IBusBusPrivate *)ibus_bus_get_instance_private (o))
40 
41 enum {
42     CONNECTED,
43     DISCONNECTED,
44     GLOBAL_ENGINE_CHANGED,
45     NAME_OWNER_CHANGED,
46     LAST_SIGNAL,
47 };
48 
49 enum {
50     PROP_0 = 0,
51     PROP_CONNECT_ASYNC,
52     PROP_CLIENT_ONLY,
53 };
54 
55 /* IBusBusPriv */
56 struct _IBusBusPrivate {
57     GFileMonitor *monitor;
58     GDBusConnection *connection;
59     gboolean connected;
60     gboolean watch_dbus_signal;
61     guint watch_dbus_signal_id;
62     gboolean watch_ibus_signal;
63     guint watch_ibus_signal_id;
64     IBusConfig *config;
65     gchar *unique_name;
66     gboolean connect_async;
67     gchar *bus_address;
68     gboolean use_portal;
69     gboolean client_only;
70     GCancellable *cancellable;
71     guint portal_name_watch_id;
72 };
73 
74 static guint    bus_signals[LAST_SIGNAL] = { 0 };
75 
76 static IBusBus *_bus = NULL;
77 
78 /* functions prototype */
79 static GObject  *ibus_bus_constructor           (GType                   type,
80                                                  guint                   n_params,
81                                                  GObjectConstructParam  *params);
82 static void      ibus_bus_destroy               (IBusObject             *object);
83 static void      ibus_bus_connect_async         (IBusBus                *bus);
84 static void      ibus_bus_watch_dbus_signal     (IBusBus                *bus);
85 static void      ibus_bus_unwatch_dbus_signal   (IBusBus                *bus);
86 static void      ibus_bus_watch_ibus_signal     (IBusBus                *bus);
87 static void      ibus_bus_unwatch_ibus_signal   (IBusBus                *bus);
88 static GVariant *ibus_bus_call_sync             (IBusBus                *bus,
89                                                  const gchar            *service,
90                                                  const gchar            *path,
91                                                  const gchar            *interface,
92                                                  const gchar            *member,
93                                                  GVariant               *parameters,
94                                                  const GVariantType     *reply_type);
95 static void      ibus_bus_call_async             (IBusBus                *bus,
96                                                   const gchar            *service,
97                                                   const gchar            *path,
98                                                   const gchar            *interface,
99                                                   const gchar            *member,
100                                                   GVariant               *parameters,
101                                                   const GVariantType     *reply_type,
102                                                   gpointer                source_tag,
103                                                   gint                    timeout_msec,
104                                                   GCancellable           *cancellable,
105                                                   GAsyncReadyCallback     callback,
106                                                   gpointer                user_data);
107 static void      ibus_bus_set_property           (IBusBus                *bus,
108                                                   guint                   prop_id,
109                                                   const GValue           *value,
110                                                   GParamSpec             *pspec);
111 static void      ibus_bus_get_property           (IBusBus                *bus,
112                                                   guint                   prop_id,
113                                                   GValue                 *value,
114                                                   GParamSpec             *pspec);
115 
116 static void     ibus_bus_close_connection        (IBusBus                *bus);
117 
G_DEFINE_TYPE_WITH_PRIVATE(IBusBus,ibus_bus,IBUS_TYPE_OBJECT)118 G_DEFINE_TYPE_WITH_PRIVATE (IBusBus, ibus_bus, IBUS_TYPE_OBJECT)
119 
120 static void
121 ibus_bus_class_init (IBusBusClass *class)
122 {
123     GObjectClass *gobject_class = G_OBJECT_CLASS (class);
124     IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class);
125 
126     gobject_class->constructor = ibus_bus_constructor;
127     gobject_class->set_property =
128             (GObjectSetPropertyFunc) ibus_bus_set_property;
129     gobject_class->get_property =
130             (GObjectGetPropertyFunc) ibus_bus_get_property;
131     ibus_object_class->destroy = ibus_bus_destroy;
132 
133     /* install properties */
134     /**
135      * IBusBus:connect-async:
136      *
137      * Whether the #IBusBus object should connect asynchronously to the bus.
138      *
139      */
140     g_object_class_install_property (
141             gobject_class,
142             PROP_CONNECT_ASYNC,
143             g_param_spec_boolean ("connect-async",
144                                   "Connect Async",
145                                   "Connect asynchronously to the bus",
146                                   FALSE,
147                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
148     /**
149      * IBusBus:client-only:
150      *
151      * Whether the #IBusBus object is for client use only.
152      *
153      */
154     g_object_class_install_property (
155             gobject_class,
156             PROP_CLIENT_ONLY,
157             g_param_spec_boolean ("client-only",
158                                   "ClientOnly",
159                                   "Client use only",
160                                   FALSE,
161                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
162 
163     /* install signals */
164     /**
165      * IBusBus::connected:
166      * @bus: The #IBusBus object which recevied the signal
167      *
168      * Emitted when #IBusBus is connected to ibus-daemon.
169      *
170      */
171     bus_signals[CONNECTED] =
172         g_signal_new (I_("connected"),
173             G_TYPE_FROM_CLASS (class),
174             G_SIGNAL_RUN_LAST,
175             0,
176             NULL, NULL,
177             _ibus_marshal_VOID__VOID,
178             G_TYPE_NONE,
179             0);
180 
181     /**
182      * IBusBus::disconnected:
183      * @bus: The #IBusBus object which recevied the signal
184      *
185      * Emitted when #IBusBus is disconnected from ibus-daemon.
186      *
187      */
188     bus_signals[DISCONNECTED] =
189         g_signal_new (I_("disconnected"),
190             G_TYPE_FROM_CLASS (class),
191             G_SIGNAL_RUN_LAST,
192             0,
193             NULL, NULL,
194             _ibus_marshal_VOID__VOID,
195             G_TYPE_NONE,
196             0);
197 
198     /**
199      * IBusBus::global-engine-changed:
200      * @bus: The #IBusBus object which recevied the signal
201      * @name: The name of the new global engine.
202      *
203      * Emitted when global engine is changed.
204      *
205      */
206     bus_signals[GLOBAL_ENGINE_CHANGED] =
207         g_signal_new (I_("global-engine-changed"),
208             G_TYPE_FROM_CLASS (class),
209             G_SIGNAL_RUN_LAST,
210             0,
211             NULL, NULL,
212             _ibus_marshal_VOID__STRING,
213             G_TYPE_NONE,
214             1,
215             G_TYPE_STRING);
216 
217     /**
218      * IBusBus::name-owner-changed:
219      * @bus: The #IBusBus object which recevied the signal
220      * @name: The name which ower is changed.
221      * @old_owner: The unique bus name of the old owner.
222      * @new_owner: The unique bus name of the new owner.
223      *
224      * Emitted when D-Bus name owner is changed.
225      *
226      */
227     bus_signals[NAME_OWNER_CHANGED] =
228         g_signal_new (I_("name-owner-changed"),
229             G_TYPE_FROM_CLASS (class),
230             G_SIGNAL_RUN_LAST,
231             0,
232             NULL, NULL,
233             _ibus_marshal_VOID__STRING_STRING_STRING,
234             G_TYPE_NONE,
235             3,
236             G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
237 }
238 
239 static void
_connection_dbus_signal_cb(GDBusConnection * connection,const gchar * sender_name,const gchar * object_path,const gchar * interface_name,const gchar * signal_name,GVariant * parameters,gpointer user_data)240 _connection_dbus_signal_cb (GDBusConnection *connection,
241                             const gchar *sender_name,
242                             const gchar *object_path,
243                             const gchar *interface_name,
244                             const gchar *signal_name,
245                             GVariant *parameters,
246                             gpointer user_data)
247 {
248     g_return_if_fail (user_data != NULL);
249     g_return_if_fail (IBUS_IS_BUS (user_data));
250 
251     if (g_strcmp0 (signal_name, "NameOwnerChanged") == 0) {
252         gchar *name = NULL;
253         gchar *old_owner = NULL;
254         gchar *new_owner = NULL;
255         g_variant_get (parameters, "(&s&s&s)", &name, &old_owner, &new_owner);
256         g_signal_emit (IBUS_BUS (user_data),
257                        bus_signals[NAME_OWNER_CHANGED], 0,
258                        name, old_owner, new_owner);
259     }
260     /* FIXME handle other D-Bus signals if needed */
261 }
262 
263 static void
_connection_ibus_signal_cb(GDBusConnection * connection,const gchar * sender_name,const gchar * object_path,const gchar * interface_name,const gchar * signal_name,GVariant * parameters,gpointer user_data)264 _connection_ibus_signal_cb (GDBusConnection *connection,
265                             const gchar *sender_name,
266                             const gchar *object_path,
267                             const gchar *interface_name,
268                             const gchar *signal_name,
269                             GVariant *parameters,
270                             gpointer user_data)
271 {
272     g_return_if_fail (user_data != NULL);
273     g_return_if_fail (IBUS_IS_BUS (user_data));
274 
275     if (g_strcmp0 (signal_name, "GlobalEngineChanged") == 0) {
276         gchar *engine_name = NULL;
277         g_variant_get (parameters, "(&s)", &engine_name);
278         g_signal_emit (IBUS_BUS (user_data),
279                        bus_signals[GLOBAL_ENGINE_CHANGED], 0,
280                        engine_name);
281     }
282     /* FIXME handle org.freedesktop.IBus.RegistryChanged signal if needed */
283 }
284 
285 static void
_connection_closed_cb(GDBusConnection * connection,gboolean remote_peer_vanished,GError * error,IBusBus * bus)286 _connection_closed_cb (GDBusConnection  *connection,
287                        gboolean          remote_peer_vanished,
288                        GError           *error,
289                        IBusBus          *bus)
290 {
291     if (error) {
292         /* We replaced g_warning with g_debug here because
293          * currently when ibus-daemon restarts, GTK client calls this and
294          * _g_dbus_worker_do_read_cb() sets the error message:
295          * "Underlying GIOStream returned 0 bytes on an async read"
296          * http://git.gnome.org/browse/glib/tree/gio/gdbusprivate.c#n693
297          * However we think the error message is almost harmless. */
298         g_debug ("_connection_closed_cb: %s", error->message);
299     }
300     ibus_bus_close_connection (bus);
301 }
302 
303 static void
ibus_bus_close_connection(IBusBus * bus)304 ibus_bus_close_connection (IBusBus *bus)
305 {
306     g_free (bus->priv->unique_name);
307     bus->priv->unique_name = NULL;
308 
309     bus->priv->watch_dbus_signal_id = 0;
310     bus->priv->watch_ibus_signal_id = 0;
311 
312     g_free (bus->priv->bus_address);
313     bus->priv->bus_address = NULL;
314 
315     /* Cancel ongoing connect request. */
316     g_cancellable_cancel (bus->priv->cancellable);
317     g_cancellable_reset (bus->priv->cancellable);
318 
319     bus->priv->connected = FALSE;
320 
321     /* unref the old connection at first */
322     if (bus->priv->connection != NULL) {
323         g_signal_handlers_disconnect_by_func (bus->priv->connection,
324                                               G_CALLBACK (_connection_closed_cb),
325                                               bus);
326         if (!g_dbus_connection_is_closed(bus->priv->connection))
327             g_dbus_connection_close(bus->priv->connection, NULL, NULL, NULL);
328         g_object_unref (bus->priv->connection);
329         bus->priv->connection = NULL;
330         g_signal_emit (bus, bus_signals[DISCONNECTED], 0);
331     }
332 }
333 
334 static void
ibus_bus_connect_completed(IBusBus * bus)335 ibus_bus_connect_completed (IBusBus *bus)
336 {
337     g_assert (bus->priv->connection);
338 
339     bus->priv->connected = TRUE;
340     /* FIXME */
341     ibus_bus_hello (bus);
342 
343     g_signal_connect (bus->priv->connection,
344                       "closed",
345                       (GCallback) _connection_closed_cb,
346                       bus);
347     if (bus->priv->watch_dbus_signal) {
348         ibus_bus_watch_dbus_signal (bus);
349     }
350     if (bus->priv->watch_ibus_signal) {
351         ibus_bus_watch_ibus_signal (bus);
352     }
353 
354     g_signal_emit (bus, bus_signals[CONNECTED], 0);
355 }
356 
357 static void
_bus_connect_start_portal_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)358 _bus_connect_start_portal_cb (GObject      *source_object,
359                               GAsyncResult *res,
360                               gpointer      user_data)
361 {
362     IBusBus *bus = IBUS_BUS (user_data);
363     GVariant *result;
364     GError *error = NULL;
365 
366     result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
367                                             res,
368                                             &error);
369     if (result != NULL) {
370         ibus_bus_connect_completed (bus);
371         g_variant_unref (result);
372     } else {
373         g_error_free (error);
374 
375         g_dbus_connection_close (bus->priv->connection, NULL, NULL, NULL);
376         g_object_unref (bus->priv->connection);
377         bus->priv->connection = NULL;
378 
379         g_free (bus->priv->bus_address);
380         bus->priv->bus_address = NULL;
381     }
382 
383     g_object_unref (bus);
384 }
385 
386 static void
_bus_connect_async_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)387 _bus_connect_async_cb (GObject      *source_object,
388                        GAsyncResult *res,
389                        gpointer      user_data)
390 {
391     g_return_if_fail (user_data != NULL);
392     g_return_if_fail (IBUS_IS_BUS (user_data));
393 
394     IBusBus *bus   = IBUS_BUS (user_data);
395     GError  *error = NULL;
396 
397     bus->priv->connection =
398                 g_dbus_connection_new_for_address_finish (res, &error);
399 
400     if (error != NULL) {
401         g_warning ("Unable to connect to ibus: %s", error->message);
402         g_error_free (error);
403         error = NULL;
404     }
405 
406     if (bus->priv->connection != NULL) {
407         if (bus->priv->use_portal) {
408             g_object_set_data (G_OBJECT (bus->priv->connection),
409                                "ibus-portal-connection",
410                                GINT_TO_POINTER (TRUE));
411             g_dbus_connection_call (
412                     bus->priv->connection,
413                     IBUS_SERVICE_PORTAL,
414                     IBUS_PATH_IBUS,
415                     "org.freedesktop.DBus.Peer",
416                     "Ping",
417                     g_variant_new ("()"),
418                     G_VARIANT_TYPE ("()"),
419                     G_DBUS_CALL_FLAGS_NONE,
420                     -1,
421                     bus->priv->cancellable,
422                     (GAsyncReadyCallback) _bus_connect_start_portal_cb,
423                     g_object_ref (bus));
424         } else {
425             ibus_bus_connect_completed (bus);
426         }
427     }
428     else {
429         g_free (bus->priv->bus_address);
430         bus->priv->bus_address = NULL;
431     }
432 
433     /* unref the ref from ibus_bus_connect */
434     g_object_unref (bus);
435 }
436 
437 static gchar *
ibus_bus_get_bus_address(IBusBus * bus)438 ibus_bus_get_bus_address (IBusBus *bus)
439 {
440     if (_bus->priv->use_portal)
441         return g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SESSION, NULL, NULL);
442     else
443         return g_strdup (ibus_get_address ());
444 }
445 
446 static void
ibus_bus_connect_async(IBusBus * bus)447 ibus_bus_connect_async (IBusBus *bus)
448 {
449     gchar *bus_address = ibus_bus_get_bus_address (bus);
450 
451     if (bus_address == NULL)
452         return;
453 
454     if (g_strcmp0 (bus->priv->bus_address, bus_address) == 0) {
455         g_free (bus_address);
456         return;
457     }
458 
459     /* Close current connection and cancel ongoing connect request. */
460     ibus_bus_close_connection (bus);
461 
462     bus->priv->bus_address = bus_address;
463     g_object_ref (bus);
464     g_dbus_connection_new_for_address (
465             bus_address,
466             G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
467             G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
468             NULL,
469             bus->priv->cancellable,
470             _bus_connect_async_cb, bus);
471 }
472 
473 static gboolean
is_in_flatpak(void)474 is_in_flatpak (void)
475 {
476     static gboolean flatpak_info_read;
477     static gboolean in_flatpak;
478 
479     if (flatpak_info_read)
480         return in_flatpak;
481 
482     flatpak_info_read = TRUE;
483     if (g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS))
484         in_flatpak = TRUE;
485     return in_flatpak;
486 }
487 
488 static gboolean
ibus_bus_should_connect_portal(IBusBus * bus)489 ibus_bus_should_connect_portal (IBusBus *bus)
490 {
491     return bus->priv->client_only &&
492         (is_in_flatpak () || g_getenv ("IBUS_USE_PORTAL") != NULL);
493 }
494 
495 static void
ibus_bus_connect(IBusBus * bus)496 ibus_bus_connect (IBusBus *bus)
497 {
498     const gchar *bus_address = ibus_get_address ();
499 
500     if (bus_address == NULL)
501         return;
502 
503     if (g_strcmp0 (bus_address, bus->priv->bus_address) == 0 &&
504         bus->priv->connection != NULL)
505         return;
506 
507     /* Close current connection and cancel ongoing connect request. */
508     ibus_bus_close_connection (bus);
509 
510     bus->priv->connection = g_dbus_connection_new_for_address_sync (
511             bus_address,
512             G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
513             G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
514             NULL, NULL, NULL);
515     if (bus->priv->connection) {
516         bus->priv->bus_address = g_strdup (bus_address);
517         ibus_bus_connect_completed (bus);
518     }
519 }
520 
521 static void
_changed_cb(GFileMonitor * monitor,GFile * file,GFile * other_file,GFileMonitorEvent event_type,IBusBus * bus)522 _changed_cb (GFileMonitor       *monitor,
523              GFile              *file,
524              GFile              *other_file,
525              GFileMonitorEvent   event_type,
526              IBusBus            *bus)
527 {
528     if (event_type != G_FILE_MONITOR_EVENT_CHANGED &&
529         event_type != G_FILE_MONITOR_EVENT_CREATED &&
530         event_type != G_FILE_MONITOR_EVENT_DELETED)
531         return;
532 
533     ibus_bus_connect_async (bus);
534 }
535 
536 static void
ibus_bus_init(IBusBus * bus)537 ibus_bus_init (IBusBus *bus)
538 {
539     struct stat buf;
540     gchar *path;
541 
542     bus->priv = IBUS_BUS_GET_PRIVATE (bus);
543 
544     bus->priv->config = NULL;
545     bus->priv->connection = NULL;
546     bus->priv->watch_dbus_signal = FALSE;
547     bus->priv->watch_dbus_signal_id = 0;
548     bus->priv->watch_ibus_signal = FALSE;
549     bus->priv->watch_ibus_signal_id = 0;
550     bus->priv->unique_name = NULL;
551     bus->priv->connect_async = FALSE;
552     bus->priv->client_only = FALSE;
553     bus->priv->bus_address = NULL;
554     bus->priv->cancellable = g_cancellable_new ();
555 
556     path = g_path_get_dirname (ibus_get_socket_path ());
557 
558     g_mkdir_with_parents (path, 0700);
559 
560     if (stat (path, &buf) == 0) {
561         if (buf.st_uid != getuid ()) {
562             g_warning ("The owner of %s is not %s!",
563                        path, ibus_get_user_name ());
564             return;
565         }
566         if (buf.st_mode != (S_IFDIR | S_IRWXU)) {
567             errno = 0;
568             if (g_chmod (path, 0700))
569                 g_warning ("chmod failed: %s", errno ? g_strerror (errno) : "");
570         }
571     }
572 
573     g_free (path);
574 }
575 
576 static void
ibus_bus_set_property(IBusBus * bus,guint prop_id,const GValue * value,GParamSpec * pspec)577 ibus_bus_set_property (IBusBus      *bus,
578                        guint         prop_id,
579                        const GValue *value,
580                        GParamSpec   *pspec)
581 {
582     switch (prop_id) {
583     case PROP_CONNECT_ASYNC:
584         bus->priv->connect_async = g_value_get_boolean (value);
585         break;
586     case PROP_CLIENT_ONLY:
587         bus->priv->client_only = g_value_get_boolean (value);
588         break;
589     default:
590         G_OBJECT_WARN_INVALID_PROPERTY_ID (bus, prop_id, pspec);
591     }
592 }
593 
594 static void
ibus_bus_get_property(IBusBus * bus,guint prop_id,GValue * value,GParamSpec * pspec)595 ibus_bus_get_property (IBusBus    *bus,
596                        guint       prop_id,
597                        GValue     *value,
598                        GParamSpec *pspec)
599 {
600     switch (prop_id) {
601     case PROP_CONNECT_ASYNC:
602         g_value_set_boolean (value, bus->priv->connect_async);
603         break;
604     case PROP_CLIENT_ONLY:
605         g_value_set_boolean (value, bus->priv->client_only);
606         break;
607     default:
608         G_OBJECT_WARN_INVALID_PROPERTY_ID (bus, prop_id, pspec);
609     }
610 }
611 
612 static void
portal_name_appeared(GDBusConnection * connection,const gchar * name,const gchar * owner,gpointer user_data)613 portal_name_appeared (GDBusConnection *connection,
614                       const gchar     *name,
615                       const gchar     *owner,
616                       gpointer         user_data)
617 {
618     IBusBus *bus = IBUS_BUS (user_data);
619 
620     if (bus->priv->connection == NULL)
621         ibus_bus_connect_async (bus);
622 }
623 
624 static void
portal_name_vanished(GDBusConnection * connection,const gchar * name,gpointer user_data)625 portal_name_vanished (GDBusConnection *connection,
626                       const gchar     *name,
627                       gpointer         user_data)
628 {
629     IBusBus *bus = IBUS_BUS (user_data);
630 
631     if (bus->priv->connection)
632         g_dbus_connection_close (bus->priv->connection, NULL, NULL, NULL);
633 }
634 
635 
636 static GObject*
ibus_bus_constructor(GType type,guint n_params,GObjectConstructParam * params)637 ibus_bus_constructor (GType                  type,
638                       guint                  n_params,
639                       GObjectConstructParam *params)
640 {
641     GObject *object;
642     GFile *file;
643 
644     /* share one IBusBus instance in whole application */
645     if (_bus == NULL) {
646         object = G_OBJECT_CLASS (ibus_bus_parent_class)->constructor (
647                 type, n_params, params);
648         /* make bus object sink */
649         g_object_ref_sink (object);
650         _bus = IBUS_BUS (object);
651 
652         _bus->priv->use_portal = ibus_bus_should_connect_portal (_bus);
653 
654         if (!_bus->priv->use_portal) {
655             file = g_file_new_for_path (ibus_get_socket_path ());
656             _bus->priv->monitor = g_file_monitor_file (file, 0, NULL, NULL);
657             g_signal_connect (_bus->priv->monitor, "changed",
658                               (GCallback) _changed_cb, _bus);
659             g_object_unref (file);
660         } else {
661             _bus->priv->portal_name_watch_id =
662                 g_bus_watch_name (G_BUS_TYPE_SESSION,
663                                   IBUS_SERVICE_PORTAL,
664                                   G_BUS_NAME_WATCHER_FLAGS_NONE,
665                                   portal_name_appeared,
666                                   portal_name_vanished,
667                                   _bus, NULL);
668         }
669 
670 
671         if (_bus->priv->connect_async)
672             ibus_bus_connect_async (_bus);
673         else
674             ibus_bus_connect (_bus);
675     }
676     else {
677         object = g_object_ref (G_OBJECT (_bus));
678     }
679 
680     return object;
681 }
682 
683 static void
ibus_bus_destroy(IBusObject * object)684 ibus_bus_destroy (IBusObject *object)
685 {
686     g_assert (_bus == (IBusBus *)object);
687 
688     IBusBus * bus = _bus;
689     _bus = NULL;
690 
691     if (bus->priv->monitor) {
692         g_object_unref (bus->priv->monitor);
693         bus->priv->monitor = NULL;
694     }
695 
696     if (bus->priv->config) {
697         ibus_proxy_destroy ((IBusProxy *) bus->priv->config);
698         bus->priv->config = NULL;
699     }
700 
701     if (bus->priv->connection) {
702         g_signal_handlers_disconnect_by_func (bus->priv->connection,
703                                               G_CALLBACK (_connection_closed_cb),
704                                               bus);
705         /* FIXME should use async close function */
706         g_dbus_connection_close_sync (bus->priv->connection, NULL, NULL);
707         g_object_unref (bus->priv->connection);
708         bus->priv->connection = NULL;
709     }
710 
711     g_free (bus->priv->unique_name);
712     bus->priv->unique_name = NULL;
713 
714     g_free (bus->priv->bus_address);
715     bus->priv->bus_address = NULL;
716 
717     g_cancellable_cancel (bus->priv->cancellable);
718     g_object_unref (bus->priv->cancellable);
719     bus->priv->cancellable = NULL;
720 
721     if (bus->priv->portal_name_watch_id) {
722         g_bus_unwatch_name (bus->priv->portal_name_watch_id);
723         bus->priv->portal_name_watch_id = 0;
724     }
725 
726     IBUS_OBJECT_CLASS (ibus_bus_parent_class)->destroy (object);
727 }
728 
729 static gboolean
_async_finish_void(GTask * task,GError ** error)730 _async_finish_void (GTask   *task,
731                     GError **error)
732 {
733     /* g_task_propagate_error() is not a public API and
734      * g_task_had_error() needs to be called before
735      * g_task_propagate_pointer() clears task->error.
736      */
737     gboolean had_error = g_task_had_error (task);
738     g_task_propagate_pointer (task, error);
739     if (had_error)
740         return FALSE;
741     return TRUE;
742 }
743 
744 static gchar *
_async_finish_object_path(GTask * task,GError ** error)745 _async_finish_object_path (GTask   *task,
746                            GError **error)
747 {
748     gboolean had_error = g_task_had_error (task);
749     GVariant *result = g_task_propagate_pointer (task, error);
750     GVariant *variant = NULL;
751     gchar *path = NULL;
752 
753     if (had_error) {
754         g_assert (result == NULL);
755         return NULL;
756     }
757     g_return_val_if_fail (result != NULL, NULL);
758     g_variant_get (result, "(v)", &variant);
759     path = g_variant_dup_string (variant, NULL);
760     g_variant_unref (variant);
761     g_variant_unref (result);
762     return path;
763 }
764 
765 static gchar *
_async_finish_string(GTask * task,GError ** error)766 _async_finish_string (GTask   *task,
767                       GError **error)
768 {
769     gboolean had_error = g_task_had_error (task);
770     GVariant *variant = g_task_propagate_pointer (task, error);
771     gchar *s = NULL;
772 
773     if (had_error) {
774         g_assert (variant == NULL);
775         return NULL;
776     }
777     g_return_val_if_fail (variant != NULL, NULL);
778     g_variant_get (variant, "(&s)", &s);
779     g_variant_unref (variant);
780     return s;
781 }
782 
783 static gboolean
_async_finish_gboolean(GTask * task,GError ** error)784 _async_finish_gboolean (GTask   *task,
785                         GError **error)
786 {
787     gboolean had_error = g_task_had_error (task);
788     GVariant *variant = g_task_propagate_pointer (task, error);
789     gboolean retval = FALSE;
790 
791     if (had_error) {
792         g_assert (variant == NULL);
793         return FALSE;
794     }
795     g_return_val_if_fail (variant != NULL, FALSE);
796     g_variant_get (variant, "(b)", &retval);
797     g_variant_unref (variant);
798     return retval;
799 }
800 
801 static guint
_async_finish_guint(GTask * task,GError ** error)802 _async_finish_guint (GTask   *task,
803                      GError **error)
804 {
805     gboolean had_error = g_task_had_error (task);
806     GVariant *variant = g_task_propagate_pointer (task, error);
807     static const guint bad_id = 0;
808     guint id = 0;
809 
810     if (had_error) {
811         g_assert (variant == NULL);
812         return bad_id;
813     }
814     g_return_val_if_fail (variant != NULL, bad_id);
815     g_variant_get (variant, "(u)", &id);
816     g_variant_unref (variant);
817     return id;
818 }
819 
820 IBusBus *
ibus_bus_new(void)821 ibus_bus_new (void)
822 {
823     IBusBus *bus = IBUS_BUS (g_object_new (IBUS_TYPE_BUS,
824                                            "connect-async", FALSE,
825                                            "client-only", FALSE,
826                                            NULL));
827 
828     return bus;
829 }
830 
831 IBusBus *
ibus_bus_new_async(void)832 ibus_bus_new_async (void)
833 {
834     IBusBus *bus = IBUS_BUS (g_object_new (IBUS_TYPE_BUS,
835                                            "connect-async", TRUE,
836                                            "client-only", FALSE,
837                                            NULL));
838 
839     return bus;
840 }
841 
842 IBusBus *
ibus_bus_new_async_client(void)843 ibus_bus_new_async_client (void)
844 {
845     IBusBus *bus = IBUS_BUS (g_object_new (IBUS_TYPE_BUS,
846                                            "connect-async", TRUE,
847                                            "client-only", TRUE,
848                                            NULL));
849 
850     return bus;
851 }
852 
853 gboolean
ibus_bus_is_connected(IBusBus * bus)854 ibus_bus_is_connected (IBusBus *bus)
855 {
856     g_return_val_if_fail (IBUS_IS_BUS (bus), FALSE);
857 
858     if (bus->priv->connection == NULL || g_dbus_connection_is_closed (bus->priv->connection))
859         return FALSE;
860 
861     return bus->priv->connected;
862 }
863 
864 IBusInputContext *
ibus_bus_create_input_context(IBusBus * bus,const gchar * client_name)865 ibus_bus_create_input_context (IBusBus      *bus,
866                                const gchar  *client_name)
867 {
868     g_return_val_if_fail (IBUS_IS_BUS (bus), NULL);
869     g_return_val_if_fail (client_name != NULL, NULL);
870 
871     gchar *path;
872     IBusInputContext *context = NULL;
873     GVariant *result;
874     result = ibus_bus_call_sync (bus,
875                                  IBUS_SERVICE_IBUS,
876                                  IBUS_PATH_IBUS,
877                                  IBUS_INTERFACE_IBUS,
878                                  "CreateInputContext",
879                                  g_variant_new ("(s)", client_name),
880                                  G_VARIANT_TYPE ("(o)"));
881 
882     if (result != NULL) {
883         GError *error = NULL;
884         g_variant_get (result, "(&o)", &path);
885         context = ibus_input_context_new (path, bus->priv->connection, NULL, &error);
886         g_variant_unref (result);
887         if (context == NULL) {
888             g_warning ("ibus_bus_create_input_context: %s", error->message);
889             g_error_free (error);
890         }
891     }
892 
893     return context;
894 }
895 
896 static void
_create_input_context_async_step_two_done(GObject * source_object,GAsyncResult * res,GTask * task)897 _create_input_context_async_step_two_done (GObject      *source_object,
898                                            GAsyncResult *res,
899                                            GTask        *task)
900 {
901     GError *error = NULL;
902     IBusInputContext *context =
903             ibus_input_context_new_async_finish (res, &error);
904     if (context == NULL)
905         g_task_return_error (task, error);
906     else
907         g_task_return_pointer (task, context, NULL);
908     g_object_unref (task);
909 }
910 
911 static void
_create_input_context_async_step_one_done(GDBusConnection * connection,GAsyncResult * res,GTask * task)912 _create_input_context_async_step_one_done (GDBusConnection *connection,
913                                            GAsyncResult    *res,
914                                            GTask           *task)
915 {
916     GError *error = NULL;
917     GVariant *variant = g_dbus_connection_call_finish (connection, res, &error);
918     const gchar *path = NULL;
919     IBusBus *bus;
920     GCancellable *cancellable;
921 
922     if (variant == NULL) {
923         g_task_return_error (task, error);
924         g_object_unref (task);
925         return;
926     }
927 
928     if (g_dbus_connection_is_closed (connection)) {
929         /*
930          * The connection is closed, can not continue next steps, so complete
931          * the asynchronous request with error.
932          */
933         g_variant_unref(variant);
934         g_task_return_new_error (task,
935                 G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Connection is closed.");
936         return;
937     }
938 
939     g_variant_get (variant, "(&o)", &path);
940     g_variant_unref(variant);
941 
942     bus = (IBusBus *)g_task_get_source_object (task);
943     g_assert (IBUS_IS_BUS (bus));
944 
945     cancellable = g_task_get_cancellable (task);
946 
947     ibus_input_context_new_async (path,
948             bus->priv->connection,
949             cancellable,
950             (GAsyncReadyCallback)_create_input_context_async_step_two_done,
951             task);
952 }
953 
954 void
ibus_bus_create_input_context_async(IBusBus * bus,const gchar * client_name,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)955 ibus_bus_create_input_context_async (IBusBus            *bus,
956                                      const gchar        *client_name,
957                                      gint                timeout_msec,
958                                      GCancellable       *cancellable,
959                                      GAsyncReadyCallback callback,
960                                      gpointer            user_data)
961 {
962     GTask *task;
963 
964     g_return_if_fail (IBUS_IS_BUS (bus));
965     g_return_if_fail (client_name != NULL);
966     g_return_if_fail (callback != NULL);
967 
968     task = g_task_new (bus, cancellable, callback, user_data);
969     g_task_set_source_tag (task, ibus_bus_create_input_context_async);
970 
971     /* do not use ibus_bus_call_async, instead use g_dbus_connection_call
972      * directly, because we need two async steps for create an IBusInputContext.
973      * 1. Call CreateInputContext to request ibus-daemon create a remote IC.
974      * 2. New local IBusInputContext proxy of the remote IC
975      */
976     g_dbus_connection_call (bus->priv->connection,
977             ibus_bus_get_service_name (bus),
978             IBUS_PATH_IBUS,
979             bus->priv->use_portal ? IBUS_INTERFACE_PORTAL : IBUS_INTERFACE_IBUS,
980             "CreateInputContext",
981             g_variant_new ("(s)", client_name),
982             G_VARIANT_TYPE("(o)"),
983             G_DBUS_CALL_FLAGS_NO_AUTO_START,
984             timeout_msec,
985             cancellable,
986             (GAsyncReadyCallback)_create_input_context_async_step_one_done,
987             task);
988 }
989 
990 IBusInputContext *
ibus_bus_create_input_context_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)991 ibus_bus_create_input_context_async_finish (IBusBus      *bus,
992                                             GAsyncResult *res,
993                                             GError      **error)
994 {
995     GTask *task;
996     gboolean had_error;
997     IBusInputContext *context = NULL;
998 
999     g_assert (IBUS_IS_BUS (bus));
1000     g_assert (g_task_is_valid (res, bus));
1001 
1002     task = G_TASK (res);
1003     g_assert (g_task_get_source_tag (task) ==
1004                       ibus_bus_create_input_context_async);
1005     had_error = g_task_had_error (task);
1006     context = g_task_propagate_pointer (task, error);
1007     if (had_error) {
1008         g_assert (context == NULL);
1009         return NULL;
1010     }
1011     g_assert (IBUS_IS_INPUT_CONTEXT (context));
1012     return context;
1013 }
1014 
1015 gchar *
ibus_bus_current_input_context(IBusBus * bus)1016 ibus_bus_current_input_context (IBusBus      *bus)
1017 {
1018     g_return_val_if_fail (IBUS_IS_BUS (bus), NULL);
1019 
1020     gchar *path = NULL;
1021     GVariant *result;
1022     result = ibus_bus_call_sync (bus,
1023                                  IBUS_SERVICE_IBUS,
1024                                  IBUS_PATH_IBUS,
1025                                  "org.freedesktop.DBus.Properties",
1026                                  "Get",
1027                                  g_variant_new ("(ss)",
1028                                                 IBUS_INTERFACE_IBUS,
1029                                                 "CurrentInputContext"),
1030                                  G_VARIANT_TYPE ("(v)"));
1031 
1032     if (result != NULL) {
1033         GVariant *variant = NULL;
1034         g_variant_get (result, "(v)", &variant);
1035         path = g_variant_dup_string (variant, NULL);
1036         g_variant_unref (variant);
1037         g_variant_unref (result);
1038     }
1039 
1040     return path;
1041 }
1042 
1043 void
ibus_bus_current_input_context_async(IBusBus * bus,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1044 ibus_bus_current_input_context_async (IBusBus            *bus,
1045                                       gint                timeout_msec,
1046                                       GCancellable       *cancellable,
1047                                       GAsyncReadyCallback callback,
1048                                       gpointer            user_data)
1049 {
1050     g_return_if_fail (IBUS_IS_BUS (bus));
1051 
1052     ibus_bus_call_async (bus,
1053                          IBUS_SERVICE_IBUS,
1054                          IBUS_PATH_IBUS,
1055                          "org.freedesktop.DBus.Properties",
1056                          "Get",
1057                          g_variant_new ("(ss)",
1058                                         IBUS_INTERFACE_IBUS,
1059                                         "CurrentInputContext"),
1060                          G_VARIANT_TYPE ("(v)"),
1061                          ibus_bus_current_input_context_async,
1062                          timeout_msec,
1063                          cancellable,
1064                          callback,
1065                          user_data);
1066 }
1067 
1068 gchar *
ibus_bus_current_input_context_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)1069 ibus_bus_current_input_context_async_finish (IBusBus      *bus,
1070                                              GAsyncResult *res,
1071                                              GError      **error)
1072 {
1073     GTask *task;
1074 
1075     g_assert (IBUS_IS_BUS (bus));
1076     g_assert (g_task_is_valid (res, bus));
1077 
1078     task = G_TASK (res);
1079     g_assert(g_task_get_source_tag (task) ==
1080                      ibus_bus_current_input_context_async);
1081     return _async_finish_object_path (task, error);
1082 }
1083 
1084 static void
ibus_bus_watch_dbus_signal(IBusBus * bus)1085 ibus_bus_watch_dbus_signal (IBusBus *bus)
1086 {
1087     g_return_if_fail (bus->priv->connection != NULL);
1088     g_return_if_fail (bus->priv->watch_dbus_signal_id == 0);
1089 
1090     /* Subscribe to dbus signals such as NameOwnerChanged. */
1091     bus->priv->watch_dbus_signal_id
1092         = g_dbus_connection_signal_subscribe (bus->priv->connection,
1093                                               DBUS_SERVICE_DBUS,
1094                                               DBUS_INTERFACE_DBUS,
1095                                               "NameOwnerChanged",
1096                                               DBUS_PATH_DBUS,
1097                                               NULL /* arg0 */,
1098                                               (GDBusSignalFlags) 0,
1099                                               _connection_dbus_signal_cb,
1100                                               bus,
1101                                               NULL /* user_data_free_func */);
1102     /* FIXME handle other D-Bus signals if needed */
1103 }
1104 
1105 static void
ibus_bus_unwatch_dbus_signal(IBusBus * bus)1106 ibus_bus_unwatch_dbus_signal (IBusBus *bus)
1107 {
1108     g_return_if_fail (bus->priv->watch_dbus_signal_id != 0);
1109     g_dbus_connection_signal_unsubscribe (bus->priv->connection,
1110                                           bus->priv->watch_dbus_signal_id);
1111     bus->priv->watch_dbus_signal_id = 0;
1112 }
1113 
1114 void
ibus_bus_set_watch_dbus_signal(IBusBus * bus,gboolean watch)1115 ibus_bus_set_watch_dbus_signal (IBusBus        *bus,
1116                                 gboolean        watch)
1117 {
1118     g_return_if_fail (IBUS_IS_BUS (bus));
1119 
1120     if (bus->priv->watch_dbus_signal == watch)
1121         return;
1122 
1123     bus->priv->watch_dbus_signal = watch;
1124 
1125     if (ibus_bus_is_connected (bus)) {
1126         if (watch) {
1127             ibus_bus_watch_dbus_signal (bus);
1128         }
1129         else {
1130             ibus_bus_unwatch_dbus_signal (bus);
1131         }
1132     }
1133 }
1134 
1135 static void
ibus_bus_watch_ibus_signal(IBusBus * bus)1136 ibus_bus_watch_ibus_signal (IBusBus *bus)
1137 {
1138     g_return_if_fail (bus->priv->connection != NULL);
1139     g_return_if_fail (bus->priv->watch_ibus_signal_id == 0);
1140 
1141     /* Subscribe to ibus signals such as GlboalEngineChanged. */
1142     bus->priv->watch_ibus_signal_id
1143         = g_dbus_connection_signal_subscribe (bus->priv->connection,
1144                                               "org.freedesktop.IBus",
1145                                               IBUS_INTERFACE_IBUS,
1146                                               "GlobalEngineChanged",
1147                                               IBUS_PATH_IBUS,
1148                                               NULL /* arg0 */,
1149                                               (GDBusSignalFlags) 0,
1150                                               _connection_ibus_signal_cb,
1151                                               bus,
1152                                               NULL /* user_data_free_func */);
1153     /* FIXME handle org.freedesktop.IBus.RegistryChanged signal if needed */
1154 }
1155 
1156 static void
ibus_bus_unwatch_ibus_signal(IBusBus * bus)1157 ibus_bus_unwatch_ibus_signal (IBusBus *bus)
1158 {
1159     g_return_if_fail (bus->priv->watch_ibus_signal_id != 0);
1160     g_dbus_connection_signal_unsubscribe (bus->priv->connection,
1161                                           bus->priv->watch_ibus_signal_id);
1162     bus->priv->watch_ibus_signal_id = 0;
1163 }
1164 
1165 void
ibus_bus_set_watch_ibus_signal(IBusBus * bus,gboolean watch)1166 ibus_bus_set_watch_ibus_signal (IBusBus        *bus,
1167                                 gboolean        watch)
1168 {
1169     g_return_if_fail (IBUS_IS_BUS (bus));
1170 
1171     if (bus->priv->watch_ibus_signal == watch)
1172         return;
1173 
1174     bus->priv->watch_ibus_signal = watch;
1175 
1176     if (ibus_bus_is_connected (bus)) {
1177         if (watch) {
1178             ibus_bus_watch_ibus_signal (bus);
1179         }
1180         else {
1181             ibus_bus_unwatch_ibus_signal (bus);
1182         }
1183     }
1184 }
1185 
1186 const gchar *
ibus_bus_hello(IBusBus * bus)1187 ibus_bus_hello (IBusBus *bus)
1188 {
1189     g_return_val_if_fail (IBUS_IS_BUS (bus), NULL);
1190     g_return_val_if_fail (ibus_bus_is_connected (bus), NULL);
1191 
1192     /* gdbus connection will say hello by self. */
1193     if (bus->priv->connection)
1194         return g_dbus_connection_get_unique_name (bus->priv->connection);
1195     return NULL;
1196 }
1197 
1198 guint32
ibus_bus_request_name(IBusBus * bus,const gchar * name,guint32 flags)1199 ibus_bus_request_name (IBusBus      *bus,
1200                        const gchar  *name,
1201                        guint32       flags)
1202 {
1203     g_return_val_if_fail (IBUS_IS_BUS (bus), 0);
1204     g_return_val_if_fail (name != NULL, 0);
1205 
1206     guint32 retval = 0;
1207     GVariant *result;
1208     result = ibus_bus_call_sync (bus,
1209                                  DBUS_SERVICE_DBUS,
1210                                  DBUS_PATH_DBUS,
1211                                  DBUS_INTERFACE_DBUS,
1212                                  "RequestName",
1213                                  g_variant_new ("(su)", name, flags),
1214                                  G_VARIANT_TYPE ("(u)"));
1215 
1216     if (result) {
1217         g_variant_get (result, "(u)", &retval);
1218         g_variant_unref (result);
1219     }
1220 
1221     return retval;
1222 }
1223 
1224 void
ibus_bus_request_name_async(IBusBus * bus,const gchar * name,guint flags,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1225 ibus_bus_request_name_async (IBusBus            *bus,
1226                              const gchar        *name,
1227                              guint               flags,
1228                              gint                timeout_msec,
1229                              GCancellable       *cancellable,
1230                              GAsyncReadyCallback callback,
1231                              gpointer            user_data)
1232 {
1233     g_return_if_fail (IBUS_IS_BUS (bus));
1234     g_return_if_fail (name != NULL);
1235 
1236     ibus_bus_call_async (bus,
1237                          DBUS_SERVICE_DBUS,
1238                          DBUS_PATH_DBUS,
1239                          DBUS_INTERFACE_DBUS,
1240                          "RequestName",
1241                          g_variant_new ("(su)", name, flags),
1242                          G_VARIANT_TYPE ("(u)"),
1243                          ibus_bus_request_name_async,
1244                          timeout_msec,
1245                          cancellable,
1246                          callback,
1247                          user_data);
1248 }
1249 
1250 guint
ibus_bus_request_name_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)1251 ibus_bus_request_name_async_finish (IBusBus      *bus,
1252                                     GAsyncResult *res,
1253                                     GError      **error)
1254 {
1255     GTask *task;
1256 
1257     g_assert (IBUS_IS_BUS (bus));
1258     g_assert (g_task_is_valid (res, bus));
1259 
1260     task = G_TASK (res);
1261     g_assert(g_task_get_source_tag (task) == ibus_bus_request_name_async);
1262     return _async_finish_guint (task, error);
1263 }
1264 
1265 guint
ibus_bus_release_name(IBusBus * bus,const gchar * name)1266 ibus_bus_release_name (IBusBus      *bus,
1267                        const gchar  *name)
1268 {
1269     g_return_val_if_fail (IBUS_IS_BUS (bus), 0);
1270     g_return_val_if_fail (name != NULL, 0);
1271 
1272     guint retval = 0;
1273     GVariant *result;
1274     result = ibus_bus_call_sync (bus,
1275                                  DBUS_SERVICE_DBUS,
1276                                  DBUS_PATH_DBUS,
1277                                  DBUS_INTERFACE_DBUS,
1278                                  "ReleaseName",
1279                                  g_variant_new ("(s)", name),
1280                                  G_VARIANT_TYPE ("(u)"));
1281 
1282     if (result) {
1283         g_variant_get (result, "(u)", &retval);
1284         g_variant_unref (result);
1285     }
1286 
1287     return retval;
1288 }
1289 
1290 void
ibus_bus_release_name_async(IBusBus * bus,const gchar * name,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1291 ibus_bus_release_name_async (IBusBus            *bus,
1292                              const gchar        *name,
1293                              gint                timeout_msec,
1294                              GCancellable       *cancellable,
1295                              GAsyncReadyCallback callback,
1296                              gpointer            user_data)
1297 {
1298     g_return_if_fail (IBUS_IS_BUS (bus));
1299     g_return_if_fail (name != NULL);
1300 
1301     ibus_bus_call_async (bus,
1302                          DBUS_SERVICE_DBUS,
1303                          DBUS_PATH_DBUS,
1304                          DBUS_INTERFACE_DBUS,
1305                          "ReleaseName",
1306                          g_variant_new ("(s)", name),
1307                          G_VARIANT_TYPE ("(u)"),
1308                          ibus_bus_release_name_async,
1309                          timeout_msec,
1310                          cancellable,
1311                          callback,
1312                          user_data);
1313 }
1314 
1315 guint
ibus_bus_release_name_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)1316 ibus_bus_release_name_async_finish (IBusBus      *bus,
1317                                     GAsyncResult *res,
1318                                     GError      **error)
1319 {
1320     GTask *task;
1321 
1322     g_assert (IBUS_IS_BUS (bus));
1323     g_assert (g_task_is_valid (res, bus));
1324 
1325     task = G_TASK (res);
1326     g_assert(g_task_get_source_tag (task) == ibus_bus_release_name_async);
1327     return _async_finish_guint (task, error);
1328 }
1329 
1330 GList *
ibus_bus_list_queued_owners(IBusBus * bus,const gchar * name)1331 ibus_bus_list_queued_owners (IBusBus      *bus,
1332                              const gchar  *name)
1333 {
1334     GList *retval = NULL;
1335     GVariant *result;
1336 
1337     g_return_val_if_fail (IBUS_IS_BUS (bus), NULL);
1338     g_return_val_if_fail (name != NULL, NULL);
1339 
1340     result = ibus_bus_call_sync (bus,
1341                                  DBUS_SERVICE_DBUS,
1342                                  DBUS_PATH_DBUS,
1343                                  DBUS_INTERFACE_DBUS,
1344                                  "ListQueuedOwners",
1345                                  g_variant_new ("(s)", name),
1346                                  G_VARIANT_TYPE ("(as)"));
1347 
1348     if (result) {
1349         GVariantIter *iter = NULL;
1350         const gchar *name = NULL;
1351         g_variant_get (result, "(as)", &iter);
1352         while (g_variant_iter_loop (iter, "&s", &name)) {
1353             if (name == NULL) {
1354                 continue;
1355             }
1356             retval = g_list_append (retval, g_strdup (name));
1357         }
1358         g_variant_iter_free (iter);
1359         g_variant_unref (result);
1360     }
1361 
1362     return retval;
1363 }
1364 
1365 gboolean
ibus_bus_name_has_owner(IBusBus * bus,const gchar * name)1366 ibus_bus_name_has_owner (IBusBus        *bus,
1367                          const gchar    *name)
1368 {
1369     g_return_val_if_fail (IBUS_IS_BUS (bus), FALSE);
1370     g_return_val_if_fail (name != NULL, FALSE);
1371 
1372     gboolean retval = FALSE;
1373     GVariant *result;
1374     result = ibus_bus_call_sync (bus,
1375                                  DBUS_SERVICE_DBUS,
1376                                  DBUS_PATH_DBUS,
1377                                  DBUS_INTERFACE_DBUS,
1378                                  "NameHasOwner",
1379                                  g_variant_new ("(s)", name),
1380                                  G_VARIANT_TYPE ("(b)"));
1381 
1382     if (result) {
1383         g_variant_get (result, "(b)", &retval);
1384         g_variant_unref (result);
1385     }
1386 
1387     return retval;
1388 }
1389 
1390 void
ibus_bus_name_has_owner_async(IBusBus * bus,const gchar * name,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1391 ibus_bus_name_has_owner_async (IBusBus            *bus,
1392                                const gchar        *name,
1393                                gint                timeout_msec,
1394                                GCancellable       *cancellable,
1395                                GAsyncReadyCallback callback,
1396                                gpointer            user_data)
1397 {
1398     g_return_if_fail (IBUS_IS_BUS (bus));
1399     g_return_if_fail (name != NULL);
1400 
1401     ibus_bus_call_async (bus,
1402                          DBUS_SERVICE_DBUS,
1403                          DBUS_PATH_DBUS,
1404                          DBUS_INTERFACE_DBUS,
1405                          "NameHasOwner",
1406                          g_variant_new ("(s)", name),
1407                          G_VARIANT_TYPE ("(b)"),
1408                          ibus_bus_name_has_owner_async,
1409                          timeout_msec,
1410                          cancellable,
1411                          callback,
1412                          user_data);
1413 }
1414 
1415 gboolean
ibus_bus_name_has_owner_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)1416 ibus_bus_name_has_owner_async_finish (IBusBus      *bus,
1417                                       GAsyncResult *res,
1418                                       GError      **error)
1419 {
1420     GTask *task;
1421 
1422     g_assert (IBUS_IS_BUS (bus));
1423     g_assert (g_task_is_valid (res, bus));
1424 
1425     task = G_TASK (res);
1426     g_assert(g_task_get_source_tag (task) == ibus_bus_name_has_owner_async);
1427     return _async_finish_gboolean (task, error);
1428 }
1429 
1430 GList *
ibus_bus_list_names(IBusBus * bus)1431 ibus_bus_list_names (IBusBus    *bus)
1432 {
1433     g_return_val_if_fail (IBUS_IS_BUS (bus), NULL);
1434     return NULL;
1435 }
1436 
1437 gboolean
ibus_bus_add_match(IBusBus * bus,const gchar * rule)1438 ibus_bus_add_match (IBusBus     *bus,
1439                     const gchar *rule)
1440 {
1441     g_return_val_if_fail (IBUS_IS_BUS (bus), FALSE);
1442     g_return_val_if_fail (rule != NULL, FALSE);
1443 
1444     GVariant *result;
1445     result = ibus_bus_call_sync (bus,
1446                                  DBUS_SERVICE_DBUS,
1447                                  DBUS_PATH_DBUS,
1448                                  DBUS_INTERFACE_DBUS,
1449                                  "AddMatch",
1450                                  g_variant_new ("(s)", rule),
1451                                  NULL);
1452 
1453     if (result) {
1454         g_variant_unref (result);
1455         return TRUE;
1456     }
1457     return FALSE;
1458 }
1459 
1460 void
ibus_bus_add_match_async(IBusBus * bus,const gchar * rule,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1461 ibus_bus_add_match_async (IBusBus            *bus,
1462                           const gchar        *rule,
1463                           gint                timeout_msec,
1464                           GCancellable       *cancellable,
1465                           GAsyncReadyCallback callback,
1466                           gpointer            user_data)
1467 {
1468     g_return_if_fail (IBUS_IS_BUS (bus));
1469     g_return_if_fail (rule != NULL);
1470 
1471     ibus_bus_call_async (bus,
1472                          DBUS_SERVICE_DBUS,
1473                          DBUS_PATH_DBUS,
1474                          DBUS_INTERFACE_DBUS,
1475                          "AddMatch",
1476                          g_variant_new ("(s)", rule),
1477                          NULL,
1478                          ibus_bus_add_match_async,
1479                          timeout_msec,
1480                          cancellable,
1481                          callback,
1482                          user_data);
1483 }
1484 
1485 gboolean
ibus_bus_add_match_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)1486 ibus_bus_add_match_async_finish (IBusBus      *bus,
1487                                  GAsyncResult *res,
1488                                  GError      **error)
1489 {
1490     GTask *task;
1491 
1492     g_assert (IBUS_IS_BUS (bus));
1493     g_assert (g_task_is_valid (res, bus));
1494 
1495     task = G_TASK (res);
1496     g_assert(g_task_get_source_tag (task) == ibus_bus_add_match_async);
1497     return _async_finish_void (task, error);
1498 }
1499 
1500 gboolean
ibus_bus_remove_match(IBusBus * bus,const gchar * rule)1501 ibus_bus_remove_match (IBusBus      *bus,
1502                        const gchar  *rule)
1503 {
1504     g_return_val_if_fail (IBUS_IS_BUS (bus), FALSE);
1505     g_return_val_if_fail (rule != NULL, FALSE);
1506 
1507     GVariant *result;
1508     result = ibus_bus_call_sync (bus,
1509                                  DBUS_SERVICE_DBUS,
1510                                  DBUS_PATH_DBUS,
1511                                  DBUS_INTERFACE_DBUS,
1512                                  "RemoveMatch",
1513                                  g_variant_new ("(s)", rule),
1514                                  NULL);
1515 
1516     if (result) {
1517         g_variant_unref (result);
1518         return TRUE;
1519     }
1520     return FALSE;
1521 }
1522 
1523 void
ibus_bus_remove_match_async(IBusBus * bus,const gchar * rule,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1524 ibus_bus_remove_match_async (IBusBus            *bus,
1525                              const gchar        *rule,
1526                              gint                timeout_msec,
1527                              GCancellable       *cancellable,
1528                              GAsyncReadyCallback callback,
1529                              gpointer            user_data)
1530 {
1531     g_return_if_fail (IBUS_IS_BUS (bus));
1532     g_return_if_fail (rule != NULL);
1533 
1534     ibus_bus_call_async (bus,
1535                          DBUS_SERVICE_DBUS,
1536                          DBUS_PATH_DBUS,
1537                          DBUS_INTERFACE_DBUS,
1538                          "RemoveMatch",
1539                          g_variant_new ("(s)", rule),
1540                          NULL,
1541                          ibus_bus_remove_match_async,
1542                          timeout_msec,
1543                          cancellable,
1544                          callback,
1545                          user_data);
1546 }
1547 
1548 gboolean
ibus_bus_remove_match_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)1549 ibus_bus_remove_match_async_finish (IBusBus      *bus,
1550                                     GAsyncResult *res,
1551                                     GError      **error)
1552 {
1553     GTask *task;
1554 
1555     g_assert (IBUS_IS_BUS (bus));
1556     g_assert (g_task_is_valid (res, bus));
1557 
1558     task = G_TASK (res);
1559     g_assert(g_task_get_source_tag (task) == ibus_bus_remove_match_async);
1560     return _async_finish_void (task, error);
1561 }
1562 
1563 gchar *
ibus_bus_get_name_owner(IBusBus * bus,const gchar * name)1564 ibus_bus_get_name_owner (IBusBus        *bus,
1565                          const gchar    *name)
1566 {
1567     g_return_val_if_fail (IBUS_IS_BUS (bus), NULL);
1568     g_return_val_if_fail (name != NULL, NULL);
1569 
1570     gchar *retval = NULL;
1571     GVariant *result;
1572     result = ibus_bus_call_sync (bus,
1573                                  DBUS_SERVICE_DBUS,
1574                                  DBUS_PATH_DBUS,
1575                                  DBUS_INTERFACE_DBUS,
1576                                  "GetNameOwner",
1577                                  g_variant_new ("(s)", name),
1578                                  G_VARIANT_TYPE ("(s)"));
1579 
1580     if (result) {
1581         g_variant_get (result, "(s)", &retval);
1582         g_variant_unref (result);
1583     }
1584 
1585     return retval;
1586 }
1587 
1588 void
ibus_bus_get_name_owner_async(IBusBus * bus,const gchar * name,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1589 ibus_bus_get_name_owner_async (IBusBus            *bus,
1590                                const gchar        *name,
1591                                gint                timeout_msec,
1592                                GCancellable       *cancellable,
1593                                GAsyncReadyCallback callback,
1594                                gpointer            user_data)
1595 {
1596     g_return_if_fail (IBUS_IS_BUS (bus));
1597     g_return_if_fail (name != NULL);
1598 
1599     ibus_bus_call_async (bus,
1600                          DBUS_SERVICE_DBUS,
1601                          DBUS_PATH_DBUS,
1602                          DBUS_INTERFACE_DBUS,
1603                          "GetNameOwner",
1604                          g_variant_new ("(s)", name),
1605                          G_VARIANT_TYPE ("(s)"),
1606                          ibus_bus_get_name_owner_async,
1607                          timeout_msec,
1608                          cancellable,
1609                          callback,
1610                          user_data);
1611 }
1612 
1613 gchar *
ibus_bus_get_name_owner_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)1614 ibus_bus_get_name_owner_async_finish (IBusBus      *bus,
1615                                       GAsyncResult *res,
1616                                       GError      **error)
1617 {
1618     GTask *task;
1619 
1620     g_assert (IBUS_IS_BUS (bus));
1621     g_assert (g_task_is_valid (res, bus));
1622 
1623     task = G_TASK (res);
1624     g_assert(g_task_get_source_tag (task) == ibus_bus_get_name_owner_async);
1625     return g_strdup (_async_finish_string (task, error));
1626 }
1627 
1628 GDBusConnection *
ibus_bus_get_connection(IBusBus * bus)1629 ibus_bus_get_connection (IBusBus *bus)
1630 {
1631     g_return_val_if_fail (IBUS_IS_BUS (bus), NULL);
1632 
1633     return bus->priv->connection;
1634 }
1635 
1636 const gchar *
ibus_bus_get_service_name(IBusBus * bus)1637 ibus_bus_get_service_name (IBusBus *bus)
1638 {
1639     if (bus->priv->use_portal)
1640         return IBUS_SERVICE_PORTAL;
1641     return IBUS_SERVICE_IBUS;
1642 }
1643 
1644 gboolean
ibus_bus_exit(IBusBus * bus,gboolean restart)1645 ibus_bus_exit (IBusBus *bus,
1646                gboolean restart)
1647 {
1648     g_return_val_if_fail (IBUS_IS_BUS (bus), FALSE);
1649 
1650     GVariant *result;
1651     result = ibus_bus_call_sync (bus,
1652                                  IBUS_SERVICE_IBUS,
1653                                  IBUS_PATH_IBUS,
1654                                  IBUS_INTERFACE_IBUS,
1655                                  "Exit",
1656                                  g_variant_new ("(b)", restart),
1657                                  NULL);
1658 
1659     ibus_bus_close_connection (bus);
1660 
1661     if (result) {
1662         g_variant_unref (result);
1663         return TRUE;
1664     }
1665     return FALSE;
1666 }
1667 
1668 void
ibus_bus_exit_async(IBusBus * bus,gboolean restart,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1669 ibus_bus_exit_async (IBusBus            *bus,
1670                      gboolean            restart,
1671                      gint                timeout_msec,
1672                      GCancellable       *cancellable,
1673                      GAsyncReadyCallback callback,
1674                      gpointer            user_data)
1675 {
1676     g_return_if_fail (IBUS_IS_BUS (bus));
1677 
1678     ibus_bus_call_async (bus,
1679                          IBUS_SERVICE_IBUS,
1680                          IBUS_PATH_IBUS,
1681                          IBUS_INTERFACE_IBUS,
1682                          "Exit",
1683                          g_variant_new ("(b)", restart),
1684                          NULL,
1685                          ibus_bus_exit_async,
1686                          timeout_msec,
1687                          cancellable,
1688                          callback,
1689                          user_data);
1690 }
1691 
1692 gboolean
ibus_bus_exit_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)1693 ibus_bus_exit_async_finish (IBusBus      *bus,
1694                             GAsyncResult *res,
1695                             GError      **error)
1696 {
1697     GTask *task;
1698 
1699     g_assert (IBUS_IS_BUS (bus));
1700     g_assert (g_task_is_valid (res, bus));
1701 
1702     task = G_TASK (res);
1703     g_assert (g_task_get_source_tag (task) == ibus_bus_exit_async);
1704     return _async_finish_void (task, error);
1705 }
1706 
1707 gboolean
ibus_bus_register_component(IBusBus * bus,IBusComponent * component)1708 ibus_bus_register_component (IBusBus       *bus,
1709                              IBusComponent *component)
1710 {
1711     g_return_val_if_fail (IBUS_IS_BUS (bus), FALSE);
1712     g_return_val_if_fail (IBUS_IS_COMPONENT (component), FALSE);
1713 
1714     GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)component);
1715     GVariant *result = ibus_bus_call_sync (bus,
1716                                            IBUS_SERVICE_IBUS,
1717                                            IBUS_PATH_IBUS,
1718                                            IBUS_INTERFACE_IBUS,
1719                                            "RegisterComponent",
1720                                            g_variant_new ("(v)", variant),
1721                                            NULL);
1722     if (result) {
1723         g_variant_unref (result);
1724         return TRUE;
1725     }
1726     return FALSE;
1727 }
1728 
1729 void
ibus_bus_register_component_async(IBusBus * bus,IBusComponent * component,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1730 ibus_bus_register_component_async (IBusBus            *bus,
1731                                    IBusComponent      *component,
1732                                    gint                timeout_msec,
1733                                    GCancellable       *cancellable,
1734                                    GAsyncReadyCallback callback,
1735                                    gpointer            user_data)
1736 {
1737     g_return_if_fail (IBUS_IS_BUS (bus));
1738     g_return_if_fail (IBUS_IS_COMPONENT (component));
1739 
1740     GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)component);
1741     ibus_bus_call_async (bus,
1742                          IBUS_SERVICE_IBUS,
1743                          IBUS_PATH_IBUS,
1744                          IBUS_INTERFACE_IBUS,
1745                          "RegisterComponent",
1746                          g_variant_new ("(v)", variant),
1747                          NULL,
1748                          ibus_bus_register_component_async,
1749                          timeout_msec,
1750                          cancellable,
1751                          callback,
1752                          user_data);
1753 }
1754 
1755 gboolean
ibus_bus_register_component_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)1756 ibus_bus_register_component_async_finish (IBusBus      *bus,
1757                                           GAsyncResult *res,
1758                                           GError      **error)
1759 {
1760     GTask *task;
1761 
1762     g_assert (IBUS_IS_BUS (bus));
1763     g_assert (g_task_is_valid (res, bus));
1764 
1765     task = G_TASK (res);
1766     g_assert (
1767             g_task_get_source_tag (task) == ibus_bus_register_component_async);
1768     return _async_finish_void (task, error);
1769 }
1770 
1771 static GList *
ibus_bus_do_list_engines(IBusBus * bus,gboolean active_engines_only)1772 ibus_bus_do_list_engines (IBusBus *bus, gboolean active_engines_only)
1773 {
1774     g_return_val_if_fail (IBUS_IS_BUS (bus), NULL);
1775 
1776     GList *retval = NULL;
1777     GVariant *result;
1778     const gchar *property =
1779             active_engines_only ? "ActiveEngines" : "Engines";
1780     result = ibus_bus_call_sync (bus,
1781                                  IBUS_SERVICE_IBUS,
1782                                  IBUS_PATH_IBUS,
1783                                  "org.freedesktop.DBus.Properties",
1784                                  "Get",
1785                                  g_variant_new ("(ss)",
1786                                                 IBUS_INTERFACE_IBUS,
1787                                                 property),
1788                                  G_VARIANT_TYPE ("(v)"));
1789 
1790     if (result) {
1791         GVariant *variant = NULL;
1792         GVariantIter *iter = NULL;
1793 
1794         g_variant_get (result, "(v)", &variant);
1795         iter = g_variant_iter_new (variant);
1796         GVariant *var;
1797         while (g_variant_iter_loop (iter, "v", &var)) {
1798             IBusSerializable *serializable = ibus_serializable_deserialize (var);
1799             g_object_ref_sink (serializable);
1800             retval = g_list_append (retval, serializable);
1801         }
1802         g_variant_iter_free (iter);
1803         g_variant_unref (variant);
1804         g_variant_unref (result);
1805     }
1806 
1807     return retval;
1808 }
1809 
1810 GList *
ibus_bus_list_engines(IBusBus * bus)1811 ibus_bus_list_engines (IBusBus *bus)
1812 {
1813     return ibus_bus_do_list_engines (bus, FALSE);
1814 }
1815 
1816 void
ibus_bus_list_engines_async(IBusBus * bus,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1817 ibus_bus_list_engines_async (IBusBus            *bus,
1818                              gint                timeout_msec,
1819                              GCancellable       *cancellable,
1820                              GAsyncReadyCallback callback,
1821                              gpointer            user_data)
1822 {
1823     g_return_if_fail (IBUS_IS_BUS (bus));
1824 
1825     ibus_bus_call_async (bus,
1826                          IBUS_SERVICE_IBUS,
1827                          IBUS_PATH_IBUS,
1828                          "org.freedesktop.DBus.Properties",
1829                          "Get",
1830                          g_variant_new ("(ss)",
1831                                         IBUS_INTERFACE_IBUS,
1832                                         "Engines"),
1833                          G_VARIANT_TYPE ("(v)"),
1834                          ibus_bus_list_engines_async,
1835                          timeout_msec,
1836                          cancellable,
1837                          callback,
1838                          user_data);
1839 }
1840 
1841 GList *
ibus_bus_list_engines_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)1842 ibus_bus_list_engines_async_finish (IBusBus      *bus,
1843                                     GAsyncResult *res,
1844                                     GError      **error)
1845 {
1846     GTask *task;
1847     gboolean had_error;
1848     GVariant *result = NULL;
1849     GVariant *variant = NULL;
1850     GList *retval = NULL;
1851     GVariantIter *iter = NULL;
1852     GVariant *var;
1853 
1854     g_assert (g_task_is_valid (res, bus));
1855 
1856     task = G_TASK (res);
1857     had_error = g_task_had_error (task);
1858     result = g_task_propagate_pointer (task, error);
1859     if (had_error) {
1860         g_assert (result == NULL);
1861         return NULL;
1862     }
1863     g_return_val_if_fail (result != NULL, NULL);
1864 
1865     g_variant_get (result, "(v)", &variant);
1866     iter = g_variant_iter_new (variant);
1867     while (g_variant_iter_loop (iter, "v", &var)) {
1868         IBusSerializable *serializable = ibus_serializable_deserialize (var);
1869         g_object_ref_sink (serializable);
1870         retval = g_list_append (retval, serializable);
1871     }
1872     g_variant_iter_free (iter);
1873     g_variant_unref (variant);
1874     g_variant_unref (result);
1875     return retval;
1876 }
1877 
1878 #ifndef IBUS_DISABLE_DEPRECATED
1879 GList *
ibus_bus_list_active_engines(IBusBus * bus)1880 ibus_bus_list_active_engines (IBusBus *bus)
1881 {
1882     return ibus_bus_do_list_engines (bus, TRUE);
1883 }
1884 
1885 void
ibus_bus_list_active_engines_async(IBusBus * bus,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1886 ibus_bus_list_active_engines_async (IBusBus            *bus,
1887                                     gint                timeout_msec,
1888                                     GCancellable       *cancellable,
1889                                     GAsyncReadyCallback callback,
1890                                     gpointer            user_data)
1891 {
1892     g_return_if_fail (IBUS_IS_BUS (bus));
1893 
1894     ibus_bus_call_async (bus,
1895                          IBUS_SERVICE_IBUS,
1896                          IBUS_PATH_IBUS,
1897                          "org.freedesktop.DBus.Properties",
1898                          "Get",
1899                          g_variant_new ("(ss)",
1900                                         IBUS_INTERFACE_IBUS,
1901                                         "ActiveEngines"),
1902                          G_VARIANT_TYPE ("(v)"),
1903                          ibus_bus_list_active_engines_async,
1904                          timeout_msec,
1905                          cancellable,
1906                          callback,
1907                          user_data);
1908 }
1909 
1910 GList *
ibus_bus_list_active_engines_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)1911 ibus_bus_list_active_engines_async_finish (IBusBus      *bus,
1912                                            GAsyncResult *res,
1913                                            GError      **error)
1914 {
1915     return ibus_bus_list_engines_async_finish (bus, res, error);
1916 }
1917 #endif /* IBUS_DISABLE_DEPRECATED */
1918 
1919 IBusEngineDesc **
ibus_bus_get_engines_by_names(IBusBus * bus,const gchar * const * names)1920 ibus_bus_get_engines_by_names (IBusBus             *bus,
1921                                const gchar * const *names)
1922 {
1923     g_return_val_if_fail (IBUS_IS_BUS (bus), NULL);
1924 
1925     GVariant *result;
1926     result = ibus_bus_call_sync (bus,
1927                                  IBUS_SERVICE_IBUS,
1928                                  IBUS_PATH_IBUS,
1929                                  IBUS_INTERFACE_IBUS,
1930                                  "GetEnginesByNames",
1931                                  g_variant_new("(^as)", names),
1932                                  G_VARIANT_TYPE ("(av)"));
1933     if (result == NULL)
1934         return NULL;
1935 
1936     GArray *array = g_array_new (TRUE, TRUE, sizeof (IBusEngineDesc *));
1937     GVariantIter *iter = NULL;
1938     g_variant_get (result, "(av)", &iter);
1939     GVariant *var;
1940     while (g_variant_iter_loop (iter, "v", &var)) {
1941         IBusEngineDesc *desc = (IBusEngineDesc *) ibus_serializable_deserialize (var);
1942         g_object_ref_sink (desc);
1943         g_array_append_val (array, desc);
1944     }
1945     g_variant_iter_free (iter);
1946     g_variant_unref (result);
1947 
1948     return (IBusEngineDesc **)g_array_free (array, FALSE);
1949 }
1950 
1951 static void
_config_destroy_cb(IBusConfig * config,IBusBus * bus)1952 _config_destroy_cb (IBusConfig *config,
1953                     IBusBus    *bus)
1954 {
1955     IBusBusPrivate *priv;
1956     priv = IBUS_BUS_GET_PRIVATE (bus);
1957 
1958     g_assert (priv->config == config);
1959 
1960     g_object_unref (config);
1961     priv->config = NULL;
1962 }
1963 
1964 IBusConfig *
ibus_bus_get_config(IBusBus * bus)1965 ibus_bus_get_config (IBusBus *bus)
1966 {
1967     g_assert (IBUS_IS_BUS (bus));
1968     g_return_val_if_fail (ibus_bus_is_connected (bus), NULL);
1969 
1970     IBusBusPrivate *priv;
1971     priv = IBUS_BUS_GET_PRIVATE (bus);
1972 
1973     if (priv->config == NULL && priv->connection) {
1974         priv->config = ibus_config_new (priv->connection, NULL, NULL);
1975         if (priv->config) {
1976             g_signal_connect (priv->config, "destroy", G_CALLBACK (_config_destroy_cb), bus);
1977         }
1978     }
1979 
1980     return priv->config;
1981 }
1982 
1983 #ifndef IBUS_DISABLE_DEPRECATED
1984 gboolean
ibus_bus_get_use_sys_layout(IBusBus * bus)1985 ibus_bus_get_use_sys_layout (IBusBus *bus)
1986 {
1987     g_return_val_if_fail (IBUS_IS_BUS (bus), FALSE);
1988 
1989     gboolean retval = FALSE;
1990     GVariant *result;
1991     result = ibus_bus_call_sync (bus,
1992                                  IBUS_SERVICE_IBUS,
1993                                  IBUS_PATH_IBUS,
1994                                  IBUS_INTERFACE_IBUS,
1995                                  "GetUseSysLayout",
1996                                  NULL,
1997                                  G_VARIANT_TYPE ("(b)"));
1998 
1999     if (result) {
2000         g_variant_get (result, "(b)", &retval);
2001         g_variant_unref (result);
2002     }
2003 
2004     return retval;
2005 }
2006 
2007 void
ibus_bus_get_use_sys_layout_async(IBusBus * bus,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2008 ibus_bus_get_use_sys_layout_async (IBusBus            *bus,
2009                                    gint                timeout_msec,
2010                                    GCancellable       *cancellable,
2011                                    GAsyncReadyCallback callback,
2012                                    gpointer            user_data)
2013 {
2014     g_return_if_fail (IBUS_IS_BUS (bus));
2015 
2016     ibus_bus_call_async (bus,
2017                          IBUS_SERVICE_IBUS,
2018                          IBUS_PATH_IBUS,
2019                          IBUS_INTERFACE_IBUS,
2020                          "GetUseSysLayout",
2021                          NULL,
2022                          G_VARIANT_TYPE ("(b)"),
2023                          ibus_bus_get_use_sys_layout_async,
2024                          timeout_msec,
2025                          cancellable,
2026                          callback,
2027                          user_data);
2028 }
2029 
2030 gboolean
ibus_bus_get_use_sys_layout_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)2031 ibus_bus_get_use_sys_layout_async_finish (IBusBus      *bus,
2032                                           GAsyncResult *res,
2033                                           GError      **error)
2034 {
2035     GTask *task;
2036 
2037     g_assert (IBUS_IS_BUS (bus));
2038     g_assert (g_task_is_valid (res, bus));
2039 
2040     task = G_TASK (res);
2041     g_assert(g_task_get_source_tag (task) == ibus_bus_get_use_sys_layout_async);
2042     return _async_finish_gboolean (task, error);
2043 }
2044 
2045 gboolean
ibus_bus_get_use_global_engine(IBusBus * bus)2046 ibus_bus_get_use_global_engine (IBusBus *bus)
2047 {
2048     g_return_val_if_fail (IBUS_IS_BUS (bus), FALSE);
2049 
2050     gboolean retval = FALSE;
2051     GVariant *result;
2052     result = ibus_bus_call_sync (bus,
2053                                  IBUS_SERVICE_IBUS,
2054                                  IBUS_PATH_IBUS,
2055                                  IBUS_INTERFACE_IBUS,
2056                                  "GetUseGlobalEngine",
2057                                  NULL,
2058                                  G_VARIANT_TYPE ("(b)"));
2059 
2060     if (result) {
2061         g_variant_get (result, "(b)", &retval);
2062         g_variant_unref (result);
2063     }
2064 
2065     return retval;
2066 }
2067 
2068 void
ibus_bus_get_use_global_engine_async(IBusBus * bus,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2069 ibus_bus_get_use_global_engine_async (IBusBus            *bus,
2070                                       gint                timeout_msec,
2071                                       GCancellable       *cancellable,
2072                                       GAsyncReadyCallback callback,
2073                                       gpointer            user_data)
2074 {
2075     g_return_if_fail (IBUS_IS_BUS (bus));
2076 
2077     ibus_bus_call_async (bus,
2078                          IBUS_SERVICE_IBUS,
2079                          IBUS_PATH_IBUS,
2080                          IBUS_INTERFACE_IBUS,
2081                          "GetUseGlobalEngine",
2082                          NULL,
2083                          G_VARIANT_TYPE ("(b)"),
2084                          ibus_bus_get_use_global_engine_async,
2085                          timeout_msec,
2086                          cancellable,
2087                          callback,
2088                          user_data);
2089 }
2090 
2091 gboolean
ibus_bus_get_use_global_engine_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)2092 ibus_bus_get_use_global_engine_async_finish (IBusBus      *bus,
2093                                              GAsyncResult *res,
2094                                              GError      **error)
2095 {
2096     GTask *task;
2097 
2098     g_assert (IBUS_IS_BUS (bus));
2099     g_assert (g_task_is_valid (res, bus));
2100 
2101     task = G_TASK (res);
2102     g_assert(g_task_get_source_tag (task) ==
2103                      ibus_bus_get_use_global_engine_async);
2104     return _async_finish_gboolean (task, error);
2105 }
2106 
2107 gboolean
ibus_bus_is_global_engine_enabled(IBusBus * bus)2108 ibus_bus_is_global_engine_enabled (IBusBus *bus)
2109 {
2110     g_return_val_if_fail (IBUS_IS_BUS (bus), FALSE);
2111 
2112     gboolean retval = FALSE;
2113     GVariant *result;
2114     result = ibus_bus_call_sync (bus,
2115                                  IBUS_SERVICE_IBUS,
2116                                  IBUS_PATH_IBUS,
2117                                  IBUS_INTERFACE_IBUS,
2118                                  "IsGlobalEngineEnabled",
2119                                  NULL,
2120                                  G_VARIANT_TYPE ("(b)"));
2121 
2122     if (result) {
2123         g_variant_get (result, "(b)", &retval);
2124         g_variant_unref (result);
2125     }
2126 
2127     return retval;
2128 }
2129 
ibus_bus_is_global_engine_enabled_async(IBusBus * bus,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2130 void ibus_bus_is_global_engine_enabled_async (IBusBus            *bus,
2131                                               gint                timeout_msec,
2132                                               GCancellable       *cancellable,
2133                                               GAsyncReadyCallback callback,
2134                                               gpointer            user_data)
2135 {
2136     g_return_if_fail (IBUS_IS_BUS (bus));
2137 
2138     ibus_bus_call_async (bus,
2139                          IBUS_SERVICE_IBUS,
2140                          IBUS_PATH_IBUS,
2141                          IBUS_INTERFACE_IBUS,
2142                          "IsGlobalEngineEnabled",
2143                          NULL,
2144                          G_VARIANT_TYPE ("(b)"),
2145                          ibus_bus_is_global_engine_enabled_async,
2146                          timeout_msec,
2147                          cancellable,
2148                          callback,
2149                          user_data);
2150 }
2151 
ibus_bus_is_global_engine_enabled_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)2152 gboolean ibus_bus_is_global_engine_enabled_async_finish (IBusBus      *bus,
2153                                                          GAsyncResult *res,
2154                                                          GError      **error)
2155 {
2156     GTask *task;
2157 
2158     g_assert (IBUS_IS_BUS (bus));
2159     g_assert (g_task_is_valid (res, bus));
2160 
2161     task = G_TASK (res);
2162     g_assert(g_task_get_source_tag (task) ==
2163                      ibus_bus_is_global_engine_enabled_async);
2164     return _async_finish_gboolean (task, error);
2165 }
2166 #endif /* IBUS_DISABLE_DEPRECATED */
2167 
2168 IBusEngineDesc *
ibus_bus_get_global_engine(IBusBus * bus)2169 ibus_bus_get_global_engine (IBusBus *bus)
2170 {
2171     g_return_val_if_fail (IBUS_IS_BUS (bus), NULL);
2172 
2173     GVariant *result;
2174     IBusEngineDesc *engine = NULL;
2175     result = ibus_bus_call_sync (bus,
2176                                  IBUS_SERVICE_IBUS,
2177                                  IBUS_PATH_IBUS,
2178                                  "org.freedesktop.DBus.Properties",
2179                                  "Get",
2180                                  g_variant_new ("(ss)",
2181                                                 IBUS_INTERFACE_IBUS,
2182                                                 "GlobalEngine"),
2183                                  G_VARIANT_TYPE ("(v)"));
2184 
2185     if (result) {
2186         GVariant *variant = NULL;
2187         g_variant_get (result, "(v)", &variant);
2188         if (variant) {
2189             GVariant *obj = g_variant_get_variant (variant);
2190             engine = IBUS_ENGINE_DESC (ibus_serializable_deserialize (obj));
2191             g_variant_unref (obj);
2192             g_variant_unref (variant);
2193         }
2194         g_variant_unref (result);
2195     }
2196 
2197     return engine;
2198 }
2199 
2200 void
ibus_bus_get_global_engine_async(IBusBus * bus,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2201 ibus_bus_get_global_engine_async (IBusBus            *bus,
2202                                   gint                timeout_msec,
2203                                   GCancellable       *cancellable,
2204                                   GAsyncReadyCallback callback,
2205                                   gpointer            user_data)
2206 {
2207     g_return_if_fail (IBUS_IS_BUS (bus));
2208 
2209     ibus_bus_call_async (bus,
2210                          IBUS_SERVICE_IBUS,
2211                          IBUS_PATH_IBUS,
2212                          "org.freedesktop.DBus.Properties",
2213                          "Get",
2214                          g_variant_new ("(ss)",
2215                                         IBUS_INTERFACE_IBUS,
2216                                         "GlobalEngine"),
2217                          G_VARIANT_TYPE ("(v)"),
2218                          ibus_bus_get_global_engine_async,
2219                          timeout_msec,
2220                          cancellable,
2221                          callback,
2222                          user_data);
2223 }
2224 
2225 IBusEngineDesc *
ibus_bus_get_global_engine_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)2226 ibus_bus_get_global_engine_async_finish (IBusBus      *bus,
2227                                          GAsyncResult *res,
2228                                          GError      **error)
2229 {
2230     GTask *task;
2231     gboolean had_error;
2232     GVariant *result = NULL;
2233 
2234     g_assert (g_task_is_valid (res, bus));
2235 
2236     task = G_TASK (res);
2237     had_error = g_task_had_error (task);
2238     result = g_task_propagate_pointer (task, error);
2239     if (had_error) {
2240         g_assert (result == NULL);
2241         return NULL;
2242     }
2243     g_return_val_if_fail (result != NULL, NULL);
2244     GVariant *variant = NULL;
2245     g_variant_get (result, "(v)", &variant);
2246 
2247     IBusEngineDesc *engine = NULL;
2248     if (variant) {
2249         GVariant *obj = g_variant_get_variant (variant);
2250         engine = IBUS_ENGINE_DESC (ibus_serializable_deserialize (obj));
2251         g_variant_unref (obj);
2252         g_variant_unref (variant);
2253     }
2254     g_variant_unref (result);
2255     return engine;
2256 }
2257 
2258 gboolean
ibus_bus_set_global_engine(IBusBus * bus,const gchar * global_engine)2259 ibus_bus_set_global_engine (IBusBus     *bus,
2260                             const gchar *global_engine)
2261 {
2262     g_return_val_if_fail (IBUS_IS_BUS (bus), FALSE);
2263     g_return_val_if_fail (global_engine != NULL, FALSE);
2264 
2265     GVariant *result;
2266     result = ibus_bus_call_sync (bus,
2267                                  IBUS_SERVICE_IBUS,
2268                                  IBUS_PATH_IBUS,
2269                                  IBUS_INTERFACE_IBUS,
2270                                  "SetGlobalEngine",
2271                                  g_variant_new ("(s)", global_engine),
2272                                  NULL);
2273 
2274     if (result) {
2275         g_variant_unref (result);
2276         return TRUE;
2277     }
2278     return FALSE;
2279 }
2280 
2281 void
ibus_bus_set_global_engine_async(IBusBus * bus,const gchar * global_engine,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2282 ibus_bus_set_global_engine_async (IBusBus            *bus,
2283                                   const gchar        *global_engine,
2284                                   gint                timeout_msec,
2285                                   GCancellable       *cancellable,
2286                                   GAsyncReadyCallback callback,
2287                                   gpointer            user_data)
2288 {
2289     g_return_if_fail (IBUS_IS_BUS (bus));
2290     g_return_if_fail (global_engine != NULL);
2291 
2292     ibus_bus_call_async (bus,
2293                          IBUS_SERVICE_IBUS,
2294                          IBUS_PATH_IBUS,
2295                          IBUS_INTERFACE_IBUS,
2296                          "SetGlobalEngine",
2297                          g_variant_new ("(s)", global_engine),
2298                          NULL, /* no return value */
2299                          ibus_bus_set_global_engine_async,
2300                          timeout_msec,
2301                          cancellable,
2302                          callback,
2303                          user_data);
2304 }
2305 
2306 gboolean
ibus_bus_set_global_engine_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)2307 ibus_bus_set_global_engine_async_finish (IBusBus      *bus,
2308                                          GAsyncResult *res,
2309                                          GError      **error)
2310 {
2311     GTask *task;
2312 
2313     g_assert (IBUS_IS_BUS (bus));
2314     g_assert (g_task_is_valid (res, bus));
2315 
2316     task = G_TASK (res);
2317     g_assert (g_task_get_source_tag (task) == ibus_bus_set_global_engine_async);
2318     return _async_finish_void (task, error);
2319 }
2320 
2321 gboolean
ibus_bus_preload_engines(IBusBus * bus,const gchar * const * names)2322 ibus_bus_preload_engines (IBusBus             *bus,
2323                           const gchar * const *names)
2324 {
2325     GVariant *result;
2326     GVariant *variant = NULL;
2327 
2328     g_return_val_if_fail (IBUS_IS_BUS (bus), FALSE);
2329     g_return_val_if_fail (names != NULL && names[0] != NULL, FALSE);
2330 
2331     variant = g_variant_new_strv(names, -1);
2332     result = ibus_bus_call_sync (bus,
2333                                  IBUS_SERVICE_IBUS,
2334                                  IBUS_PATH_IBUS,
2335                                  "org.freedesktop.DBus.Properties",
2336                                  "Set",
2337                                  g_variant_new ("(ssv)",
2338                                                 IBUS_INTERFACE_IBUS,
2339                                                 "PreloadEngines",
2340                                                 variant),
2341                                  NULL);
2342 
2343     if (result) {
2344         g_variant_unref (result);
2345         return TRUE;
2346     }
2347 
2348     return FALSE;
2349 }
2350 
2351 void
ibus_bus_preload_engines_async(IBusBus * bus,const gchar * const * names,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2352 ibus_bus_preload_engines_async (IBusBus             *bus,
2353                                 const gchar * const *names,
2354                                 gint                 timeout_msec,
2355                                 GCancellable        *cancellable,
2356                                 GAsyncReadyCallback  callback,
2357                                 gpointer             user_data)
2358 {
2359     GVariant *variant = NULL;
2360 
2361     g_return_if_fail (IBUS_IS_BUS (bus));
2362     g_return_if_fail (names != NULL && names[0] != NULL);
2363 
2364     variant = g_variant_new_strv(names, -1);
2365     ibus_bus_call_async (bus,
2366                          IBUS_SERVICE_IBUS,
2367                          IBUS_PATH_IBUS,
2368                          "org.freedesktop.DBus.Properties",
2369                          "Set",
2370                          g_variant_new ("(ssv)",
2371                                         IBUS_INTERFACE_IBUS,
2372                                         "PreloadEngines",
2373                                         variant),
2374                          NULL, /* no return value */
2375                          ibus_bus_preload_engines_async,
2376                          timeout_msec,
2377                          cancellable,
2378                          callback,
2379                          user_data);
2380 }
2381 
2382 gboolean
ibus_bus_preload_engines_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)2383 ibus_bus_preload_engines_async_finish (IBusBus       *bus,
2384                                        GAsyncResult  *res,
2385                                        GError       **error)
2386 {
2387     GTask *task;
2388 
2389     g_assert (IBUS_IS_BUS (bus));
2390     g_assert (g_task_is_valid (res, bus));
2391 
2392     task = G_TASK (res);
2393     g_assert (g_task_get_source_tag (task) == ibus_bus_preload_engines_async);
2394     return _async_finish_void (task, error);
2395 }
2396 
2397 GVariant *
ibus_bus_get_ibus_property(IBusBus * bus,const gchar * property_name)2398 ibus_bus_get_ibus_property (IBusBus     *bus,
2399                             const gchar *property_name)
2400 {
2401     GVariant *result;
2402     GVariant *retval = NULL;
2403 
2404     g_return_val_if_fail (IBUS_IS_BUS (bus), NULL);
2405     g_return_val_if_fail (property_name != NULL, NULL);
2406 
2407     result = ibus_bus_call_sync (bus,
2408                                  IBUS_SERVICE_IBUS,
2409                                  IBUS_PATH_IBUS,
2410                                  "org.freedesktop.DBus.Properties",
2411                                  "Get",
2412                                  g_variant_new ("(ss)",
2413                                                 IBUS_INTERFACE_IBUS,
2414                                                 property_name),
2415                                  G_VARIANT_TYPE ("(v)"));
2416 
2417     if (result) {
2418         g_variant_get (result, "(v)", &retval);
2419         g_variant_unref (result);
2420     }
2421 
2422     return retval;
2423 }
2424 
2425 void
ibus_bus_get_ibus_property_async(IBusBus * bus,const gchar * property_name,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2426 ibus_bus_get_ibus_property_async (IBusBus            *bus,
2427                                   const gchar        *property_name,
2428                                   gint                timeout_msec,
2429                                   GCancellable       *cancellable,
2430                                   GAsyncReadyCallback callback,
2431                                   gpointer            user_data)
2432 {
2433     g_return_if_fail (IBUS_IS_BUS (bus));
2434     g_return_if_fail (property_name != NULL);
2435 
2436     ibus_bus_call_async (bus,
2437                          IBUS_SERVICE_IBUS,
2438                          IBUS_PATH_IBUS,
2439                          "org.freedesktop.DBus.Properties",
2440                          "Get",
2441                          g_variant_new ("(ss)",
2442                                         IBUS_INTERFACE_IBUS,
2443                                         property_name),
2444                          G_VARIANT_TYPE ("(v)"),
2445                          ibus_bus_get_ibus_property_async,
2446                          timeout_msec,
2447                          cancellable,
2448                          callback,
2449                          user_data);
2450 }
2451 
2452 GVariant *
ibus_bus_get_ibus_property_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)2453 ibus_bus_get_ibus_property_async_finish (IBusBus      *bus,
2454                                          GAsyncResult *res,
2455                                          GError      **error)
2456 {
2457     GTask *task;
2458     gboolean had_error;
2459     GVariant *result = NULL;
2460 
2461     g_assert (g_task_is_valid (res, bus));
2462 
2463     task = G_TASK (res);
2464     had_error = g_task_had_error (task);
2465     result = g_task_propagate_pointer (task, error);
2466     if (had_error) {
2467         g_assert (result == NULL);
2468         return NULL;
2469     }
2470     g_return_val_if_fail (result != NULL, NULL);
2471     GVariant *retval = NULL;
2472     g_variant_get (result, "(v)", &retval);
2473     g_variant_unref (result);
2474 
2475     return retval;
2476 }
2477 
2478 void
ibus_bus_set_ibus_property(IBusBus * bus,const gchar * property_name,GVariant * value)2479 ibus_bus_set_ibus_property (IBusBus     *bus,
2480                             const gchar *property_name,
2481                             GVariant    *value)
2482 {
2483     GVariant *result;
2484 
2485     g_return_if_fail (IBUS_IS_BUS (bus));
2486     g_return_if_fail (property_name != NULL);
2487 
2488     result = ibus_bus_call_sync (bus,
2489                                  IBUS_SERVICE_IBUS,
2490                                  IBUS_PATH_IBUS,
2491                                  "org.freedesktop.DBus.Properties",
2492                                  "Set",
2493                                  g_variant_new ("(ssv)",
2494                                                 IBUS_INTERFACE_IBUS,
2495                                                 property_name,
2496                                                 value),
2497                                  NULL);
2498 
2499     if (result) {
2500         g_variant_unref (result);
2501     }
2502 }
2503 
2504 void
ibus_bus_set_ibus_property_async(IBusBus * bus,const gchar * property_name,GVariant * value,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2505 ibus_bus_set_ibus_property_async (IBusBus             *bus,
2506                                   const gchar         *property_name,
2507                                   GVariant            *value,
2508                                   gint                 timeout_msec,
2509                                   GCancellable        *cancellable,
2510                                   GAsyncReadyCallback  callback,
2511                                   gpointer             user_data)
2512 {
2513     g_return_if_fail (IBUS_IS_BUS (bus));
2514     g_return_if_fail (property_name != NULL);
2515 
2516     ibus_bus_call_async (bus,
2517                          IBUS_SERVICE_IBUS,
2518                          IBUS_PATH_IBUS,
2519                          "org.freedesktop.DBus.Properties",
2520                          "Set",
2521                          g_variant_new ("(ssv)",
2522                                         IBUS_INTERFACE_IBUS,
2523                                         property_name,
2524                                         value),
2525                          NULL, /* no return value */
2526                          ibus_bus_set_ibus_property_async,
2527                          timeout_msec,
2528                          cancellable,
2529                          callback,
2530                          user_data);
2531 }
2532 
2533 gboolean
ibus_bus_set_ibus_property_async_finish(IBusBus * bus,GAsyncResult * res,GError ** error)2534 ibus_bus_set_ibus_property_async_finish (IBusBus       *bus,
2535                                          GAsyncResult  *res,
2536                                          GError       **error)
2537 {
2538     GTask *task;
2539     g_assert (IBUS_IS_BUS (bus));
2540     g_assert (g_task_is_valid (res, bus));
2541 
2542     task = G_TASK (res);
2543     g_return_val_if_fail (
2544             g_task_get_source_tag (task) == ibus_bus_set_ibus_property_async,
2545             FALSE);
2546     return _async_finish_void (task, error);
2547 }
2548 
2549 static GVariant *
ibus_bus_call_sync(IBusBus * bus,const gchar * bus_name,const gchar * path,const gchar * interface,const gchar * member,GVariant * parameters,const GVariantType * reply_type)2550 ibus_bus_call_sync (IBusBus            *bus,
2551                     const gchar        *bus_name,
2552                     const gchar        *path,
2553                     const gchar        *interface,
2554                     const gchar        *member,
2555                     GVariant           *parameters,
2556                     const GVariantType *reply_type)
2557 {
2558     g_assert (IBUS_IS_BUS (bus));
2559     g_assert (member != NULL);
2560     g_return_val_if_fail (ibus_bus_is_connected (bus), NULL);
2561 
2562     if (bus->priv->use_portal &&
2563         g_strcmp0 (bus_name, IBUS_SERVICE_IBUS) == 0)  {
2564         bus_name = IBUS_SERVICE_PORTAL;
2565         if (g_strcmp0 (interface, IBUS_INTERFACE_IBUS) == 0)
2566             interface = IBUS_INTERFACE_PORTAL;
2567     }
2568 
2569     GError *error = NULL;
2570     GVariant *result;
2571     result = g_dbus_connection_call_sync (bus->priv->connection,
2572                                           bus_name,
2573                                           path,
2574                                           interface,
2575                                           member,
2576                                           parameters,
2577                                           reply_type,
2578                                           G_DBUS_CALL_FLAGS_NO_AUTO_START,
2579                                           ibus_get_timeout (),
2580                                           NULL,
2581                                           &error);
2582 
2583     if (result == NULL) {
2584         g_warning ("ibus_bus_call_sync: %s.%s: %s", interface, member, error->message);
2585         g_error_free (error);
2586         return NULL;
2587     }
2588 
2589     return result;
2590 }
2591 
2592 static void
ibus_bus_call_async_done(GDBusConnection * connection,GAsyncResult * res,gpointer user_data)2593 ibus_bus_call_async_done (GDBusConnection *connection,
2594                           GAsyncResult    *res,
2595                           gpointer         user_data)
2596 {
2597     GTask *task;
2598     GError *error = NULL;
2599     GVariant *variant;
2600 
2601     g_assert (G_IS_DBUS_CONNECTION (connection));
2602 
2603     task = (GTask* ) user_data;
2604     variant = g_dbus_connection_call_finish (connection, res, &error);
2605 
2606     if (variant == NULL)
2607         g_task_return_error (task, error);
2608     else
2609         g_task_return_pointer (task, variant, (GDestroyNotify) g_variant_unref);
2610     g_object_unref (task);
2611 }
2612 
2613 static void
ibus_bus_call_async(IBusBus * bus,const gchar * bus_name,const gchar * path,const gchar * interface,const gchar * member,GVariant * parameters,const GVariantType * reply_type,gpointer source_tag,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2614 ibus_bus_call_async (IBusBus            *bus,
2615                      const gchar        *bus_name,
2616                      const gchar        *path,
2617                      const gchar        *interface,
2618                      const gchar        *member,
2619                      GVariant           *parameters,
2620                      const GVariantType *reply_type,
2621                      gpointer            source_tag,
2622                      gint                timeout_msec,
2623                      GCancellable       *cancellable,
2624                      GAsyncReadyCallback callback,
2625                      gpointer            user_data)
2626 {
2627     GTask *task;
2628 
2629     g_assert (IBUS_IS_BUS (bus));
2630     g_assert (member != NULL);
2631     g_return_if_fail (ibus_bus_is_connected (bus));
2632 
2633     task = g_task_new (bus, cancellable, callback, user_data);
2634     g_task_set_source_tag (task, source_tag);
2635 
2636     if (bus->priv->use_portal &&
2637         g_strcmp0 (bus_name, IBUS_SERVICE_IBUS) == 0)  {
2638         bus_name = IBUS_SERVICE_PORTAL;
2639         if (g_strcmp0 (interface, IBUS_INTERFACE_IBUS) == 0)
2640             interface = IBUS_INTERFACE_PORTAL;
2641     }
2642 
2643     g_dbus_connection_call (bus->priv->connection,
2644                             bus_name,
2645                             path,
2646                             interface,
2647                             member,
2648                             parameters,
2649                             reply_type,
2650                             G_DBUS_CALL_FLAGS_NO_AUTO_START,
2651                             timeout_msec,
2652                             cancellable,
2653                             (GAsyncReadyCallback) ibus_bus_call_async_done,
2654                             task);
2655 }
2656