diff --git a/autogen.sh b/autogen.sh
index 1861f1b4..c4cea1a4 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -22,4 +22,4 @@ which gnome-autogen.sh || {
touch $srcdir/ChangeLog
}
-ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I m4" REQUIRED_AUTOMAKE_VERSION=1.10 CFLAGS="-Wall -Werror $CFLAGS" . gnome-autogen.sh
+ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I m4" REQUIRED_AUTOMAKE_VERSION=1.10 CFLAGS="-Wall $CFLAGS" . gnome-autogen.sh
diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c
index 059d6602..d1242c85 100644
--- a/bus/ibusimpl.c
+++ b/bus/ibusimpl.c
@@ -48,7 +48,7 @@ struct _BusIBusImpl {
/* 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.) */
@@ -65,10 +65,7 @@ struct _BusIBusImpl {
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. */
IBusKeymap *keymap;
@@ -131,36 +128,6 @@ static gboolean ibus_ibus_impl_service_set_property
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_check_global_engine
- (BusIBusImpl *ibus);
static void bus_ibus_impl_registry_changed (BusIBusImpl *ibus);
static void bus_ibus_impl_global_engine_changed
(BusIBusImpl *ibus);
@@ -168,15 +135,6 @@ 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);
static BusInputContext
@@ -216,6 +174,10 @@ static const gchar introspection_xml[] =
" \n"
" \n"
" \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
" \n"
" \n"
" \n"
@@ -282,398 +244,6 @@ _panel_destroy_cb (BusPanelProxy *panel,
g_object_unref (panel);
}
-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_check_global_engine (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)
@@ -730,47 +300,6 @@ _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
}
}
}
- 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);
}
@@ -808,8 +337,6 @@ bus_ibus_impl_init (BusIBusImpl *ibus)
ibus->contexts = NULL;
ibus->focused_context = NULL;
ibus->panel = NULL;
- ibus->config = NULL;
-
ibus->registry = bus_registry_new ();
g_signal_connect (ibus->registry,
@@ -824,13 +351,12 @@ bus_ibus_impl_init (BusIBusImpl *ibus)
}
#endif
- ibus->hotkey_profile = ibus_hotkey_profile_new ();
ibus->keymap = ibus_keymap_get ("us");
ibus->use_sys_layout = FALSE;
ibus->embed_preedit_text = TRUE;
- ibus->enable_by_default = FALSE;
- ibus->use_global_engine = FALSE;
+ ibus->enable_by_default = TRUE;
+ ibus->use_global_engine = TRUE;
ibus->global_engine_name = NULL;
ibus->global_previous_engine_name = NULL;
@@ -904,11 +430,6 @@ bus_ibus_impl_destroy (BusIBusImpl *ibus)
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;
@@ -972,7 +493,6 @@ _find_engine_desc_by_name (BusIBusImpl *ibus,
if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
return desc;
}
-
return NULL;
}
@@ -999,180 +519,10 @@ static IBusEngineDesc *
bus_ibus_impl_get_engine_desc (BusIBusImpl *ibus,
const gchar *engine_name)
{
- IBusEngineDesc *desc = NULL;
+ g_return_val_if_fail (engine_name != NULL, NULL);
+ g_return_val_if_fail (engine_name[0] != '\0', NULL);
- if (engine_name != NULL && engine_name[0] != '\0') {
- /* request engine by name */
- desc = _find_engine_desc_by_name (ibus, engine_name);
- if (desc == NULL) {
- g_warning ("_context_request_engine_cb: Invalid engine '%s' is requested.", engine_name);
- return 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 NULL;
- }
- }
-
- return desc;
-}
-
-/**
- * bus_ibus_impl_context_request_rotate_engine_in_menu:
- *
- * Process the "next_engine_in_menu" or "previous_engine" hotkey.
- */
-static void
-bus_ibus_impl_context_request_rotate_engine_in_menu (BusIBusImpl *ibus,
- BusInputContext *context,
- gboolean is_next)
-{
- BusEngineProxy *engine;
- IBusEngineDesc *desc;
- IBusEngineDesc *next_desc = NULL;
- GList *p = NULL;
-
- engine = bus_input_context_get_engine (context);
- if (engine == NULL) {
- desc = bus_ibus_impl_get_engine_desc (ibus, NULL);
- if (desc != NULL)
- bus_ibus_impl_set_context_engine_from_desc (ibus,
- context,
- desc);
- return;
- }
-
- desc = bus_engine_proxy_get_desc (engine);
-
- p = g_list_find (ibus->register_engine_list, desc);
- if (p != NULL) {
- if (is_next) {
- p = p->next;
- } else {
- p = p->prev;
- }
- }
-
- /* Rotate register_engine_list and engine_list. */
- if (p == NULL && g_list_find (ibus->register_engine_list, desc) != NULL) {
- if (is_next) {
- p = ibus->engine_list;
- } else {
- p = g_list_last (ibus->engine_list);
- }
- }
-
- if (p == NULL) {
- p = g_list_find (ibus->engine_list, desc);
- if (p != NULL) {
- if (is_next) {
- p = p->next;
- } else {
- p = p->prev;
- }
- }
- }
-
- /* Rerotate register_engine_list and engine_list. */
- if (p == NULL && g_list_find (ibus->engine_list, desc) != NULL) {
- if (is_next) {
- p = ibus->register_engine_list;
- if (p == NULL) {
- p = ibus->engine_list;
- }
- } else {
- p = g_list_last (ibus->register_engine_list);
- if (p == NULL) {
- p = g_list_last (ibus->engine_list);
- }
- }
- }
-
- 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;
- }
- }
-
- bus_ibus_impl_set_context_engine_from_desc (ibus, context, next_desc);
-}
-
-/**
- * bus_ibus_impl_context_request_previous_engine:
- *
- * Process the "previous_engine" hotkey.
- */
-static void
-bus_ibus_impl_context_request_previous_engine (BusIBusImpl *ibus,
- BusInputContext *context)
-{
- 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;
- if (engine_name != NULL) {
- /* If the previous engine is removed from the engine list or the
- current engine and the previous engine are the same one, force
- to pick a new one. */
- if (!_find_engine_desc_by_name (ibus, engine_name) ||
- g_strcmp0 (engine_name, ibus->global_engine_name) == 0) {
- g_free (engine_name);
- ibus->global_previous_engine_name = engine_name = NULL;
- }
- }
- }
-
- if (!engine_name) {
- bus_ibus_impl_context_request_rotate_engine_in_menu (ibus, context,
- FALSE);
- return;
- }
-
- IBusEngineDesc *desc = NULL;
- desc = bus_ibus_impl_get_engine_desc (ibus, engine_name);
- if (desc != NULL) {
- bus_ibus_impl_set_context_engine_from_desc (ibus,
- context,
- desc);
- }
+ return bus_registry_find_engine_by_name (ibus->registry, engine_name);
}
static void
@@ -1214,7 +564,8 @@ bus_ibus_impl_set_focused_context (BusIBusImpl *ibus,
/* dettach engine from the focused context */
engine = bus_input_context_get_engine (ibus->focused_context);
if (engine) {
- is_enabled = bus_input_context_is_enabled (ibus->focused_context);
+ // is_enabled = bus_input_context_is_enabled (ibus->focused_context);
+ is_enabled = TRUE;
g_object_ref (engine);
bus_input_context_set_engine (ibus->focused_context, NULL);
}
@@ -1361,9 +712,6 @@ _context_engine_changed_cb (BusInputContext *context,
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);
}
}
@@ -1443,30 +791,6 @@ _context_destroy_cb (BusInputContext *context,
g_object_unref (context);
}
-/**
- * _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"
@@ -1493,8 +817,6 @@ bus_ibus_impl_create_input_context (BusIBusImpl *ibus,
{ "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;
@@ -1671,6 +993,37 @@ _ibus_list_engines (BusIBusImpl *ibus,
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
}
+/**
+ * _ibus_get_engines_by_names:
+ *
+ * Implement the "GetEnginesByNames" method call of the org.freedesktop.IBus interface.
+ */
+static void
+_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 = bus_registry_find_engine_by_name (
+ ibus->registry, 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_list_active_engines:
*
@@ -1863,7 +1216,7 @@ _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,
@@ -1906,7 +1259,7 @@ _ibus_is_global_engine_enabled (BusIBusImpl *ibus,
if (context == NULL)
break;
- enabled = bus_input_context_is_enabled (context);
+ enabled = TRUE;
} while (0);
g_dbus_method_invocation_return_value (invocation,
@@ -1946,6 +1299,7 @@ bus_ibus_impl_service_method_call (IBusService *service,
{ "CurrentInputContext", _ibus_current_input_context },
{ "RegisterComponent", _ibus_register_component },
{ "ListEngines", _ibus_list_engines },
+ { "GetEnginesByNames", _ibus_get_engines_by_names },
{ "ListActiveEngines", _ibus_list_active_engines },
{ "Exit", _ibus_exit },
{ "Ping", _ibus_ping },
@@ -1994,14 +1348,6 @@ bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
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)
{
@@ -2064,207 +1410,9 @@ bus_ibus_impl_filter_keyboard_shortcuts (BusIBusImpl *ibus,
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 TRUE;
- }
- if (event == enable_unconditional) {
- gboolean enabled = bus_input_context_is_enabled (context);
- if (!enabled) {
- bus_input_context_enable (context);
- }
- return TRUE;
- }
- if (event == disable_unconditional) {
- gboolean enabled = bus_input_context_is_enabled (context);
- if (enabled) {
- bus_input_context_disable (context);
- }
- return TRUE;
- }
- if (event == next) {
- if (bus_input_context_is_enabled (context)) {
- bus_ibus_impl_context_request_rotate_engine_in_menu (ibus, context,
- TRUE);
- }
- 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);
- }
- 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;
- }
- }
-
- if (current_engine_desc != new_engine_desc) {
- bus_ibus_impl_set_context_engine_from_desc (ibus, context, new_engine_desc);
- }
-
- return TRUE;
- }
-
return FALSE;
}
-/**
- * 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) {
- engine_name = g_variant_dup_string (variant, NULL);
- g_variant_unref (variant);
- }
- return engine_name;
-}
-
-/**
- * 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)
-{
- g_assert (BUS_IS_IBUS_IMPL (ibus));
-
- if (ibus->config &&
- ibus->use_global_engine &&
- ibus->global_engine_name) {
- ibus_config_set_value (ibus->config,
- "general", "global_engine",
- g_variant_new_string (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));
-
- GVariant *value = ibus_config_get_value (ibus->config, "general", "global_previous_engine");
- if (value == NULL)
- return NULL;
- gchar *engine_name = g_variant_dup_string (value, NULL);
- g_variant_unref (value);
- return engine_name;
-}
-
-/**
- * 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)
-{
- g_assert (BUS_IS_IBUS_IMPL (ibus));
-
- 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_string (ibus->global_previous_engine_name));
- }
-}
-
/**
* _add_engine_hotkey:
*
diff --git a/bus/ibusimpl.h b/bus/ibusimpl.h
index 42edbf83..0b212bb9 100644
--- a/bus/ibusimpl.h
+++ b/bus/ibusimpl.h
@@ -50,8 +50,6 @@
#define BUS_DEFAULT_IBUS \
(bus_ibus_impl_get_default ())
-#define BUS_DEFAULT_HOTKEY_PROFILE \
- (bus_ibus_impl_get_hotkey_profile (BUS_DEFAULT_IBUS))
#define BUS_DEFAULT_KEYMAP \
(bus_ibus_impl_get_keymap (BUS_DEFAULT_IBUS))
#define BUS_DEFAULT_REGISTRY \
@@ -90,8 +88,6 @@ gboolean bus_ibus_impl_filter_keyboard_shortcuts
/* accessors */
BusFactoryProxy *bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
const gchar *path);
-IBusHotkeyProfile
- *bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus);
IBusKeymap *bus_ibus_impl_get_keymap (BusIBusImpl *ibus);
BusRegistry *bus_ibus_impl_get_registry (BusIBusImpl *ibus);
gboolean bus_ibus_impl_is_use_sys_layout (BusIBusImpl *ibus);
diff --git a/bus/inputcontext.c b/bus/inputcontext.c
index 3c81688f..55b601b4 100644
--- a/bus/inputcontext.c
+++ b/bus/inputcontext.c
@@ -53,7 +53,6 @@ struct _BusInputContext {
gchar *client;
gboolean has_focus;
- gboolean enabled;
/* client capabilities */
guint capabilities;
@@ -96,6 +95,7 @@ struct _BusInputContextClass {
IBusServiceClass parent;
/* class members */
+ IBusEngineDesc *default_engine_desc;
};
enum {
@@ -118,8 +118,6 @@ enum {
CURSOR_DOWN_LOOKUP_TABLE,
REGISTER_PROPERTIES,
UPDATE_PROPERTY,
- ENABLED,
- DISABLED,
ENGINE_CHANGED,
REQUEST_ENGINE,
LAST_SIGNAL,
@@ -163,12 +161,6 @@ static gboolean bus_input_context_service_set_property
GVariant *value,
GError **error);
*/
-static gboolean bus_input_context_filter_keyboard_shortcuts
- (BusInputContext *context,
- guint keyval,
- guint keycode,
- guint modifiers);
-
static void bus_input_context_unset_engine (BusInputContext *context);
static void bus_input_context_commit_text (BusInputContext *context,
IBusText *text);
@@ -247,11 +239,6 @@ static const gchar introspection_xml[] =
" "
" "
" "
- " "
- " "
- " "
- " "
- " "
" "
" "
" "
@@ -275,8 +262,6 @@ static const gchar introspection_xml[] =
" "
" "
" "
- " "
- " "
" "
" "
" "
@@ -337,6 +322,16 @@ bus_input_context_class_init (BusInputContextClass *class)
{
IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class);
+ class->default_engine_desc = ibus_engine_desc_new ("dummy",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "ibus-engine",
+ "");
+ g_object_ref_sink (class->default_engine_desc);
+
ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_input_context_destroy;
/* override the parent class's implementation. */
@@ -543,26 +538,6 @@ bus_input_context_class_init (BusInputContextClass *class)
1,
IBUS_TYPE_PROPERTY);
- context_signals[ENABLED] =
- g_signal_new (I_("enabled"),
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- bus_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-
- context_signals[DISABLED] =
- g_signal_new (I_("disabled"),
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- bus_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-
context_signals[ENGINE_CHANGED] =
g_signal_new (I_("engine-changed"),
G_TYPE_FROM_CLASS (class),
@@ -732,17 +707,8 @@ _ic_process_key_event (BusInputContext *context,
}
}
- if (G_LIKELY (context->has_focus)) {
- gboolean retval = bus_input_context_filter_keyboard_shortcuts (context, keyval, keycode, modifiers);
- /* If it is keyboard shortcut, reply TRUE to client */
- if (G_UNLIKELY (retval)) {
- g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
- return;
- }
- }
-
/* ignore key events, if it is a fake input context */
- if (context->has_focus && context->enabled && context->engine && context->fake == FALSE) {
+ if (context->has_focus && context->engine && context->fake == FALSE) {
bus_engine_proxy_process_key_event (context->engine,
keyval,
keycode,
@@ -770,7 +736,7 @@ _ic_set_cursor_location (BusInputContext *context,
g_variant_get (parameters, "(iiii)",
&context->x, &context->y, &context->w, &context->h);
- if (context->has_focus && context->enabled && context->engine) {
+ if (context->has_focus && context->engine) {
bus_engine_proxy_set_cursor_location (context->engine,
context->x, context->y, context->w, context->h);
}
@@ -792,7 +758,7 @@ _ic_process_hand_writing_event (BusInputContext *context,
GDBusMethodInvocation *invocation)
{
/* do nothing if it is a fake input context */
- if (context->has_focus && context->enabled &&
+ if (context->has_focus &&
context->engine && context->fake == FALSE) {
bus_engine_proxy_process_hand_writing_event (context->engine, parameters);
}
@@ -808,7 +774,7 @@ _ic_cancel_hand_writing (BusInputContext *context,
g_variant_get (parameters, "(u)", &n_strokes);
/* do nothing if it is a fake input context */
- if (context->has_focus && context->enabled &&
+ if (context->has_focus &&
context->engine && context->fake == FALSE) {
bus_engine_proxy_cancel_hand_writing (context->engine, n_strokes);
}
@@ -865,7 +831,7 @@ _ic_reset (BusInputContext *context,
GVariant *parameters,
GDBusMethodInvocation *invocation)
{
- if (context->enabled && context->engine) {
+ if (context->engine) {
bus_engine_proxy_reset (context->engine);
}
g_dbus_method_invocation_return_value (invocation, NULL);
@@ -903,7 +869,7 @@ _ic_property_activate (BusInputContext *context,
guint prop_state = 0;
g_variant_get (parameters, "(&su)", &prop_name, &prop_state);
- if (context->enabled && context->engine) {
+ if (context->engine) {
bus_engine_proxy_property_activate (context->engine, prop_name, prop_state);
}
@@ -921,47 +887,6 @@ _ic_property_activate (BusInputContext *context,
g_dbus_method_invocation_return_value (invocation, NULL);
}
-/**
- * _ic_enable:
- *
- * Implement the "Enable" method call of the org.freedesktop.IBus.InputContext interface.
- */
-static void
-_ic_enable (BusInputContext *context,
- GVariant *parameters,
- GDBusMethodInvocation *invocation)
-{
- bus_input_context_enable (context);
- g_dbus_method_invocation_return_value (invocation, NULL);
-}
-
-/**
- * _ic_disable:
- *
- * Implement the "Disable" method call of the org.freedesktop.IBus.InputContext interface.
- */
-static void
-_ic_disable (BusInputContext *context,
- GVariant *parameters,
- GDBusMethodInvocation *invocation)
-{
- bus_input_context_disable (context);
- g_dbus_method_invocation_return_value (invocation, NULL);
-}
-
-/**
- * _ic_is_enabled:
- *
- * Implement the "IsEnabled" method call of the org.freedesktop.IBus.InputContext interface.
- */
-static void
-_ic_is_enabled (BusInputContext *context,
- GVariant *parameters,
- GDBusMethodInvocation *invocation)
-{
- g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", context->enabled));
-}
-
static void
_ic_set_engine_done (BusInputContext *context,
GAsyncResult *res,
@@ -1033,18 +958,13 @@ _ic_get_engine (BusInputContext *context,
GVariant *parameters,
GDBusMethodInvocation *invocation)
{
- if (context->engine) {
- IBusEngineDesc *desc = bus_engine_proxy_get_desc (context->engine);
- g_dbus_method_invocation_return_value (invocation,
- g_variant_new ("(v)", ibus_serializable_serialize ((IBusSerializable *)desc)));
- }
- else {
- g_dbus_method_invocation_return_error (
- invocation,
- IBUS_ERROR,
- IBUS_ERROR_NO_ENGINE,
- "Input context does not have engine.");
- }
+ IBusEngineDesc *desc = context->engine ?
+ bus_engine_proxy_get_desc (context->engine) :
+ BUS_INPUT_CONTEXT_GET_CLASS (context)->default_engine_desc;
+
+
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(v)", ibus_serializable_serialize ((IBusSerializable *)desc)));
}
/**
@@ -1071,7 +991,7 @@ _ic_set_surrounding_text (BusInputContext *context,
g_variant_unref (variant);
if ((context->capabilities & IBUS_CAP_SURROUNDING_TEXT) &&
- context->has_focus && context->enabled && context->engine) {
+ context->has_focus && context->engine) {
bus_engine_proxy_set_surrounding_text (context->engine,
text,
cursor_pos,
@@ -1121,9 +1041,6 @@ bus_input_context_service_method_call (IBusService *service,
{ "Reset", _ic_reset },
{ "SetCapabilities", _ic_set_capabilities },
{ "PropertyActivate", _ic_property_activate },
- { "Enable", _ic_enable },
- { "Disable", _ic_disable },
- { "IsEnabled", _ic_is_enabled },
{ "SetEngine", _ic_set_engine },
{ "GetEngine", _ic_get_engine },
{ "SetSurroundingText", _ic_set_surrounding_text},
@@ -1163,7 +1080,7 @@ bus_input_context_focus_in (BusInputContext *context)
context->prev_keyval = IBUS_VoidSymbol;
context->prev_modifiers = 0;
- if (context->engine == NULL && context->enabled) {
+ if (context->engine == NULL) {
/* request an engine, e.g. a global engine if the feature is enabled. */
IBusEngineDesc *desc = NULL;
g_signal_emit (context,
@@ -1181,7 +1098,7 @@ bus_input_context_focus_in (BusInputContext *context)
}
}
- if (context->engine && context->enabled) {
+ if (context->engine) {
bus_engine_proxy_focus_in (context->engine);
bus_engine_proxy_enable (context->engine);
bus_engine_proxy_set_capabilities (context->engine, context->capabilities);
@@ -1190,7 +1107,7 @@ bus_input_context_focus_in (BusInputContext *context)
if (context->capabilities & IBUS_CAP_FOCUS) {
g_signal_emit (context, context_signals[FOCUS_IN], 0);
- if (context->engine && context->enabled) {
+ if (context->engine) {
/* if necessary, emit glib signals to the context object to update panel status. see the comment for PREEDIT_CONDITION
* for details. */
if (context->preedit_visible && !PREEDIT_CONDITION) {
@@ -1252,7 +1169,7 @@ bus_input_context_focus_out (BusInputContext *context)
bus_input_context_update_lookup_table (context, lookup_table_empty, FALSE);
bus_input_context_register_properties (context, props_empty);
- if (context->engine && context->enabled) {
+ if (context->engine) {
bus_engine_proxy_focus_out (context->engine);
}
@@ -1269,7 +1186,7 @@ bus_input_context_focus_out (BusInputContext *context)
{ \
g_assert (BUS_IS_INPUT_CONTEXT (context)); \
\
- if (context->has_focus && context->enabled && context->engine) { \
+ if (context->has_focus && context->engine) { \
bus_engine_proxy_##name (context->engine); \
} \
}
@@ -1289,7 +1206,7 @@ bus_input_context_candidate_clicked (BusInputContext *context,
{
g_assert (BUS_IS_INPUT_CONTEXT (context));
- if (context->enabled && context->engine) {
+ if (context->engine) {
bus_engine_proxy_candidate_clicked (context->engine,
index,
button,
@@ -1304,7 +1221,7 @@ bus_input_context_property_activate (BusInputContext *context,
{
g_assert (BUS_IS_INPUT_CONTEXT (context));
- if (context->enabled && context->engine) {
+ if (context->engine) {
bus_engine_proxy_property_activate (context->engine, prop_name, prop_state);
}
}
@@ -1315,9 +1232,6 @@ bus_input_context_commit_text (BusInputContext *context,
{
g_assert (BUS_IS_INPUT_CONTEXT (context));
- if (!context->enabled)
- return;
-
if (text == text_empty || text == NULL)
return;
@@ -1829,9 +1743,6 @@ _engine_forward_key_event_cb (BusEngineProxy *engine,
g_assert (context->engine == engine);
- if (!context->enabled)
- return;
-
bus_input_context_emit_signal (context,
"ForwardKeyEvent",
g_variant_new ("(uuu)", keyval, keycode, state),
@@ -1854,9 +1765,6 @@ _engine_delete_surrounding_text_cb (BusEngineProxy *engine,
g_assert (context->engine == engine);
- if (!context->enabled)
- return;
-
bus_input_context_emit_signal (context,
"DeleteSurroundingText",
g_variant_new ("(iu)", offset_from_cursor, nchars),
@@ -1877,9 +1785,6 @@ _engine_require_surrounding_text_cb (BusEngineProxy *engine,
g_assert (context->engine == engine);
- if (!context->enabled)
- return;
-
bus_input_context_emit_signal (context,
"RequireSurroundingText",
NULL,
@@ -1905,9 +1810,6 @@ _engine_update_preedit_text_cb (BusEngineProxy *engine,
g_assert (context->engine == engine);
- if (!context->enabled)
- return;
-
bus_input_context_update_preedit_text (context, text, cursor_pos, visible, mode);
}
@@ -1928,9 +1830,6 @@ _engine_update_auxiliary_text_cb (BusEngineProxy *engine,
g_assert (context->engine == engine);
- if (!context->enabled)
- return;
-
bus_input_context_update_auxiliary_text (context, text, visible);
}
@@ -1951,9 +1850,6 @@ _engine_update_lookup_table_cb (BusEngineProxy *engine,
g_assert (context->engine == engine);
- if (!context->enabled)
- return;
-
bus_input_context_update_lookup_table (context, table, visible);
}
@@ -1973,9 +1869,6 @@ _engine_register_properties_cb (BusEngineProxy *engine,
g_assert (context->engine == engine);
- if (!context->enabled)
- return;
-
bus_input_context_register_properties (context, props);
}
@@ -1995,9 +1888,6 @@ _engine_update_property_cb (BusEngineProxy *engine,
g_assert (context->engine == engine);
- if (!context->enabled)
- return;
-
bus_input_context_update_property (context, prop);
}
@@ -2011,9 +1901,6 @@ _engine_update_property_cb (BusEngineProxy *engine,
\
g_assert (context->engine == engine); \
\
- if (!context->enabled) \
- return; \
- \
bus_input_context_##name (context); \
}
@@ -2077,7 +1964,6 @@ bus_input_context_enable (BusInputContext *context)
g_assert (BUS_IS_INPUT_CONTEXT (context));
if (!context->has_focus) {
- context->enabled = TRUE;
/* FIXME Do we need to emit "enabled" signal? */
return;
}
@@ -2101,20 +1987,10 @@ bus_input_context_enable (BusInputContext *context)
if (context->engine == NULL)
return;
- context->enabled = TRUE;
-
bus_engine_proxy_focus_in (context->engine);
bus_engine_proxy_enable (context->engine);
bus_engine_proxy_set_capabilities (context->engine, context->capabilities);
bus_engine_proxy_set_cursor_location (context->engine, context->x, context->y, context->w, context->h);
-
- bus_input_context_emit_signal (context,
- "Enabled",
- NULL,
- NULL);
- g_signal_emit (context,
- context_signals[ENABLED],
- 0);
}
void
@@ -2131,24 +2007,6 @@ bus_input_context_disable (BusInputContext *context)
bus_engine_proxy_focus_out (context->engine);
bus_engine_proxy_disable (context->engine);
}
-
- bus_input_context_emit_signal (context,
- "Disabled",
- NULL,
- NULL);
- g_signal_emit (context,
- context_signals[DISABLED],
- 0);
-
- context->enabled = FALSE;
-}
-
-gboolean
-bus_input_context_is_enabled (BusInputContext *context)
-{
- g_assert (BUS_IS_INPUT_CONTEXT (context));
-
- return context->enabled;
}
/* A list of signals (and their handler functions) that could be emit by the engine proxy object. */
@@ -2228,7 +2086,7 @@ bus_input_context_set_engine (BusInputContext *context,
engine_signals[i].callback,
context);
}
- if (context->has_focus && context->enabled) {
+ if (context->has_focus) {
bus_engine_proxy_focus_in (context->engine);
bus_engine_proxy_enable (context->engine);
bus_engine_proxy_set_capabilities (context->engine, context->capabilities);
@@ -2461,44 +2319,6 @@ bus_input_context_get_engine_desc (BusInputContext *context)
return NULL;
}
-static gboolean
-bus_input_context_filter_keyboard_shortcuts (BusInputContext *context,
- guint keyval,
- guint keycode,
- guint modifiers)
-{
- g_assert (BUS_IS_INPUT_CONTEXT (context));
-
- gboolean retval = FALSE;
-
- if (context->filter_release){
- if (modifiers & IBUS_RELEASE_MASK) {
- /* filter release key event */
- return TRUE;
- }
- else {
- /* stop filter release key event */
- context->filter_release = FALSE;
- }
- }
-
- retval = bus_ibus_impl_filter_keyboard_shortcuts (BUS_DEFAULT_IBUS,
- context,
- keyval,
- modifiers,
- context->prev_keyval,
- context->prev_modifiers);
- context->prev_keyval = keyval;
- context->prev_modifiers = modifiers;
-
- if (retval == TRUE) {
- /* begin filter release key event */
- context->filter_release = TRUE;
- }
-
- return retval;
-}
-
guint
bus_input_context_get_capabilities (BusInputContext *context)
{
diff --git a/bus/inputcontext.h b/bus/inputcontext.h
index bc4e096e..b76d02de 100644
--- a/bus/inputcontext.h
+++ b/bus/inputcontext.h
@@ -91,12 +91,6 @@ void bus_input_context_enable (BusInputContext *con
*/
void bus_input_context_disable (BusInputContext *context);
-/**
- * bus_input_context_is_enabled:
- * @returns: context->enabled.
- */
-gboolean bus_input_context_is_enabled (BusInputContext *context);
-
/**
* bus_input_context_page_up:
*
diff --git a/bus/panelproxy.c b/bus/panelproxy.c
index 30059098..7bf13ab2 100644
--- a/bus/panelproxy.c
+++ b/bus/panelproxy.c
@@ -625,8 +625,6 @@ static const struct {
{ "register-properties", G_CALLBACK (_context_register_properties_cb) },
{ "update-property", G_CALLBACK (_context_update_property_cb) },
- { "enabled", G_CALLBACK (_context_state_changed_cb) },
- { "disabled", G_CALLBACK (_context_state_changed_cb) },
{ "engine-changed", G_CALLBACK (_context_state_changed_cb) },
{ "destroy", G_CALLBACK (_context_destroy_cb) },
diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c
index 72db581d..1fcd2b2c 100644
--- a/client/gtk2/ibusimcontext.c
+++ b/client/gtk2/ibusimcontext.c
@@ -47,8 +47,6 @@ struct _IBusIMContext {
GtkIMContext *slave;
GdkWindow *client_window;
- /* enabled */
- gboolean enable;
IBusInputContext *ibuscontext;
/* preedit status */
@@ -271,7 +269,7 @@ _process_key_event_done (GObject *object,
static void
_request_surrounding_text (IBusIMContext *context)
{
- if (context && context->enable &&
+ if (context &&
(context->caps & IBUS_CAP_SURROUNDING_TEXT) != 0 &&
context->ibuscontext != NULL &&
ibus_input_context_needs_surrounding_text (context->ibuscontext)) {
@@ -566,9 +564,6 @@ ibus_im_context_init (GObject *obj)
ibusimcontext->client_window = NULL;
- // Init ibus status
- ibusimcontext->enable = FALSE;
-
// Init preedit status
ibusimcontext->preedit_string = NULL;
ibusimcontext->preedit_attrs = NULL;
@@ -840,36 +835,31 @@ ibus_im_context_get_preedit_string (GtkIMContext *context,
IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context);
- if (ibusimcontext->enable) {
- if (ibusimcontext->preedit_visible) {
- if (str) {
- *str = g_strdup (ibusimcontext->preedit_string ? ibusimcontext->preedit_string: "");
- }
-
- if (attrs) {
- *attrs = ibusimcontext->preedit_attrs ?
- pango_attr_list_ref (ibusimcontext->preedit_attrs):
- pango_attr_list_new ();
- }
-
- if (cursor_pos) {
- *cursor_pos = ibusimcontext->preedit_cursor_pos;
- }
+ if (ibusimcontext->preedit_visible) {
+ if (str) {
+ *str = g_strdup (ibusimcontext->preedit_string ? ibusimcontext->preedit_string: "");
}
- else {
- if (str) {
- *str = g_strdup ("");
- }
- if (attrs) {
- *attrs = pango_attr_list_new ();
- }
- if (cursor_pos) {
- *cursor_pos = 0;
- }
+
+ if (attrs) {
+ *attrs = ibusimcontext->preedit_attrs ?
+ pango_attr_list_ref (ibusimcontext->preedit_attrs):
+ pango_attr_list_new ();
+ }
+
+ if (cursor_pos) {
+ *cursor_pos = ibusimcontext->preedit_cursor_pos;
}
}
else {
- gtk_im_context_get_preedit_string (ibusimcontext->slave, str, attrs, cursor_pos);
+ if (str) {
+ *str = g_strdup ("");
+ }
+ if (attrs) {
+ *attrs = pango_attr_list_new ();
+ }
+ if (cursor_pos) {
+ *cursor_pos = 0;
+ }
}
IDEBUG ("str=%s", *str);
}
@@ -1040,7 +1030,7 @@ ibus_im_context_set_surrounding (GtkIMContext *context,
IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context);
- if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
+ if (ibusimcontext->ibuscontext) {
IBusText *ibustext;
guint cursor_pos;
guint utf8_len;
@@ -1399,36 +1389,6 @@ _ibus_context_hide_preedit_text_cb (IBusInputContext *ibuscontext,
g_signal_emit (ibusimcontext, _signal_preedit_end_id, 0);
}
-static void
-_ibus_context_enabled_cb (IBusInputContext *ibuscontext,
- IBusIMContext *ibusimcontext)
-{
- IDEBUG ("%s", __FUNCTION__);
-
- ibusimcontext->enable = TRUE;
-
- /* retrieve the initial surrounding-text (regardless of whether
- * the current IBus engine needs surrounding-text) */
- _request_surrounding_text (ibusimcontext);
-}
-
-static void
-_ibus_context_disabled_cb (IBusInputContext *ibuscontext,
- IBusIMContext *ibusimcontext)
-{
- IDEBUG ("%s", __FUNCTION__);
- ibusimcontext->enable = FALSE;
-
- /* clear preedit */
- ibusimcontext->preedit_visible = FALSE;
- ibusimcontext->preedit_cursor_pos = 0;
- g_free (ibusimcontext->preedit_string);
- ibusimcontext->preedit_string = NULL;
-
- g_signal_emit (ibusimcontext, _signal_preedit_changed_id, 0);
- g_signal_emit (ibusimcontext, _signal_preedit_end_id, 0);
-}
-
static void
_ibus_context_destroy_cb (IBusInputContext *ibuscontext,
IBusIMContext *ibusimcontext)
@@ -1439,8 +1399,6 @@ _ibus_context_destroy_cb (IBusInputContext *ibuscontext,
g_object_unref (ibusimcontext->ibuscontext);
ibusimcontext->ibuscontext = NULL;
- ibusimcontext->enable = FALSE;
-
/* clear preedit */
ibusimcontext->preedit_visible = FALSE;
ibusimcontext->preedit_cursor_pos = 0;
@@ -1497,14 +1455,6 @@ _create_input_context_done (IBusBus *bus,
"hide-preedit-text",
G_CALLBACK (_ibus_context_hide_preedit_text_cb),
ibusimcontext);
- g_signal_connect (ibusimcontext->ibuscontext,
- "enabled",
- G_CALLBACK (_ibus_context_enabled_cb),
- ibusimcontext);
- g_signal_connect (ibusimcontext->ibuscontext,
- "disabled",
- G_CALLBACK (_ibus_context_disabled_cb),
- ibusimcontext);
g_signal_connect (ibusimcontext->ibuscontext, "destroy",
G_CALLBACK (_ibus_context_destroy_cb),
ibusimcontext);
@@ -1549,10 +1499,6 @@ _slave_commit_cb (GtkIMContext *slave,
gchar *string,
IBusIMContext *ibusimcontext)
{
-#if 0
- if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (_client))
- return;
-#endif
g_signal_emit (ibusimcontext, _signal_commit_id, 0, string);
}
@@ -1560,7 +1506,7 @@ static void
_slave_preedit_changed_cb (GtkIMContext *slave,
IBusIMContext *ibusimcontext)
{
- if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
+ if (ibusimcontext->ibuscontext) {
return;
}
@@ -1571,7 +1517,7 @@ static void
_slave_preedit_start_cb (GtkIMContext *slave,
IBusIMContext *ibusimcontext)
{
- if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
+ if (ibusimcontext->ibuscontext) {
return;
}
@@ -1582,7 +1528,7 @@ static void
_slave_preedit_end_cb (GtkIMContext *slave,
IBusIMContext *ibusimcontext)
{
- if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
+ if (ibusimcontext->ibuscontext) {
return;
}
g_signal_emit (ibusimcontext, _signal_preedit_end_id, 0);
@@ -1594,7 +1540,7 @@ _slave_retrieve_surrounding_cb (GtkIMContext *slave,
{
gboolean return_value;
- if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
+ if (ibusimcontext->ibuscontext) {
return FALSE;
}
g_signal_emit (ibusimcontext, _signal_retrieve_surrounding_id, 0,
@@ -1610,7 +1556,7 @@ _slave_delete_surrounding_cb (GtkIMContext *slave,
{
gboolean return_value;
- if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
+ if (ibusimcontext->ibuscontext) {
return FALSE;
}
g_signal_emit (ibusimcontext, _signal_delete_surrounding_id, 0, offset_from_cursor, nchars, &return_value);
diff --git a/configure.ac b/configure.ac
index 94563978..53fac5ec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -105,6 +105,7 @@ AC_SUBST(DATE_DISPLAY)
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CC_STDC
+AM_PROG_VALAC([0.14])
AC_PROG_INSTALL
AC_PROG_MAKE_SET
@@ -473,6 +474,7 @@ ui/Makefile
ui/gtk/Makefile
ui/gtk/ibus-ui-gtk
ui/gtk/gtkpanel.xml.in
+ui/gtk3/Makefile
setup/Makefile
setup/ibus-setup
gconf/Makefile
diff --git a/ibus/bus.py b/ibus/bus.py
index a8a458d9..179fd4ea 100644
--- a/ibus/bus.py
+++ b/ibus/bus.py
@@ -137,6 +137,10 @@ class Bus(object.Object):
def list_engines(self):
engines = self.__ibus.ListEngines()
return map(serializable.deserialize_object, engines)
+
+ def get_engines_by_names(self, names):
+ engines = self.__ibus.GetEnginesByNames(names)
+ return map(serializable.deserialize_object, engines)
def list_active_engines(self):
engines = self.__ibus.ListActiveEngines()
diff --git a/ibus/inputcontext.py b/ibus/inputcontext.py
index 64a6ba23..a2989091 100644
--- a/ibus/inputcontext.py
+++ b/ibus/inputcontext.py
@@ -153,10 +153,6 @@ class InputContext(object.Object):
self.__signal_matches.append(m)
m = self.__context.connect_to_signal("RequireSurroundingText", self.__require_surrounding_text_cb)
self.__signal_matches.append(m)
- m = self.__context.connect_to_signal("Enabled", self.__enabled_cb)
- self.__signal_matches.append(m)
- m = self.__context.connect_to_signal("Disabled", self.__disabled_cb)
- self.__signal_matches.append(m)
m = self.__context.connect_to_signal("ForwardKeyEvent", lambda *args: self.emit("forward-key-event", *args))
self.__signal_matches.append(m)
@@ -185,14 +181,6 @@ class InputContext(object.Object):
m = self.__context.connect_to_signal("CursorDownLookupTable", lambda *args: self.emit("cursor-down-lookup-table"))
self.__signal_matches.append(m)
- def __enabled_cb(self, *args):
- self.__needs_surrounding_text = False
- self.emit("enabled")
-
- def __disabled_cb(self, *args):
- self.__needs_surrounding_text = False
- self.emit("disabled")
-
def __commit_text_cb(self, *args):
text = serializable.deserialize_object(args[0])
self.emit("commit-text", text)
@@ -253,15 +241,6 @@ class InputContext(object.Object):
def reset(self):
return self.__context.Reset()
- def enable(self):
- return self.__context.Enable()
-
- def disable(self):
- return self.__context.Disable()
-
- def is_enabled(self):
- return self.__context.IsEnabled()
-
def set_capabilities(self, caps):
caps = dbus.UInt32(caps)
return self.__context.SetCapabilities(caps)
@@ -319,8 +298,6 @@ def test():
self.__context.connect("show-preedit-text", self.__show_preedit_text_cb)
self.__context.connect("update-auxiliary-text", self.__update_auxiliary_text_cb)
self.__context.connect("update-lookup-table", self.__update_lookup_table_cb)
- self.__context.connect("enabled", self.__enabled_cb)
- self.__context.connect("disabled", self.__disabled_cb)
self.set_events(gtk.gdk.KEY_PRESS_MASK | gtk.gdk.KEY_RELEASE_MASK | gtk.gdk.FOCUS_CHANGE_MASK)
@@ -350,14 +327,6 @@ def test():
def __update_lookup_table_cb(self, context, table, visible):
print "update-lookup-table:", visible
- def __enabled_cb(self, context):
- print "enabled"
- info = context.get_factory_info()
- print "factory = %s" % info.name
-
- def __disabled_cb(self, context):
- print "disabled"
-
def __key_press_event_cb(self, widget, event):
self.__context.process_key_event(event.keyval, event.state)
diff --git a/ibus/interface/iibus.py b/ibus/interface/iibus.py
index 678d5179..99874c41 100644
--- a/ibus/interface/iibus.py
+++ b/ibus/interface/iibus.py
@@ -62,6 +62,9 @@ class IIBus(dbus.service.Object):
@method(out_signature="av")
def ListEngines(self, dbusconn): pass
+
+ @method(in_signature="as", out_signature="av")
+ def GetEnginesByNames(self, names, dbusconn): pass
@method(out_signature="av")
def ListActiveEngines(self, dbusconn): pass
diff --git a/ibus/interface/iinputcontext.py b/ibus/interface/iinputcontext.py
index 06ce519b..62047919 100644
--- a/ibus/interface/iinputcontext.py
+++ b/ibus/interface/iinputcontext.py
@@ -61,15 +61,6 @@ class IInputContext(dbus.service.Object):
@method()
def Reset(self): pass
- @method()
- def Enable(self): pass
-
- @method()
- def Disable(self): pass
-
- @method(out_signature="b")
- def IsEnabled(self): pass
-
@method(in_signature="u")
def SetCapabilities(self, caps): pass
@@ -86,12 +77,6 @@ class IInputContext(dbus.service.Object):
@signal(signature="v")
def CommitText(self, text): pass
- @signal()
- def Enabled(self): pass
-
- @signal()
- def Disabled(self): pass
-
@signal(signature="uuu")
def ForwardKeyEvent(self, keyval, keycode, state): pass
diff --git a/src/ibusbus.c b/src/ibusbus.c
index 2607448b..61374417 100644
--- a/src/ibusbus.c
+++ b/src/ibusbus.c
@@ -1478,6 +1478,37 @@ ibus_bus_list_active_engines_async_finish (IBusBus *bus,
return ibus_bus_list_engines_async_finish (bus, res, error);
}
+IBusEngineDesc **
+ibus_bus_get_engines_by_names (IBusBus *bus,
+ const gchar * const *names)
+{
+ g_return_val_if_fail (IBUS_IS_BUS (bus), NULL);
+
+ GVariant *result;
+ result = ibus_bus_call_sync (bus,
+ IBUS_SERVICE_IBUS,
+ IBUS_PATH_IBUS,
+ IBUS_INTERFACE_IBUS,
+ "GetEnginesByNames",
+ g_variant_new("(^as)", names),
+ G_VARIANT_TYPE ("(av)"));
+ if (result == NULL)
+ return NULL;
+
+ GArray *array = g_array_new (TRUE, TRUE, sizeof (IBusEngineDesc *));
+ GVariantIter *iter = NULL;
+ g_variant_get (result, "(av)", &iter);
+ GVariant *var;
+ while (g_variant_iter_loop (iter, "v", &var)) {
+ IBusEngineDesc *desc = (IBusEngineDesc *) ibus_serializable_deserialize (var);
+ g_array_append_val (array, desc);
+ }
+ g_variant_iter_free (iter);
+ g_variant_unref (result);
+
+ return (IBusEngineDesc **)g_array_free (array, FALSE);
+}
+
static void
_config_destroy_cb (IBusConfig *config,
IBusBus *bus)
diff --git a/src/ibusbus.h b/src/ibusbus.h
index 7c4fdeed..abcf2c4b 100644
--- a/src/ibusbus.h
+++ b/src/ibusbus.h
@@ -710,6 +710,19 @@ GList *ibus_bus_list_active_engines_async_finish
GAsyncResult *res,
GError **error);
+/**
+ * ibus_bus_get_engines_by_names:
+ * @bus: An #IBusBus.
+ * @names: A %NULL-terminated array of names.
+ * @returns: (transfer container) (element-type IBusEngineDesc): A %NULL-terminated array of engines.
+ *
+ * Get engines by given names synchronously.
+ * TODO(penghuang): add asynchronous version
+ */
+IBusEngineDesc **
+ ibus_bus_get_engines_by_names
+ (IBusBus *bus,
+ const gchar * const *names);
/**
* ibus_bus_get_use_sys_layout:
* @bus: An #IBusBus.
diff --git a/src/ibusinputcontext.c b/src/ibusinputcontext.c
index 54e30aea..fa8301b0 100644
--- a/src/ibusinputcontext.c
+++ b/src/ibusinputcontext.c
@@ -1009,45 +1009,6 @@ ibus_input_context_property_hide (IBusInputContext *context,
);
}
-void
-ibus_input_context_is_enabled_async (IBusInputContext *context,
- gint timeout_msec,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- g_assert (IBUS_IS_INPUT_CONTEXT (context));
- g_dbus_proxy_call ((GDBusProxy *) context,
- "IsEnabled", /* method_name */
- NULL, /* parameters */
- G_DBUS_CALL_FLAGS_NONE, /* flags */
- timeout_msec,
- cancellable,
- callback,
- user_data);
-}
-
-gboolean
-ibus_input_context_is_enabled_async_finish (IBusInputContext *context,
- GAsyncResult *res,
- GError **error)
-{
- g_assert (IBUS_IS_INPUT_CONTEXT (context));
- g_assert (G_IS_ASYNC_RESULT (res));
- g_assert (error == NULL || *error == NULL);
-
- gboolean enabled = FALSE;
-
- GVariant *variant = g_dbus_proxy_call_finish ((GDBusProxy *) context,
- res, error);
- if (variant != NULL) {
- g_variant_get (variant, "(b)", &enabled);
- g_variant_unref (variant);
- }
-
- return enabled;
-}
-
void
ibus_input_context_set_surrounding_text (IBusInputContext *context,
IBusText *text,
@@ -1096,34 +1057,6 @@ ibus_input_context_needs_surrounding_text (IBusInputContext *context)
return priv->needs_surrounding_text;
}
-gboolean
-ibus_input_context_is_enabled (IBusInputContext *context)
-{
- g_assert (IBUS_IS_INPUT_CONTEXT (context));
- GVariant *result;
- GError *error = NULL;
- result = g_dbus_proxy_call_sync ((GDBusProxy *) context,
- "IsEnabled", /* method_name */
- NULL, /* parameters */
- G_DBUS_CALL_FLAGS_NONE, /* flags */
- -1, /* timeout */
- NULL, /* cancellable */
- &error /* error */
- );
-
- if (result == NULL) {
- g_warning ("%s.IsEnabled: %s", IBUS_INTERFACE_INPUT_CONTEXT, error->message);
- g_error_free (error);
- return FALSE;
- }
-
- gboolean retval = FALSE;
- g_variant_get (result, "(b)", &retval);
- g_variant_unref (result);
-
- return retval;
-}
-
void
ibus_input_context_get_engine_async (IBusInputContext *context,
gint timeout_msec,
@@ -1242,6 +1175,4 @@ DEFINE_FUNC(page_up, PageUp);
DEFINE_FUNC(page_down, PageDown);
DEFINE_FUNC(cursor_up, CursorUp);
DEFINE_FUNC(cursor_down, CursorDown);
-DEFINE_FUNC(enable, Enable);
-DEFINE_FUNC(disable, Disable);
#undef DEFINE_FUNC
diff --git a/src/ibusinputcontext.h b/src/ibusinputcontext.h
index f584de31..659732b1 100644
--- a/src/ibusinputcontext.h
+++ b/src/ibusinputcontext.h
@@ -371,73 +371,6 @@ void ibus_input_context_focus_out (IBusInputContext *context);
*/
void ibus_input_context_reset (IBusInputContext *context);
-/**
- * ibus_input_context_enable:
- * @context: An IBusInputContext.
- *
- * Invoked when the IME is enabled, either by IME switch hotkey or select from the menu.
- * An asynchronous IPC will be performed.
- *
- * see_also: #IBusEngine::enable
- */
-void ibus_input_context_enable (IBusInputContext *context);
-
-/**
- * ibus_input_context_disable:
- * @context: An IBusInputContext.
- *
- * Invoked when the IME is disabled, either by IME switch hotkey or select from the menu.
- * An asynchronous IPC will be performed.
- *
- * see_also: #IBusEngine::disable
- */
-void ibus_input_context_disable (IBusInputContext *context);
-
-
-/**
- * ibus_input_context_is_enabled_async:
- * @context: An #IBusInputContext.
- * @timeout_msec: The timeout in milliseconds or -1 to use the default timeout.
- * @cancellable: A #GCancellable or %NULL.
- * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL
- * if you don't care about the result of the method invocation.
- * @user_data: The data to pass to callback.
- *
- * An asynchronous IPC will be performed.
- */
-void ibus_input_context_is_enabled_async
- (IBusInputContext *context,
- gint timeout_msec,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-
-/**
- * ibus_input_context_is_enabled_async_finish:
- * @context: An #IBusInputContext.
- * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to
- * ibus_input_context_is_enabled_async().
- * @error: Return location for error or %NULL.
- * @returns: %TRUE if the IME is enabled on the contextfor success;
- * %FALSE otherwise or some errors happen and the @error will be set.
- *
- * Finishes an operation started with ibus_input_context_is_enabled_async().
- */
-gboolean ibus_input_context_is_enabled_async_finish
- (IBusInputContext *context,
- GAsyncResult *res,
- GError **error);
-
-/**
- * ibus_input_context_is_enabled:
- * @context: An IBusInputContext.
- * @returns: TRUE if the IME is enabled on the context.
- *
- * Returns TRUE if the IME is enabled on the context.
- * A asynchronous IPC will be performed.
- */
-gboolean ibus_input_context_is_enabled (IBusInputContext *context);
-
/**
* ibus_input_context_get_engine_async:
* @context: An #IBusInputContext.
diff --git a/src/tests/ibus-inputcontext.c b/src/tests/ibus-inputcontext.c
index 846e635d..9053ca02 100644
--- a/src/tests/ibus-inputcontext.c
+++ b/src/tests/ibus-inputcontext.c
@@ -56,10 +56,6 @@ call_basic_ipcs (IBusInputContext *context)
ibus_input_context_set_capabilities (context, IBUS_CAP_FOCUS);
ibus_input_context_property_activate (context, "dummy.prop.name", PROP_STATE_CHECKED);
ibus_input_context_reset (context);
- ibus_input_context_disable (context);
- /* g_assert (ibus_input_context_is_enabled (context) == FALSE); */ /* see below. */
- ibus_input_context_enable (context);
- /* g_assert (ibus_input_context_is_enabled (context) == TRUE); */ /* see below. */
/* When enable() is called, ibus-daemon may start a global (or preloaded,
* or default) engine in an asynchrnous manner and return immediately.
@@ -119,31 +115,6 @@ test_input_context (void)
g_list_free (engines);
}
-static void
-finish_is_enabled_async (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
-{
- IBusInputContext *context = IBUS_INPUT_CONTEXT (source_object);
- GError *error = NULL;
- gboolean result = ibus_input_context_is_enabled_async_finish (context,
- res,
- &error);
- g_assert (result);
- g_debug ("ibus_context_is_enabled_async_finish: OK");
- call_next_async_function (context);
-}
-
-static void
-start_is_enabled_async (IBusInputContext *context)
-{
- ibus_input_context_is_enabled_async (context,
- -1, /* timeout */
- NULL, /* cancellable */
- finish_is_enabled_async,
- NULL); /* user_data */
-}
-
static void
finish_get_engine_async (GObject *source_object,
GAsyncResult *res,
@@ -220,7 +191,6 @@ static void
call_next_async_function (IBusInputContext *context)
{
static void (*async_functions[])(IBusInputContext *) = {
- start_is_enabled_async,
start_get_engine_async,
start_process_key_event_async,
};
diff --git a/ui/Makefile.am b/ui/Makefile.am
index ba6d4ffb..b28e03f2 100644
--- a/ui/Makefile.am
+++ b/ui/Makefile.am
@@ -23,6 +23,7 @@
if ENABLE_PYTHON
SUBDIRS = \
gtk \
+ gtk3 \
$(NULL)
endif
diff --git a/ui/gtk/candidatepanel.py b/ui/gtk/candidatepanel.py
index 462c7021..159b2bcf 100644
--- a/ui/gtk/candidatepanel.py
+++ b/ui/gtk/candidatepanel.py
@@ -202,7 +202,6 @@ class CandidatePanel(gtk.VBox):
gdk.BUTTON_PRESS_MASK | \
gdk.BUTTON_RELEASE_MASK | \
gdk.BUTTON1_MOTION_MASK)
- self.__begin_move = False
self.__toplevel.connect("size-allocate", lambda w, a: self.__check_position())
self.__orientation = ibus.ORIENTATION_VERTICAL
diff --git a/ui/gtk/languagebar.py b/ui/gtk/languagebar.py
index c642d8f3..c3701a6e 100644
--- a/ui/gtk/languagebar.py
+++ b/ui/gtk/languagebar.py
@@ -354,7 +354,7 @@ class LanguageBar(gtk.Toolbar):
self.__properties.append(item)
menu.insert(item, 0)
- about_label = _("About") + " - " + self.__im_name
+ about_label = _("About") + " - " + (self.__im_name or "")
prop = ibus.Property(key=u"about",
label=unicode(about_label),
icon=unicode(gtk.STOCK_ABOUT),
diff --git a/ui/gtk/panel.py b/ui/gtk/panel.py
index f71a36da..42dde5d0 100644
--- a/ui/gtk/panel.py
+++ b/ui/gtk/panel.py
@@ -220,7 +220,7 @@ class Panel(ibus.PanelBase):
def focus_in(self, ic):
self.reset()
self.__focus_ic = ibus.InputContext(self.__bus, ic)
- enabled = self.__focus_ic.is_enabled()
+ enabled = True or self.__focus_ic.is_enabled()
self.__language_bar.set_enabled(enabled)
if not enabled:
@@ -414,7 +414,11 @@ class Panel(ibus.PanelBase):
# return menu
def __create_im_menu(self):
- engines = self.__bus.list_active_engines()
+ # FIXME
+ # engines = self.__bus.list_engines()
+ names = self.__config.get_value("general", "preload_engines",
+ ["xkb:us::eng", "xkb:us:intl:eng", "pinyin"])
+ engines = self.__bus.get_engines_by_names(names)
current_engine = \
(self.__focus_ic != None and self.__focus_ic.get_engine()) or \
(engines and engines[0]) or \
@@ -439,7 +443,7 @@ class Panel(ibus.PanelBase):
item = gtk.ImageMenuItem(_("Turn off input method"))
item.set_image(_icon.IconWidget("gtk-close", size[0]))
item.connect("activate", self.__im_menu_item_activate_cb, None)
- if self.__focus_ic == None or not self.__focus_ic.is_enabled():
+ if self.__focus_ic == None:
item.set_sensitive(False)
menu.add(item)
diff --git a/ui/gtk3/Makefile.am b/ui/gtk3/Makefile.am
new file mode 100644
index 00000000..1483a911
--- /dev/null
+++ b/ui/gtk3/Makefile.am
@@ -0,0 +1,84 @@
+# vim:set noet ts=4:
+#
+# ibus - The Input Bus
+#
+# Copyright (c) 2007-2010 Peng Huang
+# Copyright (c) 2007-2010 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
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307 USA
+
+NULL =
+
+libibus = $(top_builddir)/src/libibus-@IBUS_API_VERSION@.la
+
+INCLUDES = \
+ -I$(top_srcdir)/src \
+ -I$(top_builddir)/src \
+ $(NULL)
+
+AM_CFLAGS = \
+ @GLIB2_CFLAGS@ \
+ @GIO2_CFLAGS@ \
+ @GTHREAD2_CFLAGS@ \
+ @GTK3_CFLAGS@ \
+ @X11_CFLAGS@ \
+ -DG_LOG_DOMAIN=\"IBUS\" \
+ -DPKGDATADIR=\"$(pkgdatadir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DBINDIR=\"@bindir@\" \
+ $(INCLUDES) \
+ $(NULL)
+
+AM_LDADD = \
+ @GOBJECT2_LIBS@ \
+ @GLIB2_LIBS@ \
+ @GIO2_LIBS@ \
+ @GTHREAD2_LIBS@ \
+ @GTK3_LIBS@ \
+ @X11_LIBS@ \
+ $(libibus) \
+ $(NULL)
+
+AM_VALAFLAGS = \
+ --vapidir=$(top_builddir)/bindings/vala \
+ --pkg=gtk+-3.0 \
+ --pkg=gdk-x11-3.0 \
+ --pkg=ibus-1.0 \
+ $(NULL)
+
+bin_PROGRAMS = ibus-ui-gtk3
+
+ibus_ui_gtk3_SOURCES = \
+ application.vala \
+ candidatearea.vala \
+ candidatepanel.vala \
+ handle.vala \
+ iconwidget.vala \
+ keybindingmanager.vala \
+ panel.vala \
+ pango.vala \
+ separator.vala \
+ $(NULL)
+
+ibus_ui_gtk3_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(NULL)
+
+ibus_ui_gtk3_LDADD = \
+ $(AM_LDADD) \
+ $(NULL)
+
+-include $(top_srcdir)/git.mk
diff --git a/ui/gtk3/application.vala b/ui/gtk3/application.vala
new file mode 100644
index 00000000..4e7a2a2a
--- /dev/null
+++ b/ui/gtk3/application.vala
@@ -0,0 +1,109 @@
+/* vim:set et sts=4 sw=4:
+ *
+ * ibus - The Input Bus
+ *
+ * Copyright(c) 2011 Peng Huang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or(at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307 USA
+ */
+
+using IBus;
+using GLib;
+using Gtk;
+
+class Application {
+ private IBus.Bus m_bus;
+ private Panel m_panel;
+ private KeybindingManager m_keybinding_manager;
+
+ public Application(string[] argv) {
+ IBus.init();
+ Gtk.init(ref argv);
+
+ m_keybinding_manager = new KeybindingManager();
+ m_bus = new IBus.Bus();
+ m_panel = new Panel(m_bus);
+
+ m_bus.connected.connect(bus_connected);
+ m_bus.disconnected.connect(bus_disconnected);
+
+ if (m_bus.is_connected()) {
+ init();
+ }
+ m_keybinding_manager.bind("V", hotkey_triggered);
+ }
+
+ private void init() {
+ DBusConnection connection = m_bus.get_connection();
+ connection.signal_subscribe("org.freedesktop.DBus",
+ "org.freedesktop.DBus",
+ "NameAcquired",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.IBus.Panel",
+ DBusSignalFlags.NONE,
+ this.bus_name_acquired);
+ connection.signal_subscribe("org.freedesktop.DBus",
+ "org.freedesktop.DBus",
+ "NameLost",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.IBus.Panel",
+ DBusSignalFlags.NONE,
+ this.bus_name_lost);
+
+ m_bus.request_name("org.freedesktop.IBus.Panel", 2);
+ }
+
+ public int run() {
+ Gtk.main();
+ return 0;
+ }
+
+ private void bus_name_acquired(DBusConnection connection,
+ string sender_name,
+ string object_path,
+ string interface_name,
+ string signal_name,
+ Variant parameters) {
+ debug("signal_name = %s", signal_name);
+ }
+
+ private void bus_name_lost(DBusConnection connection,
+ string sender_name,
+ string object_path,
+ string interface_name,
+ string signal_name,
+ Variant parameters) {
+ debug("signal_name = %s", signal_name);
+ }
+
+ private void bus_disconnected(IBus.Bus bus) {
+ debug("connection is lost.");
+ Gtk.main_quit();
+ }
+
+ private void bus_connected(IBus.Bus bus) {
+ init();
+ }
+
+ private void hotkey_triggered() {
+ debug("hotkey");
+ }
+
+ public static void main(string[] argv) {
+ Application app = new Application(argv);
+ app.run();
+ }
+}
diff --git a/ui/gtk3/candidatearea.vala b/ui/gtk3/candidatearea.vala
new file mode 100644
index 00000000..13ebf769
--- /dev/null
+++ b/ui/gtk3/candidatearea.vala
@@ -0,0 +1,252 @@
+/* vim:set et sts=4 sw=4:
+ *
+ * ibus - The Input Bus
+ *
+ * Copyright(c) 2011 Peng Huang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or(at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307 USA
+ */
+
+using Gtk;
+using IBus;
+using Pango;
+
+class CandidateArea : Gtk.Box {
+ private bool m_vertical;
+ private Gtk.Label[] m_labels;
+ private Gtk.Label[] m_candidates;
+ private Gtk.Widget[] m_widgets;
+
+ private IBus.Text[] m_ibus_candidates;
+ private uint m_focus_candidate;
+ private bool m_show_cursor;
+
+ public signal void candidate_clicked(uint index, uint button, uint state);
+ public signal void page_up();
+ public signal void page_down();
+ public signal void cursor_up();
+ public signal void cursor_down();
+
+ public CandidateArea(bool vertical) {
+ GLib.Object(
+ orientation: vertical ? Gtk.Orientation.VERTICAL : Gtk.Orientation.HORIZONTAL
+ );
+ m_vertical = vertical;
+ recreate_ui();
+ show_all();
+ }
+
+ public void set_vertical(bool vertical) {
+ if (m_vertical == vertical)
+ return;
+ m_vertical = vertical;
+ recreate_ui();
+
+ // Workaround a vala issue https://bugzilla.gnome.org/show_bug.cgi?id=661130
+ set_candidates((owned)m_ibus_candidates, m_focus_candidate, m_show_cursor);
+ if (m_candidates.length > 0)
+ show_all();
+ }
+
+ public void set_labels(string[] labels) {
+ if (labels == null) {
+ const string labels[] = {
+ "1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.",
+ "9.", "0.", "a.", "b.", "c.", "d.", "e.", "f."
+ };
+ for (int i = 0 ; i < 16; i++)
+ m_labels[i].set_text(labels[i]);
+ } else {
+ int i = 0;
+ foreach (string label in labels)
+ m_labels[i].set_text(label);
+ }
+ }
+
+ public void set_candidates(IBus.Text[] candidates,
+ uint focus_candidate = 0,
+ bool show_cursor = true) {
+ m_ibus_candidates = candidates;
+ m_focus_candidate = focus_candidate;
+ m_show_cursor = show_cursor;
+
+ assert(candidates.length < 16);
+ for (int i = 0 ; i < 16 ; i++) {
+ Gtk.Label label = m_candidates[i];
+ bool visible = false;
+ if (i < candidates.length) {
+ Pango.AttrList attrs = get_pango_attr_list_from_ibus_text(candidates[i]);
+ if (i == focus_candidate && show_cursor) {
+ Gtk.StyleContext context = m_candidates[i].get_style_context();
+ Gdk.RGBA color = context.get_color(Gtk.StateFlags.SELECTED);
+ Pango.Attribute pango_attr = Pango.attr_foreground_new(
+ (uint16)(color.red * uint16.MAX),
+ (uint16)(color.green * uint16.MAX),
+ (uint16)(color.blue * uint16.MAX));
+ pango_attr.start_index = 0;
+ pango_attr.end_index = candidates[i].get_text().length;
+ attrs.insert((owned)pango_attr);
+
+ color = context.get_background_color(Gtk.StateFlags.SELECTED);
+ pango_attr = Pango.attr_background_new(
+ (uint16)(color.red * uint16.MAX),
+ (uint16)(color.green * uint16.MAX),
+ (uint16)(color.blue * uint16.MAX));
+ pango_attr.start_index = 0;
+ pango_attr.end_index = candidates[i].get_text().length;
+ attrs.insert((owned)pango_attr);
+ }
+ label.set_text(candidates[i].get_text());
+ label.set_attributes(attrs);
+ visible = true;
+ } else {
+ label.set_text("");
+ label.set_attributes(new Pango.AttrList());
+ }
+ if (m_vertical) {
+ m_widgets[i * 2].set_visible(visible);
+ m_widgets[i * 2 +1].set_visible(visible);
+ } else {
+ m_widgets[i].set_visible(visible);
+ }
+ }
+ }
+
+ private void recreate_ui() {
+ foreach (Gtk.Widget w in get_children()) {
+ w.destroy();
+ }
+
+ const string labels[] = {
+ "1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.",
+ "9.", "0.", "a.", "b.", "c.", "d.", "e.", "f."
+ };
+
+ Gtk.Button prev_button = new Gtk.Button();
+ prev_button.clicked.connect((b) => page_up());
+ prev_button.set_image(new Gtk.Image.from_icon_name(Gtk.Stock.GO_UP, Gtk.IconSize.MENU));
+ prev_button.set_relief(Gtk.ReliefStyle.NONE);
+
+ Gtk.Button next_button = new Gtk.Button();
+ next_button.clicked.connect((b) => page_down());
+ next_button.set_image(new Gtk.Image.from_icon_name(Gtk.Stock.GO_DOWN, Gtk.IconSize.MENU));
+ next_button.set_relief(Gtk.ReliefStyle.NONE);
+
+ if (m_vertical) {
+ // Add Candidates
+ Gtk.HBox candidates_hbox = new Gtk.HBox(false, 0);
+ pack_start(candidates_hbox, false, false, 0);
+ Gtk.VBox labels_vbox = new Gtk.VBox(true, 0);
+ Gtk.VBox candidates_vbox = new Gtk.VBox(true, 0);
+ candidates_hbox.pack_start(labels_vbox, false, false, 4);
+ candidates_hbox.pack_start(new VSeparator(), false, false, 0);
+ candidates_hbox.pack_start(candidates_vbox, true, true, 4);
+
+ // Add HSeparator
+ pack_start(new HSeparator(), false, false, 0);
+
+ // Add buttons
+ Gtk.HBox buttons_hbox = new Gtk.HBox(false, 0);
+ Gtk.Label state_label = new Gtk.Label(null);
+ state_label.set_size_request(20, -1);
+ buttons_hbox.pack_start(state_label, true, true, 0);
+ buttons_hbox.pack_start(prev_button, false, false, 0);
+ buttons_hbox.pack_start(next_button, false, false, 0);
+ pack_start(buttons_hbox, false, false, 0);
+
+ m_labels = {};
+ m_candidates = {};
+ m_widgets = {};
+ for (int i = 0; i < 16; i++) {
+ Gtk.Label label = new Gtk.Label(labels[i]);
+ label.set_alignment(0.0f, 0.5f);
+ label.show();
+ m_labels += label;
+
+ Gtk.Label candidate = new Gtk.Label("test");
+ candidate.set_alignment(0.0f, 0.5f);
+ candidate.show();
+ m_candidates += candidate;
+
+ label.set_property("xpad", 8);
+ candidate.set_property("xpad", 8);
+
+ // Make a copy of i to workaround a bug in vala.
+ // https://bugzilla.gnome.org/show_bug.cgi?id=628336
+ int index = i;
+ Gtk.EventBox label_ebox = new Gtk.EventBox();
+ label_ebox.set_no_show_all(true);
+ label_ebox.button_press_event.connect((w, e) => {
+ candidate_clicked(i, e.button, e.state);
+ return true;
+ });
+ label_ebox.add(label);
+ labels_vbox.pack_start(label_ebox, false, false, 2);
+ m_widgets += label_ebox;
+
+ Gtk.EventBox candidate_ebox = new Gtk.EventBox();
+ candidate_ebox.set_no_show_all(true);
+ candidate_ebox.button_press_event.connect((w, e) => {
+ candidate_clicked(index, e.button, e.state);
+ return true;
+ });
+ candidate_ebox.add(candidate);
+ candidates_vbox.pack_start(candidate_ebox, false, false, 2);
+ m_widgets += candidate_ebox;
+ }
+ } else {
+ Gtk.HBox hbox = new Gtk.HBox(false, 0);
+ add(hbox);
+
+ m_labels = {};
+ m_candidates = {};
+ m_widgets = {};
+ for (int i = 0; i < 16; i++) {
+ Gtk.Label label = new Gtk.Label(labels[i]);
+ label.set_alignment(0.0f, 0.5f);
+ label.show();
+ m_labels += label;
+
+ Gtk.Label candidate = new Gtk.Label("test");
+ candidate.set_alignment(0.0f, 0.5f);
+ candidate.show();
+ m_candidates += candidate;
+
+ Gtk.HBox candidate_hbox = new Gtk.HBox(false, 0);
+ candidate_hbox.show();
+ candidate_hbox.pack_start(label, false, false, 2);
+ candidate_hbox.pack_start(candidate, false, false, 2);
+
+ // Make a copy of i to workaround a bug in vala.
+ // https://bugzilla.gnome.org/show_bug.cgi?id=628336
+ int index = i;
+ Gtk.EventBox ebox = new Gtk.EventBox();
+ ebox.set_no_show_all(true);
+ ebox.button_press_event.connect((w, e) => {
+ candidate_clicked(index, e.button, e.state);
+ return true;
+ });
+ ebox.add(candidate_hbox);
+ hbox.pack_start(ebox, false, false, 4);
+ m_widgets += ebox;
+ }
+ hbox.pack_start(new VSeparator(), false, false, 0);
+ hbox.pack_start(prev_button, false, false, 0);
+ hbox.pack_start(next_button, false, false, 0);
+ }
+ }
+}
+
diff --git a/ui/gtk3/candidatepanel.vala b/ui/gtk3/candidatepanel.vala
new file mode 100644
index 00000000..b31913ef
--- /dev/null
+++ b/ui/gtk3/candidatepanel.vala
@@ -0,0 +1,238 @@
+/* vim:set et sts=4 sw=4:
+ *
+ * ibus - The Input Bus
+ *
+ * Copyright(c) 2011 Peng Huang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or(at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307 USA
+ */
+
+using Gtk;
+using Pango;
+
+class CandidatePanel : Gtk.HBox{
+ private bool m_vertical = true;
+ private Gtk.Window m_toplevel;
+ private Gtk.VBox m_vbox;
+
+ private Gtk.Label m_preedit_label;
+ private Gtk.Label m_aux_label;
+ private CandidateArea m_candidate_area;
+ private HSeparator m_hseparator;
+
+ private Gdk.Rectangle m_cursor_location;
+
+ public signal void cursor_up();
+ public signal void cursor_down();
+ public signal void page_up();
+ public signal void page_down();
+ public signal void candidate_clicked(uint index,
+ uint button,
+ uint state);
+
+ public CandidatePanel() {
+ // Call base class constructor
+ GLib.Object(
+ name : "IBusCandidate"
+ );
+
+ m_toplevel = new Gtk.Window(Gtk.WindowType.POPUP);
+ m_toplevel.add_events(Gdk.EventMask.BUTTON_PRESS_MASK);
+ m_toplevel.button_press_event.connect((w, e) => {
+ if (e.button != 1 || (e.state & Gdk.ModifierType.CONTROL_MASK) == 0)
+ return false;
+ set_vertical(!m_vertical);
+ return true;
+ });
+
+ m_vbox = new Gtk.VBox(false, 0);
+ Handle handle = new Handle();
+ pack_start(handle, false, false, 0);
+ pack_start(m_vbox, false, false, 0);
+
+ m_toplevel.add(this);
+
+ create_ui();
+ }
+
+ public void set_vertical(bool vertical) {
+ if (m_vertical == vertical)
+ return;
+ m_vertical = vertical;
+ m_candidate_area.set_vertical(vertical);
+ }
+
+ public void set_cursor_location(int x, int y, int width, int height) {
+ Gdk.Rectangle location = { x, y, width, height };
+ if (m_cursor_location == location)
+ return;
+ m_cursor_location = location;
+ adjust_window_position();
+ }
+
+ public void set_labels(string[] labels) {
+ m_candidate_area.set_labels(labels);
+ }
+
+ public void set_preedit_text(IBus.Text? text, uint cursor) {
+ if (text != null) {
+ m_preedit_label.set_text(text.get_text());
+ m_preedit_label.show();
+ } else {
+ m_preedit_label.set_text("");
+ m_preedit_label.hide();
+ }
+ update();
+ }
+
+ public void set_auxiliary_text(IBus.Text? text) {
+ if (text != null) {
+ m_aux_label.set_text(text.get_text());
+ m_aux_label.show();
+ } else {
+ m_aux_label.set_text("");
+ m_aux_label.hide();
+ }
+ update();
+ }
+
+ public void set_lookup_table(IBus.LookupTable? table) {
+ IBus.Text[] candidates = {};
+ uint cursor_in_page = 0;
+ bool show_cursor = true;
+
+ if (table != null) {
+ uint page_size = table.get_page_size();
+ uint ncandidates = table.get_number_of_candidates();
+ uint cursor = table.get_cursor_pos();
+ cursor_in_page = table.get_cursor_in_page();
+ show_cursor = table.is_cursor_visible();
+
+ uint page_start_pos = cursor / page_size * page_size;
+ uint page_end_pos = uint.min(page_start_pos + page_size, ncandidates);
+ for (uint i = page_start_pos; i < page_end_pos; i++)
+ candidates += table.get_candidate(i);
+ }
+ m_candidate_area.set_candidates(candidates, cursor_in_page, show_cursor);
+ if (candidates.length != 0)
+ m_candidate_area.show_all();
+ else
+ m_candidate_area.hide();
+
+ update();
+ }
+
+ private void update() {
+ if (m_candidate_area.get_visible() ||
+ m_preedit_label.get_visible() ||
+ m_aux_label.get_visible())
+ m_toplevel.show();
+ else
+ m_toplevel.hide();
+
+ if (m_aux_label.get_visible() &&
+ (m_candidate_area.get_visible() || m_preedit_label.get_visible()))
+ m_hseparator.show();
+ else
+ m_hseparator.hide();
+ }
+
+ public override void get_preferred_width(out int minimum_width, out int natural_width) {
+ base.get_preferred_width(out minimum_width, out natural_width);
+ m_toplevel.resize(1, 1);
+ }
+
+ public override void get_preferred_height(out int minimum_width, out int natural_width) {
+ base.get_preferred_height(out minimum_width, out natural_width);
+ m_toplevel.resize(1, 1);
+ }
+
+ private void create_ui() {
+ m_preedit_label = new Gtk.Label(null);
+ m_preedit_label.set_size_request(20, -1);
+ m_preedit_label.set_alignment(0.0f, 0.5f);
+ m_preedit_label.set_padding(8, 0);
+ m_preedit_label.set_no_show_all(true);
+
+ m_aux_label = new Gtk.Label(null);
+ m_aux_label.set_size_request(20, -1);
+ m_aux_label.set_alignment(0.0f, 0.5f);
+ m_aux_label.set_padding(8, 0);
+ m_aux_label.set_no_show_all(true);
+
+ m_candidate_area = new CandidateArea(m_vertical);
+ m_candidate_area.candidate_clicked.connect((w, i, b, s) => candidate_clicked(i, b, s));
+ m_candidate_area.page_up.connect((c) => page_up());
+ m_candidate_area.page_down.connect((c) => page_down());
+ m_candidate_area.cursor_up.connect((c) => cursor_up());
+ m_candidate_area.cursor_down.connect((c) => cursor_down());
+ m_candidate_area.show();
+
+ m_hseparator = new HSeparator();
+
+ pack_all_widgets();
+ }
+
+ private void pack_all_widgets() {
+ m_vbox.pack_start(m_preedit_label, false, false, 4);
+ m_vbox.pack_start(m_aux_label, false, false, 4);
+ m_vbox.pack_start(m_hseparator, false, false, 0);
+ m_vbox.pack_start(m_candidate_area, false, false, 0);
+ }
+
+ public new void show() {
+ m_toplevel.show_all();
+ }
+
+ public new void hide() {
+ m_toplevel.hide();
+ }
+
+ private void move(int x, int y) {
+ m_toplevel.move(x, y);
+ }
+
+ private void adjust_window_position() {
+ Gdk.Point cursor_right_bottom = {
+ m_cursor_location.x + m_cursor_location.width,
+ m_cursor_location.y + m_cursor_location.height
+ };
+
+ Gtk.Allocation allocation;
+ m_toplevel.get_allocation(out allocation);
+ Gdk.Point window_right_bottom = {
+ cursor_right_bottom.x + allocation.width,
+ cursor_right_bottom.y + allocation.height
+ };
+
+ Gdk.Window root = Gdk.get_default_root_window();
+ int root_width = root.get_width();
+ int root_height = root.get_height();
+
+ int x, y;
+ if (window_right_bottom.x > root_width)
+ x = root_width - allocation.width;
+ else
+ x = cursor_right_bottom.x;
+
+ if (window_right_bottom.y > root_height)
+ y = m_cursor_location.y - allocation.height;
+ else
+ y = cursor_right_bottom.y;
+
+ move(x, y);
+ }
+}
diff --git a/ui/gtk3/handle.vala b/ui/gtk3/handle.vala
new file mode 100644
index 00000000..6738415f
--- /dev/null
+++ b/ui/gtk3/handle.vala
@@ -0,0 +1,161 @@
+/* vim:set et sts=4 sw=4:
+ *
+ * ibus - The Input Bus
+ *
+ * Copyright(c) 2011 Peng Huang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or(at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307 USA
+ */
+
+using Cairo;
+using Gdk;
+using Gtk;
+
+class Handle : Gtk.EventBox {
+ private bool m_move_begined;
+ private Gdk.Rectangle m_workarea;
+ private Gdk.Point m_press_pos;
+
+ public signal void move_begin();
+ public signal void move_end();
+
+ public Handle() {
+ set_size_request(6, -1);
+ Gdk.EventMask mask = Gdk.EventMask.EXPOSURE_MASK |
+ Gdk.EventMask.BUTTON_PRESS_MASK |
+ Gdk.EventMask.BUTTON_RELEASE_MASK |
+ Gdk.EventMask.BUTTON1_MOTION_MASK;
+ set_events(mask);
+ m_move_begined = false;
+ }
+
+ public override void realize() {
+ base.realize();
+ // get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.FLEUR));
+ }
+
+ public override bool button_press_event(Gdk.EventButton event) {
+ if (event.button != 1)
+ return false;
+ m_workarea = {0, 0, int.MAX, int.MAX};
+ do {
+ Gdk.Window root = Gdk.get_default_root_window();
+ Gdk.Atom property = Gdk.Atom.intern("_NET_CURRENT_DESKTOP", false);
+ Gdk.Atom type = Gdk.Atom.intern("CARDINAL", false);
+ Gdk.Atom actual_type;
+ int format;
+ uchar[] data;
+ bool result;
+ result = Gdk.property_get(root,
+ property,
+ type,
+ 0, long.MAX,
+ 0,
+ out actual_type,
+ out format,
+ out data);
+ if (!result || actual_type != type || format != 32 || data.length != 4)
+ break;
+ int index = data[0] |
+ data[1] << 8 |
+ data[2] << 16 |
+ data[3] << 24;
+ property = Gdk.Atom.intern("_NET_WORKAREA", false);
+ type = Gdk.Atom.intern("CARDINAL", false);
+ result = Gdk.property_get(root,
+ property,
+ type,
+ 0, long.MAX,
+ 0,
+ out actual_type,
+ out format,
+ out data);
+ if (!result || actual_type != type || format != 32 || data.length < (index + 1) * 16)
+ break;
+ int i = index * 4 * 4;
+ m_workarea.x = data[i] |
+ data[i + 1] << 8 |
+ data[i + 2] << 16 |
+ data[i + 3] << 24;
+ i += 4;
+ m_workarea.y = data[i] |
+ data[i + 1] << 8 |
+ data[i + 2] << 16 |
+ data[i + 3] << 24;
+ i += 4;
+ m_workarea.width = data[i] |
+ data[i + 1] << 8 |
+ data[i + 2] << 16 |
+ data[i + 3] << 24;
+ i += 4;
+ m_workarea.height = data[i] |
+ data[i + 1] << 8 |
+ data[i + 2] << 16 |
+ data[i + 3] << 24;
+ } while (false);
+ m_move_begined = true;
+ int x, y;
+ Gtk.Window toplevel = (Gtk.Window)get_toplevel();
+ toplevel.get_position(out x, out y);
+ m_press_pos = { (int)event.x_root - x, (int)event.y_root - y };
+ move_begin();
+ return true;
+ }
+
+ public override bool button_release_event(Gdk.EventButton event) {
+ if (event.button != 1)
+ return false;
+ m_move_begined = false;
+ m_press_pos = { 0, 0 };
+ get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR));
+ move_end();
+ return true;
+ }
+
+ public override bool motion_notify_event(Gdk.EventMotion event) {
+ if (!m_move_begined)
+ return false;
+ Gtk.Window toplevel = (Gtk.Window)get_toplevel();
+ int x = (int)(event.x_root - m_press_pos.x);
+ int y = (int)(event.y_root - m_press_pos.y);
+
+ if (x < m_workarea.x && x > m_workarea.x - 16)
+ x = m_workarea.x;
+ if (y < m_workarea.y && y > m_workarea.y - 16)
+ y = m_workarea.y;
+ int w, h;
+ toplevel.get_size(out w, out h);
+ if (x + w > m_workarea.x + m_workarea.width &&
+ x + w < m_workarea.x + m_workarea.width + 16)
+ x = m_workarea.x + m_workarea.width - w;
+ if (y + h > m_workarea.y + m_workarea.height &&
+ y + h < m_workarea.y + m_workarea.height + 16)
+ y = m_workarea.y + m_workarea.height - w;
+ toplevel.move(x, y);
+ return true;
+ }
+
+ public override bool draw(Cairo.Context cr) {
+ if (Gtk.cairo_should_draw_window(cr, get_window())) {
+ Gtk.StyleContext context = get_style_context();
+ Gtk.Allocation allocation;
+ get_allocation(out allocation);
+ Gtk.render_handle(context, cr,
+ allocation.x, allocation.y + (allocation.height - 40) / 2, allocation.width, 40.0);
+ }
+ return false;
+ }
+}
diff --git a/ui/gtk3/iconwidget.vala b/ui/gtk3/iconwidget.vala
new file mode 100644
index 00000000..d73cb6be
--- /dev/null
+++ b/ui/gtk3/iconwidget.vala
@@ -0,0 +1,56 @@
+/* vim:set et sts=4 sw=4:
+ *
+ * ibus - The Input Bus
+ *
+ * Copyright(c) 2011 Peng Huang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or(at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307 USA
+ */
+
+using Gdk;
+using GLib;
+using Gtk;
+
+class IconWidget: Gtk.Image {
+ public IconWidget(string icon, int size) {
+ Gdk.Pixbuf pixbuf = null;
+ try {
+ if (icon[0] == '/') {
+ pixbuf = new Gdk.Pixbuf.from_file(icon);
+ } else {
+ var theme = Gtk.IconTheme.get_default();
+ pixbuf = theme.load_icon(icon, size, 0);
+ }
+ } catch (GLib.Error e) {
+ try {
+ var theme = Gtk.IconTheme.get_default();
+ pixbuf = theme.load_icon(Gtk.Stock.MISSING_IMAGE, size, 0);
+ } catch (GLib.Error e) {}
+ }
+
+ if (pixbuf == null)
+ return;
+ float width = (float)pixbuf.get_width();
+ float height = (float)pixbuf.get_height();
+ float scale = size / (width > height ? width : height);
+ width *= scale;
+ height *= scale;
+
+ pixbuf = pixbuf.scale_simple((int)width, (int)height, Gdk.InterpType.BILINEAR);
+ set_from_pixbuf(pixbuf);
+ show();
+ }
+}
diff --git a/ui/gtk3/keybindingmanager.vala b/ui/gtk3/keybindingmanager.vala
new file mode 100644
index 00000000..e9f46e4b
--- /dev/null
+++ b/ui/gtk3/keybindingmanager.vala
@@ -0,0 +1,186 @@
+/*
+valac --pkg gtk+-2.0 --pkg x11 --pkg gdk-x11-2.0 --pkg gee-1.0 keybinding-manager.vala
+*/
+
+/**
+ * This class is in charge to grab keybindings on the X11 display
+ * and filter X11-events and passing on such events to the registed
+ * handler methods.
+ *
+ * @author Oliver Sauder
+ */
+
+using Gdk;
+using GLib;
+using Gtk;
+using X;
+
+class KeybindingManager : GLib.Object
+{
+ /**
+ * list of binded keybindings
+ */
+ private GLib.List bindings = new GLib.List();
+
+ /**
+ * locked modifiers used to grab all keys whatever lock key
+ * is pressed.
+ */
+ private static uint[] lock_modifiers = {
+ 0,
+ Gdk.ModifierType.MOD2_MASK, // NUM_LOCK
+ Gdk.ModifierType.LOCK_MASK, // CAPS_LOCK
+ Gdk.ModifierType.MOD5_MASK, // SCROLL_LOCK
+ Gdk.ModifierType.MOD2_MASK|Gdk.ModifierType.LOCK_MASK,
+ Gdk.ModifierType.MOD2_MASK|Gdk.ModifierType.MOD5_MASK,
+ Gdk.ModifierType.LOCK_MASK|Gdk.ModifierType.MOD5_MASK,
+ Gdk.ModifierType.MOD2_MASK|Gdk.ModifierType.LOCK_MASK|Gdk.ModifierType.MOD5_MASK
+ };
+
+ /**
+ * Helper class to store keybinding
+ */
+ private class Keybinding
+ {
+ public Keybinding(string accelerator, int keycode,
+ Gdk.ModifierType modifiers, KeybindingHandlerFunc handler)
+ {
+ this.accelerator = accelerator;
+ this.keycode = keycode;
+ this.modifiers = modifiers;
+ this.handler = handler;
+ }
+
+ public string accelerator { get; set; }
+ public int keycode { get; set; }
+ public Gdk.ModifierType modifiers { get; set; }
+ public unowned KeybindingHandlerFunc handler { get; set; }
+ }
+
+ /**
+ * Keybinding func needed to bind key to handler
+ *
+ * @param event passing on gdk event
+ */
+ public delegate void KeybindingHandlerFunc(Gdk.Event event);
+
+ public KeybindingManager()
+ {
+ // init filter to retrieve X.Events
+ Gdk.Window rootwin = Gdk.get_default_root_window();
+ if(rootwin != null) {
+ rootwin.add_filter(event_filter);
+ }
+ }
+
+ /**
+ * Bind accelerator to given handler
+ *
+ * @param accelerator accelerator parsable by Gtk.accelerator_parse
+ * @param handler handler called when given accelerator is pressed
+ */
+ public void bind(string accelerator, KeybindingHandlerFunc handler)
+ {
+ debug("Binding key " + accelerator);
+
+ // convert accelerator
+ uint keysym;
+ Gdk.ModifierType modifiers;
+ Gtk.accelerator_parse(accelerator, out keysym, out modifiers);
+
+ unowned X.Display display = Gdk.x11_get_default_xdisplay();
+
+ int keycode = display.keysym_to_keycode(keysym);
+
+ if(keycode != 0) {
+ // trap XErrors to avoid closing of application
+ // even when grabing of key fails
+ Gdk.error_trap_push();
+
+ // grab key finally
+ // also grab all keys which are combined with a lock key such NumLock
+ foreach(uint lock_modifier in lock_modifiers) {
+ display.grab_key(keycode, modifiers|lock_modifier, Gdk.x11_get_default_root_xwindow(), false,
+ X.GrabMode.Async, X.GrabMode.Async);
+ }
+
+ // wait until all X request have been processed
+ Gdk.flush();
+
+ // store binding
+ Keybinding binding = new Keybinding(accelerator, keycode, modifiers, handler);
+ bindings.append(binding);
+
+ debug("Successfully binded key " + accelerator);
+ }
+ }
+
+ /**
+ * Unbind given accelerator.
+ *
+ * @param accelerator accelerator parsable by Gtk.accelerator_parse
+ */
+ public void unbind(string accelerator)
+ {
+ debug("Unbinding key " + accelerator);
+
+ unowned X.Display display = Gdk.x11_get_default_xdisplay();
+
+ // unbind all keys with given accelerator
+ GLib.List remove_bindings = new GLib.List();
+ foreach(Keybinding binding in bindings) {
+ if(str_equal(accelerator, binding.accelerator)) {
+ foreach(uint lock_modifier in lock_modifiers) {
+ display.ungrab_key(binding.keycode, binding.modifiers | lock_modifier, Gdk.x11_get_default_root_xwindow());
+ }
+ remove_bindings.append(binding);
+ }
+ }
+
+ // remove unbinded keys
+ foreach(Keybinding binding in remove_bindings)
+ bindings.remove(binding);
+ }
+
+ /**
+ * Event filter method needed to fetch X.Events
+ */
+ public Gdk.FilterReturn event_filter(Gdk.XEvent gdk_xevent, Gdk.Event gdk_event)
+ {
+ Gdk.FilterReturn filter_return = Gdk.FilterReturn.CONTINUE;
+
+ void* pointer = &gdk_xevent;
+ X.Event* xevent = (X.Event*) pointer;
+
+ if(xevent->type == X.EventType.KeyPress) {
+ foreach(Keybinding binding in bindings) {
+ // remove NumLock, CapsLock and ScrollLock from key state
+ uint event_mods = xevent.xkey.state & ~ (lock_modifiers[7]);
+ if(xevent->xkey.keycode == binding.keycode && event_mods == binding.modifiers) {
+ // call all handlers with pressed key and modifiers
+ binding.handler(gdk_event);
+ }
+ }
+ }
+
+ return filter_return;
+ }
+}
+
+/*
+public static int main (string[] args)
+{
+ Gtk.init (ref args);
+
+ KeybindingManager manager = new KeybindingManager();
+ manager.bind("V", test);
+
+ Gtk.main ();
+ return 0;
+}
+
+private static void test()
+{
+ debug("hotkey pressed");
+}
+*/
diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
new file mode 100644
index 00000000..dc63064c
--- /dev/null
+++ b/ui/gtk3/panel.vala
@@ -0,0 +1,168 @@
+/* vim:set et sts=4 sw=4:
+ *
+ * ibus - The Input Bus
+ *
+ * Copyright(c) 2011 Peng Huang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or(at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307 USA
+ */
+
+using IBus;
+using GLib;
+using Gtk;
+
+class Panel : IBus.PanelService {
+ private IBus.Bus m_bus;
+ private IBus.Config m_config;
+ // private IBus.PanelService m_service;
+ private Gtk.StatusIcon m_status_icon;
+ private Gtk.Menu m_ime_menu;
+ private IBus.EngineDesc[] m_engines;
+ private CandidatePanel m_candidate_panel;
+ private KeybindingManager m_keybinding_manager;
+
+ public Panel(IBus.Bus bus) {
+ assert(bus.is_connected());
+ // Chain up base class constructor
+ GLib.Object(connection : bus.get_connection(),
+ object_path : "/org/freedesktop/IBus/Panel");
+
+ m_bus = bus;
+
+ m_config = bus.get_config();
+
+ // init ui
+ m_status_icon = new Gtk.StatusIcon();
+ m_status_icon.set_name("ibus-ui-gtk");
+ m_status_icon.set_title("IBus Panel");
+ m_status_icon.popup_menu.connect(status_icon_popup_menu);
+ m_status_icon.activate.connect(status_icon_activate);
+ m_status_icon.set_from_icon_name("ibus-keyboard");
+
+ m_candidate_panel = new CandidatePanel();
+
+ m_candidate_panel.hide();
+ m_candidate_panel.show();
+
+ update_engines();
+
+ m_keybinding_manager = new KeybindingManager();
+ m_keybinding_manager.bind("space", (d) => {
+ // Switch to next engine
+ IBus.EngineDesc engine = m_bus.get_global_engine();
+ int i;
+ for (i = 0; i < m_engines.length && engine != null; i++) {
+ if (m_engines[i].get_name() == engine.get_name())
+ break;
+ }
+ i ++;
+ if (i >= m_engines.length) i = 0;
+ if (i >= m_engines.length)
+ return;
+ m_bus.set_global_engine(m_engines[i].get_name());
+ });
+ }
+
+ private void update_engines() {
+ Variant variant = m_config.get_value("general", "preload_engines");
+ if (variant != null)
+ m_engines = m_bus.get_engines_by_names(variant.get_strv());
+ else
+ m_engines = m_bus.get_engines_by_names({"xkb:us:eng", "pinyin"});
+ m_ime_menu = null;
+ }
+
+ private void status_icon_popup_menu(Gtk.StatusIcon status_icon,
+ uint button,
+ uint activate_time) {
+ debug("popup-menu %u %u", button, activate_time);
+ }
+
+ private void status_icon_activate(Gtk.StatusIcon status_icon) {
+ if (m_ime_menu == null) {
+ int width, height;
+ Gtk.icon_size_lookup(Gtk.IconSize.MENU, out width, out height);
+ m_ime_menu = new Gtk.Menu();
+ foreach (var engine in m_engines) {
+ var lang = engine.get_language();
+ var name = engine.get_name();
+ var item = new Gtk.ImageMenuItem.with_label(lang + " - " + name);
+ if (engine.get_icon() != "") {
+ var icon = new IconWidget(engine.get_icon(), width);
+ item.set_image(icon);
+ }
+ // Make a copy of engine to workaround a bug in vala.
+ // https://bugzilla.gnome.org/show_bug.cgi?id=628336
+ var e = engine;
+ item.activate.connect((i) => {
+ m_bus.set_global_engine(e.get_name());
+ });
+ m_ime_menu.add(item);
+ }
+ m_ime_menu.show_all();
+ m_ime_menu.set_take_focus(false);
+ }
+ m_ime_menu.popup(null,
+ null,
+ m_status_icon.position_menu,
+ 0,
+ Gtk.get_current_event_time());
+ }
+
+ public override void set_cursor_location(int x, int y, int width, int height) {
+ m_candidate_panel.set_cursor_location(x, y, width, height);
+ }
+
+ public override void focus_in(string input_context_path) {
+ debug("focus_in ic=%s", input_context_path);
+ }
+
+ public override void focus_out(string input_context_path) {
+ debug("focus_out ic=%s", input_context_path);
+ }
+
+ public override void update_preedit_text(IBus.Text text,
+ uint cursor_pos,
+ bool visible) {
+ if (visible)
+ m_candidate_panel.set_preedit_text(text, cursor_pos);
+ else
+ m_candidate_panel.set_preedit_text(null, 0);
+ }
+
+ public override void hide_preedit_text() {
+ m_candidate_panel.set_preedit_text(null, 0);
+ }
+
+ public override void update_auxiliary_text(IBus.Text text,
+ bool visible) {
+ m_candidate_panel.set_auxiliary_text(visible ? text : null);
+ }
+
+ public override void hide_auxiliary_text() {
+ m_candidate_panel.set_auxiliary_text(null);
+ }
+
+ public override void update_lookup_table(IBus.LookupTable table,
+ bool visible) {
+ m_candidate_panel.set_lookup_table(visible ? table : null);
+ }
+
+ public override void hide_lookup_table() {
+ m_candidate_panel.set_lookup_table(null);
+ }
+}
+
diff --git a/ui/gtk3/pango.vala b/ui/gtk3/pango.vala
new file mode 100644
index 00000000..adcce439
--- /dev/null
+++ b/ui/gtk3/pango.vala
@@ -0,0 +1,84 @@
+/* vim:set et sts=4 sw=4:
+ *
+ * ibus - The Input Bus
+ *
+ * Copyright(c) 2011 Peng Huang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or(at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307 USA
+ */
+
+using IBus;
+using Pango;
+
+Pango.AttrList get_pango_attr_list_from_ibus_text(IBus.Text text) {
+ Pango.AttrList pango_attrs = new Pango.AttrList();
+ unowned IBus.AttrList attrs = text.get_attributes();
+ if (attrs == null)
+ return pango_attrs;
+
+ unowned string str = text.get_text();
+ long nchars = str.char_count();
+ long[] offsets = new long[nchars + 1];
+ for (int i = 0; i <= nchars; i++)
+ offsets[i] = str.index_of_nth_char(i);
+
+ IBus.Attribute attr;
+ int i = 0;
+ while(true) {
+ attr = attrs.get(i++);
+ if (attr == null)
+ break;
+ long start_index = attr.start_index;
+ if (start_index <= 0) start_index = 0;
+ start_index = start_index <= nchars ? offsets[start_index] : offsets[-1];
+
+ long end_index = attr.end_index;
+ if (end_index <= 0) end_index = 0;
+ end_index = end_index <= nchars ? offsets[end_index] : offsets[-1];
+
+ Pango.Attribute pango_attr = null;
+ switch(attr.type) {
+ case IBus.AttrType.FOREGROUND:
+ {
+ uint16 r = (uint16)(attr.value & 0x00ff0000) >> 8;
+ uint16 g = (uint16)(attr.value & 0x0000ff00);
+ uint16 b = (uint16)(attr.value & 0x000000ff) << 8;
+ pango_attr = Pango.attr_foreground_new(r, g, b);
+ break;
+ }
+ case IBus.AttrType.BACKGROUND:
+ {
+ uint16 r = (uint16)(attr.value & 0x00ff0000) >> 8;
+ uint16 g = (uint16)(attr.value & 0x0000ff00);
+ uint16 b = (uint16)(attr.value & 0x000000ff) << 8;
+ pango_attr = Pango.attr_background_new(r, g, b);
+ break;
+ }
+ case IBus.AttrType.UNDERLINE:
+ {
+ pango_attr = Pango.attr_underline_new((Pango.Underline)attr.value);
+ break;
+ }
+ default:
+ continue;
+ }
+ pango_attr.start_index = (uint)start_index;
+ pango_attr.end_index = (uint)end_index;
+ // Transfer the ownership to pango_attrs
+ pango_attrs.insert((owned)pango_attr);
+ }
+ return pango_attrs;
+}
diff --git a/ui/gtk3/separator.vala b/ui/gtk3/separator.vala
new file mode 100644
index 00000000..0917f4c2
--- /dev/null
+++ b/ui/gtk3/separator.vala
@@ -0,0 +1,39 @@
+/* vim:set et sts=4 sw=4:
+ *
+ * ibus - The Input Bus
+ *
+ * Copyright(c) 2011 Peng Huang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or(at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307 USA
+ */
+
+using Gtk;
+
+class HSeparator : Gtk.HSeparator {
+ public HSeparator() {
+ GLib.Object(
+ margin : 2
+ );
+ }
+}
+
+class VSeparator : Gtk.VSeparator {
+ public VSeparator() {
+ GLib.Object(
+ margin : 2
+ );
+ }
+}