[gnome-settings-daemon] keyboard: Apply variants and XKB options from IBus engine descriptions
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-settings-daemon] keyboard: Apply variants and XKB options from IBus engine descriptions
- Date: Fri, 5 Oct 2012 11:56:49 +0000 (UTC)
commit 83ece09d5b3ba0305806c9424f8f1f509d10d37d
Author: Rui Matos <tiagomatos gmail com>
Date: Thu Sep 27 14:55:06 2012 +0200
keyboard: Apply variants and XKB options from IBus engine descriptions
The 'layout' in an IBus engine description might actually also include
a variant and XKB options.
https://bugzilla.gnome.org/show_bug.cgi?id=684855
plugins/keyboard/gsd-keyboard-manager.c | 160 ++++++++++++++++++++++++++++--
1 files changed, 149 insertions(+), 11 deletions(-)
---
diff --git a/plugins/keyboard/gsd-keyboard-manager.c b/plugins/keyboard/gsd-keyboard-manager.c
index 65d3273..e83b871 100644
--- a/plugins/keyboard/gsd-keyboard-manager.c
+++ b/plugins/keyboard/gsd-keyboard-manager.c
@@ -421,6 +421,92 @@ set_ibus_xkb_engine (GsdKeyboardManager *manager,
set_ibus_engine (manager, ibus_engine_desc_get_name (engine));
}
+
+static gchar *
+layout_from_ibus_layout (const gchar *ibus_layout)
+{
+ const gchar *p;
+
+ /* we get something like "layout(variant)[option1,option2]" */
+
+ p = ibus_layout;
+ while (*p) {
+ if (*p == '(' || *p == '[')
+ break;
+ p += 1;
+ }
+
+ return g_strndup (ibus_layout, p - ibus_layout);
+}
+
+static gchar *
+variant_from_ibus_layout (const gchar *ibus_layout)
+{
+ const gchar *a, *b;
+
+ /* we get something like "layout(variant)[option1,option2]" */
+
+ a = ibus_layout;
+ while (*a) {
+ if (*a == '(')
+ break;
+ a += 1;
+ }
+ if (!*a)
+ return NULL;
+
+ a += 1;
+ b = a;
+ while (*b) {
+ if (*b == ')')
+ break;
+ b += 1;
+ }
+ if (!*b)
+ return NULL;
+
+ return g_strndup (a, b - a);
+}
+
+static gchar **
+options_from_ibus_layout (const gchar *ibus_layout)
+{
+ const gchar *a, *b;
+ GPtrArray *opt_array;
+
+ /* we get something like "layout(variant)[option1,option2]" */
+
+ a = ibus_layout;
+ while (*a) {
+ if (*a == '[')
+ break;
+ a += 1;
+ }
+ if (!*a)
+ return NULL;
+
+ opt_array = g_ptr_array_new ();
+
+ do {
+ a += 1;
+ b = a;
+ while (*b) {
+ if (*b == ',' || *b == ']')
+ break;
+ b += 1;
+ }
+ if (!*b)
+ goto out;
+
+ g_ptr_array_add (opt_array, g_strndup (a, b - a));
+
+ a = b;
+ } while (*a && *a == ',');
+
+out:
+ g_ptr_array_add (opt_array, NULL);
+ return (gchar **) g_ptr_array_free (opt_array, FALSE);
+}
#endif /* HAVE_IBUS */
static gboolean
@@ -671,6 +757,9 @@ replace_layout_and_variant (GsdKeyboardManager *manager,
if (!layout)
return;
+ if (!variant)
+ variant = "";
+
locale = setlocale (LC_MESSAGES, NULL);
/* If LANG is empty, default to en_US */
if (!locale)
@@ -750,14 +839,48 @@ build_xkb_options_string (gchar **options)
return string;
}
+static gchar **
+append_options (gchar **a,
+ gchar **b)
+{
+ gchar **c, **p;
+
+ if (!a && !b)
+ return NULL;
+ else if (!a)
+ return g_strdupv (b);
+ else if (!b)
+ return g_strdupv (a);
+
+ c = g_new0 (gchar *, g_strv_length (a) + g_strv_length (b) + 1);
+ p = c;
+
+ while (*a) {
+ *p = g_strdup (*a);
+ p += 1;
+ a += 1;
+ }
+ while (*b) {
+ *p = g_strdup (*b);
+ p += 1;
+ b += 1;
+ }
+
+ return c;
+}
+
static void
add_xkb_options (GsdKeyboardManager *manager,
- XkbRF_VarDefsRec *xkb_var_defs)
+ XkbRF_VarDefsRec *xkb_var_defs,
+ gchar **extra_options)
{
gchar **options;
+ gchar **settings_options;
- options = g_settings_get_strv (manager->priv->input_sources_settings,
- KEY_KEYBOARD_OPTIONS);
+ settings_options = g_settings_get_strv (manager->priv->input_sources_settings,
+ KEY_KEYBOARD_OPTIONS);
+ options = append_options (settings_options, extra_options);
+ g_strfreev (settings_options);
free (xkb_var_defs->options);
xkb_var_defs->options = build_xkb_options_string (options);
@@ -768,7 +891,8 @@ add_xkb_options (GsdKeyboardManager *manager,
static void
apply_xkb_settings (GsdKeyboardManager *manager,
const gchar *layout,
- const gchar *variant)
+ const gchar *variant,
+ gchar **options)
{
XkbRF_RulesRec *xkb_rules;
XkbRF_VarDefsRec *xkb_var_defs;
@@ -776,7 +900,7 @@ apply_xkb_settings (GsdKeyboardManager *manager,
gnome_xkb_info_get_var_defs (&rules_file_path, &xkb_var_defs);
- add_xkb_options (manager, xkb_var_defs);
+ add_xkb_options (manager, xkb_var_defs, options);
replace_layout_and_variant (manager, xkb_var_defs, layout, variant);
gdk_error_trap_push ();
@@ -830,8 +954,9 @@ apply_input_sources_settings (GSettings *settings,
guint n_sources;
const gchar *type = NULL;
const gchar *id = NULL;
- const gchar *layout = NULL;
- const gchar *variant = NULL;
+ gchar *layout = NULL;
+ gchar *variant = NULL;
+ gchar **options = NULL;
sources = g_settings_get_value (priv->input_sources_settings, KEY_INPUT_SOURCES);
current = g_settings_get_uint (priv->input_sources_settings, KEY_CURRENT_INPUT_SOURCE);
@@ -854,7 +979,11 @@ apply_input_sources_settings (GSettings *settings,
g_variant_get_child (sources, current, "(&s&s)", &type, &id);
if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) {
- gnome_xkb_info_get_layout_info (priv->xkb_info, id, NULL, NULL, &layout, &variant);
+ const gchar *l, *v;
+ gnome_xkb_info_get_layout_info (priv->xkb_info, id, NULL, NULL, &l, &v);
+
+ layout = g_strdup (l);
+ variant = g_strdup (v);
if (!layout || !layout[0]) {
g_warning ("Couldn't find XKB input source '%s'", id);
@@ -877,8 +1006,14 @@ apply_input_sources_settings (GSettings *settings,
goto exit; /* we'll be called again when ibus is up and running */
if (engine_desc) {
- layout = ibus_engine_desc_get_layout (engine_desc);
- variant = "";
+ const gchar *ibus_layout;
+ ibus_layout = ibus_engine_desc_get_layout (engine_desc);
+
+ if (ibus_layout) {
+ layout = layout_from_ibus_layout (ibus_layout);
+ variant = variant_from_ibus_layout (ibus_layout);
+ options = options_from_ibus_layout (ibus_layout);
+ }
} else {
g_warning ("Couldn't find IBus input source '%s'", id);
goto exit;
@@ -894,8 +1029,11 @@ apply_input_sources_settings (GSettings *settings,
}
exit:
- apply_xkb_settings (manager, layout, variant);
+ apply_xkb_settings (manager, layout, variant, options);
g_variant_unref (sources);
+ g_free (layout);
+ g_free (variant);
+ g_strfreev (options);
/* Prevent individual "changed" signal invocations since we
don't need them. */
return TRUE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]