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-2013 Peng Huang <shawn.p.huang@gmail.com>
5
* Copyright (C) 2008-2013 Red Hat, Inc.
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
28
#include <sys/types.h>
32
#include "connection.h"
34
#include "factoryproxy.h"
36
#include "inputcontext.h"
37
#include "panelproxy.h"
43
/* instance members */
44
GHashTable *factory_dict;
46
/* registered components */
47
GList *registered_components;
50
/* a fake input context for global engine support */
51
BusInputContext *fake_context;
53
/* a list of engines that are started by a user (without the --ibus
54
* command line flag.) */
55
GList *register_engine_list;
57
/* if TRUE, ibus-daemon uses a keysym translated by the system
58
* (i.e. XKB) as-is. otherwise, ibus-daemon itself converts keycode
60
gboolean use_sys_layout;
62
gboolean embed_preedit_text;
64
IBusRegistry *registry;
66
/* a list of BusComponent objects that are created from component XML
67
* files (or from the cache of them). */
70
/* a mapping from an engine name (e.g. 'pinyin') to the corresponding
71
* IBusEngineDesc object. */
72
GHashTable *engine_table;
74
BusInputContext *focused_context;
77
/* a default keymap of ibus-daemon (usually "us") which is used only
78
* when use_sys_layout is FALSE. */
81
gboolean use_global_engine;
82
gchar *global_engine_name;
83
gchar *global_previous_engine_name;
86
struct _BusIBusImplClass {
87
IBusServiceClass parent;
101
static guint _signals[LAST_SIGNAL] = { 0 };
104
/* functions prototype */
105
static void bus_ibus_impl_destroy (BusIBusImpl *ibus);
106
static void bus_ibus_impl_service_method_call
107
(IBusService *service,
108
GDBusConnection *connection,
110
const gchar *object_path,
111
const gchar *interface_name,
112
const gchar *method_name,
113
GVariant *parameters,
114
GDBusMethodInvocation
117
bus_ibus_impl_service_get_property
118
(IBusService *service,
119
GDBusConnection *connection,
121
const gchar *object_path,
122
const gchar *interface_name,
123
const gchar *property_name,
126
bus_ibus_impl_service_set_property
127
(IBusService *service,
128
GDBusConnection *connection,
130
const gchar *object_path,
131
const gchar *interface_name,
132
const gchar *property_name,
135
static void bus_ibus_impl_registry_init
137
static void bus_ibus_impl_registry_changed
139
static void bus_ibus_impl_registry_destroy
141
static void bus_ibus_impl_component_name_owner_changed
144
const gchar *old_name,
145
const gchar *new_name);
146
static void bus_ibus_impl_global_engine_changed
148
static void bus_ibus_impl_set_context_engine_from_desc
150
BusInputContext *context,
151
IBusEngineDesc *desc);
152
static BusInputContext
153
*bus_ibus_impl_create_input_context
155
BusConnection *connection,
156
const gchar *client);
157
static IBusEngineDesc
158
*bus_ibus_impl_get_engine_desc
160
const gchar *engine_name);
161
static void bus_ibus_impl_set_focused_context
163
BusInputContext *context);
164
static void bus_ibus_impl_property_changed
165
(BusIBusImpl *service,
166
const gchar *property_name,
168
/* some callback functions */
169
static void _context_engine_changed_cb
170
(BusInputContext *context,
173
/* The interfaces available in this class, which consists of a list of
174
* methods this class implements and a list of signals this class may emit.
175
* Method calls to the interface that are not defined in this XML will
176
* be automatically rejected by the GDBus library (see src/ibusservice.c
178
* Implement org.freedesktop.DBus.Properties
179
* http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties */
180
static const gchar introspection_xml[] =
182
" <interface name='org.freedesktop.IBus'>\n"
183
" <property name='Address' type='s' access='read' />\n"
184
" <property name='CurrentInputContext' type='o' access='read' />\n"
185
" <property name='Engines' type='av' access='read' />\n"
186
" <property name='GlobalEngine' type='v' access='read' />\n"
187
" <property name='PreloadEngines' type='as' access='write'>\n"
189
" name='org.freedesktop.DBus.Property.EmitsChangedSignal'\n"
192
" <property name='EmbedPreeditText' type='b' access='readwrite'>\n"
194
" name='org.freedesktop.DBus.Property.EmitsChangedSignal'\n"
197
" <method name='CreateInputContext'>\n"
198
" <arg direction='in' type='s' name='client_name' />\n"
199
" <arg direction='out' type='o' name='object_path' />\n"
201
" <method name='RegisterComponent'>\n"
202
" <arg direction='in' type='v' name='component' />\n"
204
" <method name='GetEnginesByNames'>\n"
205
" <arg direction='in' type='as' name='names' />\n"
206
" <arg direction='out' type='av' name='engines' />\n"
208
" <method name='Exit'>\n"
209
" <arg direction='in' type='b' name='restart' />\n"
211
" <method name='Ping'>\n"
212
" <arg direction='in' type='v' name='data' />\n"
213
" <arg direction='out' type='v' name='data' />\n"
215
" <method name='SetGlobalEngine'>\n"
216
" <arg direction='in' type='s' name='engine_name' />\n"
218
" <signal name='RegistryChanged'>\n"
220
" <signal name='GlobalEngineChanged'>\n"
221
" <arg type='s' name='engine_name' />\n"
223
" <property name='ActiveEngines' type='av' access='read' />\n"
224
" <method name='GetAddress'>\n"
225
" <arg direction='out' type='s' name='address' />\n"
226
" <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
228
" <method name='CurrentInputContext'>\n"
229
" <arg direction='out' type='o' name='object_path' />\n"
230
" <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
232
" <method name='ListEngines'>\n"
233
" <arg direction='out' type='av' name='engines' />\n"
234
" <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
236
" <method name='ListActiveEngines'>\n"
237
" <arg direction='out' type='av' name='engines' />\n"
238
" <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
240
" <method name='GetUseSysLayout'>\n"
241
" <arg direction='out' type='b' name='enabled' />\n"
242
" <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
244
" <method name='GetUseGlobalEngine'>\n"
245
" <arg direction='out' type='b' name='enabled' />\n"
247
" <method name='IsGlobalEngineEnabled'>\n"
248
" <arg direction='out' type='b' name='enabled' />\n"
249
" <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
251
" <method name='GetGlobalEngine'>\n"
252
" <arg direction='out' type='v' name='desc' />\n"
253
" <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
259
G_DEFINE_TYPE (BusIBusImpl, bus_ibus_impl, IBUS_TYPE_SERVICE)
262
bus_ibus_impl_class_init (BusIBusImplClass *class)
264
IBUS_OBJECT_CLASS (class)->destroy =
265
(IBusObjectDestroyFunc) bus_ibus_impl_destroy;
267
/* override the parent class's implementation. */
268
IBUS_SERVICE_CLASS (class)->service_method_call =
269
bus_ibus_impl_service_method_call;
270
IBUS_SERVICE_CLASS (class)->service_get_property =
271
bus_ibus_impl_service_get_property;
272
IBUS_SERVICE_CLASS (class)->service_set_property =
273
bus_ibus_impl_service_set_property;
274
/* register the xml so that bus_ibus_impl_service_method_call will be
275
* called on a method call defined in the xml (e.g. 'GetAddress'.) */
276
ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class),
283
* A callback function which is called when (1) the connection to the panel process is terminated,
284
* or (2) ibus_proxy_destroy (ibus->panel); is called. See src/ibusproxy.c for details.
287
_panel_destroy_cb (BusPanelProxy *panel,
290
g_assert (BUS_IS_PANEL_PROXY (panel));
291
g_assert (BUS_IS_IBUS_IMPL (ibus));
293
g_return_if_fail (ibus->panel == panel);
296
g_object_unref (panel);
300
_registry_changed_cb (IBusRegistry *registry,
303
bus_ibus_impl_registry_changed (ibus);
307
* _dbus_name_owner_changed_cb:
309
* A callback function to be called when the name-owner-changed signal is sent to the dbus object.
310
* This usually means a client (e.g. a panel/config/engine process or an application) is connected/disconnected to/from the bus.
313
_dbus_name_owner_changed_cb (BusDBusImpl *dbus,
314
BusConnection *orig_connection,
316
const gchar *old_name,
317
const gchar *new_name,
320
g_assert (BUS_IS_DBUS_IMPL (dbus));
321
g_assert (name != NULL);
322
g_assert (old_name != NULL);
323
g_assert (new_name != NULL);
324
g_assert (BUS_IS_IBUS_IMPL (ibus));
326
if (g_strcmp0 (name, IBUS_SERVICE_PANEL) == 0) {
327
if (g_strcmp0 (new_name, "") != 0) {
328
/* a Panel process is started. */
329
BusConnection *connection;
330
BusInputContext *context = NULL;
332
if (ibus->panel != NULL) {
333
ibus_proxy_destroy ((IBusProxy *) ibus->panel);
334
/* panel should be NULL after destroy. See _panel_destroy_cb for details. */
335
g_assert (ibus->panel == NULL);
338
connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
339
g_return_if_fail (connection != NULL);
341
ibus->panel = bus_panel_proxy_new (connection);
343
g_signal_connect (ibus->panel,
345
G_CALLBACK (_panel_destroy_cb),
348
if (ibus->focused_context != NULL) {
349
context = ibus->focused_context;
351
else if (ibus->use_global_engine) {
352
context = ibus->fake_context;
355
if (context != NULL) {
356
BusEngineProxy *engine;
358
bus_panel_proxy_focus_in (ibus->panel, context);
360
engine = bus_input_context_get_engine (context);
361
if (engine != NULL) {
362
IBusPropList *prop_list =
363
bus_engine_proxy_get_properties (engine);
364
bus_panel_proxy_register_properties (ibus->panel,
371
bus_ibus_impl_component_name_owner_changed (ibus, name, old_name, new_name);
375
* bus_ibus_impl_init:
377
* The constructor of BusIBusImpl. Initialize all member variables of a BusIBusImpl object.
380
bus_ibus_impl_init (BusIBusImpl *ibus)
382
ibus->factory_dict = g_hash_table_new_full (
386
(GDestroyNotify) g_object_unref);
388
ibus->fake_context = bus_input_context_new (NULL, "fake");
389
g_object_ref_sink (ibus->fake_context);
390
bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
391
(IBusService *) ibus->fake_context);
392
bus_input_context_set_capabilities (ibus->fake_context,
393
IBUS_CAP_PREEDIT_TEXT |
395
IBUS_CAP_SURROUNDING_TEXT);
396
g_signal_connect (ibus->fake_context,
398
G_CALLBACK (_context_engine_changed_cb),
400
bus_input_context_focus_in (ibus->fake_context);
402
ibus->register_engine_list = NULL;
403
ibus->contexts = NULL;
404
ibus->focused_context = NULL;
407
ibus->keymap = ibus_keymap_get ("us");
409
ibus->use_sys_layout = TRUE;
410
ibus->embed_preedit_text = TRUE;
411
ibus->use_global_engine = TRUE;
412
ibus->global_engine_name = NULL;
413
ibus->global_previous_engine_name = NULL;
415
/* focus the fake_context, if use_global_engine is enabled. */
416
if (ibus->use_global_engine)
417
bus_ibus_impl_set_focused_context (ibus, ibus->fake_context);
419
g_signal_connect (BUS_DEFAULT_DBUS,
420
"name-owner-changed",
421
G_CALLBACK (_dbus_name_owner_changed_cb),
424
bus_ibus_impl_registry_init (ibus);
428
* bus_ibus_impl_destroy:
430
* The destructor of BusIBusImpl.
433
bus_ibus_impl_destroy (BusIBusImpl *ibus)
440
g_list_foreach (ibus->components, (GFunc) bus_component_stop, NULL);
446
while ((pid = waitpid (0, &status, WNOHANG)) > 0);
448
if (pid == -1) { /* all children finished */
451
if (pid == 0) { /* no child status changed */
454
if (timeout >= G_USEC_PER_SEC) {
457
old = signal (SIGTERM, SIG_IGN);
458
/* send TERM signal to the whole process group (i.e. engines, panel, and config daemon.) */
459
kill (-getpid (), SIGTERM);
460
signal (SIGTERM, old);
464
g_warning ("Not every child processes exited!");
471
g_list_free_full (ibus->register_engine_list, g_object_unref);
472
ibus->register_engine_list = NULL;
474
if (ibus->factory_dict != NULL) {
475
g_hash_table_destroy (ibus->factory_dict);
476
ibus->factory_dict = NULL;
479
if (ibus->keymap != NULL) {
480
g_object_unref (ibus->keymap);
484
g_free (ibus->global_engine_name);
485
ibus->global_engine_name = NULL;
487
g_free (ibus->global_previous_engine_name);
488
ibus->global_previous_engine_name = NULL;
490
if (ibus->fake_context) {
491
g_object_unref (ibus->fake_context);
492
ibus->fake_context = NULL;
495
bus_ibus_impl_registry_destroy (ibus);
497
IBUS_OBJECT_CLASS (bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
503
* Implement the "Address" method call of the org.freedesktop.IBus interface.
506
_ibus_get_address (BusIBusImpl *ibus,
507
GDBusConnection *connection,
514
return g_variant_new_string (bus_server_get_address ());
518
_ibus_get_address_depre (BusIBusImpl *ibus,
519
GVariant *parameters,
520
GDBusMethodInvocation *invocation)
522
GDBusConnection *connection =
523
g_dbus_method_invocation_get_connection (invocation);
524
GError *error = NULL;
525
GVariant *variant = NULL;
527
g_warning ("org.freedesktop.IBus.GetAddress() is deprecated!");
529
variant = _ibus_get_address (ibus, connection, &error);
531
g_dbus_method_invocation_return_value (invocation,
532
g_variant_new ("(s)", g_variant_get_string (variant, NULL)));
534
g_variant_unref (variant);
537
static IBusEngineDesc *
538
_find_engine_desc_by_name (BusIBusImpl *ibus,
539
const gchar *engine_name)
541
IBusEngineDesc *desc = NULL;
544
/* find engine in registered engine list */
545
for (p = ibus->register_engine_list; p != NULL; p = p->next) {
546
desc = (IBusEngineDesc *) p->data;
547
if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
555
* _context_request_engine_cb:
557
* A callback function to be called when the "request-engine" signal is sent to the context.
559
static IBusEngineDesc *
560
_context_request_engine_cb (BusInputContext *context,
561
const gchar *engine_name,
564
if (engine_name == NULL || engine_name[0] == '\0')
565
engine_name = DEFAULT_ENGINE;
567
return bus_ibus_impl_get_engine_desc (ibus, engine_name);
571
* bus_ibus_impl_get_engine_desc:
573
* Get the IBusEngineDesc by engine_name. If the engine_name is NULL, return
574
* a default engine desc.
576
static IBusEngineDesc *
577
bus_ibus_impl_get_engine_desc (BusIBusImpl *ibus,
578
const gchar *engine_name)
580
g_return_val_if_fail (engine_name != NULL, NULL);
581
g_return_val_if_fail (engine_name[0] != '\0', NULL);
583
IBusEngineDesc *desc = _find_engine_desc_by_name (ibus, engine_name);
585
desc = (IBusEngineDesc *) g_hash_table_lookup (ibus->engine_table,
592
bus_ibus_impl_set_context_engine_from_desc (BusIBusImpl *ibus,
593
BusInputContext *context,
594
IBusEngineDesc *desc)
596
bus_input_context_set_engine_by_desc (context,
598
g_gdbus_timeout, /* timeout in msec. */
599
NULL, /* we do not cancel the call. */
600
NULL, /* use the default callback function. */
605
* bus_ibus_impl_set_focused_context:
607
* Set the current focused context.
610
bus_ibus_impl_set_focused_context (BusIBusImpl *ibus,
611
BusInputContext *context)
613
g_assert (BUS_IS_IBUS_IMPL (ibus));
614
g_assert (context == NULL || BUS_IS_INPUT_CONTEXT (context));
615
g_assert (context == NULL || bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS);
617
/* Do noting if it is focused context. */
618
if (ibus->focused_context == context) {
622
BusEngineProxy *engine = NULL;
624
if (ibus->focused_context) {
625
if (ibus->use_global_engine) {
626
/* dettach engine from the focused context */
627
engine = bus_input_context_get_engine (ibus->focused_context);
629
g_object_ref (engine);
630
bus_input_context_set_engine (ibus->focused_context, NULL);
634
if (ibus->panel != NULL)
635
bus_panel_proxy_focus_out (ibus->panel, ibus->focused_context);
637
g_object_unref (ibus->focused_context);
638
ibus->focused_context = NULL;
641
if (context == NULL && ibus->use_global_engine) {
642
context = ibus->fake_context;
646
ibus->focused_context = (BusInputContext *) g_object_ref (context);
647
/* attach engine to the focused context */
648
if (engine != NULL) {
649
bus_input_context_set_engine (context, engine);
650
bus_input_context_enable (context);
653
if (ibus->panel != NULL)
654
bus_panel_proxy_focus_in (ibus->panel, context);
658
g_object_unref (engine);
662
bus_ibus_impl_set_global_engine (BusIBusImpl *ibus,
663
BusEngineProxy *engine)
665
if (!ibus->use_global_engine)
668
if (ibus->focused_context) {
669
bus_input_context_set_engine (ibus->focused_context, engine);
670
} else if (ibus->fake_context) {
671
bus_input_context_set_engine (ibus->fake_context, engine);
676
bus_ibus_impl_set_global_engine_by_name (BusIBusImpl *ibus,
679
if (!ibus->use_global_engine)
682
BusInputContext *context =
683
ibus->focused_context != NULL ? ibus->focused_context : ibus->fake_context;
685
if (context == NULL) {
689
if (g_strcmp0 (name, ibus->global_engine_name) == 0) {
690
/* If the user requested the same global engine, then we just enable the
692
bus_input_context_enable (context);
696
/* If there is a focused input context, then we just change the engine of
697
* the focused context, which will then change the global engine
698
* automatically. Otherwise, we need to change the global engine directly.
700
IBusEngineDesc *desc = NULL;
701
desc = bus_ibus_impl_get_engine_desc (ibus, name);
703
bus_ibus_impl_set_context_engine_from_desc (ibus,
709
/* When preload_engines and register_engiens are changed, this function
710
* will check the global engine. If necessay, it will change the global engine.
713
bus_ibus_impl_check_global_engine (BusIBusImpl *ibus)
715
GList *engine_list = NULL;
718
if (!ibus->use_global_engine)
721
/* The current global engine is not removed, so do nothing. */
722
if (ibus->global_engine_name != NULL &&
723
_find_engine_desc_by_name (ibus, ibus->global_engine_name)) {
727
/* If the previous engine is available, then just switch to it. */
728
if (ibus->global_previous_engine_name != NULL &&
729
_find_engine_desc_by_name (ibus, ibus->global_previous_engine_name)) {
730
bus_ibus_impl_set_global_engine_by_name (
731
ibus, ibus->global_previous_engine_name);
735
/* Just switch to the fist engine in the list. */
736
engine_list = ibus->register_engine_list;
739
IBusEngineDesc *engine_desc = (IBusEngineDesc *)engine_list->data;
740
bus_ibus_impl_set_global_engine_by_name (ibus,
741
ibus_engine_desc_get_name (engine_desc));
745
/* No engine available? Just disable global engine. */
746
bus_ibus_impl_set_global_engine (ibus, NULL);
750
* _context_engine_changed_cb:
752
* A callback function to be called when the "engine-changed" signal is sent to the context.
753
* Update global engine as well if necessary.
756
_context_engine_changed_cb (BusInputContext *context,
759
if (!ibus->use_global_engine)
762
if ((context == ibus->focused_context) ||
763
(ibus->focused_context == NULL && context == ibus->fake_context)) {
764
BusEngineProxy *engine = bus_input_context_get_engine (context);
765
if (engine != NULL) {
766
/* only set global engine if engine is not NULL */
767
const gchar *name = ibus_engine_desc_get_name (bus_engine_proxy_get_desc (engine));
768
if (g_strcmp0 (name, ibus->global_engine_name) == 0)
770
g_free (ibus->global_previous_engine_name);
771
ibus->global_previous_engine_name = ibus->global_engine_name;
772
ibus->global_engine_name = g_strdup (name);
773
bus_ibus_impl_global_engine_changed (ibus);
779
* _context_focus_in_cb:
781
* A callback function to be called when the "focus-in" signal is sent to the context.
782
* If necessary, enables the global engine on the context and update ibus->focused_context.
785
_context_focus_in_cb (BusInputContext *context,
788
g_assert (BUS_IS_IBUS_IMPL (ibus));
789
g_assert (BUS_IS_INPUT_CONTEXT (context));
791
/* Do nothing if context does not support focus.
792
* The global engine shoule be detached from the focused context. */
793
if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
797
bus_ibus_impl_set_focused_context (ibus, context);
801
* _context_focus_out_cb:
803
* A callback function to be called when the "focus-out" signal is sent to the context.
806
_context_focus_out_cb (BusInputContext *context,
809
g_assert (BUS_IS_IBUS_IMPL (ibus));
810
g_assert (BUS_IS_INPUT_CONTEXT (context));
812
/* Do noting if context does not support focus.
813
* Actually, the context should emit focus signals, if it does not support focus */
814
if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
818
/* Do noting if it is not focused context. */
819
if (ibus->focused_context != context) {
823
bus_ibus_impl_set_focused_context (ibus, NULL);
827
* _context_destroy_cb:
829
* A callback function to be called when the "destroy" signal is sent to the
833
_context_destroy_cb (BusInputContext *context,
836
g_assert (BUS_IS_IBUS_IMPL (ibus));
837
g_assert (BUS_IS_INPUT_CONTEXT (context));
839
if (context == ibus->focused_context)
840
bus_ibus_impl_set_focused_context (ibus, NULL);
843
bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS)
844
bus_panel_proxy_destroy_context (ibus->panel, context);
846
ibus->contexts = g_list_remove (ibus->contexts, context);
847
g_object_unref (context);
851
* bus_ibus_impl_create_input_context:
852
* @client: A name of a client. e.g. "gtk-im"
853
* @returns: A BusInputContext object.
855
* Create a new BusInputContext object for the client.
857
static BusInputContext *
858
bus_ibus_impl_create_input_context (BusIBusImpl *ibus,
859
BusConnection *connection,
862
BusInputContext *context = bus_input_context_new (connection, client);
863
g_object_ref_sink (context);
864
ibus->contexts = g_list_append (ibus->contexts, context);
866
/* Installs glib signal handlers so that the ibus object could be notified when e.g. an IBus.InputContext D-Bus method is called. */
867
static const struct {
871
{ "request-engine", G_CALLBACK (_context_request_engine_cb) },
872
{ "engine-changed", G_CALLBACK (_context_engine_changed_cb) },
873
{ "focus-in", G_CALLBACK (_context_focus_in_cb) },
874
{ "focus-out", G_CALLBACK (_context_focus_out_cb) },
875
{ "destroy", G_CALLBACK (_context_destroy_cb) },
879
for (i = 0; i < G_N_ELEMENTS (signals); i++) {
880
g_signal_connect (context,
886
bus_input_context_enable (context);
888
/* register the context object so that the object could handle IBus.InputContext method calls. */
889
bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
890
(IBusService *) context);
891
g_object_ref (context);
896
* _ibus_create_input_context:
898
* Implement the "CreateInputContext" method call of the org.freedesktop.IBus interface.
901
_ibus_create_input_context (BusIBusImpl *ibus,
902
GVariant *parameters,
903
GDBusMethodInvocation *invocation)
905
const gchar *client_name = NULL; // e.g. "gtk-im"
906
g_variant_get (parameters, "(&s)", &client_name);
908
BusConnection *connection =
909
bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
910
BusInputContext *context =
911
bus_ibus_impl_create_input_context (ibus,
915
const gchar *path = ibus_service_get_object_path ((IBusService *) context);
916
/* the format-string 'o' is for a D-Bus object path. */
917
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
918
g_object_unref (context);
921
g_dbus_method_invocation_return_error (invocation,
924
"Create input context failed!");
929
* _ibus_get_current_input_context:
931
* Implement the "CurrentInputContext" method call of the
932
* org.freedesktop.IBus interface.
935
_ibus_get_current_input_context (BusIBusImpl *ibus,
936
GDBusConnection *connection,
943
if (!ibus->focused_context)
945
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
946
"No focused input context");
950
const gchar *path = ibus_service_get_object_path (
951
(IBusService *) ibus->focused_context);
952
/* the format-string 'o' is for a D-Bus object path. */
953
return g_variant_new_object_path (path);
958
_ibus_current_input_context_depre (BusIBusImpl *ibus,
959
GVariant *parameters,
960
GDBusMethodInvocation *invocation)
962
GDBusConnection *connection =
963
g_dbus_method_invocation_get_connection (invocation);
964
GVariant *variant = NULL;
965
GError *error = NULL;
967
g_warning ("org.freedesktop.IBus.CurrentInputContext() is deprecated!");
969
variant = _ibus_get_current_input_context (ibus, connection, &error);
971
if (variant == NULL) {
972
g_dbus_method_invocation_return_error (
973
invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
974
"%s", error->message);
975
g_error_free (error);
977
const gchar *path = g_variant_get_string (variant, NULL);
978
g_dbus_method_invocation_return_value (invocation,
979
g_variant_new ("(o)", path));
980
g_variant_unref (variant);
985
_component_destroy_cb (BusComponent *component,
988
g_assert (BUS_IS_IBUS_IMPL (ibus));
989
g_assert (BUS_IS_COMPONENT (component));
991
ibus->registered_components = g_list_remove (ibus->registered_components, component);
993
/* remove engines from engine_list */
994
GList *engines = bus_component_get_engines (component);
996
for (p = engines; p != NULL; p = p->next) {
997
if (g_list_find (ibus->register_engine_list, p->data)) {
998
ibus->register_engine_list = g_list_remove (ibus->register_engine_list, p->data);
999
g_object_unref (p->data);
1002
g_list_free (engines);
1004
g_object_unref (component);
1006
bus_ibus_impl_check_global_engine (ibus);
1010
* _ibus_register_component:
1012
* Implement the "RegisterComponent" method call of the
1013
* org.freedesktop.IBus interface.
1016
_ibus_register_component (BusIBusImpl *ibus,
1017
GVariant *parameters,
1018
GDBusMethodInvocation *invocation)
1020
GVariant *variant = g_variant_get_child_value (parameters, 0);
1021
IBusComponent *component =
1022
(IBusComponent *) ibus_serializable_deserialize (variant);
1024
if (!IBUS_IS_COMPONENT (component)) {
1026
g_object_unref (component);
1027
g_dbus_method_invocation_return_error (
1028
invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1029
"The first argument should be an IBusComponent.");
1033
BusConnection *connection = bus_connection_lookup (
1034
g_dbus_method_invocation_get_connection (invocation));
1035
BusFactoryProxy *factory = bus_factory_proxy_new (connection);
1037
if (factory == NULL) {
1038
g_object_unref (component);
1039
g_dbus_method_invocation_return_error (
1040
invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1041
"Create factory failed.");
1045
g_object_ref_sink (component);
1047
BusComponent *buscomp = bus_component_new (component, factory);
1048
bus_component_set_destroy_with_factory (buscomp, TRUE);
1049
g_object_unref (component);
1050
g_object_unref (factory);
1052
ibus->registered_components = g_list_append (ibus->registered_components,
1053
g_object_ref_sink (buscomp));
1054
GList *engines = bus_component_get_engines (buscomp);
1055
g_list_foreach (engines, (GFunc) g_object_ref, NULL);
1056
ibus->register_engine_list = g_list_concat (ibus->register_engine_list,
1059
g_signal_connect (buscomp,
1061
G_CALLBACK (_component_destroy_cb),
1064
g_dbus_method_invocation_return_value (invocation, NULL);
1068
* _ibus_get_engines:
1070
* Implement the "Engines" method call of the org.freedesktop.IBus interface.
1073
_ibus_get_engines (BusIBusImpl *ibus,
1074
GDBusConnection *connection,
1077
GVariantBuilder builder;
1078
GList *engines = NULL;
1085
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1087
engines = g_hash_table_get_values (ibus->engine_table);
1089
for (p = engines; p != NULL; p = p->next) {
1090
g_variant_builder_add (
1092
ibus_serializable_serialize ((IBusSerializable *) p->data));
1095
g_list_free (engines);
1097
return g_variant_builder_end (&builder);
1101
_ibus_list_engines_depre (BusIBusImpl *ibus,
1102
GVariant *parameters,
1103
GDBusMethodInvocation *invocation)
1105
GDBusConnection *connection =
1106
g_dbus_method_invocation_get_connection (invocation);
1107
GError *error = NULL;
1108
GVariant *variant = NULL;
1110
g_warning ("org.freedesktop.IBus.ListEngines() is deprecated!");
1112
variant = _ibus_get_engines (ibus, connection, &error);
1114
g_dbus_method_invocation_return_value (invocation,
1115
g_variant_new ("(@av)", variant));
1119
* _ibus_get_engines_by_names:
1121
* Implement the "GetEnginesByNames" method call of the org.freedesktop.IBus interface.
1124
_ibus_get_engines_by_names (BusIBusImpl *ibus,
1125
GVariant *parameters,
1126
GDBusMethodInvocation *invocation)
1128
const gchar **names = NULL;
1129
g_variant_get (parameters, "(^a&s)", &names);
1131
g_assert (names != NULL);
1134
GVariantBuilder builder;
1135
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1136
while (names[i] != NULL) {
1137
IBusEngineDesc *desc = (IBusEngineDesc *) g_hash_table_lookup (
1138
ibus->engine_table, names[i++]);
1141
g_variant_builder_add (
1144
ibus_serializable_serialize ((IBusSerializable *)desc));
1146
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1150
* _ibus_get_active_engines:
1152
* Implement the "ActiveEngines" method call of the
1153
* org.freedesktop.IBus interface.
1156
_ibus_get_active_engines (BusIBusImpl *ibus,
1157
GDBusConnection *connection,
1160
GVariantBuilder builder;
1167
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1169
for (p = ibus->register_engine_list; p != NULL; p = p->next) {
1170
g_variant_builder_add (
1172
ibus_serializable_serialize ((IBusSerializable *) p->data));
1175
return g_variant_builder_end (&builder);
1179
_ibus_list_active_engines_depre (BusIBusImpl *ibus,
1180
GVariant *parameters,
1181
GDBusMethodInvocation *invocation)
1183
GDBusConnection *connection =
1184
g_dbus_method_invocation_get_connection (invocation);
1185
GError *error = NULL;
1186
GVariant *variant = NULL;
1188
g_warning ("org.freedesktop.IBus.ListActiveEngines() is deprecated!");
1190
variant = _ibus_get_active_engines (ibus, connection, &error);
1192
g_dbus_method_invocation_return_value (invocation,
1193
g_variant_new ("(@av)", variant));
1199
* Implement the "Exit" method call of the org.freedesktop.IBus interface.
1202
_ibus_exit (BusIBusImpl *ibus,
1203
GVariant *parameters,
1204
GDBusMethodInvocation *invocation)
1206
gboolean restart = FALSE;
1207
g_variant_get (parameters, "(b)", &restart);
1209
g_dbus_method_invocation_return_value (invocation, NULL);
1211
/* Make sure the reply has been sent out before exit */
1212
g_dbus_connection_flush_sync (
1213
g_dbus_method_invocation_get_connection (invocation),
1217
bus_server_quit (restart);
1223
* Implement the "Ping" method call of the org.freedesktop.IBus interface.
1226
_ibus_ping (BusIBusImpl *ibus,
1227
GVariant *parameters,
1228
GDBusMethodInvocation *invocation)
1230
g_dbus_method_invocation_return_value (invocation, parameters);
1234
* _ibus_get_use_sys_layout:
1236
* Implement the "UseSysLayout" method call of the
1237
* org.freedesktop.IBus interface.
1240
_ibus_get_use_sys_layout (BusIBusImpl *ibus,
1241
GDBusConnection *connection,
1248
return g_variant_new_boolean (ibus->use_sys_layout);
1252
_ibus_get_use_sys_layout_depre (BusIBusImpl *ibus,
1253
GVariant *parameters,
1254
GDBusMethodInvocation *invocation)
1256
GDBusConnection *connection =
1257
g_dbus_method_invocation_get_connection (invocation);
1258
GError *error = NULL;
1259
GVariant *variant = NULL;
1261
g_warning ("org.freedesktop.IBus.GetUseSysLayout() is deprecated!");
1263
variant = _ibus_get_use_sys_layout (ibus, connection, &error);
1265
g_dbus_method_invocation_return_value (invocation,
1266
g_variant_new ("(b)", g_variant_get_boolean (variant)));
1268
g_variant_unref (variant);
1272
* _ibus_get_use_global_engine:
1274
* Implement the "UseGlobalEngine" method call of the
1275
* org.freedesktop.IBus interface.
1278
_ibus_get_use_global_engine (BusIBusImpl *ibus,
1279
GDBusConnection *connection,
1286
return g_variant_new_boolean (ibus->use_global_engine);
1290
_ibus_get_use_global_engine_depre (BusIBusImpl *ibus,
1291
GVariant *parameters,
1292
GDBusMethodInvocation *invocation)
1294
GDBusConnection *connection =
1295
g_dbus_method_invocation_get_connection (invocation);
1296
GError *error = NULL;
1297
GVariant *variant = NULL;
1299
g_warning ("org.freedesktop.IBus.GetUseGlobalEngine() is deprecated!");
1301
variant = _ibus_get_use_global_engine (ibus, connection, &error);
1303
g_dbus_method_invocation_return_value (invocation,
1304
g_variant_new ("(b)", g_variant_get_boolean (variant)));
1306
g_variant_unref (variant);
1310
* _ibus_get_global_engine:
1312
* Implement the "GlobalEngine" method call of the
1313
* org.freedesktop.IBus interface.
1316
_ibus_get_global_engine (BusIBusImpl *ibus,
1317
GDBusConnection *connection,
1320
IBusEngineDesc *desc = NULL;
1327
if (!ibus->use_global_engine)
1329
BusInputContext *context = ibus->focused_context;
1330
if (context == NULL)
1331
context = ibus->fake_context;
1333
desc = bus_input_context_get_engine_desc (context);
1338
GVariant *variant = ibus_serializable_serialize (
1339
(IBusSerializable *) desc);
1340
// Set type "v" for introspection_xml.
1341
return g_variant_new_variant (variant);
1345
G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1346
"No global engine.");
1351
_ibus_get_global_engine_depre (BusIBusImpl *ibus,
1352
GVariant *parameters,
1353
GDBusMethodInvocation *invocation)
1355
GDBusConnection *connection =
1356
g_dbus_method_invocation_get_connection (invocation);
1357
GError *error = NULL;
1358
GVariant *variant = NULL;
1360
g_warning ("org.freedesktop.IBus.GetGlobalEngine() is deprecated!");
1362
variant = _ibus_get_global_engine (ibus, connection, &error);
1364
if (variant == NULL) {
1365
g_dbus_method_invocation_return_error (
1367
G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1368
"%s", error->message);
1369
g_error_free (error);
1371
GVariant *retval = g_variant_get_variant (variant);
1372
g_dbus_method_invocation_return_value (invocation,
1373
g_variant_new ("(v)", retval));
1374
g_variant_unref (variant);
1378
struct _SetGlobalEngineData {
1380
GDBusMethodInvocation *invocation;
1382
typedef struct _SetGlobalEngineData SetGlobalEngineData;
1385
_ibus_set_global_engine_ready_cb (BusInputContext *context,
1387
SetGlobalEngineData *data)
1389
BusIBusImpl *ibus = data->ibus;
1391
GError *error = NULL;
1392
if (!bus_input_context_set_engine_by_desc_finish (context, res, &error)) {
1393
g_error_free (error);
1394
g_dbus_method_invocation_return_error (data->invocation,
1396
G_DBUS_ERROR_FAILED,
1397
"Set global engine failed.");
1400
g_dbus_method_invocation_return_value (data->invocation, NULL);
1402
if (ibus->use_global_engine && (context != ibus->focused_context)) {
1403
/* context and ibus->focused_context don't match. This means that
1404
* the focus is moved before _ibus_set_global_engine() asynchronous
1405
* call finishes. In this case, the engine for the context currently
1406
* being focused hasn't been updated. Update the engine here so that
1407
* subsequent _ibus_get_global_engine() call could return a
1408
* consistent engine name. */
1409
BusEngineProxy *engine = bus_input_context_get_engine (context);
1410
if (engine && ibus->focused_context != NULL) {
1411
g_object_ref (engine);
1412
bus_input_context_set_engine (context, NULL);
1413
bus_input_context_set_engine (ibus->focused_context, engine);
1414
g_object_unref (engine);
1419
g_object_unref (ibus);
1420
g_slice_free (SetGlobalEngineData, data);
1424
* _ibus_set_global_engine:
1426
* Implement the "SetGlobalEngine" method call of the
1427
* org.freedesktop.IBus interface.
1430
_ibus_set_global_engine (BusIBusImpl *ibus,
1431
GVariant *parameters,
1432
GDBusMethodInvocation *invocation)
1434
if (!ibus->use_global_engine) {
1435
g_dbus_method_invocation_return_error (invocation,
1436
G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1437
"Global engine feature is disabled.");
1441
BusInputContext *context = ibus->focused_context;
1442
if (context == NULL)
1443
context = ibus->fake_context;
1445
const gchar *engine_name = NULL;
1446
g_variant_get (parameters, "(&s)", &engine_name);
1448
IBusEngineDesc *desc = bus_ibus_impl_get_engine_desc(ibus, engine_name);
1450
g_dbus_method_invocation_return_error (invocation,
1452
G_DBUS_ERROR_FAILED,
1453
"Can not find engine %s.",
1458
SetGlobalEngineData *data = g_slice_new0 (SetGlobalEngineData);
1459
data->ibus = g_object_ref (ibus);
1460
data->invocation = invocation;
1461
bus_input_context_set_engine_by_desc (context,
1463
g_gdbus_timeout, /* timeout in msec. */
1464
NULL, /* we do not cancel the call. */
1465
(GAsyncReadyCallback) _ibus_set_global_engine_ready_cb,
1470
* _ibus_get_global_engine_enabled:
1472
* Implement the "GlobalEngineEnabled" method call of the
1473
* org.freedesktop.IBus interface.
1476
_ibus_get_global_engine_enabled (BusIBusImpl *ibus,
1477
GDBusConnection *connection,
1480
gboolean enabled = FALSE;
1487
if (!ibus->use_global_engine)
1490
BusInputContext *context = ibus->focused_context;
1491
if (context == NULL)
1492
context = ibus->fake_context;
1493
if (context == NULL)
1499
return g_variant_new_boolean (enabled);
1503
_ibus_is_global_engine_enabled_depre (BusIBusImpl *ibus,
1504
GVariant *parameters,
1505
GDBusMethodInvocation *invocation)
1507
GDBusConnection *connection =
1508
g_dbus_method_invocation_get_connection (invocation);
1509
GError *error = NULL;
1510
GVariant *variant = NULL;
1512
g_warning ("org.freedesktop.IBus.IsGlobalEngineEnabled() is deprecated!");
1514
variant = _ibus_get_global_engine_enabled (ibus, connection, &error);
1516
g_dbus_method_invocation_return_value (invocation,
1517
g_variant_new ("(b)", g_variant_get_boolean (variant)));
1519
g_variant_unref (variant);
1523
* _ibus_set_preload_engines:
1525
* Implement the "PreloadEngines" method call of the
1526
* org.freedesktop.IBus interface.
1529
_ibus_set_preload_engines (BusIBusImpl *ibus,
1530
GDBusConnection *connection,
1535
const gchar **names = NULL;
1536
IBusEngineDesc *desc = NULL;
1537
BusComponent *component = NULL;
1538
BusFactoryProxy *factory = NULL;
1539
GPtrArray *array = g_ptr_array_new ();
1545
g_variant_get (value, "^a&s", &names);
1547
for (i = 0; names[i] != NULL; i++) {
1548
gboolean has_component = FALSE;
1550
desc = bus_ibus_impl_get_engine_desc(ibus, names[i]);
1555
G_DBUS_ERROR_FAILED,
1556
"Can not find engine %s.",
1558
g_ptr_array_free (array, FALSE);
1562
component = bus_component_from_engine_desc (desc);
1563
factory = bus_component_get_factory (component);
1565
if (factory != NULL) {
1569
for (j = 0; j < array->len; j++) {
1570
if (component == (BusComponent *) g_ptr_array_index (array, j)) {
1571
has_component = TRUE;
1576
if (!has_component) {
1577
g_ptr_array_add (array, component);
1581
for (j = 0; j < array->len; j++) {
1582
bus_component_start ((BusComponent *) g_ptr_array_index (array, j),
1586
g_ptr_array_free (array, FALSE);
1588
bus_ibus_impl_property_changed (ibus, "PreloadEngines", value);
1594
* _ibus_get_embed_preedit_text:
1596
* Implement the "EmbedPreeditText" method call of
1597
* the org.freedesktop.IBus interface.
1600
_ibus_get_embed_preedit_text (BusIBusImpl *ibus,
1601
GDBusConnection *connection,
1608
return g_variant_new_boolean (ibus->embed_preedit_text);
1612
* _ibus_set_embed_preedit_text:
1614
* Implement the "EmbedPreeditText" method call of
1615
* the org.freedesktop.IBus interface.
1618
_ibus_set_embed_preedit_text (BusIBusImpl *ibus,
1619
GDBusConnection *connection,
1627
gboolean embed_preedit_text = g_variant_get_boolean (value);
1628
if (embed_preedit_text != ibus->embed_preedit_text) {
1629
ibus->embed_preedit_text = embed_preedit_text;
1630
bus_ibus_impl_property_changed (ibus, "EmbedPreeditText", value);
1637
* bus_ibus_impl_service_method_call:
1639
* Handle a D-Bus method call whose destination and interface name are
1640
* both "org.freedesktop.IBus"
1643
bus_ibus_impl_service_method_call (IBusService *service,
1644
GDBusConnection *connection,
1645
const gchar *sender,
1646
const gchar *object_path,
1647
const gchar *interface_name,
1648
const gchar *method_name,
1649
GVariant *parameters,
1650
GDBusMethodInvocation *invocation)
1652
if (g_strcmp0 (interface_name, IBUS_INTERFACE_IBUS) != 0) {
1653
IBUS_SERVICE_CLASS (bus_ibus_impl_parent_class)->service_method_call (
1654
service, connection, sender, object_path,
1655
interface_name, method_name,
1656
parameters, invocation);
1660
/* all methods in the xml definition above should be listed here. */
1661
static const struct {
1662
const gchar *method_name;
1663
void (* method_callback) (BusIBusImpl *,
1665
GDBusMethodInvocation *);
1667
/* IBus interface */
1668
{ "CreateInputContext", _ibus_create_input_context },
1669
{ "RegisterComponent", _ibus_register_component },
1670
{ "GetEnginesByNames", _ibus_get_engines_by_names },
1671
{ "Exit", _ibus_exit },
1672
{ "Ping", _ibus_ping },
1673
{ "SetGlobalEngine", _ibus_set_global_engine },
1674
/* Start of deprecated methods */
1675
{ "GetAddress", _ibus_get_address_depre },
1676
{ "CurrentInputContext", _ibus_current_input_context_depre },
1677
{ "ListEngines", _ibus_list_engines_depre },
1678
{ "ListActiveEngines", _ibus_list_active_engines_depre },
1679
{ "GetUseSysLayout", _ibus_get_use_sys_layout_depre },
1680
{ "GetUseGlobalEngine", _ibus_get_use_global_engine_depre },
1681
{ "GetGlobalEngine", _ibus_get_global_engine_depre },
1682
{ "IsGlobalEngineEnabled", _ibus_is_global_engine_enabled_depre },
1683
/* End of deprecated methods */
1687
for (i = 0; i < G_N_ELEMENTS (methods); i++) {
1688
if (g_strcmp0 (methods[i].method_name, method_name) == 0) {
1689
methods[i].method_callback ((BusIBusImpl *) service,
1696
g_warning ("service_method_call received an unknown method: %s",
1697
method_name ? method_name : "(null)");
1701
* bus_ibus_impl_service_get_property:
1703
* Handle org.freedesktop.DBus.Properties.Get
1706
bus_ibus_impl_service_get_property (IBusService *service,
1707
GDBusConnection *connection,
1708
const gchar *sender,
1709
const gchar *object_path,
1710
const gchar *interface_name,
1711
const gchar *property_name,
1716
static const struct {
1717
const gchar *method_name;
1718
GVariant * (* method_callback) (BusIBusImpl *,
1722
{ "Address", _ibus_get_address },
1723
{ "CurrentInputContext", _ibus_get_current_input_context },
1724
{ "Engines", _ibus_get_engines },
1725
{ "ActiveEngines", _ibus_get_active_engines },
1726
{ "GlobalEngine", _ibus_get_global_engine },
1727
{ "EmbedPreeditText", _ibus_get_embed_preedit_text },
1730
if (g_strcmp0 (interface_name, IBUS_INTERFACE_IBUS) != 0) {
1731
return IBUS_SERVICE_CLASS (
1732
bus_ibus_impl_parent_class)->service_get_property (
1733
service, connection, sender, object_path,
1734
interface_name, property_name,
1738
for (i = 0; i < G_N_ELEMENTS (methods); i++) {
1739
if (g_strcmp0 (methods[i].method_name, property_name) == 0) {
1740
return methods[i].method_callback ((BusIBusImpl *) service,
1746
g_warning ("service_get_property received an unknown property: %s",
1747
property_name ? property_name : "(null)");
1752
* bus_ibus_impl_service_set_property:
1754
* Handle org.freedesktop.DBus.Properties.Set
1757
bus_ibus_impl_service_set_property (IBusService *service,
1758
GDBusConnection *connection,
1759
const gchar *sender,
1760
const gchar *object_path,
1761
const gchar *interface_name,
1762
const gchar *property_name,
1768
static const struct {
1769
const gchar *method_name;
1770
gboolean (* method_callback) (BusIBusImpl *,
1775
{ "PreloadEngines", _ibus_set_preload_engines },
1776
{ "EmbedPreeditText", _ibus_set_embed_preedit_text },
1779
if (g_strcmp0 (interface_name, IBUS_INTERFACE_IBUS) != 0) {
1780
return IBUS_SERVICE_CLASS (
1781
bus_ibus_impl_parent_class)->service_set_property (
1782
service, connection, sender, object_path,
1783
interface_name, property_name,
1787
for (i = 0; i < G_N_ELEMENTS (methods); i++) {
1788
if (g_strcmp0 (methods[i].method_name, property_name) == 0) {
1789
return methods[i].method_callback ((BusIBusImpl *) service,
1796
g_warning ("service_set_property received an unknown property: %s",
1797
property_name ? property_name : "(null)");
1802
bus_ibus_impl_get_default (void)
1804
static BusIBusImpl *ibus = NULL;
1807
ibus = (BusIBusImpl *) g_object_new (BUS_TYPE_IBUS_IMPL,
1808
"object-path", IBUS_PATH_IBUS,
1815
bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
1818
g_assert (BUS_IS_IBUS_IMPL (ibus));
1820
BusFactoryProxy *factory;
1822
factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path);
1828
bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
1831
g_assert (BUS_IS_IBUS_IMPL (ibus));
1833
return ibus->keymap;
1837
* bus_ibus_impl_registry_init:
1839
* Initialize IBusRegistry.
1842
bus_ibus_impl_registry_init (BusIBusImpl *ibus)
1846
IBusRegistry *registry = ibus_registry_new ();
1848
ibus->registry = NULL;
1849
ibus->components = NULL;
1850
ibus->engine_table = g_hash_table_new (g_str_hash, g_str_equal);
1852
if (g_strcmp0 (g_cache, "none") == 0) {
1853
/* Only load registry, but not read and write cache. */
1854
ibus_registry_load (registry);
1856
else if (g_strcmp0 (g_cache, "refresh") == 0) {
1857
/* Load registry and overwrite the cache. */
1858
ibus_registry_load (registry);
1859
ibus_registry_save_cache (registry, TRUE);
1861
else if (g_strcmp0 (g_cache, "auto") == 0) {
1862
/* Load registry from cache. If the cache does not exist or
1863
* it is outdated, then generate it.
1865
if (ibus_registry_load_cache (registry, FALSE) == FALSE ||
1866
ibus_registry_check_modification (registry)) {
1868
ibus_object_destroy (IBUS_OBJECT (registry));
1869
registry = ibus_registry_new ();
1871
if (ibus_registry_load_cache (registry, TRUE) == FALSE ||
1872
ibus_registry_check_modification (registry)) {
1874
ibus_object_destroy (IBUS_OBJECT (registry));
1875
registry = ibus_registry_new ();
1876
ibus_registry_load (registry);
1877
ibus_registry_save_cache (registry, TRUE);
1882
ibus->registry = registry;
1883
components = ibus_registry_get_components (registry);
1885
for (p = components; p != NULL; p = p->next) {
1886
IBusComponent *component = (IBusComponent *) p->data;
1887
BusComponent *buscomp = bus_component_new (component,
1888
NULL /* factory */);
1889
GList *engines = NULL;
1892
g_object_ref_sink (buscomp);
1893
ibus->components = g_list_append (ibus->components, buscomp);
1895
engines = bus_component_get_engines (buscomp);
1896
for (p1 = engines; p1 != NULL; p1 = p1->next) {
1897
IBusEngineDesc *desc = (IBusEngineDesc *) p1->data;
1898
const gchar *name = ibus_engine_desc_get_name (desc);
1899
if (g_hash_table_lookup (ibus->engine_table, name) == NULL) {
1900
g_hash_table_insert (ibus->engine_table,
1904
g_message ("Engine %s is already registered by other component",
1908
g_list_free (engines);
1911
g_list_free (components);
1913
g_signal_connect (ibus->registry,
1915
G_CALLBACK (_registry_changed_cb),
1917
ibus_registry_start_monitor_changes (ibus->registry);
1921
bus_ibus_impl_registry_destroy (BusIBusImpl *ibus)
1923
g_list_free_full (ibus->components, g_object_unref);
1924
ibus->components = NULL;
1926
g_hash_table_destroy (ibus->engine_table);
1927
ibus->engine_table = NULL;
1929
ibus_object_destroy (IBUS_OBJECT (ibus->registry));
1930
ibus->registry = NULL;
1934
_component_is_name_cb (BusComponent *component,
1937
g_assert (BUS_IS_COMPONENT (component));
1940
return g_strcmp0 (bus_component_get_name (component), name);
1944
bus_ibus_impl_component_name_owner_changed (BusIBusImpl *ibus,
1946
const gchar *old_name,
1947
const gchar *new_name)
1949
BusComponent *component;
1950
BusFactoryProxy *factory;
1952
g_assert (BUS_IS_IBUS_IMPL (ibus));
1954
g_assert (old_name);
1955
g_assert (new_name);
1957
component = bus_ibus_impl_lookup_component_by_name (ibus, name);
1959
if (component == NULL) {
1960
/* name is a unique name, or a well-known name we don't know. */
1964
if (g_strcmp0 (old_name, "") != 0) {
1965
/* the component is stopped. */
1966
factory = bus_component_get_factory (component);
1968
if (factory != NULL) {
1969
ibus_proxy_destroy ((IBusProxy *) factory);
1973
if (g_strcmp0 (new_name, "") != 0) {
1974
/* the component is started. */
1975
BusConnection *connection =
1976
bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS,
1978
if (connection == NULL)
1981
factory = bus_factory_proxy_new (connection);
1982
if (factory == NULL)
1984
bus_component_set_factory (component, factory);
1985
g_object_unref (factory);
1990
bus_ibus_impl_lookup_component_by_name (BusIBusImpl *ibus,
1995
g_assert (BUS_IS_IBUS_IMPL (ibus));
1998
p = g_list_find_custom (ibus->components,
2000
(GCompareFunc) _component_is_name_cb);
2002
return (BusComponent *) p->data;
2010
* bus_ibus_impl_property_changed
2012
* Send a "PropertiesChanged" D-Bus signal for a property to buses
2013
* (connections) that are listening to the signal.
2016
bus_ibus_impl_property_changed (BusIBusImpl *service,
2017
const gchar *property_name,
2020
GDBusMessage *message =
2021
g_dbus_message_new_signal ("/org/freedesktop/IBus",
2022
"org.freedesktop.DBus.Properties",
2023
"PropertiesChanged");
2025
/* set a non-zero serial to make libdbus happy */
2026
g_dbus_message_set_serial (message, 1);
2027
g_dbus_message_set_sender (message, "org.freedesktop.IBus");
2029
GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
2030
g_variant_builder_add (builder, "{sv}", property_name, value);
2031
g_dbus_message_set_body (message,
2032
g_variant_new ("(sa{sv}as)",
2033
"org.freedesktop.IBus",
2037
bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
2038
g_object_unref (message);
2042
* bus_ibus_impl_emit_signal:
2044
* Send a D-Bus signal to buses (connections) that are listening to the signal.
2047
bus_ibus_impl_emit_signal (BusIBusImpl *ibus,
2048
const gchar *signal_name,
2049
GVariant *parameters)
2051
GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/IBus",
2052
"org.freedesktop.IBus",
2054
/* set a non-zero serial to make libdbus happy */
2055
g_dbus_message_set_serial (message, 1);
2056
g_dbus_message_set_sender (message, "org.freedesktop.IBus");
2058
g_dbus_message_set_body (message, parameters);
2059
bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
2060
g_object_unref (message);
2064
bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
2066
bus_ibus_impl_emit_signal (ibus, "RegistryChanged", NULL);
2070
bus_ibus_impl_global_engine_changed (BusIBusImpl *ibus)
2072
const gchar *name = ibus->global_engine_name ? ibus->global_engine_name : "";
2073
bus_ibus_impl_emit_signal (ibus, "GlobalEngineChanged",
2074
g_variant_new ("(s)", name));
2078
bus_ibus_impl_is_use_sys_layout (BusIBusImpl *ibus)
2080
g_assert (BUS_IS_IBUS_IMPL (ibus));
2082
return ibus->use_sys_layout;
2086
bus_ibus_impl_is_embed_preedit_text (BusIBusImpl *ibus)
2088
g_assert (BUS_IS_IBUS_IMPL (ibus));
2090
return ibus->embed_preedit_text;
2094
bus_ibus_impl_get_focused_input_context (BusIBusImpl *ibus)
2096
g_assert (BUS_IS_IBUS_IMPL (ibus));
2098
return ibus->focused_context;