Sophie

Sophie

distrib > Fedora > 17 > x86_64 > by-pkgid > cfb2a44530008ccbb467fb595101b149 > files > 5

ibus-m17n-1.3.4-3.fc17.src.rpm

From 98ae1c6dbd279e17ef3c20493a37c959f1b1e61f Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@unixuser.org>
Date: Fri, 30 Mar 2012 12:36:08 +0900
Subject: [PATCH 4/4] Add virtual keyboard support.

---
 configure.ac          |   17 +++
 src/Makefile.am       |    5 +
 src/default.xml.in.in |  111 +++++++++++++++++++
 src/engine.c          |  289 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/m17nutil.c        |   10 ++-
 src/m17nutil.h        |    3 +
 6 files changed, 434 insertions(+), 1 deletions(-)

Index: ibus-m17n-1.3.4/configure.ac
===================================================================
--- ibus-m17n-1.3.4.orig/configure.ac
+++ ibus-m17n-1.3.4/configure.ac
@@ -88,6 +88,23 @@ fi
 
 AM_CONDITIONAL([HAVE_GTK],[test x$with_gtk != xno])
 
+dnl check eekboard for virtual keyboard
+AC_MSG_CHECKING([whether you enable eekboard])
+AC_ARG_ENABLE(eekboard,
+              AS_HELP_STRING([--enable-eekboard=no/yes],
+                             [Enable eekboard default=yes]),
+              enable_eekboard=$enableval,
+              enable_eekboard=yes)
+
+if test x$enable_eekboard = xyes; then
+  PKG_CHECK_MODULES([EEKBOARD], [eekboard-0.90], , enable_xtest=no)
+  if test x$enable_eekboard = xyes; then
+    AC_DEFINE([HAVE_EEKBOARD], [1], [Define if eekboard is found])
+  fi
+fi
+AM_CONDITIONAL(ENABLE_EEKBOARD, [test x$enable_eekboard = xyes])
+AC_MSG_RESULT($enable_eekboard)
+
 # check if minput_list, which is available in m17n-lib 1.6.2+ (CVS)
 save_CFLAGS="$CFLAGS"
 save_LIBS="$LIBS"
Index: ibus-m17n-1.3.4/src/Makefile.am
===================================================================
--- ibus-m17n-1.3.4.orig/src/Makefile.am
+++ ibus-m17n-1.3.4/src/Makefile.am
@@ -65,10 +65,15 @@ ibus_engine_m17n_SOURCES = \
 	engine.c \
 	engine.h \
 	$(NULL)
+ibus_engine_m17n_CFLAGS = \
+	@EEKBOARD_CFLAGS@ \
+	$(AM_CFLAGS) \
+	$(NULL)
 ibus_engine_m17n_LDADD = \
 	libm17ncommon.la \
 	@IBUS_LIBS@ \
 	@M17N_LIBS@ \
+	@EEKBOARD_LIBS@ \
 	$(NULL)
 
 if HAVE_GTK
Index: ibus-m17n-1.3.4/src/default.xml.in.in
===================================================================
--- ibus-m17n-1.3.4.orig/src/default.xml.in.in
+++ ibus-m17n-1.3.4/src/default.xml.in.in
@@ -11,6 +11,7 @@
 		<rank>0</rank>
 		<preedit-highlight>FALSE</preedit-highlight>
 		<symbol></symbol>
+		<virtual-keyboard>us</virtual-keyboard>
 	</engine>
 	<!-- Blacklist some engines -->
 	<!-- kbd engines are duplicate of xkb engines -->
@@ -440,4 +441,114 @@
 		<name>m17n:zh:tonepy*</name>
 		<symbol>调</symbol>
 	</engine>
+
+	<!-- Virtual keyboard. -->
+	<engine>
+		<name>m17n:ar:kbd</name>
+		<virtual-keyboard>ar,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:be:kbd</name>
+		<virtual-keyboard>be,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:fa:kbd</name>
+		<virtual-keyboard>fa,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:he:kbd</name>
+		<virtual-keyboard>he,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:kk:kbd</name>
+		<virtual-keyboard>kk,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:ks:kbd</name>
+		<virtual-keyboard>ks,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:my:kbd</name>
+		<virtual-keyboard>my,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:ru:kbd</name>
+		<virtual-keyboard>ru,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:ua:kbd</name>
+		<virtual-keyboard>ua,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:ug:kbd</name>
+		<virtual-keyboard>ug,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:be:kbd</name>
+		<virtual-keyboard>be,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:th:*</name>
+		<virtual-keyboard>th,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:zh:bopomofo</name>
+		<virtual-keyboard>zh-bopomofo,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:as:inscript</name>
+		<virtual-keyboard>as-inscript,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:bn:inscript</name>
+		<virtual-keyboard>bn-inscript,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:gu:inscript</name>
+		<virtual-keyboard>gu-inscript,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:hi:inscript</name>
+		<virtual-keyboard>hi-inscript,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:kn:inscript</name>
+		<virtual-keyboard>kn-inscript,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:ks:inscript</name>
+		<virtual-keyboard>kn-inscript,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:mai:inscript</name>
+		<virtual-keyboard>mai-inscript,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:ml:inscript</name>
+		<virtual-keyboard>ml-inscript,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:mr:inscript</name>
+		<virtual-keyboard>mr-inscript,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:or:inscript</name>
+		<virtual-keyboard>or-inscript,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:pa:inscript</name>
+		<virtual-keyboard>pa-inscript,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:sd:inscript</name>
+		<virtual-keyboard>sd-inscript,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:ta:inscript</name>
+		<virtual-keyboard>ta-inscript,us</virtual-keyboard>
+	</engine>
+	<engine>
+		<name>m17n:te:inscript</name>
+		<virtual-keyboard>te-inscript,us</virtual-keyboard>
+	</engine>
 </engines>
Index: ibus-m17n-1.3.4/src/engine.c
===================================================================
--- ibus-m17n-1.3.4.orig/src/engine.c
+++ ibus-m17n-1.3.4/src/engine.c
@@ -7,6 +7,9 @@
 #include <m17n.h>
 #include <string.h>
 #include "m17nutil.h"
+#ifdef HAVE_EEKBOARD
+#include <eekboard/eekboard-client.h>
+#endif  /* HAVE_EEKBOARD */
 #include "engine.h"
 
 typedef struct _IBusM17NEngine IBusM17NEngine;
@@ -18,10 +21,12 @@ struct _IBusM17NEngine {
     /* members */
     MInputContext *context;
     IBusLookupTable *table;
+
     IBusProperty    *status_prop;
 #ifdef HAVE_SETUP
     IBusProperty    *setup_prop;
 #endif  /* HAVE_SETUP */
+    IBusProperty    *virtkbd_prop;
     IBusPropList    *prop_list;
 };
 
@@ -35,9 +40,16 @@ struct _IBusM17NEngineClass {
     gint preedit_underline;
     IBusPreeditFocusMode preedit_focus_mode;
     gint lookup_table_orientation;
+    gchar *virtual_keyboard;
 
     gchar *title;
     MInputMethod *im;
+
+#ifdef HAVE_EEKBOARD
+    EekboardContext *econtext;
+    GSList *keyboards;
+    GSList *keyboards_head;
+#endif  /* HAVE_EEKBOARD */
 };
 
 /* functions prototype */
@@ -101,13 +113,184 @@ static IBusEngineClass *parent_class = N
 
 static IBusConfig      *config = NULL;
 
+#ifdef HAVE_EEKBOARD
+static EekboardClient  *eekboard = NULL;
+
+static void
+client_destroyed_cb (EekboardClient *client,
+                     gpointer        user_data)
+{
+    if (eekboard) {
+        g_object_unref (eekboard);
+        eekboard = NULL;
+    }
+}
+
+static void
+context_destroyed_cb (EekboardContext *context,
+                      IBusM17NEngineClass *klass)
+{
+    if (klass->econtext) {
+        g_object_unref (klass->econtext);
+        klass->econtext = NULL;
+    }
+}
+
+static EekboardContext *
+create_context (IBusM17NEngineClass *klass)
+{
+    EekboardContext *context = eekboard_client_create_context (eekboard,
+                                                               "ibus-m17n",
+                                                               NULL);
+    g_signal_connect (context, "destroyed",
+                      G_CALLBACK (context_destroyed_cb), klass);
+
+    g_slist_free (klass->keyboards);
+    klass->keyboards = NULL;
+
+    gchar **keyboards = g_strsplit (klass->virtual_keyboard, ",", -1);
+    gchar **p;
+
+    for (p = keyboards; *p; p++) {
+        guint keyboard = eekboard_context_add_keyboard (context,
+                                                        g_strstrip (*p),
+                                                        NULL);
+        klass->keyboards = g_slist_prepend (klass->keyboards,
+                                            GUINT_TO_POINTER (keyboard));
+    }
+    g_strfreev (keyboards);
+
+    klass->keyboards = g_slist_reverse (klass->keyboards);
+    klass->keyboards_head = klass->keyboards;
+
+    eekboard_context_set_keyboard (context,
+                                   GPOINTER_TO_UINT (klass->keyboards_head->data),
+                                   NULL);
+    return context;
+}
+
+static void
+key_activated_cb (EekboardContext *context,
+                  guint            keycode,
+                  EekSymbol       *symbol,
+                  guint            modifiers,
+                  IBusM17NEngine  *m17n)
+{
+    IBusM17NEngineClass *klass = (IBusM17NEngineClass *) G_OBJECT_GET_CLASS (m17n);
+    IBusEngine *engine = IBUS_ENGINE (m17n);
+
+    if (EEK_IS_TEXT (symbol)) {
+        const gchar *string;
+        IBusText *text;
+
+        string = eek_text_get_text (EEK_TEXT (symbol));
+        text = ibus_text_new_from_static_string (string);
+        ibus_engine_commit_text (engine, text);
+    } else if (EEK_IS_KEYSYM (symbol)) {
+        guint keyval = eek_keysym_get_xkeysym (EEK_KEYSYM (symbol));
+        ibus_engine_forward_key_event (engine,
+                                       keyval,
+                                       0,
+                                       modifiers);
+        ibus_engine_forward_key_event (engine,
+                                       keyval,
+                                       0,
+                                       modifiers | IBUS_RELEASE_MASK);
+    } else if (g_strcmp0 (eek_symbol_get_name (symbol),
+                          "cycle-keyboard") == 0) {
+        klass->keyboards_head = g_slist_next (klass->keyboards_head);
+        if (klass->keyboards_head == NULL)
+            klass->keyboards_head = klass->keyboards;
+        eekboard_context_set_keyboard (klass->econtext,
+                                       GPOINTER_TO_UINT (klass->keyboards_head->data),
+                                       NULL);
+    }
+}
+
+static void
+init_eekboard ()
+{
+    GDBusConnection *connection;
+    GError *error;
+
+    error = NULL;
+    connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+    if (connection == NULL) {
+        g_printerr ("Can't connect to the session bus: %s\n",
+                    error->message);
+        g_error_free (error);
+        return;
+    }
+
+    eek_init ();
+
+    eekboard = eekboard_client_new (connection, NULL);
+    g_object_unref (connection);
+
+    g_signal_connect (eekboard, "destroyed",
+                      G_CALLBACK (client_destroyed_cb), NULL);
+}
+#endif  /* HAVE_EEKBOARD */
+
+static GType ibus_m17n_virtual_keyboard_implementation_type = 0;
+
+typedef enum {
+    IBUS_M17N_VIRTUAL_KEYBOARD_IMPLEMENTATION_EEKBOARD,
+    IBUS_M17N_VIRTUAL_KEYBOARD_IMPLEMENTATION_IOK
+} IBusM17NVirtualKeyboardImplementation;
+
+#ifdef HAVE_EEKBOARD
+static IBusM17NVirtualKeyboardImplementation virtual_keyboard_implementation =
+    IBUS_M17N_VIRTUAL_KEYBOARD_IMPLEMENTATION_EEKBOARD;
+#else
+static IBusM17NVirtualKeyboardImplementation virtual_keyboard_implementation =
+    IBUS_M17N_VIRTUAL_KEYBOARD_IMPLEMENTATION_IOK;
+#endif
+
 void
 ibus_m17n_init (IBusBus *bus)
 {
+    static const GEnumValue evalues[] = {
+        { IBUS_M17N_VIRTUAL_KEYBOARD_IMPLEMENTATION_EEKBOARD,
+          "IBUS_M17N_VIRTUAL_KEYBOARD_IMPLEMENTATION_EEKBOARD",
+          "eekboard" },
+        { IBUS_M17N_VIRTUAL_KEYBOARD_IMPLEMENTATION_IOK,
+          "IBUS_M17N_VIRTUAL_KEYBOARD_IMPLEMENTATION_IOK",
+          "iok" }
+    };
+
+    GVariant *values;
+
     config = ibus_bus_get_config (bus);
     if (config)
         g_object_ref_sink (config);
     ibus_m17n_init_common ();
+
+    ibus_m17n_virtual_keyboard_implementation_type =
+        g_enum_register_static ("IBusM17NVirtualKeyboardImplementation",
+                                evalues);
+    values = ibus_config_get_values (config, "engine/M17N");
+    if (values != NULL) {
+        GVariant *value =
+            g_variant_lookup_value (values,
+                                    "virtual_keyboard_implementation",
+                                    G_VARIANT_TYPE_STRING);
+        if (value != NULL) {
+            GEnumClass *eclass = G_ENUM_CLASS (g_type_class_peek (ibus_m17n_virtual_keyboard_implementation_type));
+            GEnumValue *evalue = g_enum_get_value_by_nick (eclass, g_variant_get_string (value, NULL));
+            if (evalue != NULL) {
+                virtual_keyboard_implementation = evalue->value;
+            }
+        }
+    }
+
+    if (virtual_keyboard_implementation == IBUS_M17N_VIRTUAL_KEYBOARD_IMPLEMENTATION_EEKBOARD) {
+#ifdef HAVE_EEKBOARD
+        init_eekboard ();
+#else
+        g_warning ("eekboard is not supported");
+#endif  /* HAVE_EEKBOARD */
+    }
 }
 
 static gboolean
@@ -268,6 +451,7 @@ ibus_m17n_engine_class_init (IBusM17NEng
         IBUS_ENGINE_PREEDIT_COMMIT :
         IBUS_ENGINE_PREEDIT_CLEAR;
     klass->lookup_table_orientation = IBUS_ORIENTATION_SYSTEM;
+    klass->virtual_keyboard = engine_config->virtual_keyboard;
 
     ibus_m17n_engine_config_free (engine_config);
 
@@ -317,6 +501,11 @@ ibus_m17n_engine_class_init (IBusM17NEng
                       klass);
 
     klass->im = NULL;
+
+#if HAVE_EEKBOARD
+    if (eekboard)
+        klass->econtext = create_context (klass);
+#endif  /* HAVE_EEKBOARD */
 }
 
 static void
@@ -354,6 +543,7 @@ ibus_m17n_engine_init (IBusM17NEngine *m
 {
     IBusText* label;
     IBusText* tooltip;
+    IBusM17NEngineClass *klass = (IBusM17NEngineClass *) G_OBJECT_GET_CLASS (m17n);
 
     m17n->prop_list = ibus_prop_list_new ();
     g_object_ref_sink (m17n->prop_list);
@@ -386,6 +576,36 @@ ibus_m17n_engine_init (IBusM17NEngine *m
     ibus_prop_list_append (m17n->prop_list, m17n->setup_prop);
 #endif  /* HAVE_SETUP */
 
+    label = ibus_text_new_from_string ("Screen Keyboard");
+    tooltip = ibus_text_new_from_string ("Show screen keyboard");
+    m17n->virtkbd_prop = ibus_property_new ("virtual-keyboard",
+                                            PROP_TYPE_NORMAL,
+                                            label,
+                                            "input-keyboard",
+                                            tooltip,
+                                            TRUE,
+                                            FALSE,
+                                            PROP_STATE_UNCHECKED,
+                                            NULL);
+    g_object_ref_sink (m17n->virtkbd_prop);
+    ibus_prop_list_append (m17n->prop_list, m17n->virtkbd_prop);
+
+#ifdef HAVE_EEKBOARD
+    if (eekboard != NULL)
+        ibus_property_set_visible (m17n->virtkbd_prop, TRUE);
+    else
+#endif  /* HAVE_EEKBOARD */
+    {
+        gchar *lang = NULL, *name = NULL;
+        if (ibus_m17n_scan_class_name (G_OBJECT_CLASS_NAME (klass),
+                                       &lang,
+                                       &name) &&
+            g_str_has_prefix (name, "inscript"))
+            ibus_property_set_visible (m17n->virtkbd_prop, TRUE);
+        g_free (lang);
+        g_free (name);
+    }
+
     m17n->table = ibus_lookup_table_new (9, 0, TRUE, TRUE);
     g_object_ref_sink (m17n->table);
     m17n->context = NULL;
@@ -471,6 +691,11 @@ ibus_m17n_engine_destroy (IBusM17NEngine
     }
 #endif  /* HAVE_SETUP */
 
+    if (m17n->virtkbd_prop) {
+        g_object_unref (m17n->virtkbd_prop);
+        m17n->virtkbd_prop = NULL;
+    }
+
     if (m17n->table) {
         g_object_unref (m17n->table);
         m17n->table = NULL;
@@ -716,6 +941,14 @@ ibus_m17n_engine_enable (IBusEngine *eng
     /* Issue a dummy ibus_engine_get_surrounding_text() call to tell
        input context that we will use surrounding-text. */
     ibus_engine_get_surrounding_text (engine, NULL, NULL, NULL);
+
+#ifdef HAVE_EEKBOARD
+    if (eekboard) {
+        IBusM17NEngineClass *klass = (IBusM17NEngineClass *) G_OBJECT_GET_CLASS (m17n);
+        if (klass->econtext)
+            eekboard_client_push_context (eekboard, klass->econtext, NULL);
+    }
+#endif  /* HAVE_EEKBOARD */
 }
 
 static void
@@ -725,6 +958,14 @@ ibus_m17n_engine_disable (IBusEngine *en
 
     ibus_m17n_engine_focus_out (engine);
     parent_class->disable (engine);
+
+#ifdef HAVE_EEKBOARD
+    if (eekboard) {
+        IBusM17NEngineClass *klass = (IBusM17NEngineClass *) G_OBJECT_GET_CLASS (m17n);
+        if (klass->econtext)
+            eekboard_client_pop_context (eekboard, NULL);
+    }
+#endif  /* HAVE_EEKBOARD */
 }
 
 static void
@@ -772,6 +1013,7 @@ ibus_m17n_engine_property_activate (IBus
                                     guint        prop_state)
 {
     IBusM17NEngine *m17n = (IBusM17NEngine *) engine;
+    IBusM17NEngineClass *klass = (IBusM17NEngineClass *) G_OBJECT_GET_CLASS (m17n);
 
 #ifdef HAVE_SETUP
     if (g_strcmp0 (prop_name, "setup") == 0) {
@@ -787,6 +1029,53 @@ ibus_m17n_engine_property_activate (IBus
     }
 #endif  /* HAVE_SETUP */
 
+    if (g_strcmp0 (prop_name, "virtual-keyboard") == 0) {
+#ifdef HAVE_EEKBOARD
+        if (eekboard) {
+            if (klass->econtext == NULL) {
+                klass->econtext = create_context (klass);
+                eekboard_client_push_context (eekboard, klass->econtext, NULL);
+            }
+            g_signal_handlers_disconnect_by_func (klass->econtext,
+                                                  G_CALLBACK (key_activated_cb),
+                                                  m17n);
+            g_signal_connect (klass->econtext, "key-activated",
+                              G_CALLBACK (key_activated_cb), m17n);
+            eekboard_context_show_keyboard (klass->econtext, NULL);
+        } else
+#endif  /* HAVE_EEKBOARD */
+        {
+            gchar *lang = NULL, *name = NULL;
+
+            if (ibus_m17n_scan_class_name (G_OBJECT_CLASS_NAME (klass),
+                                           &lang,
+                                           &name) &&
+                g_str_has_prefix (name, "inscript")) {
+                gchar *argv[4];
+                GError *error;
+
+                argv[0] = "iok";
+                argv[1] = "-n";
+                argv[2] = lang;
+                argv[3] = NULL;
+                error = NULL;
+                if (!g_spawn_async (NULL,
+                                    argv,
+                                    NULL,
+                                    G_SPAWN_SEARCH_PATH,
+                                    NULL,
+                                    NULL,
+                                    NULL,
+                                    &error)) {
+                    g_warning ("can't spawn iok: %s", error->message);
+                    g_error_free (error);
+                }
+            }
+            g_free (lang);
+            g_free (name);
+        }
+    }
+
     parent_class->property_activate (engine, prop_name, prop_state);
 }
 
Index: ibus-m17n-1.3.4/src/m17nutil.c
===================================================================
--- ibus-m17n-1.3.4.orig/src/m17nutil.c
+++ ibus-m17n-1.3.4/src/m17nutil.c
@@ -18,7 +18,8 @@ typedef enum {
     ENGINE_CONFIG_SYMBOL_MASK = 1 << 1,
     ENGINE_CONFIG_LONGNAME_MASK = 1 << 2,
     ENGINE_CONFIG_LAYOUT_MASK = 1 << 3,
-    ENGINE_CONFIG_PREEDIT_HIGHLIGHT_MASK = 1 << 4
+    ENGINE_CONFIG_PREEDIT_HIGHLIGHT_MASK = 1 << 4,
+    ENGINE_CONFIG_VIRTUAL_KEYBOARD_MASK = 1 << 5
 } EngineConfigMask;
 
 struct _EngineConfigNode {
@@ -276,6 +277,8 @@ ibus_m17n_get_engine_config (const gchar
                 config->longname = cnode->config.longname;
             if (cnode->mask & ENGINE_CONFIG_PREEDIT_HIGHLIGHT_MASK)
                 config->preedit_highlight = cnode->config.preedit_highlight;
+            if (cnode->mask & ENGINE_CONFIG_VIRTUAL_KEYBOARD_MASK)
+                config->virtual_keyboard = cnode->config.virtual_keyboard;
             if (cnode->mask & ENGINE_CONFIG_LAYOUT_MASK)
                 config->layout = cnode->config.layout;
         }
@@ -333,6 +336,11 @@ ibus_m17n_engine_config_parse_xml_node (
             cnode->mask |= ENGINE_CONFIG_PREEDIT_HIGHLIGHT_MASK;
             continue;
         }
+        if (g_strcmp0 (sub_node->name , "virtual-keyboard") == 0) {
+            cnode->config.virtual_keyboard = g_strdup (sub_node->text);
+            cnode->mask |= ENGINE_CONFIG_VIRTUAL_KEYBOARD_MASK;
+            continue;
+        }
         g_warning ("<engine> element contains invalid element <%s>",
                    sub_node->name);
     }
Index: ibus-m17n-1.3.4/src/m17nutil.h
===================================================================
--- ibus-m17n-1.3.4.orig/src/m17nutil.h
+++ ibus-m17n-1.3.4/src/m17nutil.h
@@ -25,6 +25,9 @@ struct _IBusM17NEngineConfig {
 
     /* whether to highlight preedit */
     gboolean preedit_highlight;
+
+    /* virtual keyboard type */
+    gchar *virtual_keyboard;
 };
 
 typedef struct _IBusM17NEngineConfig IBusM17NEngineConfig;