Add layout_variant and layout_option in IBusEngineDesc for XKB.
authorfujiwarat <takao.fujiwara1@gmail.com>
Tue, 16 Oct 2012 01:28:26 +0000 (10:28 +0900)
committerfujiwarat <takao.fujiwara1@gmail.com>
Tue, 16 Oct 2012 01:28:26 +0000 (10:28 +0900)
TEST=Manually

Review URL: https://codereview.appspot.com/6586075

ibus/enginedesc.py
src/ibusenginedesc.c
src/ibusenginedesc.h
src/ibusserializable.h
tools/main.vala
ui/gtk3/panel.vala

index 055a3a0..00fbade 100644 (file)
@@ -31,7 +31,10 @@ from serializable import *
 class EngineDesc(Serializable):
     __gtype_name__ = "PYIBusEngineDesc"
     __NAME__ = "IBusEngineDesc"
-    def __init__(self, name="", longname="", description="", language="", license="", author="", icon="", layout="", hotkeys="", rank=0, symbol="", setup=""):
+    def __init__(self, name="", longname="", description="", language="",
+                 license="", author="", icon="", layout="us", hotkeys="",
+                 rank=0, symbol="", setup="",
+                 layout_variant="", layout_option=""):
         super(EngineDesc, self).__init__()
         self.__name = name
         self.__longname = longname
@@ -41,6 +44,8 @@ class EngineDesc(Serializable):
         self.__author = author
         self.__icon = icon
         self.__layout = layout
+        self.__layout_variant = layout_variant
+        self.__layout_option = layout_option
         self.__rank = rank
         self.__hotkeys = hotkeys
         self.__symbol = symbol
@@ -70,6 +75,12 @@ class EngineDesc(Serializable):
     def get_layout(self):
         return self.__layout
 
+    def get_layout_variant(self):
+        return self.__layout_variant
+
+    def get_layout_option(self):
+        return self.__layout_option
+
     def get_rank(self):
         return self.__rank
 
@@ -82,18 +93,20 @@ class EngineDesc(Serializable):
     def get_setup(self):
         return self.__setup
 
-    name        = property(get_name)
-    longname    = property(get_longname)
-    description = property(get_description)
-    language    = property(get_language)
-    license     = property(get_license)
-    author      = property(get_author)
-    icon        = property(get_icon)
-    layout      = property(get_layout)
-    rank        = property(get_rank)
-    hotkeys     = property(get_hotkeys)
-    symbol      = property(get_symbol)
-    setup       = property(get_setup)
+    name                = property(get_name)
+    longname            = property(get_longname)
+    description         = property(get_description)
+    language            = property(get_language)
+    license             = property(get_license)
+    author              = property(get_author)
+    icon                = property(get_icon)
+    layout              = property(get_layout)
+    layout_variant      = property(get_layout_variant)
+    layout_option       = property(get_layout_option)
+    rank                = property(get_rank)
+    hotkeys             = property(get_hotkeys)
+    symbol              = property(get_symbol)
+    setup               = property(get_setup)
 
     def serialize(self, struct):
         super(EngineDesc, self).serialize(struct)
@@ -106,24 +119,32 @@ class EngineDesc(Serializable):
         struct.append(dbus.String(self.__icon))
         struct.append(dbus.String(self.__layout))
         struct.append(dbus.UInt32(self.__rank))
+        # Keep the serialize order.
         struct.append(dbus.String(self.__hotkeys))
         struct.append(dbus.String(self.__symbol))
         struct.append(dbus.String(self.__setup))
+        struct.append(dbus.String(self.__layout_variant))
+        struct.append(dbus.String(self.__layout_option))
 
     def deserialize(self, struct):
         super(EngineDesc, self).deserialize(struct)
-        self.__name = struct.pop(0)
-        self.__longname = struct.pop(0)
-        self.__description = struct.pop(0)
-        self.__language = struct.pop(0)
-        self.__license = struct.pop(0)
-        self.__author = struct.pop(0)
-        self.__icon = struct.pop(0)
-        self.__layout = struct.pop(0)
-        self.__rank = struct.pop(0)
-        self.__hotkeys = struct.pop(0)
-        self.__symbol = struct.pop(0)
-        self.__setup  = struct.pop(0)
+        self.__name             = struct.pop(0)
+        self.__longname         = struct.pop(0)
+        self.__description      = struct.pop(0)
+        self.__language         = struct.pop(0)
+        self.__license          = struct.pop(0)
+        self.__author           = struct.pop(0)
+        self.__icon             = struct.pop(0)
+        self.__layout           = struct.pop(0)
+        self.__rank             = struct.pop(0)
+        # Keep the serialize order.
+        self.__hotkeys          = struct.pop(0)
+        self.__symbol           = struct.pop(0)
+        self.__setup            = struct.pop(0)
+        if len(struct) < 2:
+            return
+        self.__layout_variant   = struct.pop(0)
+        self.__layout_option    = struct.pop(0)
 
 def test():
     engine = EngineDesc("Hello", "", "", "", "", "", "", "", "", 0, "", "")
index 48ecb07..d3247e2 100644 (file)
@@ -37,6 +37,8 @@ enum {
     PROP_AUTHOR,
     PROP_ICON,
     PROP_LAYOUT,
+    PROP_LAYOUT_VARIANT,
+    PROP_LAYOUT_OPTION,
     PROP_RANK,
     PROP_HOTKEYS,
     PROP_SYMBOL,
@@ -54,6 +56,8 @@ struct _IBusEngineDescPrivate {
     gchar      *author;
     gchar      *icon;
     gchar      *layout;
+    gchar      *layout_variant;
+    gchar      *layout_option;
     guint       rank;
     gchar      *hotkeys;
     gchar      *symbol;
@@ -210,6 +214,32 @@ ibus_engine_desc_class_init (IBusEngineDescClass *class)
                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
     /**
+     * IBusEngineDesc:layout-variant:
+     *
+     * The keyboard variant of engine description
+     */
+    g_object_class_install_property (gobject_class,
+                    PROP_LAYOUT_VARIANT,
+                    g_param_spec_string ("layout-variant",
+                        "description keyboard variant",
+                        "The keyboard variant of engine description",
+                        "",
+                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+    /**
+     * IBusEngineDesc:layout-option:
+     *
+     * The keyboard option of engine description
+     */
+    g_object_class_install_property (gobject_class,
+                    PROP_LAYOUT_OPTION,
+                    g_param_spec_string ("layout-option",
+                        "description keyboard option",
+                        "The keyboard option of engine description",
+                        "",
+                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+    /**
      * IBusEngineDesc:rank:
      *
      * The rank of engine description
@@ -277,6 +307,8 @@ ibus_engine_desc_init (IBusEngineDesc *desc)
     desc->priv->author = NULL;
     desc->priv->icon = NULL;
     desc->priv->layout = NULL;
+    desc->priv->layout_variant = NULL;
+    desc->priv->layout_option = NULL;
     desc->priv->rank = 0;
     desc->priv->hotkeys = NULL;
     desc->priv->symbol = NULL;
@@ -294,6 +326,8 @@ ibus_engine_desc_destroy (IBusEngineDesc *desc)
     g_free (desc->priv->author);
     g_free (desc->priv->icon);
     g_free (desc->priv->layout);
+    g_free (desc->priv->layout_variant);
+    g_free (desc->priv->layout_option);
     g_free (desc->priv->hotkeys);
     g_free (desc->priv->symbol);
     g_free (desc->priv->setup);
@@ -340,6 +374,14 @@ ibus_engine_desc_set_property (IBusEngineDesc *desc,
         g_assert (desc->priv->layout == NULL);
         desc->priv->layout = g_value_dup_string (value);
         break;
+    case PROP_LAYOUT_VARIANT:
+        g_assert (desc->priv->layout_variant == NULL);
+        desc->priv->layout_variant = g_value_dup_string (value);
+        break;
+    case PROP_LAYOUT_OPTION:
+        g_assert (desc->priv->layout_option == NULL);
+        desc->priv->layout_option = g_value_dup_string (value);
+        break;
     case PROP_RANK:
         desc->priv->rank = g_value_get_uint (value);
         break;
@@ -391,6 +433,12 @@ ibus_engine_desc_get_property (IBusEngineDesc *desc,
     case PROP_LAYOUT:
         g_value_set_string (value, ibus_engine_desc_get_layout (desc));
         break;
+    case PROP_LAYOUT_VARIANT:
+        g_value_set_string (value, ibus_engine_desc_get_layout_variant (desc));
+        break;
+    case PROP_LAYOUT_OPTION:
+        g_value_set_string (value, ibus_engine_desc_get_layout_option (desc));
+        break;
     case PROP_RANK:
         g_value_set_uint (value, ibus_engine_desc_get_rank (desc));
         break;
@@ -432,9 +480,12 @@ ibus_engine_desc_serialize (IBusEngineDesc  *desc,
     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->icon));
     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->layout));
     g_variant_builder_add (builder, "u", desc->priv->rank);
+    /* The serialized order should be kept. */
     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->hotkeys));
     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->symbol));
     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->setup));
+    g_variant_builder_add (builder, "s", NOTNULL (desc->priv->layout_variant));
+    g_variant_builder_add (builder, "s", NOTNULL (desc->priv->layout_option));
 #undef NOTNULL
 
     return TRUE;
@@ -462,9 +513,14 @@ ibus_engine_desc_deserialize (IBusEngineDesc *desc,
     g_variant_get_child (variant, retval++, "s", &desc->priv->icon);
     g_variant_get_child (variant, retval++, "s", &desc->priv->layout);
     g_variant_get_child (variant, retval++, "u", &desc->priv->rank);
+    /* The serialized order should be kept. */
     g_variant_get_child (variant, retval++, "s", &desc->priv->hotkeys);
     g_variant_get_child (variant, retval++, "s", &desc->priv->symbol);
     g_variant_get_child (variant, retval++, "s", &desc->priv->setup);
+    if (g_variant_n_children (variant) < retval + 2)
+        return retval;
+    g_variant_get_child (variant, retval++, "s", &desc->priv->layout_variant);
+    g_variant_get_child (variant, retval++, "s", &desc->priv->layout_option);
 
     return retval;
 }
@@ -487,6 +543,8 @@ ibus_engine_desc_copy (IBusEngineDesc       *dest,
     dest->priv->author           = g_strdup (src->priv->author);
     dest->priv->icon             = g_strdup (src->priv->icon);
     dest->priv->layout           = g_strdup (src->priv->layout);
+    dest->priv->layout_variant   = g_strdup (src->priv->layout_variant);
+    dest->priv->layout_option    = g_strdup (src->priv->layout_option);
     dest->priv->rank             = src->priv->rank;
     dest->priv->hotkeys          = g_strdup (src->priv->hotkeys);
     dest->priv->symbol           = g_strdup (src->priv->symbol);
@@ -527,6 +585,8 @@ ibus_engine_desc_output (IBusEngineDesc *desc,
     OUTPUT_ENTRY_1(author);
     OUTPUT_ENTRY_1(icon);
     OUTPUT_ENTRY_1(layout);
+    OUTPUT_ENTRY_1(layout_variant);
+    OUTPUT_ENTRY_1(layout_option);
     OUTPUT_ENTRY_1(hotkeys);
     OUTPUT_ENTRY_1(symbol);
     OUTPUT_ENTRY_1(setup);
@@ -562,6 +622,8 @@ ibus_engine_desc_parse_xml_node (IBusEngineDesc *desc,
         PARSE_ENTRY_1(author);
         PARSE_ENTRY_1(icon);
         PARSE_ENTRY_1(layout);
+        PARSE_ENTRY_1(layout_variant);
+        PARSE_ENTRY_1(layout_option);
         PARSE_ENTRY_1(hotkeys);
         PARSE_ENTRY_1(symbol);
         PARSE_ENTRY_1(setup);
@@ -591,6 +653,8 @@ IBUS_ENGINE_DESC_GET_PROPERTY (license, const gchar *)
 IBUS_ENGINE_DESC_GET_PROPERTY (author, const gchar *)
 IBUS_ENGINE_DESC_GET_PROPERTY (icon, const gchar *)
 IBUS_ENGINE_DESC_GET_PROPERTY (layout, const gchar *)
+IBUS_ENGINE_DESC_GET_PROPERTY (layout_variant, const gchar *)
+IBUS_ENGINE_DESC_GET_PROPERTY (layout_option, const gchar *)
 IBUS_ENGINE_DESC_GET_PROPERTY (rank, guint)
 IBUS_ENGINE_DESC_GET_PROPERTY (hotkeys, const gchar *)
 IBUS_ENGINE_DESC_GET_PROPERTY (symbol, const gchar *)
@@ -641,6 +705,8 @@ ibus_engine_desc_new_varargs (const gchar *first_property_name, ...)
     g_assert (desc->priv->author);
     g_assert (desc->priv->icon);
     g_assert (desc->priv->layout);
+    g_assert (desc->priv->layout_variant);
+    g_assert (desc->priv->layout_option);
     g_assert (desc->priv->hotkeys);
     g_assert (desc->priv->symbol);
     g_assert (desc->priv->setup);
index 928743e..35a18bf 100644 (file)
@@ -86,6 +86,8 @@ typedef struct _IBusEngineDescClass IBusEngineDescClass;
  * author: Author of the input method engine.
  * icon: Icon file of this engine.
  * layout: Keyboard layout
+ * layout_variant: Keyboard variant
+ * layout_option: Keyboard option
  * rank: Preference rank among engines, the highest ranked IME will put in
  * the front.
  * hotkeys: One or more hotkeys for switching to this engine, separated by
@@ -231,6 +233,26 @@ const gchar     *ibus_engine_desc_get_icon      (IBusEngineDesc *info);
 const gchar     *ibus_engine_desc_get_layout    (IBusEngineDesc *info);
 
 /**
+ * ibus_engine_desc_get_layout_variant:
+ * @info: An IBusEngineDesc
+ * @returns: keyboard variant property in IBusEngineDesc
+ *
+ * Return the keyboard variant property in IBusEngineDesc. It should not be freed.
+ */
+const gchar     *ibus_engine_desc_get_layout_variant
+                                                (IBusEngineDesc *info);
+
+/**
+ * ibus_engine_desc_get_layout_option:
+ * @info: An IBusEngineDesc
+ * @returns: keyboard option property in IBusEngineDesc
+ *
+ * Return the keyboard option property in IBusEngineDesc. It should not be freed.
+ */
+const gchar     *ibus_engine_desc_get_layout_option
+                                                (IBusEngineDesc *info);
+
+/**
  * ibus_engine_desc_get_rank:
  * @info: An IBusEngineDesc
  * @returns: rank property in IBusEngineDesc
index 742aeb6..c7bcd6c 100644 (file)
@@ -233,7 +233,8 @@ void                 ibus_serializable_remove_qattachment
 /**
  * ibus_serializable_copy:
  * @serializable: An #IBusSerializable.
- * @returns: A newly allocated clone object; or %NULL if @object is not serializable.
+ * @returns: (transfer none): A newly allocated clone object; or %NULL
+ *     if @object is not serializable.
  *
  * Clone an #IBusSerializable.
  * The copy method should be implemented in extended class.
@@ -257,7 +258,7 @@ GVariant            *ibus_serializable_serialize        (IBusSerializable   *ser
 /**
  * ibus_serializable_deserialize:
  * @variant: A #GVariant.
- * @returns: The deserialized #IBusSerializable.
+ * @returns: (transfer none): The deserialized #IBusSerializable.
  *
  * Deserialize a #GVariant to an #IBusSerializable/
  * The deserialize method should be implemented in extended class.
index ce3fe47..d053590 100644 (file)
@@ -88,6 +88,56 @@ int list_engine(string[] argv) {
     return Posix.EXIT_SUCCESS;
 }
 
+private int exec_setxkbmap(IBus.EngineDesc engine) {
+    string layout = engine.get_layout();
+    string variant = engine.get_layout_variant();
+    string option = engine.get_layout_option();
+    string standard_error = null;
+    int exit_status = 0;
+    string[] args = { "setxkbmap" };
+
+    if (layout != null && layout != "" && layout != "default") {
+        args += "-layout";
+        args += layout;
+    }
+    if (variant != null && variant != "" && variant != "default") {
+        args += "-variant";
+        args += variant;
+    }
+    if (option != null && option != "" && option != "default") {
+        /*TODO: Need to get the session XKB options */
+        args += "-option";
+        args += "-option";
+        args += option;
+    }
+
+    if (args.length == 1) {
+        return Posix.EXIT_FAILURE;
+    }
+
+    try {
+        if (!GLib.Process.spawn_sync(null, args, null,
+                                     GLib.SpawnFlags.SEARCH_PATH,
+                                     null, null,
+                                     out standard_error,
+                                     out exit_status)) {
+            warning("Switch xkb layout to %s failed.",
+                    engine.get_layout());
+            return Posix.EXIT_FAILURE;
+        }
+    } catch (GLib.SpawnError e) {
+        warning("Execute setxkbmap failed: %s", e.message);
+        return Posix.EXIT_FAILURE;
+    }
+
+    if (exit_status != 0) {
+        warning("Execute setxkbmap failed: %s", standard_error ?? "(null)");
+        return Posix.EXIT_FAILURE;
+    }
+
+    return Posix.EXIT_SUCCESS;
+}
+
 int get_set_engine(string[] argv) {
     var bus = get_bus();
     string engine = null;
@@ -114,18 +164,7 @@ int get_set_engine(string[] argv) {
         return Posix.EXIT_FAILURE;
     }
 
-    string cmdline = "setxkbmap %s".printf(desc.get_layout());
-    try {
-        if (!GLib.Process.spawn_command_line_sync(cmdline)) {
-            stderr.printf(_("Switch xkb layout to %s failed."),
-                          desc.get_layout());
-            return Posix.EXIT_FAILURE;
-        }
-    } catch (GLib.SpawnError e) {
-        stderr.printf("Execute setxkbmap failed: %s", e.message);
-        return Posix.EXIT_FAILURE;
-    }
-    return Posix.EXIT_SUCCESS;
+    return exec_setxkbmap(desc);
 }
 
 int message_watch(string[] argv) {
index 40079ec..6f579ac 100644 (file)
@@ -211,6 +211,51 @@ class Panel : IBus.PanelService {
         set_custom_font();
     }
 
+    private void exec_setxkbmap(IBus.EngineDesc engine) {
+        string layout = engine.get_layout();
+        string variant = engine.get_layout_variant();
+        string option = engine.get_layout_option();
+        string standard_error = null;
+        int exit_status = 0;
+        string[] args = { "setxkbmap" };
+
+        if (layout != null && layout != "" && layout != "default") {
+            args += "-layout";
+            args += layout;
+        }
+        if (variant != null && variant != "" && variant != "default") {
+            args += "-variant";
+            args += variant;
+        }
+        if (option != null && option != "" && option != "default") {
+            /*TODO: Need to get the session XKB options */
+            args += "-option";
+            args += "-option";
+            args += option;
+        }
+
+        if (args.length == 1) {
+            return;
+        }
+
+        try {
+            if (!GLib.Process.spawn_sync(null, args, null,
+                                         GLib.SpawnFlags.SEARCH_PATH,
+                                         null, null,
+                                         out standard_error,
+                                         out exit_status)) {
+                warning("Switch xkb layout to %s failed.",
+                        engine.get_layout());
+            }
+        } catch (GLib.SpawnError e) {
+            warning("Execute setxkbmap failed: %s", e.message);
+        }
+
+        if (exit_status != 0) {
+            warning("Execute setxkbmap failed: %s", standard_error ?? "(null)");
+        }
+    }
+
     private void switch_engine(int i, bool force = false) {
         GLib.assert(i >= 0 && i < m_engines.length);
 
@@ -225,15 +270,7 @@ class Panel : IBus.PanelService {
             return;
         }
         // set xkb layout
-        string cmdline = "setxkbmap %s".printf(engine.get_layout());
-        try {
-            if (!GLib.Process.spawn_command_line_sync(cmdline)) {
-                warning("Switch xkb layout to %s failed.",
-                    engine.get_layout());
-            }
-        } catch (GLib.SpawnError e) {
-            warning("Execute setxkbmap failed: %s", e.message);
-        }
+        exec_setxkbmap(engine);
     }
 
     private void config_value_changed_cb(IBus.Config config,