/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/* vim:set et sts=4: */
/* ibus - The Input Bus
- * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2008-2010 Red Hat, Inc.
+ * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
+ * Copyright (C) 2008-2013 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* Boston, MA 02111-1307, USA.
*/
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <stdlib.h>
+#include "ibusimpl.h"
+
#include <locale.h>
-#include <string.h>
+#include <signal.h>
#include <strings.h>
-#include "types.h"
-#include "ibusimpl.h"
-#include "dbusimpl.h"
-#include "server.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
#include "connection.h"
-#include "registry.h"
+#include "dbusimpl.h"
#include "factoryproxy.h"
-#include "panelproxy.h"
+#include "global.h"
#include "inputcontext.h"
-#include "option.h"
+#include "panelproxy.h"
+#include "server.h"
+#include "types.h"
struct _BusIBusImpl {
IBusService parent;
/* a fake input context for global engine support */
BusInputContext *fake_context;
-
- /* a list of engines that are preloaded. */
- GList *engine_list;
- /* a list of engines that are started by a user (without the --ibus command line flag.) */
+
+ /* a list of engines that are started by a user (without the --ibus
+ * command line flag.) */
GList *register_engine_list;
- /* if TRUE, ibus-daemon uses a keysym translated by the system (i.e. XKB) as-is.
- * otherwise, ibus-daemon itself converts keycode into keysym. */
+ /* if TRUE, ibus-daemon uses a keysym translated by the system
+ * (i.e. XKB) as-is. otherwise, ibus-daemon itself converts keycode
+ * into keysym. */
gboolean use_sys_layout;
gboolean embed_preedit_text;
- gboolean enable_by_default;
- BusRegistry *registry;
+ IBusRegistry *registry;
+
+ /* a list of BusComponent objects that are created from component XML
+ * files (or from the cache of them). */
+ GList *components;
+
+ /* a mapping from an engine name (e.g. 'pinyin') to the corresponding
+ * IBusEngineDesc object. */
+ GHashTable *engine_table;
BusInputContext *focused_context;
BusPanelProxy *panel;
- IBusConfig *config;
- /* global hotkeys such as "trigger" and "next_engine_in_menu" */
- IBusHotkeyProfile *hotkey_profile;
- /* a default keymap of ibus-daemon (usually "us") which is used only when use_sys_layout is FALSE. */
+ /* a default keymap of ibus-daemon (usually "us") which is used only
+ * when use_sys_layout is FALSE. */
IBusKeymap *keymap;
gboolean use_global_engine;
gchar *global_engine_name;
gchar *global_previous_engine_name;
-
- /* engine-specific hotkeys */
- IBusHotkeyProfile *engines_hotkey_profile;
- GHashTable *hotkey_to_engines_map;
};
struct _BusIBusImplClass {
*/
/* functions prototype */
-static void bus_ibus_impl_destroy (BusIBusImpl *ibus);
-static void bus_ibus_impl_service_method_call
- (IBusService *service,
- GDBusConnection *connection,
- const gchar *sender,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *method_name,
- GVariant *parameters,
- GDBusMethodInvocation
- *invocation);
-/* TODO use property to replace some getter and setter in future */
-#if 0
-static GVariant *ibus_ibus_impl_service_get_property
- (IBusService *service,
- GDBusConnection *connection,
- const gchar *sender,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *property_name,
- GError **error);
-static gboolean ibus_ibus_impl_service_set_property
- (IBusService *service,
- GDBusConnection *connection,
- const gchar *sender,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *property_name,
- GVariant *value,
- GError **error);
-#endif
-static void bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
- GVariant *value);
-static void bus_ibus_impl_set_next_engine_in_menu
- (BusIBusImpl *ibus,
- GVariant *value);
-static void bus_ibus_impl_set_previous_engine
- (BusIBusImpl *ibus,
- GVariant *value);
-static void bus_ibus_impl_set_preload_engines
- (BusIBusImpl *ibus,
- GVariant *value);
-static void bus_ibus_impl_set_use_sys_layout
- (BusIBusImpl *ibus,
- GVariant *value);
-static void bus_ibus_impl_set_embed_preedit_text
- (BusIBusImpl *ibus,
- GVariant *value);
-static void bus_ibus_impl_set_enable_by_default
- (BusIBusImpl *ibus,
- GVariant *value);
-static void bus_ibus_impl_set_use_global_engine
- (BusIBusImpl *ibus,
- GVariant *value);
-static void bus_ibus_impl_set_global_engine (BusIBusImpl *ibus,
- BusEngineProxy *engine);
-static void bus_ibus_impl_set_global_engine_by_name
- (BusIBusImpl *ibus,
- const gchar *name);
-static void bus_ibus_impl_engines_maybe_removed
- (BusIBusImpl *ibus);
-static void bus_ibus_impl_registry_changed (BusIBusImpl *ibus);
+static void bus_ibus_impl_destroy (BusIBusImpl *ibus);
+static void bus_ibus_impl_service_method_call
+ (IBusService *service,
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation
+ *invocation);
+static GVariant *
+ bus_ibus_impl_service_get_property
+ (IBusService *service,
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GError **error);
+static gboolean
+ bus_ibus_impl_service_set_property
+ (IBusService *service,
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GVariant *value,
+ GError **error);
+static void bus_ibus_impl_registry_init
+ (BusIBusImpl *ibus);
+static void bus_ibus_impl_registry_changed
+ (BusIBusImpl *ibus);
+static void bus_ibus_impl_registry_destroy
+ (BusIBusImpl *ibus);
+static void bus_ibus_impl_component_name_owner_changed
+ (BusIBusImpl *ibus,
+ const gchar *name,
+ const gchar *old_name,
+ const gchar *new_name);
static void bus_ibus_impl_global_engine_changed
- (BusIBusImpl *ibus);
+ (BusIBusImpl *ibus);
static void bus_ibus_impl_set_context_engine_from_desc
- (BusIBusImpl *ibus,
- BusInputContext *context,
- IBusEngineDesc *desc);
-static gchar *bus_ibus_impl_load_global_engine_name_from_config
- (BusIBusImpl *ibus);
-static void bus_ibus_impl_save_global_engine_name_to_config
- (BusIBusImpl *ibus);
-
-static gchar *bus_ibus_impl_load_global_previous_engine_name_from_config
- (BusIBusImpl *ibus);
-static void bus_ibus_impl_save_global_previous_engine_name_to_config
- (BusIBusImpl *ibus);
-static void bus_ibus_impl_update_engines_hotkey_profile
- (BusIBusImpl *ibus);
+ (BusIBusImpl *ibus,
+ BusInputContext *context,
+ IBusEngineDesc *desc);
static BusInputContext
*bus_ibus_impl_create_input_context
- (BusIBusImpl *ibus,
- BusConnection *connection,
- const gchar *client);
+ (BusIBusImpl *ibus,
+ BusConnection *connection,
+ const gchar *client);
+static IBusEngineDesc
+ *bus_ibus_impl_get_engine_desc
+ (BusIBusImpl *ibus,
+ const gchar *engine_name);
+static void bus_ibus_impl_set_focused_context
+ (BusIBusImpl *ibus,
+ BusInputContext *context);
/* some callback functions */
-static void _context_engine_changed_cb (BusInputContext *context,
- BusIBusImpl *ibus);
-
-/* The interfaces available in this class, which consists of a list of methods this class implements and
- * a list of signals this class may emit. Method calls to the interface that are not defined in this XML
- * will be automatically rejected by the GDBus library (see src/ibusservice.c for details.) */
+static void _context_engine_changed_cb
+ (BusInputContext *context,
+ BusIBusImpl *ibus);
+
+/* The interfaces available in this class, which consists of a list of
+ * methods this class implements and a list of signals this class may emit.
+ * Method calls to the interface that are not defined in this XML will
+ * be automatically rejected by the GDBus library (see src/ibusservice.c
+ * for details.)
+ * Implement org.freedesktop.DBus.Properties
+ * http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties */
static const gchar introspection_xml[] =
"<node>\n"
" <interface name='org.freedesktop.IBus'>\n"
- " <method name='GetAddress'>\n"
- " <arg direction='out' type='s' name='address' />\n"
- " </method>\n"
+ " <property name='Address' type='s' access='read' />\n"
+ " <property name='CurrentInputContext' type='o' access='read' />\n"
+ " <property name='Engines' type='av' access='read' />\n"
+ " <property name='GlobalEngine' type='v' access='read' />\n"
+ " <property name='PreloadEngines' type='as' access='write'>\n"
+ " <annotation\n"
+ " name='org.freedesktop.DBus.Property.EmitsChangedSignal'\n"
+ " value='true' />\n"
+ " </property>\n"
+ " <property name='EmbedPreeditText' type='b' access='readwrite'>\n"
+ " <annotation\n"
+ " name='org.freedesktop.DBus.Property.EmitsChangedSignal'\n"
+ " value='true' />\n"
+ " </property>\n"
" <method name='CreateInputContext'>\n"
" <arg direction='in' type='s' name='client_name' />\n"
" <arg direction='out' type='o' name='object_path' />\n"
" </method>\n"
- " <method name='CurrentInputContext'>\n"
- " <arg direction='out' type='o' name='object_path' />\n"
- " </method>\n"
" <method name='RegisterComponent'>\n"
" <arg direction='in' type='v' name='component' />\n"
" </method>\n"
- " <method name='ListEngines'>\n"
- " <arg direction='out' type='av' name='engines' />\n"
- " </method>\n"
- " <method name='ListActiveEngines'>\n"
+ " <method name='GetEnginesByNames'>\n"
+ " <arg direction='in' type='as' name='names' />\n"
" <arg direction='out' type='av' name='engines' />\n"
" </method>\n"
" <method name='Exit'>\n"
" <arg direction='in' type='v' name='data' />\n"
" <arg direction='out' type='v' name='data' />\n"
" </method>\n"
+ " <method name='SetGlobalEngine'>\n"
+ " <arg direction='in' type='s' name='engine_name' />\n"
+ " </method>\n"
+ " <signal name='RegistryChanged'>\n"
+ " </signal>\n"
+ " <signal name='GlobalEngineChanged'>\n"
+ " <arg type='s' name='engine_name' />\n"
+ " </signal>\n"
+ " <property name='ActiveEngines' type='av' access='read' />\n"
+ " <method name='GetAddress'>\n"
+ " <arg direction='out' type='s' name='address' />\n"
+ " <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
+ " </method>\n"
+ " <method name='CurrentInputContext'>\n"
+ " <arg direction='out' type='o' name='object_path' />\n"
+ " <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
+ " </method>\n"
+ " <method name='ListEngines'>\n"
+ " <arg direction='out' type='av' name='engines' />\n"
+ " <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
+ " </method>\n"
+ " <method name='ListActiveEngines'>\n"
+ " <arg direction='out' type='av' name='engines' />\n"
+ " <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
+ " </method>\n"
" <method name='GetUseSysLayout'>\n"
" <arg direction='out' type='b' name='enabled' />\n"
+ " <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
" </method>\n"
" <method name='GetUseGlobalEngine'>\n"
" <arg direction='out' type='b' name='enabled' />\n"
" </method>\n"
- " <method name='GetGlobalEngine'>\n"
- " <arg direction='out' type='v' name='desc' />\n"
- " </method>\n"
- " <method name='SetGlobalEngine'>\n"
- " <arg direction='in' type='s' name='engine_name' />\n"
- " </method>\n"
" <method name='IsGlobalEngineEnabled'>\n"
" <arg direction='out' type='b' name='enabled' />\n"
+ " <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
+ " </method>\n"
+ " <method name='GetGlobalEngine'>\n"
+ " <arg direction='out' type='v' name='desc' />\n"
+ " <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
" </method>\n"
- " <signal name='RegistryChanged'>\n"
- " </signal>\n"
- " <signal name='GlobalEngineChanged'>\n"
- " <arg type='s' name='engine_name' />\n"
- " </signal>\n"
" </interface>\n"
"</node>\n";
static void
bus_ibus_impl_class_init (BusIBusImplClass *class)
{
- IBUS_OBJECT_CLASS (class)->destroy = (IBusObjectDestroyFunc) bus_ibus_impl_destroy;
+ IBUS_OBJECT_CLASS (class)->destroy =
+ (IBusObjectDestroyFunc) bus_ibus_impl_destroy;
/* override the parent class's implementation. */
- IBUS_SERVICE_CLASS (class)->service_method_call = bus_ibus_impl_service_method_call;
- /* register the xml so that bus_ibus_impl_service_method_call will be called on a method call defined in the xml (e.g. 'GetAddress'.) */
- ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
+ IBUS_SERVICE_CLASS (class)->service_method_call =
+ bus_ibus_impl_service_method_call;
+ IBUS_SERVICE_CLASS (class)->service_get_property =
+ bus_ibus_impl_service_get_property;
+ IBUS_SERVICE_CLASS (class)->service_set_property =
+ bus_ibus_impl_service_set_property;
+ /* register the xml so that bus_ibus_impl_service_method_call will be
+ * called on a method call defined in the xml (e.g. 'GetAddress'.) */
+ ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class),
+ introspection_xml);
}
/**
}
static void
-bus_ibus_impl_set_hotkey (BusIBusImpl *ibus,
- GQuark hotkey,
- GVariant *value)
-{
- g_assert (BUS_IS_IBUS_IMPL (ibus));
-
- ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
-
- if (value == NULL) {
- return;
- }
-
- GVariantIter iter;
- g_variant_iter_init (&iter, value);
- const gchar *str = NULL;
- while (g_variant_iter_loop (&iter,"&s", &str)) {
- ibus_hotkey_profile_add_hotkey_from_string (ibus->hotkey_profile,
- str,
- hotkey);
- }
-
-}
-
-/**
- * bus_ibus_impl_set_trigger:
- *
- * A function to be called when "trigger" config is updated. If the value is NULL, the default trigger (Ctrl+space) is set.
- */
-static void
-bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
- GVariant *value)
-{
- GQuark hotkey = g_quark_from_static_string ("trigger");
- if (value != NULL) {
- bus_ibus_impl_set_hotkey (ibus, hotkey, value);
- }
-#ifndef OS_CHROMEOS
- else {
- /* set default trigger */
- ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
- ibus_hotkey_profile_add_hotkey (ibus->hotkey_profile,
- IBUS_space,
- IBUS_CONTROL_MASK,
- hotkey);
- }
-#endif
-}
-
-/**
- * bus_ibus_impl_set_enable_unconditional:
- *
- * A function to be called when "enable_unconditional" config is updated.
- */
-static void
-bus_ibus_impl_set_enable_unconditional (BusIBusImpl *ibus,
- GVariant *value)
-{
- GQuark hotkey = g_quark_from_static_string ("enable-unconditional");
- bus_ibus_impl_set_hotkey (ibus, hotkey, value);
-}
-
-/**
- * bus_ibus_impl_set_disable_unconditional:
- *
- * A function to be called when "disable_unconditional" config is updated.
- */
-static void
-bus_ibus_impl_set_disable_unconditional (BusIBusImpl *ibus,
- GVariant *value)
-{
- GQuark hotkey = g_quark_from_static_string ("disable-unconditional");
- bus_ibus_impl_set_hotkey (ibus, hotkey, value);
-}
-
-/**
- * bus_ibus_impl_set_next_engine_in_menu:
- *
- * A function to be called when "next_engine_in_menu" config is updated.
- */
-static void
-bus_ibus_impl_set_next_engine_in_menu (BusIBusImpl *ibus,
- GVariant *value)
-{
- GQuark hotkey = g_quark_from_static_string ("next-engine-in-menu");
- bus_ibus_impl_set_hotkey (ibus, hotkey, value);
-}
-
-/**
- * bus_ibus_impl_set_previous_engine:
- *
- * A function to be called when "previous_engine" config is updated.
- */
-static void
-bus_ibus_impl_set_previous_engine (BusIBusImpl *ibus,
- GVariant *value)
-{
- GQuark hotkey = g_quark_from_static_string ("previous-engine");
- bus_ibus_impl_set_hotkey (ibus, hotkey, value);
-}
-
-/**
- * bus_ibus_impl_set_preload_engines:
- *
- * A function to be called when "preload_engines" config is updated.
- */
-static void
-bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus,
- GVariant *value)
-{
- GList *engine_list = NULL;
-
- g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
- g_list_free (ibus->engine_list);
-
- if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_ARRAY) {
- GVariantIter iter;
- g_variant_iter_init (&iter, value);
- const gchar *engine_name = NULL;
- while (g_variant_iter_loop (&iter, "&s", &engine_name)) {
- IBusEngineDesc *engine = bus_registry_find_engine_by_name (ibus->registry, engine_name);
- if (engine == NULL || g_list_find (engine_list, engine) != NULL)
- continue;
- engine_list = g_list_append (engine_list, engine);
- }
- }
-
- g_list_foreach (engine_list, (GFunc) g_object_ref, NULL);
- ibus->engine_list = engine_list;
-
- if (ibus->engine_list) {
- BusComponent *component = bus_component_from_engine_desc ((IBusEngineDesc *) ibus->engine_list->data);
- if (component && !bus_component_is_running (component)) {
- bus_component_start (component, g_verbose);
- }
- }
-
- bus_ibus_impl_engines_maybe_removed (ibus);
- bus_ibus_impl_update_engines_hotkey_profile (ibus);
-}
-
-/**
- * bus_ibus_impl_set_use_sys_layout:
- *
- * A function to be called when "use_system_keyboard_layout" config is updated.
- */
-static void
-bus_ibus_impl_set_use_sys_layout (BusIBusImpl *ibus,
- GVariant *value)
-{
- if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
- ibus->use_sys_layout = g_variant_get_boolean (value);
- }
-}
-
-/**
- * bus_ibus_impl_set_embed_preedit_text:
- *
- * A function to be called when "use_embed_preedit_text" config is updated.
- */
-static void
-bus_ibus_impl_set_embed_preedit_text (BusIBusImpl *ibus,
- GVariant *value)
-{
- if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
- ibus->embed_preedit_text = g_variant_get_boolean (value);
- }
-}
-
-/**
- * bus_ibus_impl_set_enable_by_default:
- *
- * A function to be called when "enable_by_default" config is updated.
- */
-static void
-bus_ibus_impl_set_enable_by_default (BusIBusImpl *ibus,
- GVariant *value)
-{
- if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
- ibus->enable_by_default = g_variant_get_boolean (value);
- }
-}
-
-/**
- * bus_ibus_impl_set_use_global_engine:
- *
- * A function to be called when "use_global_engine" config is updated.
- */
-static void
-bus_ibus_impl_set_use_global_engine (BusIBusImpl *ibus,
- GVariant *value)
-{
- if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_BOOLEAN)
- return;
-
- gboolean new_value = g_variant_get_boolean (value);
- if (ibus->use_global_engine == new_value)
- return;
-
- if (new_value) {
- /* turn on use_global_engine option */
- ibus->use_global_engine = TRUE;
- if (ibus->panel && ibus->focused_context == NULL) {
- bus_panel_proxy_focus_in (ibus->panel, ibus->fake_context);
- }
- }
- else {
- /* turn off use_global_engine option */
- ibus->use_global_engine = FALSE;
-
- /* if fake context has the focus, we should focus out it */
- if (ibus->panel && ibus->focused_context == NULL) {
- bus_panel_proxy_focus_out (ibus->panel, ibus->fake_context);
- }
- /* remove engine in fake context */
- bus_input_context_set_engine (ibus->fake_context, NULL);
- }
-}
-
-#ifndef OS_CHROMEOS
-static gint
-_engine_desc_cmp (IBusEngineDesc *desc1,
- IBusEngineDesc *desc2)
-{
- return - ((gint) ibus_engine_desc_get_rank (desc1)) +
- ((gint) ibus_engine_desc_get_rank (desc2));
-}
-#endif
-
-/**
- * bus_ibus_impl_set_default_preload_engines:
- *
- * If the "preload_engines" config variable is not set yet, set the default value which is determined based on a current locale.
- */
-static void
-bus_ibus_impl_set_default_preload_engines (BusIBusImpl *ibus)
-{
-#ifndef OS_CHROMEOS
- g_assert (BUS_IS_IBUS_IMPL (ibus));
-
- static gboolean done = FALSE;
-
- if (done || ibus->config == NULL) {
- return;
- }
-
- GVariant *variant = ibus_config_get_value (ibus->config, "general", "preload_engines");
- if (variant != NULL) {
- done = TRUE;
- g_variant_unref (variant);
- return;
- }
-
- done = TRUE;
-
- /* The setlocale call first checks LC_ALL. If it's not available, checks
- * LC_CTYPE. If it's also not available, checks LANG. */
- gchar *lang = g_strdup (setlocale (LC_CTYPE, NULL));
- if (lang == NULL) {
- return;
- }
-
- gchar *p = index (lang, '.');
- if (p) {
- *p = '\0';
- }
-
- GList *engines = bus_registry_get_engines_by_language (ibus->registry, lang);
- if (engines == NULL) {
- p = index (lang, '_');
- if (p) {
- *p = '\0';
- engines = bus_registry_get_engines_by_language (ibus->registry, lang);
- }
- }
- g_free (lang);
-
- /* sort engines by rank */
- engines = g_list_sort (engines, (GCompareFunc) _engine_desc_cmp);
-
- GVariantBuilder builder;
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
- GList *list;
- for (list = engines; list != NULL; list = list->next) {
- IBusEngineDesc *desc = (IBusEngineDesc *) list->data;
- /* ignore engines with rank <= 0 */
- if (ibus_engine_desc_get_rank (desc) > 0)
- g_variant_builder_add (&builder, "s", ibus_engine_desc_get_name (desc));
- }
-
- GVariant *value = g_variant_builder_end (&builder);
- if (value != NULL) {
- if (g_variant_n_children (value) > 0) {
- ibus_config_set_value (ibus->config,
- "general", "preload_engines", value);
- } else {
- /* We don't update preload_engines with an empty string for safety.
- * Just unref the floating value. */
- g_variant_unref (value);
- }
- }
- g_list_free (engines);
-#endif
-}
-
-/* The list of config entries that are related to ibus-daemon. */
-const static struct {
- gchar *section;
- gchar *key;
- void (*func) (BusIBusImpl *, GVariant *);
-} bus_ibus_impl_config_items [] = {
- { "general/hotkey", "trigger", bus_ibus_impl_set_trigger },
- { "general/hotkey", "enable_unconditional", bus_ibus_impl_set_enable_unconditional },
- { "general/hotkey", "disable_unconditional", bus_ibus_impl_set_disable_unconditional },
- { "general/hotkey", "next_engine_in_menu", bus_ibus_impl_set_next_engine_in_menu },
- { "general/hotkey", "previous_engine", bus_ibus_impl_set_previous_engine },
- { "general", "preload_engines", bus_ibus_impl_set_preload_engines },
- { "general", "use_system_keyboard_layout", bus_ibus_impl_set_use_sys_layout },
- { "general", "use_global_engine", bus_ibus_impl_set_use_global_engine },
- { "general", "embed_preedit_text", bus_ibus_impl_set_embed_preedit_text },
- { "general", "enable_by_default", bus_ibus_impl_set_enable_by_default },
-};
-
-/**
- * bus_ibus_impl_reload_config
- *
- * Read config entries (e.g. preload_engines) from the config daemon.
- */
-static void
-bus_ibus_impl_reload_config (BusIBusImpl *ibus)
-{
- g_assert (BUS_IS_IBUS_IMPL (ibus));
-
- gint i;
- for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
- GVariant *variant = NULL;
- if (ibus->config != NULL)
- variant = ibus_config_get_value (ibus->config,
- bus_ibus_impl_config_items[i].section,
- bus_ibus_impl_config_items[i].key);
- bus_ibus_impl_config_items[i].func (ibus, variant); /* variant could be NULL if the deamon is not ready yet. */
- if (variant) g_variant_unref (variant);
- }
-}
-
-/**
- * _config_value_changed_cb:
- *
- * A callback function to be called when the "ValueChanged" D-Bus signal is sent from the config daemon.
- */
-static void
-_config_value_changed_cb (IBusConfig *config,
- gchar *section,
- gchar *key,
- GVariant *value,
- BusIBusImpl *ibus)
-{
- g_assert (IBUS_IS_CONFIG (config));
- g_assert (section);
- g_assert (key);
- g_assert (value);
- g_assert (BUS_IS_IBUS_IMPL (ibus));
-
- gint i;
- for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
- if (g_strcmp0 (bus_ibus_impl_config_items[i].section, section) == 0 &&
- g_strcmp0 (bus_ibus_impl_config_items[i].key, key) == 0) {
- bus_ibus_impl_config_items[i].func (ibus, value);
- break;
- }
- }
-}
-
-/**
- * _config_destroy_cb:
- *
- * A callback function which is called when (1) the connection to the config process is terminated,
- * or (2) ibus_proxy_destroy (ibus->config); is called. See src/ibusproxy.c for details.
- */
-static void
-_config_destroy_cb (IBusConfig *config,
- BusIBusImpl *ibus)
-{
- g_assert (IBUS_IS_CONFIG (config));
- g_assert (BUS_IS_IBUS_IMPL (ibus));
-
- g_assert (ibus->config == config);
-
- g_object_unref (ibus->config);
- ibus->config = NULL;
-}
-
-static void
-_registry_changed_cb (BusRegistry *registry,
- BusIBusImpl *ibus)
+_registry_changed_cb (IBusRegistry *registry,
+ BusIBusImpl *ibus)
{
bus_ibus_impl_registry_changed (ibus);
}
* This usually means a client (e.g. a panel/config/engine process or an application) is connected/disconnected to/from the bus.
*/
static void
-_dbus_name_owner_changed_cb (BusDBusImpl *dbus,
- const gchar *name,
- const gchar *old_name,
- const gchar *new_name,
- BusIBusImpl *ibus)
+_dbus_name_owner_changed_cb (BusDBusImpl *dbus,
+ BusConnection *orig_connection,
+ const gchar *name,
+ const gchar *old_name,
+ const gchar *new_name,
+ BusIBusImpl *ibus)
{
g_assert (BUS_IS_DBUS_IMPL (dbus));
g_assert (name != NULL);
if (g_strcmp0 (new_name, "") != 0) {
/* a Panel process is started. */
BusConnection *connection;
+ BusInputContext *context = NULL;
if (ibus->panel != NULL) {
ibus_proxy_destroy ((IBusProxy *) ibus->panel);
ibus);
if (ibus->focused_context != NULL) {
- bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
+ context = ibus->focused_context;
}
else if (ibus->use_global_engine) {
- bus_panel_proxy_focus_in (ibus->panel, ibus->fake_context);
+ context = ibus->fake_context;
+ }
+
+ if (context != NULL) {
+ BusEngineProxy *engine;
+
+ bus_panel_proxy_focus_in (ibus->panel, context);
+
+ engine = bus_input_context_get_engine (context);
+ if (engine != NULL) {
+ IBusPropList *prop_list =
+ bus_engine_proxy_get_properties (engine);
+ bus_panel_proxy_register_properties (ibus->panel,
+ prop_list);
+ }
}
}
}
- else if (g_strcmp0 (name, IBUS_SERVICE_CONFIG) == 0) {
- if (g_strcmp0 (new_name, "") != 0) {
- /* a config process is started. */
- BusConnection *connection;
- if (ibus->config != NULL) {
- ibus_proxy_destroy ((IBusProxy *) ibus->config);
- /* config should be NULL after destroy. See _config_destroy_cb for details. */
- g_assert (ibus->config == NULL);
- }
-
- /* get a connection between ibus-daemon and the config daemon. */
- connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
- g_return_if_fail (connection != NULL);
-
- ibus->config = g_initable_new (IBUS_TYPE_CONFIG,
- NULL,
- NULL,
- /* The following properties are necessary to initialize GDBusProxy object
- * which is a parent of the config object. */
- "g-connection", bus_connection_get_dbus_connection (connection),
- "g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
- "g-interface-name", IBUS_INTERFACE_CONFIG,
- "g-object-path", IBUS_PATH_CONFIG,
- "g-default-timeout", g_gdbus_timeout,
- NULL);
-
- g_signal_connect (ibus->config,
- "value-changed",
- G_CALLBACK (_config_value_changed_cb),
- ibus);
-
- g_signal_connect (ibus->config,
- "destroy",
- G_CALLBACK (_config_destroy_cb),
- ibus);
-
- bus_ibus_impl_set_default_preload_engines (ibus);
- bus_ibus_impl_reload_config (ibus);
- }
- }
-
- bus_registry_name_owner_changed (ibus->registry, name, old_name, new_name);
-}
+ bus_ibus_impl_component_name_owner_changed (ibus, name, old_name, new_name);
+}
/**
* bus_ibus_impl_init:
ibus);
bus_input_context_focus_in (ibus->fake_context);
- ibus->engine_list = NULL;
ibus->register_engine_list = NULL;
ibus->contexts = NULL;
ibus->focused_context = NULL;
ibus->panel = NULL;
- ibus->config = NULL;
-
- ibus->registry = bus_registry_new ();
-
- g_signal_connect (ibus->registry,
- "changed",
- G_CALLBACK (_registry_changed_cb),
- ibus);
-#ifdef G_THREADS_ENABLED
- extern gint g_monitor_timeout;
- if (g_monitor_timeout != 0) {
- /* Start the monitor of registry changes. */
- bus_registry_start_monitor_changes (ibus->registry);
- }
-#endif
- ibus->hotkey_profile = ibus_hotkey_profile_new ();
ibus->keymap = ibus_keymap_get ("us");
- ibus->use_sys_layout = FALSE;
+ ibus->use_sys_layout = TRUE;
ibus->embed_preedit_text = TRUE;
- ibus->enable_by_default = FALSE;
- ibus->use_global_engine = FALSE;
+ ibus->use_global_engine = TRUE;
ibus->global_engine_name = NULL;
ibus->global_previous_engine_name = NULL;
- ibus->engines_hotkey_profile = NULL;
- ibus->hotkey_to_engines_map = NULL;
-
- bus_ibus_impl_reload_config (ibus);
+ /* focus the fake_context, if use_global_engine is enabled. */
+ if (ibus->use_global_engine)
+ bus_ibus_impl_set_focused_context (ibus, ibus->fake_context);
g_signal_connect (BUS_DEFAULT_DBUS,
"name-owner-changed",
G_CALLBACK (_dbus_name_owner_changed_cb),
ibus);
+
+ bus_ibus_impl_registry_init (ibus);
}
/**
gint status;
gboolean flag;
- bus_registry_stop_all_components (ibus->registry);
+ g_list_foreach (ibus->components, (GFunc) bus_component_stop, NULL);
pid = 0;
timeout = 0;
}
}
- g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
- g_list_free (ibus->engine_list);
- ibus->engine_list = NULL;
-
- g_list_foreach (ibus->register_engine_list, (GFunc) g_object_unref, NULL);
- g_list_free (ibus->register_engine_list);
+ g_list_free_full (ibus->register_engine_list, g_object_unref);
ibus->register_engine_list = NULL;
if (ibus->factory_dict != NULL) {
ibus->factory_dict = NULL;
}
- if (ibus->hotkey_profile != NULL) {
- g_object_unref (ibus->hotkey_profile);
- ibus->hotkey_profile = NULL;
- }
-
if (ibus->keymap != NULL) {
g_object_unref (ibus->keymap);
ibus->keymap = NULL;
g_free (ibus->global_previous_engine_name);
ibus->global_previous_engine_name = NULL;
- if (ibus->engines_hotkey_profile != NULL) {
- g_object_unref (ibus->engines_hotkey_profile);
- ibus->engines_hotkey_profile = NULL;
- }
-
- if (ibus->hotkey_to_engines_map) {
- g_hash_table_unref (ibus->hotkey_to_engines_map);
- ibus->hotkey_to_engines_map = NULL;
- }
-
if (ibus->fake_context) {
g_object_unref (ibus->fake_context);
ibus->fake_context = NULL;
}
- bus_server_quit ();
+ bus_ibus_impl_registry_destroy (ibus);
+
IBUS_OBJECT_CLASS (bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
}
/**
* _ibus_get_address:
*
- * Implement the "GetAddress" method call of the org.freedesktop.IBus interface.
+ * Implement the "Address" method call of the org.freedesktop.IBus interface.
*/
+static GVariant *
+_ibus_get_address (BusIBusImpl *ibus,
+ GDBusConnection *connection,
+ GError **error)
+{
+ if (error) {
+ *error = NULL;
+ }
+
+ return g_variant_new_string (bus_server_get_address ());
+}
+
static void
-_ibus_get_address (BusIBusImpl *ibus,
- GVariant *parameters,
- GDBusMethodInvocation *invocation)
+_ibus_get_address_depre (BusIBusImpl *ibus,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
{
+ GDBusConnection *connection =
+ g_dbus_method_invocation_get_connection (invocation);
+ GError *error = NULL;
+ GVariant *variant = NULL;
+
+ g_warning ("org.freedesktop.IBus.GetAddress() is deprecated!");
+
+ variant = _ibus_get_address (ibus, connection, &error);
+
g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(s)", bus_server_get_address ()));
+ g_variant_new ("(s)", g_variant_get_string (variant, NULL)));
+
+ g_variant_unref (variant);
}
static IBusEngineDesc *
return desc;
}
- /* find engine in preload engine list */
- for (p = ibus->engine_list; p != NULL; p = p->next) {
- desc = (IBusEngineDesc *) p->data;
- if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
- return desc;
- }
-
return NULL;
}
*
* A callback function to be called when the "request-engine" signal is sent to the context.
*/
-static void
+static IBusEngineDesc *
_context_request_engine_cb (BusInputContext *context,
const gchar *engine_name,
BusIBusImpl *ibus)
{
- IBusEngineDesc *desc = NULL;
-
- /* context should has focus before request an engine */
- g_return_if_fail (bus_input_context_has_focus (context) ||
- context == ibus->focused_context);
-
- if (engine_name != NULL && engine_name[0] != '\0') {
- /* request engine by name */
- desc = _find_engine_desc_by_name (ibus, engine_name);
- g_return_if_fail (desc != NULL);
- }
- else {
- /* Use global engine if possible. */
- if (ibus->use_global_engine) {
- gchar *name = g_strdup (ibus->global_engine_name);
- if (name == NULL) {
- name = bus_ibus_impl_load_global_engine_name_from_config (ibus);
- }
- if (name) {
- desc = _find_engine_desc_by_name (ibus, name);
- g_free (name);
- }
- }
- /* request default engine */
- if (!desc) {
- if (ibus->register_engine_list) {
- desc = (IBusEngineDesc *) ibus->register_engine_list->data;
- }
- else if (ibus->engine_list) {
- desc = (IBusEngineDesc *) ibus->engine_list->data;
- }
- }
- if (!desc) {
- /* no engine is available. the user hasn't ran ibus-setup yet and
- * the bus_ibus_impl_set_default_preload_engines() function could
- * not find any default engines. another possiblity is that the
- * user hasn't installed an engine yet? just give up. */
- g_warning ("No engine is available. Run ibus-setup first.");
- return;
- }
- }
-
- bus_ibus_impl_set_context_engine_from_desc (ibus, context, desc);
-}
-
-/**
- * bus_ibus_impl_context_request_next_engine_in_menu:
- *
- * Process the "next_engine_in_menu" hotkey.
- */
-static void
-bus_ibus_impl_context_request_next_engine_in_menu (BusIBusImpl *ibus,
- BusInputContext *context)
-{
- BusEngineProxy *engine;
- IBusEngineDesc *desc;
- IBusEngineDesc *next_desc = NULL;
- GList *p;
-
- engine = bus_input_context_get_engine (context);
- if (engine == NULL) {
- _context_request_engine_cb (context, NULL, ibus);
- return;
- }
-
- desc = bus_engine_proxy_get_desc (engine);
-
- p = g_list_find (ibus->register_engine_list, desc);
- if (p != NULL) {
- p = p->next;
- }
- if (p == NULL) {
- p = g_list_find (ibus->engine_list, desc);
- if (p != NULL) {
- p = p->next;
- }
- }
-
- if (p != NULL) {
- next_desc = (IBusEngineDesc*) p->data;
- }
- else {
- if (ibus->register_engine_list) {
- next_desc = (IBusEngineDesc *) ibus->register_engine_list->data;
- }
- else if (ibus->engine_list) {
- next_desc = (IBusEngineDesc *) ibus->engine_list->data;
- }
- }
+ if (engine_name == NULL || engine_name[0] == '\0')
+ engine_name = DEFAULT_ENGINE;
- bus_ibus_impl_set_context_engine_from_desc (ibus, context, next_desc);
+ return bus_ibus_impl_get_engine_desc (ibus, engine_name);
}
/**
- * bus_ibus_impl_context_request_previous_engine:
+ * bus_ibus_impl_get_engine_desc:
*
- * Process the "previous_engine" hotkey.
+ * Get the IBusEngineDesc by engine_name. If the engine_name is NULL, return
+ * a default engine desc.
*/
-static void
-bus_ibus_impl_context_request_previous_engine (BusIBusImpl *ibus,
- BusInputContext *context)
+static IBusEngineDesc *
+bus_ibus_impl_get_engine_desc (BusIBusImpl *ibus,
+ const gchar *engine_name)
{
- gchar *engine_name = NULL;
- if (!ibus->use_global_engine) {
- engine_name = (gchar *) g_object_get_data (G_OBJECT (context), "previous-engine-name");
- }
- else {
- if (!ibus->global_previous_engine_name) {
- ibus->global_previous_engine_name = bus_ibus_impl_load_global_previous_engine_name_from_config (ibus);
- }
- engine_name = ibus->global_previous_engine_name;
- }
+ g_return_val_if_fail (engine_name != NULL, NULL);
+ g_return_val_if_fail (engine_name[0] != '\0', NULL);
- /*
- * If the previous engine name is not found, switch to the next engine
- * in the menu. This behavior is better than doing nothing.
- */
- if (!engine_name) {
- bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
- return;
+ IBusEngineDesc *desc = _find_engine_desc_by_name (ibus, engine_name);
+ if (desc == NULL) {
+ desc = (IBusEngineDesc *) g_hash_table_lookup (ibus->engine_table,
+ engine_name);
}
- _context_request_engine_cb (context, engine_name, ibus);
+ return desc;
}
static void
g_assert (context == NULL || BUS_IS_INPUT_CONTEXT (context));
g_assert (context == NULL || bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS);
- /* Do noting if it is not focused context. */
+ /* Do noting if it is focused context. */
if (ibus->focused_context == context) {
return;
}
/* attach engine to the focused context */
if (engine != NULL) {
bus_input_context_set_engine (context, engine);
- if (bus_engine_proxy_is_enabled (engine))
- bus_input_context_enable (context);
- g_object_unref (engine);
+ bus_input_context_enable (context);
}
if (ibus->panel != NULL)
bus_panel_proxy_focus_in (ibus->panel, context);
}
+
+ if (engine != NULL)
+ g_object_unref (engine);
}
static void
bus_ibus_impl_set_global_engine (BusIBusImpl *ibus,
BusEngineProxy *engine)
{
- BusInputContext *context = NULL;
-
if (!ibus->use_global_engine)
return;
bus_ibus_impl_set_global_engine_by_name (BusIBusImpl *ibus,
const gchar *name)
{
- gchar *old_engine_name = NULL;
-
if (!ibus->use_global_engine)
return;
+ BusInputContext *context =
+ ibus->focused_context != NULL ? ibus->focused_context : ibus->fake_context;
+
+ if (context == NULL) {
+ return;
+ }
+
if (g_strcmp0 (name, ibus->global_engine_name) == 0) {
/* If the user requested the same global engine, then we just enable the
* original one. */
- if (ibus->focused_context) {
- bus_input_context_enable (ibus->focused_context);
- }
- else if (ibus->fake_context) {
- bus_input_context_enable (ibus->fake_context);
- }
+ bus_input_context_enable (context);
return;
}
* the focused context, which will then change the global engine
* automatically. Otherwise, we need to change the global engine directly.
*/
- if (ibus->focused_context) {
- _context_request_engine_cb (ibus->focused_context, name, ibus);
- }
- else if (ibus->fake_context) {
- _context_request_engine_cb (ibus->fake_context, name, ibus);
+ IBusEngineDesc *desc = NULL;
+ desc = bus_ibus_impl_get_engine_desc (ibus, name);
+ if (desc != NULL) {
+ bus_ibus_impl_set_context_engine_from_desc (ibus,
+ context,
+ desc);
}
}
+/* When preload_engines and register_engiens are changed, this function
+ * will check the global engine. If necessay, it will change the global engine.
+ */
static void
-bus_ibus_impl_engines_maybe_removed (BusIBusImpl *ibus)
+bus_ibus_impl_check_global_engine (BusIBusImpl *ibus)
{
- const gchar *old_engine_name = NULL;
GList *engine_list = NULL;
- if (!ibus->use_global_engine || ibus->global_engine_name == NULL)
+ /* do nothing */
+ if (!ibus->use_global_engine)
return;
/* The current global engine is not removed, so do nothing. */
- if (_find_engine_desc_by_name (ibus, ibus->global_engine_name))
+ if (ibus->global_engine_name != NULL &&
+ _find_engine_desc_by_name (ibus, ibus->global_engine_name)) {
return;
+ }
/* If the previous engine is available, then just switch to it. */
- if (ibus->global_previous_engine_name &&
+ if (ibus->global_previous_engine_name != NULL &&
_find_engine_desc_by_name (ibus, ibus->global_previous_engine_name)) {
bus_ibus_impl_set_global_engine_by_name (
ibus, ibus->global_previous_engine_name);
return;
}
- /* Just choose one in the list. */
+ /* Just switch to the fist engine in the list. */
engine_list = ibus->register_engine_list;
- if (!engine_list)
- engine_list = ibus->engine_list;
if (engine_list) {
IBusEngineDesc *engine_desc = (IBusEngineDesc *)engine_list->data;
g_free (ibus->global_previous_engine_name);
ibus->global_previous_engine_name = ibus->global_engine_name;
ibus->global_engine_name = g_strdup (name);
- /* save changes */
- bus_ibus_impl_save_global_engine_name_to_config (ibus);
- bus_ibus_impl_save_global_previous_engine_name_to_config (ibus);
bus_ibus_impl_global_engine_changed (ibus);
}
}
return;
}
-
- if (ibus->use_global_engine == FALSE) {
- /* Do not change the focused context, if use_global_engine option is enabled.
- * If focused context swith to NULL, users can not swith engine in panel anymore.
- **/
- bus_ibus_impl_set_focused_context (ibus, NULL);
- }
+ bus_ibus_impl_set_focused_context (ibus, NULL);
}
/**
}
/**
- * _context_enabled_cb:
- *
- * A callback function to be called when the "enabled" signal is sent to the context.
- */
-static void
-_context_enabled_cb (BusInputContext *context,
- BusIBusImpl *ibus)
-{
- /* FIXME implement this. */
-}
-
-/**
- * _context_disabled_cb:
- *
- * A callback function to be called when the "disabled" signal is sent to the context.
- */
-static void
-_context_disabled_cb (BusInputContext *context,
- BusIBusImpl *ibus)
-{
- /* FIXME implement this. */
-}
-
-/**
* bus_ibus_impl_create_input_context:
* @client: A name of a client. e.g. "gtk-im"
* @returns: A BusInputContext object.
{ "focus-in", G_CALLBACK (_context_focus_in_cb) },
{ "focus-out", G_CALLBACK (_context_focus_out_cb) },
{ "destroy", G_CALLBACK (_context_destroy_cb) },
- { "enabled", G_CALLBACK (_context_enabled_cb) },
- { "disabled", G_CALLBACK (_context_disabled_cb) },
};
gint i;
ibus);
}
- if (ibus->enable_by_default) {
- bus_input_context_enable (context);
- }
+ bus_input_context_enable (context);
/* register the context object so that the object could handle IBus.InputContext method calls. */
bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
}
/**
- * _ibus_current_input_context:
+ * _ibus_get_current_input_context:
*
- * Implement the "CurrentInputContext" method call of the org.freedesktop.IBus interface.
+ * Implement the "CurrentInputContext" method call of the
+ * org.freedesktop.IBus interface.
*/
-static void
-_ibus_current_input_context (BusIBusImpl *ibus,
- GVariant *parameters,
- GDBusMethodInvocation *invocation)
+static GVariant *
+_ibus_get_current_input_context (BusIBusImpl *ibus,
+ GDBusConnection *connection,
+ GError **error)
{
+ if (error) {
+ *error = NULL;
+ }
+
if (!ibus->focused_context)
{
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
- "No focused input context");
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "No focused input context");
+ return NULL;
}
else {
- const gchar *path = ibus_service_get_object_path ((IBusService *) ibus->focused_context);
+ const gchar *path = ibus_service_get_object_path (
+ (IBusService *) ibus->focused_context);
/* the format-string 'o' is for a D-Bus object path. */
- g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
+ return g_variant_new_object_path (path);
+ }
+}
+
+static void
+_ibus_current_input_context_depre (BusIBusImpl *ibus,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
+{
+ GDBusConnection *connection =
+ g_dbus_method_invocation_get_connection (invocation);
+ GVariant *variant = NULL;
+ GError *error = NULL;
+
+ g_warning ("org.freedesktop.IBus.CurrentInputContext() is deprecated!");
+
+ variant = _ibus_get_current_input_context (ibus, connection, &error);
+
+ if (variant == NULL) {
+ g_dbus_method_invocation_return_error (
+ invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ error->message);
+ g_error_free (error);
+ } else {
+ const gchar *path = g_variant_get_string (variant, NULL);
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(o)", path));
+ g_variant_unref (variant);
}
}
g_object_unref (component);
- bus_ibus_impl_engines_maybe_removed (ibus);
- bus_ibus_impl_update_engines_hotkey_profile (ibus);
+ bus_ibus_impl_check_global_engine (ibus);
}
/**
* _ibus_register_component:
*
- * Implement the "RegisterComponent" method call of the org.freedesktop.IBus interface.
+ * Implement the "RegisterComponent" method call of the
+ * org.freedesktop.IBus interface.
*/
static void
_ibus_register_component (BusIBusImpl *ibus,
GDBusMethodInvocation *invocation)
{
GVariant *variant = g_variant_get_child_value (parameters, 0);
- IBusComponent *component = (IBusComponent *) ibus_serializable_deserialize (variant);
+ IBusComponent *component =
+ (IBusComponent *) ibus_serializable_deserialize (variant);
if (!IBUS_IS_COMPONENT (component)) {
if (component)
g_object_unref (component);
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
- "The first argument should be an IBusComponent.");
+ g_dbus_method_invocation_return_error (
+ invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "The first argument should be an IBusComponent.");
return;
}
- BusConnection *connection = bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
+ BusConnection *connection = bus_connection_lookup (
+ g_dbus_method_invocation_get_connection (invocation));
BusFactoryProxy *factory = bus_factory_proxy_new (connection);
if (factory == NULL) {
g_object_unref (component);
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
- "Create factory failed.");
+ g_dbus_method_invocation_return_error (
+ invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "Create factory failed.");
return;
}
ibus->register_engine_list = g_list_concat (ibus->register_engine_list,
engines);
- g_signal_connect (buscomp, "destroy", G_CALLBACK (_component_destroy_cb), ibus);
-
- bus_ibus_impl_update_engines_hotkey_profile (ibus);
+ g_signal_connect (buscomp,
+ "destroy",
+ G_CALLBACK (_component_destroy_cb),
+ ibus);
g_dbus_method_invocation_return_value (invocation, NULL);
}
/**
- * _ibus_list_engines:
+ * _ibus_get_engines:
*
- * Implement the "ListEngines" method call of the org.freedesktop.IBus interface.
+ * Implement the "Engines" method call of the org.freedesktop.IBus interface.
*/
-static void
-_ibus_list_engines (BusIBusImpl *ibus,
- GVariant *parameters,
- GDBusMethodInvocation *invocation)
+static GVariant *
+_ibus_get_engines (BusIBusImpl *ibus,
+ GDBusConnection *connection,
+ GError **error)
{
GVariantBuilder builder;
+ GList *engines = NULL;
+ GList *p;
+
+ if (error) {
+ *error = NULL;
+ }
+
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
- GList *engines = bus_registry_get_engines (ibus->registry);
- GList *p;
+ engines = g_hash_table_get_values (ibus->engine_table);
+
for (p = engines; p != NULL; p = p->next) {
- g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
+ g_variant_builder_add (
+ &builder, "v",
+ ibus_serializable_serialize ((IBusSerializable *) p->data));
}
+
g_list_free (engines);
- g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
+
+ return g_variant_builder_end (&builder);
+}
+
+static void
+_ibus_list_engines_depre (BusIBusImpl *ibus,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
+{
+ GDBusConnection *connection =
+ g_dbus_method_invocation_get_connection (invocation);
+ GError *error = NULL;
+ GVariant *variant = NULL;
+
+ g_warning ("org.freedesktop.IBus.ListEngines() is deprecated!");
+
+ variant = _ibus_get_engines (ibus, connection, &error);
+
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(@av)", variant));
}
/**
- * _ibus_list_active_engines:
+ * _ibus_get_engines_by_names:
*
- * Implement the "ListActiveEngines" method call of the org.freedesktop.IBus interface.
+ * Implement the "GetEnginesByNames" method call of the org.freedesktop.IBus interface.
*/
static void
-_ibus_list_active_engines (BusIBusImpl *ibus,
- GVariant *parameters,
- GDBusMethodInvocation *invocation)
+_ibus_get_engines_by_names (BusIBusImpl *ibus,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
{
+ const gchar **names = NULL;
+ g_variant_get (parameters, "(^a&s)", &names);
+
+ g_assert (names != NULL);
+
+ gint i = 0;
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
+ while (names[i] != NULL) {
+ IBusEngineDesc *desc = (IBusEngineDesc *) g_hash_table_lookup (
+ ibus->engine_table, names[i++]);
+ if (desc == NULL)
+ continue;
+ g_variant_builder_add (
+ &builder,
+ "v",
+ ibus_serializable_serialize ((IBusSerializable *)desc));
+ }
+ g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
+}
+/**
+ * _ibus_get_active_engines:
+ *
+ * Implement the "ActiveEngines" method call of the
+ * org.freedesktop.IBus interface.
+ */
+static GVariant *
+_ibus_get_active_engines (BusIBusImpl *ibus,
+ GDBusConnection *connection,
+ GError **error)
+{
+ GVariantBuilder builder;
GList *p;
- for (p = ibus->engine_list; p != NULL; p = p->next) {
- g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
+
+ if (error) {
+ *error = NULL;
}
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
+
for (p = ibus->register_engine_list; p != NULL; p = p->next) {
- g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
+ g_variant_builder_add (
+ &builder, "v",
+ ibus_serializable_serialize ((IBusSerializable *) p->data));
}
- g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
+
+ return g_variant_builder_end (&builder);
+}
+
+static void
+_ibus_list_active_engines_depre (BusIBusImpl *ibus,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
+{
+ GDBusConnection *connection =
+ g_dbus_method_invocation_get_connection (invocation);
+ GError *error = NULL;
+ GVariant *variant = NULL;
+
+ g_warning ("org.freedesktop.IBus.ListActiveEngines() is deprecated!");
+
+ variant = _ibus_get_active_engines (ibus, connection, &error);
+
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(@av)", variant));
}
/**
g_dbus_method_invocation_return_value (invocation, NULL);
/* Make sure the reply has been sent out before exit */
- g_dbus_connection_flush_sync (g_dbus_method_invocation_get_connection (invocation),
- NULL,
- NULL);
- bus_server_quit ();
-
- if (!restart) {
- exit (0);
- }
- else {
- extern gchar **g_argv;
- gchar *exe;
- gint fd;
-
- exe = g_strdup_printf ("/proc/%d/exe", getpid ());
- exe = g_file_read_link (exe, NULL);
-
- if (exe == NULL)
- exe = BINDIR "/ibus-daemon";
-
- /* close all fds except stdin, stdout, stderr */
- for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd ++) {
- close (fd);
- }
-
- execv (exe, g_argv);
-
- /* If the server binary is replaced while the server is running,
- * "readlink /proc/[pid]/exe" might return a path with " (deleted)"
- * suffix. */
- const gchar suffix[] = " (deleted)";
- if (g_str_has_suffix (exe, suffix)) {
- exe [strlen (exe) - sizeof (suffix) + 1] = '\0';
- execv (exe, g_argv);
- }
- g_warning ("execv %s failed!", g_argv[0]);
- exit (-1);
- }
+ g_dbus_connection_flush_sync (
+ g_dbus_method_invocation_get_connection (invocation),
+ NULL,
+ NULL);
- /* should not reach here */
- g_assert_not_reached ();
+ bus_server_quit (restart);
}
/**
/**
* _ibus_get_use_sys_layout:
*
- * Implement the "GetUseSysLayout" method call of the org.freedesktop.IBus interface.
+ * Implement the "UseSysLayout" method call of the
+ * org.freedesktop.IBus interface.
*/
+static GVariant *
+_ibus_get_use_sys_layout (BusIBusImpl *ibus,
+ GDBusConnection *connection,
+ GError **error)
+{
+ if (error) {
+ *error = NULL;
+ }
+
+ return g_variant_new_boolean (ibus->use_sys_layout);
+}
+
static void
-_ibus_get_use_sys_layout (BusIBusImpl *ibus,
- GVariant *parameters,
- GDBusMethodInvocation *invocation)
+_ibus_get_use_sys_layout_depre (BusIBusImpl *ibus,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
{
+ GDBusConnection *connection =
+ g_dbus_method_invocation_get_connection (invocation);
+ GError *error = NULL;
+ GVariant *variant = NULL;
+
+ g_warning ("org.freedesktop.IBus.GetUseSysLayout() is deprecated!");
+
+ variant = _ibus_get_use_sys_layout (ibus, connection, &error);
+
g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(b)", ibus->use_sys_layout));
+ g_variant_new ("(b)", g_variant_get_boolean (variant)));
+
+ g_variant_unref (variant);
}
/**
* _ibus_get_use_global_engine:
*
- * Implement the "GetUseGlobalEngine" method call of the org.freedesktop.IBus interface.
+ * Implement the "UseGlobalEngine" method call of the
+ * org.freedesktop.IBus interface.
*/
+static GVariant *
+_ibus_get_use_global_engine (BusIBusImpl *ibus,
+ GDBusConnection *connection,
+ GError **error)
+{
+ if (error) {
+ *error = NULL;
+ }
+
+ return g_variant_new_boolean (ibus->use_global_engine);
+}
+
static void
-_ibus_get_use_global_engine (BusIBusImpl *ibus,
- GVariant *parameters,
- GDBusMethodInvocation *invocation)
+_ibus_get_use_global_engine_depre (BusIBusImpl *ibus,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
{
+ GDBusConnection *connection =
+ g_dbus_method_invocation_get_connection (invocation);
+ GError *error = NULL;
+ GVariant *variant = NULL;
+
+ g_warning ("org.freedesktop.IBus.GetUseGlobalEngine() is deprecated!");
+
+ variant = _ibus_get_use_global_engine (ibus, connection, &error);
+
g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(b)", ibus->use_global_engine));
+ g_variant_new ("(b)", g_variant_get_boolean (variant)));
+
+ g_variant_unref (variant);
}
/**
* _ibus_get_global_engine:
*
- * Implement the "GetGlobalEngine" method call of the org.freedesktop.IBus interface.
+ * Implement the "GlobalEngine" method call of the
+ * org.freedesktop.IBus interface.
*/
-static void
-_ibus_get_global_engine (BusIBusImpl *ibus,
- GVariant *parameters,
- GDBusMethodInvocation *invocation)
+static GVariant *
+_ibus_get_global_engine (BusIBusImpl *ibus,
+ GDBusConnection *connection,
+ GError **error)
{
IBusEngineDesc *desc = NULL;
+ if (error) {
+ *error = NULL;
+ }
+
do {
if (!ibus->use_global_engine)
break;
if (desc == NULL)
break;
- GVariant *variant = ibus_serializable_serialize ((IBusSerializable *) desc);
- g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(v)", variant));
- return;
+ GVariant *variant = ibus_serializable_serialize (
+ (IBusSerializable *) desc);
+ // Set type "v" for introspection_xml.
+ return g_variant_new_variant (variant);
} while (0);
- g_dbus_method_invocation_return_error (invocation,
- G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
- "No global engine.");
+ g_set_error (error,
+ G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ "No global engine.");
+ return NULL;
}
-struct _SetGlobalEngineData {
- BusIBusImpl *ibus;
- GDBusMethodInvocation *invocation;
-};
-typedef struct _SetGlobalEngineData SetGlobalEngineData;
+static void
+_ibus_get_global_engine_depre (BusIBusImpl *ibus,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
+{
+ GDBusConnection *connection =
+ g_dbus_method_invocation_get_connection (invocation);
+ GError *error = NULL;
+ GVariant *variant = NULL;
+
+ g_warning ("org.freedesktop.IBus.GetGlobalEngine() is deprecated!");
+
+ variant = _ibus_get_global_engine (ibus, connection, &error);
+
+ if (variant == NULL) {
+ g_dbus_method_invocation_return_error (
+ invocation,
+ G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+ error->message);
+ g_error_free (error);
+ } else {
+ GVariant *retval = g_variant_get_variant (variant);
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(v)", retval));
+ g_variant_unref (variant);
+ }
+}
+
+struct _SetGlobalEngineData {
+ BusIBusImpl *ibus;
+ GDBusMethodInvocation *invocation;
+};
+typedef struct _SetGlobalEngineData SetGlobalEngineData;
static void
_ibus_set_global_engine_ready_cb (BusInputContext *context,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Set global engine failed.");
-
}
else {
g_dbus_method_invocation_return_value (data->invocation, NULL);
/**
* _ibus_set_global_engine:
*
- * Implement the "SetGlobalEngine" method call of the org.freedesktop.IBus interface.
+ * Implement the "SetGlobalEngine" method call of the
+ * org.freedesktop.IBus interface.
*/
static void
_ibus_set_global_engine (BusIBusImpl *ibus,
const gchar *engine_name = NULL;
g_variant_get (parameters, "(&s)", &engine_name);
- IBusEngineDesc *desc = _find_engine_desc_by_name (ibus, engine_name);
+ IBusEngineDesc *desc = bus_ibus_impl_get_engine_desc(ibus, engine_name);
if (desc == NULL) {
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
}
/**
- * _ibus_is_global_engine_enabled:
+ * _ibus_get_global_engine_enabled:
*
- * Implement the "IsGlobalEngineEnabled" method call of the org.freedesktop.IBus interface.
+ * Implement the "GlobalEngineEnabled" method call of the
+ * org.freedesktop.IBus interface.
*/
-static void
-_ibus_is_global_engine_enabled (BusIBusImpl *ibus,
- GVariant *parameters,
- GDBusMethodInvocation *invocation)
+static GVariant *
+_ibus_get_global_engine_enabled (BusIBusImpl *ibus,
+ GDBusConnection *connection,
+ GError **error)
{
gboolean enabled = FALSE;
+ if (error) {
+ *error = NULL;
+ }
+
do {
if (!ibus->use_global_engine)
break;
if (context == NULL)
break;
- enabled = bus_input_context_is_enabled (context);
+ enabled = TRUE;
} while (0);
+ return g_variant_new_boolean (enabled);
+}
+
+static void
+_ibus_is_global_engine_enabled_depre (BusIBusImpl *ibus,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation)
+{
+ GDBusConnection *connection =
+ g_dbus_method_invocation_get_connection (invocation);
+ GError *error = NULL;
+ GVariant *variant = NULL;
+
+ g_warning ("org.freedesktop.IBus.IsGlobalEngineEnabled() is deprecated!");
+
+ variant = _ibus_get_global_engine_enabled (ibus, connection, &error);
+
g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(b)", enabled));
+ g_variant_new ("(b)", g_variant_get_boolean (variant)));
+
+ g_variant_unref (variant);
+}
+
+/**
+ * _ibus_set_preload_engines:
+ *
+ * Implement the "PreloadEngines" method call of the
+ * org.freedesktop.IBus interface.
+ */
+static gboolean
+_ibus_set_preload_engines (BusIBusImpl *ibus,
+ GDBusConnection *connection,
+ GVariant *value,
+ GError **error)
+{
+ int i, j;
+ const gchar **names = NULL;
+ IBusEngineDesc *desc = NULL;
+ BusComponent *component = NULL;
+ BusFactoryProxy *factory = NULL;
+ GPtrArray *array = g_ptr_array_new ();
+
+ if (error) {
+ *error = NULL;
+ }
+
+ g_variant_get (value, "^a&s", &names);
+
+ for (i = 0; names[i] != NULL; i++) {
+ gboolean has_component = FALSE;
+
+ desc = bus_ibus_impl_get_engine_desc(ibus, names[i]);
+
+ if (desc == NULL) {
+ g_set_error (error,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_FAILED,
+ "Can not find engine %s.",
+ names[i]);
+ g_ptr_array_free (array, FALSE);
+ return FALSE;
+ }
+
+ component = bus_component_from_engine_desc (desc);
+ factory = bus_component_get_factory (component);
+
+ if (factory != NULL) {
+ continue;
+ }
+
+ for (j = 0; j < array->len; j++) {
+ if (component == (BusComponent *) g_ptr_array_index (array, j)) {
+ has_component = TRUE;
+ break;
+ }
+ }
+
+ if (!has_component) {
+ g_ptr_array_add (array, component);
+ }
+ }
+
+ for (j = 0; j < array->len; j++) {
+ bus_component_start ((BusComponent *) g_ptr_array_index (array, j),
+ g_verbose);
+ }
+
+ g_ptr_array_free (array, FALSE);
+
+ return TRUE;
+}
+
+/**
+ * _ibus_get_embed_preedit_text:
+ *
+ * Implement the "EmbedPreeditText" method call of
+ * the org.freedesktop.IBus interface.
+ */
+static GVariant *
+_ibus_get_embed_preedit_text (BusIBusImpl *ibus,
+ GDBusConnection *connection,
+ GError **error)
+{
+ if (error) {
+ *error = NULL;
+ }
+
+ return g_variant_new_boolean (ibus->embed_preedit_text);
+}
+
+/**
+ * _ibus_set_embed_preedit_text:
+ *
+ * Implement the "EmbedPreeditText" method call of
+ * the org.freedesktop.IBus interface.
+ */
+static gboolean
+_ibus_set_embed_preedit_text (BusIBusImpl *ibus,
+ GDBusConnection *connection,
+ GVariant *value,
+ GError **error)
+{
+ if (error) {
+ *error = NULL;
+ }
+
+ ibus->embed_preedit_text = g_variant_get_boolean (value);
+
+ return TRUE;
}
/**
* bus_ibus_impl_service_method_call:
*
- * Handle a D-Bus method call whose destination and interface name are both "org.freedesktop.IBus"
+ * Handle a D-Bus method call whose destination and interface name are
+ * both "org.freedesktop.IBus"
*/
static void
bus_ibus_impl_service_method_call (IBusService *service,
GVariant *parameters,
GDBusMethodInvocation *invocation)
{
- if (g_strcmp0 (interface_name, "org.freedesktop.IBus") != 0) {
+ if (g_strcmp0 (interface_name, IBUS_INTERFACE_IBUS) != 0) {
IBUS_SERVICE_CLASS (bus_ibus_impl_parent_class)->service_method_call (
- service, connection, sender, object_path, interface_name, method_name,
+ service, connection, sender, object_path,
+ interface_name, method_name,
parameters, invocation);
return;
}
/* all methods in the xml definition above should be listed here. */
static const struct {
const gchar *method_name;
- void (* method_callback) (BusIBusImpl *, GVariant *, GDBusMethodInvocation *);
+ void (* method_callback) (BusIBusImpl *,
+ GVariant *,
+ GDBusMethodInvocation *);
} methods [] = {
/* IBus interface */
- { "GetAddress", _ibus_get_address },
{ "CreateInputContext", _ibus_create_input_context },
- { "CurrentInputContext", _ibus_current_input_context },
{ "RegisterComponent", _ibus_register_component },
- { "ListEngines", _ibus_list_engines },
- { "ListActiveEngines", _ibus_list_active_engines },
+ { "GetEnginesByNames", _ibus_get_engines_by_names },
{ "Exit", _ibus_exit },
{ "Ping", _ibus_ping },
- { "GetUseSysLayout", _ibus_get_use_sys_layout },
- { "GetUseGlobalEngine", _ibus_get_use_global_engine },
- { "GetGlobalEngine", _ibus_get_global_engine },
{ "SetGlobalEngine", _ibus_set_global_engine },
- { "IsGlobalEngineEnabled", _ibus_is_global_engine_enabled },
+ /* Start of deprecated methods */
+ { "GetAddress", _ibus_get_address_depre },
+ { "CurrentInputContext", _ibus_current_input_context_depre },
+ { "ListEngines", _ibus_list_engines_depre },
+ { "ListActiveEngines", _ibus_list_active_engines_depre },
+ { "GetUseSysLayout", _ibus_get_use_sys_layout_depre },
+ { "GetUseGlobalEngine", _ibus_get_use_global_engine_depre },
+ { "GetGlobalEngine", _ibus_get_global_engine_depre },
+ { "IsGlobalEngineEnabled", _ibus_is_global_engine_enabled_depre },
+ /* End of deprecated methods */
};
gint i;
for (i = 0; i < G_N_ELEMENTS (methods); i++) {
if (g_strcmp0 (methods[i].method_name, method_name) == 0) {
- methods[i].method_callback ((BusIBusImpl *) service, parameters, invocation);
+ methods[i].method_callback ((BusIBusImpl *) service,
+ parameters,
+ invocation);
return;
}
}
- /* notreached - unknown method calls that are not in the introspection_xml should be handled by the GDBus library. */
- g_return_if_reached ();
+ g_warning ("service_method_call received an unknown method: %s",
+ method_name ? method_name : "(null)");
+}
+
+/**
+ * bus_ibus_impl_service_get_property:
+ *
+ * Handle org.freedesktop.DBus.Properties.Get
+ */
+static GVariant *
+bus_ibus_impl_service_get_property (IBusService *service,
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GError **error)
+{
+ gint i;
+
+ static const struct {
+ const gchar *method_name;
+ GVariant * (* method_callback) (BusIBusImpl *,
+ GDBusConnection *,
+ GError **);
+ } methods [] = {
+ { "Address", _ibus_get_address },
+ { "CurrentInputContext", _ibus_get_current_input_context },
+ { "Engines", _ibus_get_engines },
+ { "ActiveEngines", _ibus_get_active_engines },
+ { "GlobalEngine", _ibus_get_global_engine },
+ { "EmbedPreeditText", _ibus_get_embed_preedit_text },
+ };
+
+ if (g_strcmp0 (interface_name, IBUS_INTERFACE_IBUS) != 0) {
+ return IBUS_SERVICE_CLASS (
+ bus_ibus_impl_parent_class)->service_get_property (
+ service, connection, sender, object_path,
+ interface_name, property_name,
+ error);
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (methods); i++) {
+ if (g_strcmp0 (methods[i].method_name, property_name) == 0) {
+ return methods[i].method_callback ((BusIBusImpl *) service,
+ connection,
+ error);
+ }
+ }
+
+ g_warning ("service_get_property received an unknown property: %s",
+ property_name ? property_name : "(null)");
+ return NULL;
+}
+
+static void
+_emit_properties_changed (BusIBusImpl *service,
+ GDBusConnection *connection,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GVariant *value,
+ gboolean is_changed)
+{
+ GVariantBuilder *builder;
+ GVariantBuilder *invalidated_builder;
+ GError *error = NULL;
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
+ invalidated_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+
+ if (is_changed) {
+ g_variant_builder_add (builder, "{sv}", property_name, value);
+ } else {
+ g_variant_builder_add (invalidated_builder, "s", property_name);
+ }
+
+ g_dbus_connection_emit_signal (connection,
+ NULL,
+ object_path,
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ g_variant_new ("(sa{sv}as)",
+ interface_name,
+ builder,
+ invalidated_builder),
+ &error);
+
+ if (error) {
+ g_warning ("Failed to emit property %s in %s.%s: %s",
+ property_name,
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ error->message);
+ g_error_free (error);
+ }
+}
+
+/**
+ * bus_ibus_impl_service_set_property:
+ *
+ * Handle org.freedesktop.DBus.Properties.Set
+ */
+static gboolean
+bus_ibus_impl_service_set_property (IBusService *service,
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GVariant *value,
+ GError **error)
+{
+ gint i;
+
+ static const struct {
+ const gchar *method_name;
+ gboolean (* method_callback) (BusIBusImpl *,
+ GDBusConnection *,
+ GVariant *,
+ GError **);
+ } methods [] = {
+ { "PreloadEngines", _ibus_set_preload_engines },
+ { "EmbedPreeditText", _ibus_set_embed_preedit_text },
+ };
+
+ if (g_strcmp0 (interface_name, IBUS_INTERFACE_IBUS) != 0) {
+ return IBUS_SERVICE_CLASS (
+ bus_ibus_impl_parent_class)->service_set_property (
+ service, connection, sender, object_path,
+ interface_name, property_name,
+ value, error);
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (methods); i++) {
+ if (g_strcmp0 (methods[i].method_name, property_name) == 0) {
+ gboolean retval = methods[i].method_callback (
+ (BusIBusImpl *) service,
+ connection,
+ value,
+ error);
+
+ _emit_properties_changed ((BusIBusImpl *) service,
+ connection,
+ object_path,
+ interface_name,
+ property_name,
+ value,
+ retval);
+
+ return retval;
+ }
+ }
+
+ g_warning ("service_set_property received an unknown property: %s",
+ property_name ? property_name : "(null)");
+ return FALSE;
}
BusIBusImpl *
return factory;
}
-IBusHotkeyProfile *
-bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus)
-{
- g_assert (BUS_IS_IBUS_IMPL (ibus));
-
- return ibus->hotkey_profile;
-}
-
IBusKeymap *
bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
{
return ibus->keymap;
}
-BusRegistry *
-bus_ibus_impl_get_registry (BusIBusImpl *ibus)
-{
-
- g_assert (BUS_IS_IBUS_IMPL (ibus));
-
- return ibus->registry;
-}
-
/**
- * bus_ibus_impl_emit_signal:
+ * bus_ibus_impl_registry_init:
*
- * Send a D-Bus signal to buses (connections) that are listening to the signal.
+ * Initialize IBusRegistry.
*/
static void
-bus_ibus_impl_emit_signal (BusIBusImpl *ibus,
- const gchar *signal_name,
- GVariant *parameters)
-{
- static guint32 serial = 0;
- GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/IBus",
- "org.freedesktop.IBus",
- signal_name);
- /* set a non-zero serial to make libdbus happy */
- g_dbus_message_set_serial (message, ++serial);
- g_dbus_message_set_sender (message, "org.freedesktop.IBus");
- if (parameters)
- g_dbus_message_set_body (message, parameters);
- bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
- g_object_unref (message);
-}
-
-static void
-bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
-{
- bus_ibus_impl_emit_signal (ibus, "RegistryChanged", NULL);
-}
-
-static void
-bus_ibus_impl_global_engine_changed (BusIBusImpl *ibus)
+bus_ibus_impl_registry_init (BusIBusImpl *ibus)
{
- const gchar *name = ibus->global_engine_name ? ibus->global_engine_name : "";
- bus_ibus_impl_emit_signal (ibus, "GlobalEngineChanged",
- g_variant_new ("(s)", name));
-}
-
-gboolean
-bus_ibus_impl_filter_keyboard_shortcuts (BusIBusImpl *ibus,
- BusInputContext *context,
- guint keyval,
- guint modifiers,
- guint prev_keyval,
- guint prev_modifiers)
-{
- static GQuark trigger = 0;
- static GQuark enable_unconditional = 0;
- static GQuark disable_unconditional = 0;
- static GQuark next = 0;
- static GQuark previous = 0;
-
- GQuark event;
- GList *engine_list;
-
- if (trigger == 0) {
- trigger = g_quark_from_static_string ("trigger");
- enable_unconditional = g_quark_from_static_string ("enable-unconditional");
- disable_unconditional = g_quark_from_static_string ("disable-unconditional");
- next = g_quark_from_static_string ("next-engine-in-menu");
- previous = g_quark_from_static_string ("previous-engine");
- }
-
- /* Try global hotkeys first. */
- event = ibus_hotkey_profile_filter_key_event (ibus->hotkey_profile,
- keyval,
- modifiers,
- prev_keyval,
- prev_modifiers,
- 0);
-
- if (event == trigger) {
- gboolean enabled = bus_input_context_is_enabled (context);
- if (enabled) {
- bus_input_context_disable (context);
- }
- else {
- bus_input_context_enable (context);
- }
- return (enabled != bus_input_context_is_enabled (context));
- }
- if (event == enable_unconditional) {
- gboolean enabled = bus_input_context_is_enabled (context);
- if (!enabled) {
- bus_input_context_enable (context);
- }
- return bus_input_context_is_enabled (context);
- }
- if (event == disable_unconditional) {
- gboolean enabled = bus_input_context_is_enabled (context);
- if (enabled) {
- bus_input_context_disable (context);
- }
- return !bus_input_context_is_enabled (context);
- }
- if (event == next) {
- if (bus_input_context_is_enabled (context)) {
- bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
- }
- else {
- bus_input_context_enable (context);
- }
- return TRUE;
- }
- if (event == previous) {
- if (bus_input_context_is_enabled (context)) {
- bus_ibus_impl_context_request_previous_engine (ibus, context);
- }
- else {
- bus_input_context_enable (context);
+ GList *p;
+ GList *components;
+ IBusRegistry *registry = ibus_registry_new ();
+
+ ibus->registry = NULL;
+ ibus->components = NULL;
+ ibus->engine_table = g_hash_table_new (g_str_hash, g_str_equal);
+
+ if (g_strcmp0 (g_cache, "none") == 0) {
+ /* Only load registry, but not read and write cache. */
+ ibus_registry_load (registry);
+ }
+ else if (g_strcmp0 (g_cache, "refresh") == 0) {
+ /* Load registry and overwrite the cache. */
+ ibus_registry_load (registry);
+ ibus_registry_save_cache (registry, TRUE);
+ }
+ else if (g_strcmp0 (g_cache, "auto") == 0) {
+ /* Load registry from cache. If the cache does not exist or
+ * it is outdated, then generate it.
+ */
+ if (ibus_registry_load_cache (registry, FALSE) == FALSE ||
+ ibus_registry_check_modification (registry)) {
+
+ ibus_object_destroy (IBUS_OBJECT (registry));
+ registry = ibus_registry_new ();
+
+ if (ibus_registry_load_cache (registry, TRUE) == FALSE ||
+ ibus_registry_check_modification (registry)) {
+
+ ibus_object_destroy (IBUS_OBJECT (registry));
+ registry = ibus_registry_new ();
+ ibus_registry_load (registry);
+ ibus_registry_save_cache (registry, TRUE);
+ }
}
- return TRUE;
- }
-
- if (!ibus->engines_hotkey_profile || !ibus->hotkey_to_engines_map) {
- return FALSE;
- }
-
- /* Then try engines hotkeys. */
- event = ibus_hotkey_profile_filter_key_event (ibus->engines_hotkey_profile,
- keyval,
- modifiers,
- prev_keyval,
- prev_modifiers,
- 0);
- if (event == 0) {
- return FALSE;
}
- engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
- GUINT_TO_POINTER (event));
- if (engine_list) {
- BusEngineProxy *current_engine = bus_input_context_get_engine (context);
- IBusEngineDesc *current_engine_desc =
- (current_engine ? bus_engine_proxy_get_desc (current_engine) : NULL);
- IBusEngineDesc *new_engine_desc = (IBusEngineDesc *) engine_list->data;
-
- g_assert (new_engine_desc);
-
- /* Find out what engine we should switch to. If the current engine has
- * the same hotkey, then we should switch to the next engine with the
- * same hotkey in the list. Otherwise, we just switch to the first
- * engine in the list. */
- GList *p = engine_list;
- for (; p->next != NULL; p = p->next) {
- if (current_engine_desc == (IBusEngineDesc *) p->data) {
- new_engine_desc = (IBusEngineDesc *) p->next->data;
- break;
+ ibus->registry = registry;
+ components = ibus_registry_get_components (registry);
+
+ for (p = components; p != NULL; p = p->next) {
+ IBusComponent *component = (IBusComponent *) p->data;
+ BusComponent *buscomp = bus_component_new (component,
+ NULL /* factory */);
+ GList *engines = NULL;
+ GList *p1;
+
+ g_object_ref_sink (buscomp);
+ ibus->components = g_list_append (ibus->components, buscomp);
+
+ engines = bus_component_get_engines (buscomp);
+ for (p1 = engines; p1 != NULL; p1 = p1->next) {
+ IBusEngineDesc *desc = (IBusEngineDesc *) p1->data;
+ const gchar *name = ibus_engine_desc_get_name (desc);
+ if (g_hash_table_lookup (ibus->engine_table, name) == NULL) {
+ g_hash_table_insert (ibus->engine_table,
+ (gpointer) name,
+ desc);
+ } else {
+ g_message ("Engine %s is already registered by other component",
+ name);
}
}
-
- if (current_engine_desc != new_engine_desc) {
- bus_ibus_impl_set_context_engine_from_desc (ibus, context, new_engine_desc);
- }
-
- return TRUE;
+ g_list_free (engines);
}
- return FALSE;
-}
+ g_list_free (components);
-/**
- * bus_ibus_impl_load_global_engine_name_from_config:
- *
- * Retrieve the "global_engine" config from the config daemon. Return NULL if the daemon is not ready.
- */
-static gchar*
-bus_ibus_impl_load_global_engine_name_from_config (BusIBusImpl *ibus)
-{
- g_assert (BUS_IS_IBUS_IMPL (ibus));
- if (ibus->config == NULL) {
- /* the config component is not started yet. */
- return NULL;
- }
- g_assert (IBUS_IS_CONFIG (ibus->config));
-
- GVariant *variant = ibus_config_get_value (ibus->config, "general", "global_engine");
- gchar *engine_name = NULL;
- if (variant != NULL) {
- g_variant_get (variant, "s", &engine_name);
- g_variant_unref (variant);
- }
- return engine_name;
+ g_signal_connect (ibus->registry,
+ "changed",
+ G_CALLBACK (_registry_changed_cb),
+ ibus);
+ ibus_registry_start_monitor_changes (ibus->registry);
}
-/**
- * bus_ibus_impl_save_global_engine_name_to_config:
- *
- * Save the "global_engine" config value on the config daemon. No-op if the daemon is not ready.
- */
static void
-bus_ibus_impl_save_global_engine_name_to_config (BusIBusImpl *ibus)
+bus_ibus_impl_registry_destroy (BusIBusImpl *ibus)
{
- g_assert (BUS_IS_IBUS_IMPL (ibus));
+ g_list_free_full (ibus->components, g_object_unref);
+ ibus->components = NULL;
- if (ibus->config &&
- ibus->use_global_engine &&
- ibus->global_engine_name) {
- ibus_config_set_value (ibus->config,
- "general", "global_engine",
- g_variant_new ("s", ibus->global_engine_name));
- }
-}
-
-/**
- * bus_ibus_impl_load_global_previous_engine_name_from_config:
- *
- * Retrieve the "global_previous_engine" config from the config daemon. Return NULL if the daemon is not ready.
- */
-static gchar*
-bus_ibus_impl_load_global_previous_engine_name_from_config (BusIBusImpl *ibus)
-{
- g_assert (BUS_IS_IBUS_IMPL (ibus));
- if (ibus->config == NULL) {
- /* the config component is not started yet. */
- return NULL;
- }
- g_assert (IBUS_IS_CONFIG (ibus->config));
+ g_hash_table_destroy (ibus->engine_table);
+ ibus->engine_table = NULL;
- GVariant *value = ibus_config_get_value (ibus->config, "general", "global_previous_engine");
- if (value == NULL)
- return NULL;
- gchar *engine_name = NULL;
- g_variant_get (value, "(s)", &engine_name);
- g_variant_unref (value);
- return engine_name;
+ ibus_object_destroy (IBUS_OBJECT (ibus->registry));
+ ibus->registry = NULL;
}
-/**
- * bus_ibus_impl_save_global_previous_engine_name_to_config:
- *
- * Save the "global_previous_engine" config value on the config daemon. No-op if the daemon is not ready.
- */
-static void
-bus_ibus_impl_save_global_previous_engine_name_to_config (BusIBusImpl *ibus)
+static gint
+_component_is_name_cb (BusComponent *component,
+ const gchar *name)
{
- g_assert (BUS_IS_IBUS_IMPL (ibus));
+ g_assert (BUS_IS_COMPONENT (component));
+ g_assert (name);
- if (ibus->config &&
- ibus->use_global_engine &&
- ibus->global_previous_engine_name) {
- ibus_config_set_value (ibus->config,
- "general", "global_previous_engine",
- g_variant_new ("s", ibus->global_previous_engine_name));
- }
+ return g_strcmp0 (bus_component_get_name (component), name);
}
-/**
- * _add_engine_hotkey:
- *
- * Check the engine-specific hot key of the engine, and update ibus->engines_hotkey_profile.
- */
static void
-_add_engine_hotkey (IBusEngineDesc *engine, BusIBusImpl *ibus)
+bus_ibus_impl_component_name_owner_changed (BusIBusImpl *ibus,
+ const gchar *name,
+ const gchar *old_name,
+ const gchar *new_name)
{
- const gchar *hotkeys;
- gchar **hotkey_list;
- gchar **p;
- gchar *hotkey;
- GList *engine_list;
-
- GQuark event;
- guint keyval;
- guint modifiers;
+ BusComponent *component;
+ BusFactoryProxy *factory;
- if (!engine) {
- return;
- }
+ g_assert (BUS_IS_IBUS_IMPL (ibus));
+ g_assert (name);
+ g_assert (old_name);
+ g_assert (new_name);
- hotkeys = ibus_engine_desc_get_hotkeys (engine);
+ component = bus_ibus_impl_lookup_component_by_name (ibus, name);
- if (!hotkeys || !*hotkeys) {
+ if (component == NULL) {
+ /* name is a unique name, or a well-known name we don't know. */
return;
}
- hotkey_list = g_strsplit_set (hotkeys, ";,", 0);
+ if (g_strcmp0 (old_name, "") != 0) {
+ /* the component is stopped. */
+ factory = bus_component_get_factory (component);
- for (p = hotkey_list; p && *p; ++p) {
- hotkey = g_strstrip (*p);
- if (!*hotkey || !ibus_key_event_from_string (hotkey, &keyval, &modifiers)) {
- continue;
+ if (factory != NULL) {
+ ibus_proxy_destroy ((IBusProxy *) factory);
}
+ }
- /* If the hotkey already exists, we won't need to add it again. */
- event = ibus_hotkey_profile_lookup_hotkey (ibus->engines_hotkey_profile,
- keyval, modifiers);
- if (event == 0) {
- event = g_quark_from_string (hotkey);
- ibus_hotkey_profile_add_hotkey (ibus->engines_hotkey_profile,
- keyval, modifiers, event);
- }
+ if (g_strcmp0 (new_name, "") != 0) {
+ /* the component is started. */
+ BusConnection *connection =
+ bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS,
+ new_name);
+ if (connection == NULL)
+ return;
- engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
- GUINT_TO_POINTER (event));
+ factory = bus_factory_proxy_new (connection);
+ if (factory == NULL)
+ return;
+ bus_component_set_factory (component, factory);
+ g_object_unref (factory);
+ }
+}
- /* As we will rebuild the engines hotkey map whenever an engine was
- * added or removed, we don't need to hold a reference of the engine
- * here. */
- engine_list = g_list_append (engine_list, engine);
+BusComponent *
+bus_ibus_impl_lookup_component_by_name (BusIBusImpl *ibus,
+ const gchar *name)
+{
+ GList *p;
- /* We need to steal the value before adding it back, otherwise it will
- * be destroyed. */
- g_hash_table_steal (ibus->hotkey_to_engines_map, GUINT_TO_POINTER (event));
+ g_assert (BUS_IS_IBUS_IMPL (ibus));
+ g_assert (name);
- g_hash_table_insert (ibus->hotkey_to_engines_map,
- GUINT_TO_POINTER (event), engine_list);
+ p = g_list_find_custom (ibus->components,
+ name,
+ (GCompareFunc) _component_is_name_cb);
+ if (p) {
+ return (BusComponent *) p->data;
+ }
+ else {
+ return NULL;
}
-
- g_strfreev (hotkey_list);
}
/**
- * bus_ibus_impl_update_engines_hotkey_profile:
+ * bus_ibus_impl_emit_signal:
*
- * Check engine-specific hot keys of all active engines, and update ibus->engines_hotkey_profile.
+ * Send a D-Bus signal to buses (connections) that are listening to the signal.
*/
static void
-bus_ibus_impl_update_engines_hotkey_profile (BusIBusImpl *ibus)
+bus_ibus_impl_emit_signal (BusIBusImpl *ibus,
+ const gchar *signal_name,
+ GVariant *parameters)
{
- if (ibus->engines_hotkey_profile) {
- g_object_unref (ibus->engines_hotkey_profile);
- }
-
- if (ibus->hotkey_to_engines_map) {
- g_hash_table_unref (ibus->hotkey_to_engines_map);
- }
+ GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/IBus",
+ "org.freedesktop.IBus",
+ signal_name);
+ /* set a non-zero serial to make libdbus happy */
+ g_dbus_message_set_serial (message, 1);
+ g_dbus_message_set_sender (message, "org.freedesktop.IBus");
+ if (parameters)
+ g_dbus_message_set_body (message, parameters);
+ bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
+ g_object_unref (message);
+}
- ibus->engines_hotkey_profile = ibus_hotkey_profile_new ();
- ibus->hotkey_to_engines_map =
- g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_list_free);
+static void
+bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
+{
+ bus_ibus_impl_emit_signal (ibus, "RegistryChanged", NULL);
+}
- g_list_foreach (ibus->register_engine_list, (GFunc) _add_engine_hotkey, ibus);
- g_list_foreach (ibus->engine_list, (GFunc) _add_engine_hotkey, ibus);
+static void
+bus_ibus_impl_global_engine_changed (BusIBusImpl *ibus)
+{
+ const gchar *name = ibus->global_engine_name ? ibus->global_engine_name : "";
+ bus_ibus_impl_emit_signal (ibus, "GlobalEngineChanged",
+ g_variant_new ("(s)", name));
}
gboolean