[ibus/f15] Added ibus-xx-icon-symbol.patch

Takao Fujiwara fujiwara at fedoraproject.org
Tue Jun 21 08:50:15 UTC 2011


commit 63b857f037c74b6c91a009b59274099909dc21f1
Author: Takao Fujiwara <tfujiwar at redhat.com>
Date:   Tue Jun 21 17:49:07 2011 +0900

    Added ibus-xx-icon-symbol.patch
    
    - Added ibus-xx-bridge-hotkey.patch

 .gitignore                         |    2 +
 ibus-435880-surrounding-text.patch |  375 --------
 ibus-530711-preload-sys.patch      |  244 ++++-
 ibus-541492-xkb.patch              | 1790 ++++++++++++++++++++----------------
 ibus-HEAD.patch                    |  741 +++++++++++++++
 ibus-xx-bridge-hotkey.patch        |  874 ++++++++++++++++++
 ibus-xx-icon-symbol.patch          |  331 +++++++
 ibus-xx-setup-frequent-lang.patch  |   16 +-
 ibus.spec                          |   73 +-
 sources                            |    3 +-
 10 files changed, 3228 insertions(+), 1221 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 58ef980..f33ca6e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,5 @@ ibus-1.3.6.tar.gz
 /ibus_master_da.po
 /ibus-1.3.99.20110419.tar.gz
 /gnome-shell-ibus-plugins-20110601.tar.bz2
+/gnome-shell-ibus-plugins-20110621.tar.bz2
+/ibus-indicator.tar.bz2
diff --git a/ibus-530711-preload-sys.patch b/ibus-530711-preload-sys.patch
index b071d6e..7dec5ba 100644
--- a/ibus-530711-preload-sys.patch
+++ b/ibus-530711-preload-sys.patch
@@ -1,12 +1,13 @@
-From 047452beffd7cb429bf4dfeb2371f120cc8041a6 Mon Sep 17 00:00:00 2001
+From 7f81445b3e6613d14f64253506a309095a37c8d7 Mon Sep 17 00:00:00 2001
 From: fujiwarat <takao.fujiwara1 at gmail.com>
-Date: Fri, 11 Mar 2011 16:07:09 +0900
+Date: Mon, 20 Jun 2011 19:04:42 +0900
 Subject: [PATCH] Reload preload engines until users customize the list.
 
 The idea is, if users don't customize the preload_engines with ibus-setup,
 users would prefer to load the system default engines again by login.
 The gconf value 'preload_engine_mode' is
-IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE by default.
+IBUS_PRELOAD_ENGINE_MODE_USER by default but set
+IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE for the initial login.
 If preload_engine_mode is IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE,
 ibus-daemon loads the system preload engines by langs.
 If preload_engine_mode is IBUS_PRELOAD_ENGINE_MODE_USER,
@@ -15,22 +16,20 @@ On the other hand, if users enable the customized engine checkbutton
 on ibus-setup, ibus-setup sets 'preload_engine_mode' as
 IBUS_PRELOAD_ENGINE_MODE_USER and users can customize the value
 'preload_engines'.
-Loading system default may spend the startup time. If you mind it,
-your dist may like to put TRUE in 'use_local_preload_engines' value.
 ---
- bus/ibusimpl.c       |  286 +++++++++++++++++++++++++++++++++++---------------
- data/ibus.schemas.in |   13 +++
+ bus/ibusimpl.c       |  402 +++++++++++++++++++++++++++++++++++++++-----------
+ data/ibus.schemas.in |   13 ++
  ibus/common.py       |    6 +
- setup/main.py        |   37 ++++++-
+ setup/main.py        |   70 ++++++++-
  setup/setup.ui       |   21 +++-
  src/ibustypes.h      |   10 ++
- 6 files changed, 279 insertions(+), 94 deletions(-)
+ 6 files changed, 427 insertions(+), 95 deletions(-)
 
 diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c
-index 8d4ec36..0caa8c7 100644
+index a7ae52b..bb4b8ae 100644
 --- a/bus/ibusimpl.c
 +++ b/bus/ibusimpl.c
-@@ -144,6 +144,9 @@ static void     bus_ibus_impl_set_previo
+@@ -144,6 +144,9 @@ static void     bus_ibus_impl_set_previous_engine
  static void     bus_ibus_impl_set_preload_engines
                                                  (BusIBusImpl        *ibus,
                                                   GVariant           *value);
@@ -40,10 +39,28 @@ index 8d4ec36..0caa8c7 100644
  static void     bus_ibus_impl_set_use_sys_layout
                                                  (BusIBusImpl        *ibus,
                                                   GVariant           *value);
-@@ -284,6 +287,142 @@ _panel_destroy_cb (BusPanelProxy *panel,
-     g_object_unref (panel);
+@@ -285,6 +288,259 @@ _panel_destroy_cb (BusPanelProxy *panel,
  }
  
+ static void
++_config_set_value_done (GObject      *object,
++                        GAsyncResult *res,
++                        gpointer      user_data)
++{
++    IBusConfig *config = (IBusConfig *) object;
++    GVariant *value = (GVariant *) user_data;
++    GError *error = NULL;
++
++    g_assert (IBUS_IS_CONFIG (config));
++
++    if (!ibus_config_set_value_async_finish (config, res, &error)) {
++        if (error) {
++            g_error_free (error);
++        }
++    }
++    g_variant_unref (value);
++}
++
 +#ifndef OS_CHROMEOS
 +static gint
 +_engine_desc_cmp (IBusEngineDesc *desc1,
@@ -59,7 +76,7 @@ index 8d4ec36..0caa8c7 100644
 +_get_config_preload_engine_mode (BusIBusImpl *ibus)
 +{
 +    GVariant *variant = NULL;
-+    gint preload_engine_mode = IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE;
++    gint preload_engine_mode = IBUS_PRELOAD_ENGINE_MODE_USER;
 +
 +    g_assert (BUS_IS_IBUS_IMPL (ibus));
 +
@@ -68,6 +85,23 @@ index 8d4ec36..0caa8c7 100644
 +    }
 +
 +    variant = ibus_config_get_value (ibus->config, "general",
++                                     "preload_engines");
++    if (variant == NULL) {
++        /* Set LANG_RELATIVE mode for the initial login */
++        preload_engine_mode = IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE;
++        variant = g_variant_ref_sink (g_variant_new ("i", preload_engine_mode));
++        ibus_config_set_value_async (ibus->config, "general",
++                                     "preload_engine_mode", variant,
++                                     -1,
++                                     NULL,
++                                     _config_set_value_done,
++                                     variant);
++        return preload_engine_mode;
++    } else {
++        g_variant_unref (variant);
++    }
++
++    variant = ibus_config_get_value (ibus->config, "general",
 +                                     "preload_engine_mode");
 +    if (variant != NULL) {
 +        if (g_variant_classify (variant) == G_VARIANT_CLASS_INT32) {
@@ -80,6 +114,82 @@ index 8d4ec36..0caa8c7 100644
 +}
 +#endif
 +
++static int
++_compare_engine_list_value (GVariant *value_a, GVariant *value_b)
++{
++    GVariant *value;
++    GVariantIter iter;
++    const gchar *engine_name = NULL;
++    gchar *concat_engine_names;
++    gchar *concat_engine_names_a = NULL;
++    gchar *concat_engine_names_b = NULL;
++    int retval = 0;
++
++    value = value_a;
++    concat_engine_names = NULL;
++    if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_ARRAY) {
++        g_variant_iter_init (&iter, value);
++        while (g_variant_iter_loop (&iter, "&s", &engine_name)) {
++            gchar *tmp = g_strdup_printf ("%s::%s",
++                                          concat_engine_names ? concat_engine_names : "",
++                                          engine_name ? engine_name : "");
++            g_free (concat_engine_names);
++            concat_engine_names = tmp;
++        }
++    }
++    concat_engine_names_a = concat_engine_names;
++
++    value = value_b;
++    concat_engine_names = NULL;
++    if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_ARRAY) {
++        g_variant_iter_init (&iter, value);
++        while (g_variant_iter_loop (&iter, "&s", &engine_name)) {
++            gchar *tmp = g_strdup_printf ("%s::%s",
++                                          concat_engine_names ? concat_engine_names : "",
++                                          engine_name ? engine_name : "");
++            g_free (concat_engine_names);
++            concat_engine_names = tmp;
++        }
++    }
++    concat_engine_names_b = concat_engine_names;
++
++    retval = g_strcmp0 (concat_engine_names_a, concat_engine_names_b);
++    g_free (concat_engine_names_a);
++    g_free (concat_engine_names_b);
++    return retval;
++}
++
++static void
++_preload_engines_config_get_value_done (GObject      *object,
++                                        GAsyncResult *res,
++                                        gpointer      user_data)
++{
++    IBusConfig *config = (IBusConfig *) object;
++    GVariant *new_value = (GVariant *) user_data;
++    GVariant *value = NULL;
++    GError *error = NULL;
++
++    g_assert (IBUS_IS_CONFIG (config));
++
++    value = ibus_config_get_value_async_finish (config, res, &error);
++    if (error) {
++        g_error_free (error);
++    }
++    if (_compare_engine_list_value (value, new_value) != 0) {
++        ibus_config_set_value_async (config, "general",
++                                     "preload_engines", new_value,
++                                     -1,
++                                     NULL,
++                                     _config_set_value_done,
++                                     new_value);
++    } else if (new_value) {
++        g_variant_unref (new_value);
++    }
++    if (value) {
++        g_variant_unref (value);
++    }
++}
++
 +static void
 +_set_preload_engines (BusIBusImpl *ibus,
 +                      GVariant    *value)
@@ -103,11 +213,16 @@ index 8d4ec36..0caa8c7 100644
 +        }
 +
 +        if (engine_list != NULL &&
-+            ibus->config != NULL &&
-+            ibus_config_get_value (ibus->config, "general",
-+                                   "preload_engines") == NULL) {
-+            ibus_config_set_value (ibus->config, "general",
-+                                   "preload_engines", value);
++            ibus->config != NULL) {
++            /* sync function will effects the startup performance.
++             * We'd always like to save the value so that ibus-setup
++             * get the updated engine list. */
++            ibus_config_get_value_async (ibus->config, "general",
++                                         "preload_engines",
++                                         -1,
++                                         NULL,
++                                         _preload_engines_config_get_value_done,
++                                         g_variant_ref_sink (value));
 +        } else {
 +            /* We don't update preload_engines with an empty string for safety.
 +             * Just unref the floating value. */
@@ -180,10 +295,11 @@ index 8d4ec36..0caa8c7 100644
 +}
 +#endif
 +
- static void
++static void
  bus_ibus_impl_set_hotkey (BusIBusImpl *ibus,
                            GQuark       hotkey,
-@@ -394,35 +533,50 @@ static void
+                           GVariant    *value)
+@@ -394,35 +650,50 @@ static void
  bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus,
                                     GVariant    *value)
  {
@@ -220,14 +336,14 @@ index 8d4ec36..0caa8c7 100644
 +/**
 + * bus_ibus_impl_set_preload_engine_mode:
 + *
-+ * A function to be called when "preload_engines_mode" config is updated.
++ * A function to be called when "preload_engine_mode" config is updated.
 + */
 +static void
 +bus_ibus_impl_set_preload_engine_mode (BusIBusImpl *ibus,
 +                                       GVariant    *value)
 +{
 +#ifndef OS_CHROMEOS
-+    gint preload_engine_mode = IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE;
++    gint preload_engine_mode = IBUS_PRELOAD_ENGINE_MODE_USER;
  
 -    if (ibus->engine_list) {
 -        BusComponent *component = bus_component_from_engine_desc ((IBusEngineDesc *) ibus->engine_list->data);
@@ -256,7 +372,7 @@ index 8d4ec36..0caa8c7 100644
  }
  
  /**
-@@ -503,89 +657,48 @@ bus_ibus_impl_set_use_global_engine (Bus
+@@ -503,89 +774,47 @@ bus_ibus_impl_set_use_global_engine (BusIBusImpl *ibus,
      }
  }
  
@@ -279,7 +395,8 @@ index 8d4ec36..0caa8c7 100644
 + * The idea is, if users don't customize the preload_engines with ibus-setup,
 + * users would prefer to load the system default engines again by login.
 + * The gconf value 'preload_engine_mode' is
-+ * IBUS_PRELOAD_ENGINE_MODE_USER by default.
++ * IBUS_PRELOAD_ENGINE_MODE_USER by default but set
++ * IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE for the initial login.
 + * If preload_engine_mode is IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE,
 + * ibus-daemon loads the system preload engines by langs.
 + * If preload_engine_mode is IBUS_PRELOAD_ENGINE_MODE_USER,
@@ -288,8 +405,6 @@ index 8d4ec36..0caa8c7 100644
 + * on ibus-setup, ibus-setup sets 'preload_engine_mode' as
 + * IBUS_PRELOAD_ENGINE_MODE_USER and users can customize the value
 + * 'preload_engines'.
-+ * Loading system default may spend the startup time. If you mind it,
-+ * your dist may like to put TRUE in 'use_local_preload_engines' value.
   */
  static void
  bus_ibus_impl_set_default_preload_engines (BusIBusImpl *ibus)
@@ -298,7 +413,7 @@ index 8d4ec36..0caa8c7 100644
 -    g_assert (BUS_IS_IBUS_IMPL (ibus));
 -
      static gboolean done = FALSE;
-+    gint preload_engine_mode = IBUS_PRELOAD_ENGINE_MODE_LANG_RELATIVE;
++    gint preload_engine_mode = IBUS_PRELOAD_ENGINE_MODE_USER;
 +
 +    g_assert (BUS_IS_IBUS_IMPL (ibus));
  
@@ -369,16 +484,16 @@ index 8d4ec36..0caa8c7 100644
  #endif
  }
  
-@@ -601,6 +714,7 @@ const static struct {
+@@ -601,6 +830,7 @@ const static struct {
      { "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", "preload_engines_mode",         bus_ibus_impl_set_preload_engine_mode },
++    { "general", "preload_engine_mode",          bus_ibus_impl_set_preload_engine_mode },
      { "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 },
 diff --git a/data/ibus.schemas.in b/data/ibus.schemas.in
-index 7ca4899..39922a0 100644
+index 7ca4899..d4334e1 100644
 --- a/data/ibus.schemas.in
 +++ b/data/ibus.schemas.in
 @@ -13,6 +13,19 @@
@@ -389,7 +504,7 @@ index 7ca4899..39922a0 100644
 +      <applyto>/desktop/ibus/general/preload_engine_mode</applyto>
 +      <owner>ibus</owner>
 +      <type>int</type>
-+      <default>1</default>
++      <default>0</default>
 +      <locale name="C">
 +        <short>Preload engine mode</short>
 +           <long>Preload engines are loaded with this mode.
@@ -402,7 +517,7 @@ index 7ca4899..39922a0 100644
        <applyto>/desktop/ibus/general/hotkey/trigger</applyto>
        <owner>ibus</owner>
 diff --git a/ibus/common.py b/ibus/common.py
-index e105f18..20c0710 100644
+index 6483aae..127ed93 100644
 --- a/ibus/common.py
 +++ b/ibus/common.py
 @@ -40,6 +40,8 @@ __all__ = (
@@ -426,10 +541,18 @@ index e105f18..20c0710 100644
      pass
  
 diff --git a/setup/main.py b/setup/main.py
-index 7f4a040..9cdce02 100644
+index 7f4a040..192fb88 100644
 --- a/setup/main.py
 +++ b/setup/main.py
-@@ -213,15 +213,22 @@ class Setup(object):
+@@ -92,6 +92,7 @@ class Setup(object):
+         # keyboard shortcut
+         # trigger
+         self.__config = self.__bus.get_config()
++        self.__config.connect("value-changed", self.__config_value_changed_cb)
+         shortcuts = self.__config.get_value(
+                         "general/hotkey", "trigger",
+                         ibus.CONFIG_GENERAL_SHORTCUT_TRIGGER_DEFAULT)
+@@ -213,15 +214,22 @@ class Setup(object):
          self.__checkbutton_use_global_engine.connect("toggled", self.__checkbutton_use_global_engine_toggled_cb)
  
          # init engine page
@@ -457,7 +580,7 @@ index 7f4a040..9cdce02 100644
  
          self.__treeview = self.__builder.get_object("treeview_engines")
          self.__treeview.set_engines(engines)
-@@ -265,6 +272,13 @@ class Setup(object):
+@@ -265,6 +273,26 @@ class Setup(object):
              engine_names = map(lambda e: e.name, engines)
              self.__config.set_list("general", "preload_engines", engine_names, "s")
  
@@ -468,10 +591,23 @@ index 7f4a040..9cdce02 100644
 +        engines = [tmp_dict[name] for name in engine_names if name in tmp_dict]
 +        return engines
 +
++    def __compare_descs(self, engines_a, engines_b):
++        engines = engines_a
++        concat_engine_names = ""
++        for engine in engines:
++            concat_engine_names = "%s::%s" % (concat_engine_names, engine.name)
++        concat_engine_names_a = concat_engine_names
++        engines = engines_b
++        concat_engine_names = ""
++        for engine in engines:
++            concat_engine_names = "%s::%s" % (concat_engine_names, engine.name)
++        concat_engine_names_b = concat_engine_names
++        return concat_engine_names_a == concat_engine_names_b
++
      def __button_engine_add_cb(self, button):
          engine = self.__combobox.get_active_engine()
          self.__treeview.append_engine(engine)
-@@ -276,6 +290,19 @@ class Setup(object):
+@@ -276,6 +304,32 @@ class Setup(object):
              about.run()
              about.destroy()
  
@@ -483,6 +619,19 @@ index 7f4a040..9cdce02 100644
 +            self.__builder.get_object("hbox_customize_active_input_methods").set_sensitive(True)
 +            self.__treeview.notify("engines")
 +        else:
++            message = _("The list of your saved input methods will be " \
++                        "cleared immediately and the list will be " \
++                        "configured by the login language every time. " \
++                        "Do you agree with this?")
++            dlg = gtk.MessageDialog(type = gtk.MESSAGE_QUESTION,
++                    buttons = gtk.BUTTONS_YES_NO,
++                    message_format = message)
++            id = dlg.run()
++            dlg.destroy()
++            self.__flush_gtk_events()
++            if id != gtk.RESPONSE_YES:
++                button.set_active(True)
++                return
 +            self.__config.set_value("general",
 +                                    "preload_engine_mode",
 +                                    ibus.common.PRELOAD_ENGINE_MODE_LANG_RELATIVE)
@@ -491,6 +640,19 @@ index 7f4a040..9cdce02 100644
      def __init_bus(self):
          try:
              self.__bus = ibus.Bus()
+@@ -466,7 +520,11 @@ class Setup(object):
+         self.__config.set_value("general", "use_global_engine", value)
+ 
+     def __config_value_changed_cb(self, bus, section, name, value):
+-        pass
++        if section == 'general' and name == 'preload_engines':
++            engines = self.__get_engine_descs_from_names(value)
++            current_engines = self.__treeview.get_engines()
++            if self.__compare_descs(engines, current_engines) == False:
++                self.__treeview.set_engines(engines)
+ 
+     def __config_reloaded_cb(self, bus):
+         pass
 diff --git a/setup/setup.ui b/setup/setup.ui
 index f1e6d0b..562c091 100644
 --- a/setup/setup.ui
@@ -538,11 +700,11 @@ index f1e6d0b..562c091 100644
                      </child>
                    </object>
 diff --git a/src/ibustypes.h b/src/ibustypes.h
-index 035d124..0a9d7b2 100644
+index 6a31847..14b44fc 100644
 --- a/src/ibustypes.h
 +++ b/src/ibustypes.h
-@@ -177,6 +177,16 @@ typedef enum {
- } IBusBusRequestNameReply;
+@@ -186,6 +186,16 @@ typedef enum {
+ } IBusError;
  
  /**
 + * IBusPreloadEngineMode:
@@ -559,5 +721,5 @@ index 035d124..0a9d7b2 100644
   * @x: x coordinate.
   * @y: y coordinate.
 -- 
-1.7.4.1
+1.7.4.4
 
diff --git a/ibus-541492-xkb.patch b/ibus-541492-xkb.patch
index 9100d48..21f0694 100644
--- a/ibus-541492-xkb.patch
+++ b/ibus-541492-xkb.patch
@@ -1,6 +1,6 @@
-From b6b83e9484abad910271b15222d3f76f206a1ff6 Mon Sep 17 00:00:00 2001
+From 7fab90a9962d3b4f8eff40cf08939873575d153e Mon Sep 17 00:00:00 2001
 From: fujiwarat <takao.fujiwara1 at gmail.com>
-Date: Wed, 1 Jun 2011 18:24:10 +0900
+Date: Tue, 21 Jun 2011 11:34:52 +0900
 Subject: [PATCH] Add XKB layouts
 
 ---
@@ -12,30 +12,36 @@ Subject: [PATCH] Add XKB layouts
  ibus/__init__.py           |    2 +
  ibus/bus.py                |    3 +
  ibus/interface/iibus.py    |    3 +
- ibus/xkblayout.py.in       |  225 ++++++++++++++
- ibus/xkbxml.py.in          |  413 ++++++++++++++++++++++++++
+ ibus/xkblayout.py.in       |  225 ++++++++++++++++
+ ibus/xkbxml.py.in          |  413 ++++++++++++++++++++++++++++++
  setup/Makefile.am          |    1 +
  setup/enginecombobox.py    |    7 +-
  setup/main.py              |    3 +
- setup/setup.ui             |  609 ++++++++++++++++++++++++++++++++++++++-
- setup/xkbsetup.py          |  454 +++++++++++++++++++++++++++++
+ setup/setup.ui             |  609 +++++++++++++++++++++++++++++++++++++++++++-
+ setup/xkbsetup.py          |  454 +++++++++++++++++++++++++++++++++
+ src/Makefile.am            |    5 +
+ src/ibus.h                 |    1 +
  src/ibusfactory.c          |   21 ++-
  src/ibusfactory.h          |    5 +-
+ src/ibusxkbxml.c           |  440 ++++++++++++++++++++++++++++++++
+ src/ibusxkbxml.h           |  172 +++++++++++++
  ui/gtk/panel.py            |   39 +++
- xkb/Makefile.am            |  104 +++++++
- xkb/ibus-engine-xkb-main.c |  397 +++++++++++++++++++++++++
- xkb/ibus-engine-xkb-main.h |   46 +++
- xkb/ibus-xkb-main.c        |  105 +++++++
- xkb/xkblayout.xml.in       |   16 +
+ xkb/Makefile.am            |  104 ++++++++
+ xkb/ibus-engine-xkb-main.c |  397 +++++++++++++++++++++++++++++
+ xkb/ibus-engine-xkb-main.h |   46 ++++
+ xkb/ibus-xkb-main.c        |  112 ++++++++
+ xkb/xkblayout.xml.in       |   16 ++
  xkb/xkblayoutconfig.xml.in |    6 +
- xkb/xkblib.c               |  303 +++++++++++++++++++
- xkb/xkblib.h               |   40 +++
- xkb/xkbxml.c               |  696 ++++++++++++++++++++++++++++++++++++++++++++
- xkb/xkbxml.h               |  189 ++++++++++++
- 28 files changed, 3808 insertions(+), 6 deletions(-)
+ xkb/xkblib.c               |  327 ++++++++++++++++++++++++
+ xkb/xkblib.h               |   41 +++
+ xkb/xkbxml.c               |  335 ++++++++++++++++++++++++
+ xkb/xkbxml.h               |  110 ++++++++
+ 32 files changed, 4018 insertions(+), 6 deletions(-)
  create mode 100644 ibus/xkblayout.py.in
  create mode 100644 ibus/xkbxml.py.in
  create mode 100644 setup/xkbsetup.py
+ create mode 100644 src/ibusxkbxml.c
+ create mode 100644 src/ibusxkbxml.h
  create mode 100644 xkb/Makefile.am
  create mode 100644 xkb/ibus-engine-xkb-main.c
  create mode 100644 xkb/ibus-engine-xkb-main.h
@@ -48,7 +54,7 @@ Subject: [PATCH] Add XKB layouts
  create mode 100644 xkb/xkbxml.h
 
 diff --git a/Makefile.am b/Makefile.am
-index 29c57e1..dbe0b6b 100644
+index 7be558b..59fbabb 100644
 --- a/Makefile.am
 +++ b/Makefile.am
 @@ -42,6 +42,12 @@ DAEMON_DIRS =       \
@@ -73,7 +79,7 @@ index 29c57e1..dbe0b6b 100644
  	$(NULL)
  
 diff --git a/configure.ac b/configure.ac
-index 8da8c6e..ce1526c 100644
+index 5544dfa..85e5e30 100644
 --- a/configure.ac
 +++ b/configure.ac
 @@ -185,6 +185,60 @@ else
@@ -297,7 +303,7 @@ index 678d517..7de56fc 100644
  
 diff --git a/ibus/xkblayout.py.in b/ibus/xkblayout.py.in
 new file mode 100644
-index 0000000..6097ed1
+index 0000000..637f6c1
 --- /dev/null
 +++ b/ibus/xkblayout.py.in
 @@ -0,0 +1,225 @@
@@ -305,9 +311,9 @@ index 0000000..6097ed1
 +#
 +# ibus - The Input Bus
 +#
-+# Copyright (c) 2010 Takao Fujiwara <takao.fujiwara1 at gmail.com>
-+# Copyright (c) 2007-2010 Peng Huang <shawn.p.huang at gmail.com>
-+# Copyright (c) 2007-2010 Red Hat, Inc.
++# Copyright (c) 2011 Takao Fujiwara <takao.fujiwara1 at gmail.com>
++# Copyright (c) 2011 Peng Huang <shawn.p.huang at gmail.com>
++# Copyright (c) 2011 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
@@ -371,6 +377,16 @@ index 0000000..6097ed1
 +        option = ','.join(option_array)
 +        return (layout, option)
 +
++    def __get_output_from_cmdline(self, arg, string):
++        exec_command = "%s %s" % (self.__command, arg)
++        retval = None
++        for line in os.popen(exec_command).readlines():
++            line = line.strip()
++            if line.startswith(string):
++                retval = line[len(string):]
++                break
++        return retval
++
 +    def use_xkb(self, enable):
 +        if self.__command == None:
 +            return
@@ -379,38 +395,22 @@ index 0000000..6097ed1
 +    def get_layout(self):
 +        if not self.__use_xkb:
 +            return None
-+        exec_command = "%s %s" % (self.__command, "--get")
-+        retval = None
-+        for line in os.popen(exec_command).readlines():
-+            line = line.strip()
-+            if line.startswith("layout: "):
-+                retval = line[len("layout: "):]
-+                break
-+        return retval
++        return self.__get_output_from_cmdline("--get", "layout: ")
 +
 +    def get_model(self):
 +        if not self.__use_xkb:
 +            return None
-+        exec_command = "%s %s" % (self.__command, "--get")
-+        retval = None
-+        for line in os.popen(exec_command).readlines():
-+            line = line.strip()
-+            if line.startswith("model: "):
-+                retval = line[len("model: "):]
-+                break
-+        return retval
++        return self.__get_output_from_cmdline("--get", "model: ")
 +
 +    def get_option(self):
 +        if not self.__use_xkb:
 +            return None
-+        exec_command = "%s %s" % (self.__command, "--get")
-+        retval = None
-+        for line in os.popen(exec_command).readlines():
-+            line = line.strip()
-+            if line.startswith("option: "):
-+                retval = line[len("option: "):]
-+                break
-+        return retval
++        return self.__get_output_from_cmdline("--get", "option: ")
++
++    def get_group(self):
++        if not self.__use_xkb:
++            return 0
++        return int(self.__get_output_from_cmdline("--get-group", "group: "))
 +
 +    def set_layout(self, layout="default", model="default", option="default"):
 +        if not self.__use_xkb:
@@ -520,6 +520,12 @@ index 0000000..6097ed1
 +            self.__default_option = option
 +            self.__time_lag_session_xkb_option = False
 +
++    def get_default_layout(self):
++        return [self.__default_layout, self.__default_model];
++
++    def get_default_option(self):
++        return self.__default_option
++
 +    def reload_default_layout(self):
 +        if not self.__use_xkb:
 +            return
@@ -528,7 +534,7 @@ index 0000000..6097ed1
 +        self.__default_option = self.get_option()
 diff --git a/ibus/xkbxml.py.in b/ibus/xkbxml.py.in
 new file mode 100644
-index 0000000..57f54da
+index 0000000..7e5a44e
 --- /dev/null
 +++ b/ibus/xkbxml.py.in
 @@ -0,0 +1,413 @@
@@ -536,9 +542,9 @@ index 0000000..57f54da
 +#
 +# ibus - The Input Bus
 +#
-+# Copyright (c) 2010 Takao Fujiwara <takao.fujiwara1 at gmail.com>
-+# Copyright (c) 2007-2010 Peng Huang <shawn.p.huang at gmail.com>
-+# Copyright (c) 2007-2010 Red Hat, Inc.
++# Copyright (c) 2011 Takao Fujiwara <takao.fujiwara1 at gmail.com>
++# Copyright (c) 2011 Peng Huang <shawn.p.huang at gmail.com>
++# Copyright (c) 2011 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
@@ -1664,7 +1670,7 @@ index 0a69df8..f1e6d0b 100644
  </interface>
 diff --git a/setup/xkbsetup.py b/setup/xkbsetup.py
 new file mode 100644
-index 0000000..74d5212
+index 0000000..1685bff
 --- /dev/null
 +++ b/setup/xkbsetup.py
 @@ -0,0 +1,454 @@
@@ -1672,9 +1678,9 @@ index 0000000..74d5212
 +#
 +# ibus - The Input Bus
 +#
-+# Copyright (c) 2010 Takao Fujiwara <takao.fujiwara1 at gmail.com>
-+# Copyright (c) 2007-2010 Peng Huang <shawn.p.huang at gmail.com>
-+# Copyright (c) 2007-2010 Red Hat, Inc.
++# Copyright (c) 2011 Takao Fujiwara <takao.fujiwara1 at gmail.com>
++# Copyright (c) 2011 Peng Huang <shawn.p.huang at gmail.com>
++# Copyright (c) 2011 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
@@ -2122,6 +2128,34 @@ index 0000000..74d5212
 +                label.set_text(label.get_text())
 +        expander.set_data("checked", checked)
 +
+diff --git a/src/Makefile.am b/src/Makefile.am
+index a53bd23..6454522 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -184,6 +184,11 @@ typelibs_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+ CLEANFILES += $(dist_gir_DATA) $(typelibs_DATA)
+ endif
+ 
++if ENABLE_XKB
++ibus_sources += ibusxkbxml.c
++ibus_headers += ibusxkbxml.h
++endif
++
+ # gen enum types
+ ibusenumtypes.h: $(ibus_headers) ibusenumtypes.h.template
+ 	$(AM_V_GEN) ( top_builddir=`cd $(top_builddir) && pwd`; \
+diff --git a/src/ibus.h b/src/ibus.h
+index c408f3d..6bb9ff5 100644
+--- a/src/ibus.h
++++ b/src/ibus.h
+@@ -44,6 +44,7 @@
+ #include <ibuskeymap.h>
+ #include <ibusenumtypes.h>
+ #include <ibushotkey.h>
++#include <ibusxkbxml.h>
+ #include <ibusxml.h>
+ #include <ibusenginedesc.h>
+ #include <ibusobservedpath.h>
 diff --git a/src/ibusfactory.c b/src/ibusfactory.c
 index 11d9a6d..7770216 100644
 --- a/src/ibusfactory.c
@@ -2202,219 +2236,18 @@ index 47c06e0..102081c 100644
  };
  
  /**
-diff --git a/ui/gtk/panel.py b/ui/gtk/panel.py
-index 90be1d5..de64920 100644
---- a/ui/gtk/panel.py
-+++ b/ui/gtk/panel.py
-@@ -132,6 +132,22 @@ class Panel(ibus.PanelBase):
-         self.__config_load_show_im_name()
-         # self.__bus.request_name(ibus.panel.IBUS_SERVICE_PANEL, 0)
- 
-+        # init xkb
-+        self.__xkblayout = ibus.XKBLayout(self.__config)
-+        use_xkb = self.__config.get_value("general", "use_system_keyboard_layout", False)
-+        if not use_xkb:
-+            self.__xkblayout.use_xkb(use_xkb)
-+        value = str(self.__config.get_value("general", "system_keyboard_layout", ''))
-+        if value == '':
-+            value = 'default'
-+        if value != 'default':
-+            self.__xkblayout.set_default_layout(value)
-+        value = str(self.__config.get_value("general", "system_keyboard_option", ''))
-+        if value == '':
-+            value = 'default'
-+        if value != 'default':
-+            self.__xkblayout.set_default_option(value)
-+
-     def set_cursor_location(self, x, y, w, h):
-         self.__candidate_panel.set_cursor_location(x, y, w, h)
- 
-@@ -226,14 +242,20 @@ class Panel(ibus.PanelBase):
-         if not enabled:
-             self.__set_im_icon(ICON_KEYBOARD)
-             self.__set_im_name(None)
-+            if self.__bus.get_use_sys_layout():
-+                self.__xkblayout.set_layout()
-         else:
-             engine = self.__focus_ic.get_engine()
-             if engine:
-                 self.__set_im_icon(engine.icon)
-                 self.__set_im_name(engine.longname)
-+                if self.__bus.get_use_sys_layout():
-+                    self.__xkblayout.set_layout(self.__engine_get_layout_wrapper(engine))
-             else:
-                 self.__set_im_icon(ICON_KEYBOARD)
-                 self.__set_im_name(None)
-+                if self.__bus.get_use_sys_layout():
-+                    self.__xkblayout.set_layout()
-         self.__language_bar.focus_in()
- 
-     def focus_out(self, ic):
-@@ -243,6 +265,8 @@ class Panel(ibus.PanelBase):
-         self.__language_bar.focus_out()
-         self.__set_im_icon(ICON_KEYBOARD)
-         self.__set_im_name(None)
-+        if self.__bus.get_use_sys_layout():
-+            self.__xkblayout.set_layout()
- 
-     def state_changed(self):
-         if not self.__focus_ic:
-@@ -255,14 +279,20 @@ class Panel(ibus.PanelBase):
-             self.reset()
-             self.__set_im_icon(ICON_KEYBOARD)
-             self.__set_im_name(None)
-+            if self.__bus.get_use_sys_layout():
-+                self.__xkblayout.set_layout()
-         else:
-             engine = self.__focus_ic.get_engine()
-             if engine:
-                 self.__set_im_icon(engine.icon)
-                 self.__set_im_name(engine.longname)
-+                if self.__bus.get_use_sys_layout():
-+                    self.__xkblayout.set_layout(self.__engine_get_layout_wrapper(engine))
-             else:
-                 self.__set_im_icon(ICON_KEYBOARD)
-                 self.__set_im_name(None)
-+                if self.__bus.get_use_sys_layout():
-+                    self.__xkblayout.set_layout()
- 
- 
-     def reset(self):
-@@ -542,3 +572,12 @@ class Panel(ibus.PanelBase):
-                                flags=glib.SPAWN_DO_NOT_REAP_CHILD)[0]
-         self.__setup_pid = pid
-         glib.child_watch_add(self.__setup_pid, self.__child_watch_cb)
-+
-+    def __engine_get_layout_wrapper(self, engine):
-+        # This code is for the back compatibility.
-+        # Should we remove the codes after all IM engines are changed
-+        # to "default" layout?
-+        if engine.name != None and engine.name.startswith("xkb:layout:"):
-+            return engine.layout
-+        else:
-+            return "default"
-diff --git a/xkb/Makefile.am b/xkb/Makefile.am
-new file mode 100644
-index 0000000..64b1fc8
---- /dev/null
-+++ b/xkb/Makefile.am
-@@ -0,0 +1,104 @@
-+# vim:set noet ts=4:
-+#
-+# ibus - The Input Bus
-+#
-+# Copyright (C) 2010 Takao Fujiwara <takao.fujiwara1 at gmail.com>
-+# Copyright (c) 2007-2010 Peng Huang <shawn.p.huang at gmail.com>
-+# 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
-+
-+libibus = $(top_builddir)/src/libibus- at IBUS_API_VERSION@.la
-+
-+INCLUDES = \
-+        -I$(top_srcdir) \
-+        -I$(top_srcdir)/src \
-+	-DIBUS_LOCALEDIR=\"$(datadir)/locale\" \
-+	-DLIBEXECDIR=\""$(libexecdir)"\" \
-+        $(NULL)
-+
-+noinst_PROGRAMS = $(TESTS)
-+libexec_PROGRAMS =
-+EXTRA_DIST =
-+DISTCLEANFILES =
-+
-+if ENABLE_XKB
-+libexec_PROGRAMS += ibus-xkb
-+ibus_xkb_SOURCES = \
-+	ibus-xkb-main.c \
-+	xkblib.h \
-+	xkblib.c \
-+	$(NULL)
-+ibus_xkb_CFLAGS = \
-+	@XKB_CFLAGS@ \
-+	@X11_CFLAGS@ \
-+	@GLIB2_CFLAGS@ \
-+	$(NULL)
-+ibus_xkb_LDADD = \
-+	@XKB_LIBS@ \
-+	@X11_LIBS@ \
-+	@GLIB2_LIBS@ \
-+	$(libibus) \
-+	$(NULL)
-+
-+libexec_PROGRAMS += ibus-engine-xkb
-+ibus_engine_xkb_SOURCES = \
-+        ibus-engine-xkb-main.c \
-+        ibus-engine-xkb-main.h \
-+        xkbxml.c \
-+        xkbxml.h \
-+        $(NULL)
-+ibus_engine_xkb_CFLAGS = \
-+	@GLIB2_CFLAGS@ \
-+	@GOBJECT2_CFLAGS@ \
-+	@GCONF_CFLAGS@ \
-+        $(NULL)
-+ibus_engine_xkb_LDADD = \
-+	@GLIB2_LIBS@ \
-+	@GOBJECT2_LIBS@ \
-+	@GCONF_LIBS@ \
-+	$(libibus) \
-+        $(NULL)
-+
-+xkblayoutdir = $(datadir)/ibus/component
-+xkblayout_in_files = xkblayout.xml.in
-+xkblayout_DATA = $(xkblayout_in_files:.xml.in=.xml)
-+
-+xkblayoutconfigdir = $(datadir)/ibus/xkb
-+xkblayoutconfig_in_files = xkblayoutconfig.xml.in
-+xkblayoutconfig_DATA = $(xkblayoutconfig_in_files:.xml.in=.xml)
-+
-+%.xml : %.xml.in
-+	@sed -e "s|\@libexecdir\@|$(libexecdir)|g" \
-+	     -e "s|\@datadir\@|$(datadir)|g" \
-+	     -e "s|\@XKB_PRELOAD_LAYOUTS\@|$(XKB_PRELOAD_LAYOUTS)|g" \
-+	$< > $@
-+
-+INCLUDES += \
-+	-DXKBLAYOUTCONFIG_FILE=\""$(xkblayoutconfigdir)/$(xkblayoutconfig_DATA)"\" \
-+	$(NULL)
-+
-+EXTRA_DIST += \
-+        $(xkblayout_in_files) \
-+        $(xkblayoutconfig_in_files) \
-+        $(NULL)
-+
-+DISTCLEANFILES += \
-+        $(xkblayout_DATA) \
-+        $(xkblayoutconfig_DATA) \
-+        $(NULL)
-+
-+endif
-diff --git a/xkb/ibus-engine-xkb-main.c b/xkb/ibus-engine-xkb-main.c
+diff --git a/src/ibusxkbxml.c b/src/ibusxkbxml.c
 new file mode 100644
-index 0000000..e1861e8
+index 0000000..c630eb9
 --- /dev/null
-+++ b/xkb/ibus-engine-xkb-main.c
-@@ -0,0 +1,397 @@
++++ b/src/ibusxkbxml.c
+@@ -0,0 +1,440 @@
 +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 +/* vim:set et sts=4: */
 +/* bus - The Input Bus
-+ * Copyright (C) 2010 Takao Fujiwara <takao.fujiwara1 at gmail.com>
-+ * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang at gmail.com>
-+ * Copyright (C) 2008-2010 Red Hat, Inc.
++ * Copyright (C) 2011 Takao Fujiwara <takao.fujiwara1 at gmail.com>
++ * Copyright (C) 2011 Peng Huang <shawn.p.huang at gmail.com>
++ * Copyright (C) 2011 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
@@ -2435,29 +2268,854 @@ index 0000000..e1861e8
 +#include <config.h>
 +#endif
 +
-+#include <gconf/gconf-client.h>
-+#include <ibus.h>
-+#include <stdlib.h>
++#include <glib.h>
 +
-+#ifdef ENABLE_NLS
-+#include <locale.h>
-+#endif
++#include "ibus.h"
 +
-+#include "ibus-engine-xkb-main.h"
-+#include "xkbxml.h"
++#ifndef XKB_RULES_XML_FILE
++#define XKB_RULES_XML_FILE "/usr/share/X11/xkb/rules/evdev.xml"
++#endif
 +
-+#define IBUS_TYPE_XKB_ENGINE (ibus_xkb_engine_get_type ())
++#define IBUS_XKB_CONFIG_REGISTRY_GET_PRIVATE(o)  \
++   (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_XKB_CONFIG_REGISTRY, IBusXKBConfigRegistryPrivate))
 +
-+static IBusBus *bus = NULL;
-+static IBusFactory *factory = NULL;
-+static IBusEngineClass *parent_class = NULL;
-+static gboolean ibus = FALSE;
-+static gboolean xml = FALSE;
++typedef struct _IBusXKBConfigRegistryPrivate IBusXKBConfigRegistryPrivate;
 +
-+static const GOptionEntry entries[] =
-+{
-+    { "ibus", 'i', 0, G_OPTION_ARG_NONE, &ibus, "component is executed by ibus", NULL },
-+    { "xml", 'x', 0, G_OPTION_ARG_NONE, &xml, "print component xml", NULL },
++struct _IBusXKBConfigRegistryPrivate {
++    GHashTable *layout_list;
++    GHashTable *layout_lang;
++    GHashTable *layout_desc;
++    GHashTable *variant_desc;
++};
++
++
++/* functions prototype */
++static void         ibus_xkb_config_registry_destroy
++                                           (IBusXKBConfigRegistry *xkb_config);
++
++G_DEFINE_TYPE (IBusXKBConfigRegistry, ibus_xkb_config_registry, IBUS_TYPE_OBJECT)
++
++static void
++parse_xkb_xml_languagelist_node (IBusXKBConfigRegistryPrivate *priv,
++                                 XMLNode *parent_node,
++                                 const gchar *layout_name)
++{
++    XMLNode *node = parent_node;
++    XMLNode *sub_node;
++    GList *p;
++    GList *lang_list = NULL;
++
++    g_assert (node != NULL);
++    g_assert (layout_name != NULL);
++    for (p = node->sub_nodes; p; p = p->next) {
++        sub_node = (XMLNode *) p->data;
++        if (g_strcmp0 (sub_node->name, "iso639Id") == 0) {
++            lang_list = g_list_append (lang_list,
++                                       (gpointer) g_strdup (sub_node->text));
++            continue;
++        }
++    }
++    if (lang_list == NULL) {
++        /* some nodes have no lang */
++        return;
++    }
++    if (g_hash_table_lookup (priv->layout_lang, layout_name) != NULL) {
++        g_warning ("duplicated name %s exists", layout_name);
++        return;
++    }
++    g_hash_table_insert (priv->layout_lang,
++                         (gpointer) g_strdup (layout_name),
++                         (gpointer) lang_list);
++}
++
++static const gchar *
++parse_xkb_xml_configitem_node (IBusXKBConfigRegistryPrivate *priv,
++                               XMLNode *parent_node)
++{
++    XMLNode *node = parent_node;
++    XMLNode *sub_node;
++    GList *p;
++    gchar *name = NULL;
++    gchar *description = NULL;
++
++    g_assert (node != NULL);
++    for (p = node->sub_nodes; p; p = p->next) {
++        sub_node = (XMLNode *) p->data;
++        if (g_strcmp0 (sub_node->name, "name") == 0) {
++            name = sub_node->text;
++            continue;
++        }
++        if (g_strcmp0 (sub_node->name, "description") == 0) {
++            description = sub_node->text;
++            continue;
++        }
++        if (g_strcmp0 (sub_node->name, "languageList") == 0) {
++            if (name == NULL) {
++                g_warning ("layout name is NULL in node %s", node->name);
++                continue;
++            }
++            parse_xkb_xml_languagelist_node (priv, sub_node, name);
++            continue;
++        }
++    }
++    if (name == NULL) {
++        g_warning ("No name in layout node");
++        return NULL;
++    }
++    if (g_hash_table_lookup (priv->layout_desc, name) != NULL) {
++        g_warning ("duplicated name %s exists", name);
++        return name;
++    }
++    g_hash_table_insert (priv->layout_desc,
++                         (gpointer) g_strdup (name),
++                         (gpointer) g_strdup (description));
++
++    return name;
++}
++
++static const gchar *
++parse_xkb_xml_variant_configitem_node (IBusXKBConfigRegistryPrivate *priv,
++                            XMLNode *parent_node,
++                            const gchar *layout_name)
++{
++    XMLNode *node = parent_node;
++    XMLNode *sub_node;
++    GList *p;
++    gchar *name = NULL;
++    gchar *description = NULL;
++    gchar *variant_lang_name = NULL;
++
++    g_assert (node != NULL);
++    g_assert (layout_name != NULL);
++    for (p = node->sub_nodes; p; p = p->next) {
++        sub_node = (XMLNode *) p->data;
++        if (g_strcmp0 (sub_node->name, "name") == 0) {
++            name = sub_node->text;
++            continue;
++        }
++        if (g_strcmp0 (sub_node->name, "description") == 0) {
++            description = sub_node->text;
++            continue;
++        }
++        if (g_strcmp0 (sub_node->name, "languageList") == 0) {
++            if (name == NULL) {
++                g_warning ("layout name is NULL in node %s", node->name);
++                continue;
++            }
++            variant_lang_name = g_strdup_printf ("%s(%s)", layout_name, name);
++            parse_xkb_xml_languagelist_node (priv, sub_node, variant_lang_name);
++            g_free (variant_lang_name);
++            continue;
++        }
++    }
++    if (name == NULL) {
++        g_warning ("No name in layout node");
++        return NULL;
++    }
++    if (g_hash_table_lookup (priv->variant_desc, name) != NULL) {
++        /* This is an expected case. */
++        return name;
++    }
++    g_hash_table_insert (priv->variant_desc,
++                         (gpointer) g_strdup (name),
++                         (gpointer) g_strdup (description));
++    return name;
++}
++
++static const gchar *
++parse_xkb_xml_variant_node (IBusXKBConfigRegistryPrivate *priv,
++                            XMLNode *parent_node,
++                            const gchar *layout_name)
++{
++    XMLNode *node = parent_node;
++    XMLNode *sub_node;
++    GList *p;
++    const gchar *variant_name = NULL;
++
++    g_assert (node != NULL);
++    g_assert (layout_name != NULL);
++    for (p = node->sub_nodes; p; p = p->next) {
++        sub_node = (XMLNode *) p->data;
++        if (g_strcmp0 (sub_node->name, "configItem") == 0) {
++            variant_name = parse_xkb_xml_variant_configitem_node (priv, sub_node, layout_name);
++            continue;
++        }
++    }
++    return variant_name;
++}
++
++static GList *
++parse_xkb_xml_variantlist_node (IBusXKBConfigRegistryPrivate *priv,
++                                XMLNode *parent_node,
++                                const gchar *layout_name,
++                                GList *variant_list)
++{
++    XMLNode *node = parent_node;
++    XMLNode *sub_node;
++    GList *p;
++    const gchar *variant_name = NULL;
++
++    g_assert (node != NULL);
++    g_assert (layout_name != NULL);
++    for (p = node->sub_nodes; p; p = p->next) {
++        sub_node = (XMLNode *) p->data;
++        if (g_strcmp0 (sub_node->name, "variant") == 0) {
++            variant_name = parse_xkb_xml_variant_node (priv, sub_node, layout_name);
++            if (variant_name != NULL) {
++                variant_list = g_list_append (variant_list,
++                                              (gpointer) g_strdup (variant_name));
++            }
++            continue;
++        }
++    }
++    return variant_list;
++}
++
++static void
++parse_xkb_xml_layout_node (IBusXKBConfigRegistryPrivate *priv,
++                           XMLNode *parent_node)
++{
++    XMLNode *node = parent_node;
++    XMLNode *sub_node;
++    GList *p;
++    const gchar *name = NULL;
++    GList *variant_list = NULL;
++
++    g_assert (node != NULL);
++    for (p = node->sub_nodes; p; p = p->next) {
++        sub_node = (XMLNode *) p->data;
++        if (g_strcmp0 (sub_node->name, "configItem") == 0) {
++            name = parse_xkb_xml_configitem_node (priv, sub_node);
++            continue;
++        }
++        if (g_strcmp0 (sub_node->name, "variantList") == 0) {
++            if (name == NULL) {
++                g_warning ("layout name is NULL in node %s", node->name);
++                continue;
++            }
++            variant_list = parse_xkb_xml_variantlist_node (priv, sub_node,
++                                                           name,
++                                                           variant_list);
++            continue;
++        }
++    }
++    if (g_hash_table_lookup (priv->layout_list, name) != NULL) {
++        g_warning ("duplicated name %s exists", name);
++        return;
++    }
++    g_hash_table_insert (priv->layout_list,
++                         (gpointer) g_strdup (name),
++                         (gpointer) variant_list);
++}
++
++static void
++parse_xkb_xml_top_node (IBusXKBConfigRegistryPrivate *priv,
++                        XMLNode *parent_node)
++{
++    XMLNode *node = parent_node;
++    XMLNode *sub_node;
++    GList *p;
++
++    g_assert (priv != NULL);
++    g_assert (node != NULL);
++
++    if (g_strcmp0 (node->name, "xkbConfigRegistry") != 0) {
++        g_warning ("node has no xkbConfigRegistry name");
++        return;
++    }
++    for (p = node->sub_nodes; p; p = p->next) {
++        sub_node = (XMLNode *) p->data;
++        if (g_strcmp0 (sub_node->name, "layoutList") == 0) {
++            break;
++        }
++    }
++    if (p == NULL) {
++        g_warning ("xkbConfigRegistry node has no layoutList node");
++        return;
++    }
++    node = sub_node;
++    for (p = node->sub_nodes; p; p = p->next) {
++        sub_node = (XMLNode *) p->data;
++        if (g_strcmp0 (sub_node->name, "layout") == 0) {
++            parse_xkb_xml_layout_node (priv, sub_node);
++            continue;
++        }
++    }
++}
++
++static void
++free_lang_list (GList *list)
++{
++    GList *l = list;
++    while (l) {
++        g_free (l->data);
++        l->data = NULL;
++        l = l->next;
++    }
++    g_list_free (list);
++}
++
++static void
++parse_xkb_config_registry_file (IBusXKBConfigRegistryPrivate *priv,
++                                const gchar *file)
++{
++    XMLNode *node;
++
++    g_assert (file != NULL);
++
++    priv->layout_list = g_hash_table_new_full (g_str_hash,
++                                               (GEqualFunc) g_str_equal,
++                                               (GDestroyNotify) g_free,
++                                               (GDestroyNotify) free_lang_list);
++    priv->layout_desc = g_hash_table_new_full (g_str_hash,
++                                               (GEqualFunc) g_str_equal,
++                                               (GDestroyNotify) g_free,
++                                               (GDestroyNotify) g_free);
++    priv->layout_lang = g_hash_table_new_full (g_str_hash,
++                                               (GEqualFunc) g_str_equal,
++                                               (GDestroyNotify) g_free,
++                                               (GDestroyNotify) free_lang_list);
++    priv->variant_desc = g_hash_table_new_full (g_str_hash,
++                                               (GEqualFunc) g_str_equal,
++                                               (GDestroyNotify) g_free,
++                                               (GDestroyNotify) g_free);
++    node = ibus_xml_parse_file (file);
++    parse_xkb_xml_top_node (priv, node);
++    ibus_xml_free (node);
++}
++
++static void
++ibus_xkb_config_registry_init (IBusXKBConfigRegistry *xkb_config)
++{
++    IBusXKBConfigRegistryPrivate *priv;
++    const gchar *file = XKB_RULES_XML_FILE;
++
++    priv = IBUS_XKB_CONFIG_REGISTRY_GET_PRIVATE (xkb_config);
++    parse_xkb_config_registry_file (priv, file);
++}
++
++static void
++ibus_xkb_config_registry_destroy (IBusXKBConfigRegistry *xkb_config)
++{
++    IBusXKBConfigRegistryPrivate *priv;
++
++    g_return_if_fail (xkb_config != NULL);
++
++    priv = IBUS_XKB_CONFIG_REGISTRY_GET_PRIVATE (xkb_config);
++
++    g_hash_table_destroy (priv->layout_list);
++    priv->layout_list = NULL;
++    g_hash_table_destroy (priv->layout_lang);
++    priv->layout_lang= NULL;
++    g_hash_table_destroy (priv->layout_desc);
++    priv->layout_desc= NULL;
++    g_hash_table_destroy (priv->variant_desc);
++    priv->variant_desc = NULL;
++
++    IBUS_OBJECT_CLASS(ibus_xkb_config_registry_parent_class)->destroy (IBUS_OBJECT (xkb_config));
++}
++
++static void
++ibus_xkb_config_registry_class_init (IBusXKBConfigRegistryClass *klass)
++{
++    IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
++
++    g_type_class_add_private (klass, sizeof (IBusXKBConfigRegistryPrivate));
++
++    ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_xkb_config_registry_destroy;
++}
++
++IBusXKBConfigRegistry *
++ibus_xkb_config_registry_new (void)
++{
++    IBusXKBConfigRegistry *xkb_config;
++
++    xkb_config = IBUS_XKB_CONFIG_REGISTRY (g_object_new (IBUS_TYPE_XKB_CONFIG_REGISTRY, NULL));
++    return xkb_config;
++}
++
++#define TABLE_FUNC(field_name) const GHashTable *                       \
++ibus_xkb_config_registry_get_##field_name  (IBusXKBConfigRegistry *xkb_config) \
++{                                                                       \
++    IBusXKBConfigRegistryPrivate *priv;                                 \
++                                                                        \
++    g_return_val_if_fail (xkb_config != NULL, NULL);                    \
++    priv = IBUS_XKB_CONFIG_REGISTRY_GET_PRIVATE (xkb_config);           \
++    return priv->field_name;                                            \
++}
++
++TABLE_FUNC (layout_list)
++TABLE_FUNC (layout_lang)
++TABLE_FUNC (layout_desc)
++TABLE_FUNC (variant_desc)
++
++#undef TABLE_FUNC
++
++#define TABLE_LOOKUP_LIST_FUNC(field_name, value) GList *               \
++ibus_xkb_config_registry_##field_name##_get_##value  (IBusXKBConfigRegistry *xkb_config, const gchar *key) \
++{                                                                       \
++    GHashTable *table;                                                  \
++    GList *list = NULL;                                                 \
++                                                                        \
++    table = (GHashTable *)                                              \
++        ibus_xkb_config_registry_get_##field_name (xkb_config);         \
++    list = (GList *) g_hash_table_lookup (table, key);                  \
++    return g_list_copy (list);                                          \
++}
++
++#define TABLE_LOOKUP_STRING_FUNC(field_name, value) gchar *             \
++ibus_xkb_config_registry_##field_name##_get_##value  (IBusXKBConfigRegistry *xkb_config, const gchar *key) \
++{                                                                       \
++    GHashTable *table;                                                  \
++    const gchar *desc = NULL;                                           \
++                                                                        \
++    table = (GHashTable *)                                              \
++        ibus_xkb_config_registry_get_##field_name (xkb_config);         \
++    desc = (const gchar *) g_hash_table_lookup (table, key);            \
++    return g_strdup (desc);                                             \
++}
++
++TABLE_LOOKUP_LIST_FUNC (layout_list, variants)
++TABLE_LOOKUP_LIST_FUNC (layout_lang, langs)
++TABLE_LOOKUP_STRING_FUNC (layout_desc, desc)
++TABLE_LOOKUP_STRING_FUNC (variant_desc, desc)
++
++#undef TABLE_LOOKUP_LIST_FUNC
++#undef TABLE_LOOKUP_STRING_FUNC
+diff --git a/src/ibusxkbxml.h b/src/ibusxkbxml.h
+new file mode 100644
+index 0000000..6986b5c
+--- /dev/null
++++ b/src/ibusxkbxml.h
+@@ -0,0 +1,172 @@
++/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
++/* vim:set et sts=4: */
++/* bus - The Input Bus
++ * Copyright (C) 2011 Takao Fujiwara <takao.fujiwara1 at gmail.com>
++ * Copyright (C) 2011 Peng Huang <shawn.p.huang at gmail.com>
++ * Copyright (C) 2011 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 library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++#ifndef __IBUS_XKBXML_H_
++#define __IBUS_XKBXML_H_
++
++#include "ibus.h"
++
++/*
++ * Type macros.
++ */
++/* define IBusXKBConfigRegistry macros */
++#define IBUS_TYPE_XKB_CONFIG_REGISTRY                   \
++    (ibus_xkb_config_registry_get_type ())
++#define IBUS_XKB_CONFIG_REGISTRY(obj)                   \
++    (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_XKB_CONFIG_REGISTRY, IBusXKBConfigRegistry))
++#define IBUS_XKB_CONFIG_REGISTRY_CLASS(klass)           \
++    (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_XKB_CONFIG_REGISTRY, IBusXKBConfigRegistryClass))
++#define IBUS_IS_XKB_CONFIG_REGISTRY(obj)                \
++    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_XKB_CONFIG_REGISTRY))
++#define IBUS_IS_XKB_CONFIG_REGISTRY_CLASS(klass)        \
++    (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_XKB_CONFIG_REGISTRY))
++#define IBUS_XKB_CONFIG_REGISTRY_GET_CLASS(obj)         \
++    (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_XKB_CONFIG_REGISTRY, IBusXKBConfigRegistryClass))
++
++G_BEGIN_DECLS
++
++typedef struct _IBusXKBConfigRegistry IBusXKBConfigRegistry;
++typedef struct _IBusXKBConfigRegistryClass IBusXKBConfigRegistryClass;
++
++struct _IBusXKBConfigRegistry {
++    IBusObject parent;
++};
++
++struct _IBusXKBConfigRegistryClass {
++    IBusObjectClass parent;
++    /* signals */
++    /*< private >*/
++    /* padding */
++    gpointer pdummy[8];
++};
++
++
++GType            ibus_xkb_config_registry_get_type
++                                                 (void);
++
++/**
++ * ibus_xkb_config_registry_new:
++ * @returns: A newly allocated IBusXKBConfigRegistry
++ *
++ * New an IBusXKBConfigRegistry.
++ */
++IBusXKBConfigRegistry *
++                 ibus_xkb_config_registry_new
++                                                 (void);
++
++/**
++ * ibus_xkb_config_registry_get_layout_list: (skip)
++ * @xkb_config: An IBusXKBConfigRegistry.
++ * @returns: A const GHashTable
++ *
++ * a const GHashTable
++ */
++const GHashTable *
++                 ibus_xkb_config_registry_get_layout_list
++                                                 (IBusXKBConfigRegistry *xkb_config);
++
++/**
++ * ibus_xkb_config_registry_get_layout_lang: (skip)
++ * @xkb_config: An IBusXKBConfigRegistry.
++ * @returns: A const GHashTable
++ *
++ * a const GHashTable
++ */
++const GHashTable *
++                 ibus_xkb_config_registry_get_layout_lang
++                                                 (IBusXKBConfigRegistry *xkb_config);
++
++/**
++ * ibus_xkb_config_registry_get_layout_desc: (skip)
++ * @xkb_config: An IBusXKBConfigRegistry.
++ * @returns: A const GHashTable
++ *
++ * a const GHashTable
++ */
++const GHashTable *
++                 ibus_xkb_config_registry_get_layout_desc
++                                                 (IBusXKBConfigRegistry *xkb_config);
++
++/**
++ * ibus_xkb_config_registry_get_variant_desc: (skip)
++ * @xkb_config: An IBusXKBConfigRegistry.
++ * @returns: A const GHashTable
++ *
++ * a const GHashTable
++ */
++const GHashTable *
++                 ibus_xkb_config_registry_get_variant_desc
++                                                 (IBusXKBConfigRegistry *xkb_config);
++
++/**
++ * ibus_xkb_config_registry_layout_list_get_variants:
++ * @xkb_config: An IBusXKBConfigRegistry.
++ * @layout: A layout.
++ * @returns: (transfer container) (element-type utf8): A GList
++ *
++ * a GList
++ */
++GList *
++                 ibus_xkb_config_registry_layout_list_get_variants
++                                                 (IBusXKBConfigRegistry *xkb_config,
++                                                  const gchar           *layout);
++
++/**
++ * ibus_xkb_config_registry_layout_lang_get_langs:
++ * @xkb_config: An IBusXKBConfigRegistry.
++ * @layout: A layout.
++ * @returns: (transfer container) (element-type utf8): A GList
++ *
++ * a GList
++ */
++GList *
++                 ibus_xkb_config_registry_layout_lang_get_langs
++                                                 (IBusXKBConfigRegistry *xkb_config,
++                                                  const gchar           *layout);
++
++/**
++ * ibus_xkb_config_registry_layout_desc_get_desc:
++ * @xkb_config: An IBusXKBConfigRegistry.
++ * @layout: A layout.
++ * @returns: A layout description
++ *
++ * a layout description
++ */
++gchar *
++                 ibus_xkb_config_registry_layout_desc_get_desc
++                                                 (IBusXKBConfigRegistry *xkb_config,
++                                                  const gchar           *layout);
++
++/**
++ * ibus_xkb_config_registry_variant_desc_get_desc:
++ * @xkb_config: An IBusXKBConfigRegistry.
++ * @variant: A variant.
++ * @returns: A variant description
++ *
++ * a variant description
++ */
++gchar *
++                 ibus_xkb_config_registry_variant_desc_get_desc
++                                                 (IBusXKBConfigRegistry *xkb_config,
++                                                  const gchar           *variant);
++G_END_DECLS
++#endif
+diff --git a/ui/gtk/panel.py b/ui/gtk/panel.py
+index 90be1d5..de64920 100644
+--- a/ui/gtk/panel.py
++++ b/ui/gtk/panel.py
+@@ -132,6 +132,22 @@ class Panel(ibus.PanelBase):
+         self.__config_load_show_im_name()
+         # self.__bus.request_name(ibus.panel.IBUS_SERVICE_PANEL, 0)
+ 
++        # init xkb
++        self.__xkblayout = ibus.XKBLayout(self.__config)
++        use_xkb = self.__config.get_value("general", "use_system_keyboard_layout", False)
++        if not use_xkb:
++            self.__xkblayout.use_xkb(use_xkb)
++        value = str(self.__config.get_value("general", "system_keyboard_layout", ''))
++        if value == '':
++            value = 'default'
++        if value != 'default':
++            self.__xkblayout.set_default_layout(value)
++        value = str(self.__config.get_value("general", "system_keyboard_option", ''))
++        if value == '':
++            value = 'default'
++        if value != 'default':
++            self.__xkblayout.set_default_option(value)
++
+     def set_cursor_location(self, x, y, w, h):
+         self.__candidate_panel.set_cursor_location(x, y, w, h)
+ 
+@@ -226,14 +242,20 @@ class Panel(ibus.PanelBase):
+         if not enabled:
+             self.__set_im_icon(ICON_KEYBOARD)
+             self.__set_im_name(None)
++            if self.__bus.get_use_sys_layout():
++                self.__xkblayout.set_layout()
+         else:
+             engine = self.__focus_ic.get_engine()
+             if engine:
+                 self.__set_im_icon(engine.icon)
+                 self.__set_im_name(engine.longname)
++                if self.__bus.get_use_sys_layout():
++                    self.__xkblayout.set_layout(self.__engine_get_layout_wrapper(engine))
+             else:
+                 self.__set_im_icon(ICON_KEYBOARD)
+                 self.__set_im_name(None)
++                if self.__bus.get_use_sys_layout():
++                    self.__xkblayout.set_layout()
+         self.__language_bar.focus_in()
+ 
+     def focus_out(self, ic):
+@@ -243,6 +265,8 @@ class Panel(ibus.PanelBase):
+         self.__language_bar.focus_out()
+         self.__set_im_icon(ICON_KEYBOARD)
+         self.__set_im_name(None)
++        if self.__bus.get_use_sys_layout():
++            self.__xkblayout.set_layout()
+ 
+     def state_changed(self):
+         if not self.__focus_ic:
+@@ -255,14 +279,20 @@ class Panel(ibus.PanelBase):
+             self.reset()
+             self.__set_im_icon(ICON_KEYBOARD)
+             self.__set_im_name(None)
++            if self.__bus.get_use_sys_layout():
++                self.__xkblayout.set_layout()
+         else:
+             engine = self.__focus_ic.get_engine()
+             if engine:
+                 self.__set_im_icon(engine.icon)
+                 self.__set_im_name(engine.longname)
++                if self.__bus.get_use_sys_layout():
++                    self.__xkblayout.set_layout(self.__engine_get_layout_wrapper(engine))
+             else:
+                 self.__set_im_icon(ICON_KEYBOARD)
+                 self.__set_im_name(None)
++                if self.__bus.get_use_sys_layout():
++                    self.__xkblayout.set_layout()
+ 
+ 
+     def reset(self):
+@@ -542,3 +572,12 @@ class Panel(ibus.PanelBase):
+                                flags=glib.SPAWN_DO_NOT_REAP_CHILD)[0]
+         self.__setup_pid = pid
+         glib.child_watch_add(self.__setup_pid, self.__child_watch_cb)
++
++    def __engine_get_layout_wrapper(self, engine):
++        # This code is for the back compatibility.
++        # Should we remove the codes after all IM engines are changed
++        # to "default" layout?
++        if engine.name != None and engine.name.startswith("xkb:layout:"):
++            return engine.layout
++        else:
++            return "default"
+diff --git a/xkb/Makefile.am b/xkb/Makefile.am
+new file mode 100644
+index 0000000..ad9cdd9
+--- /dev/null
++++ b/xkb/Makefile.am
+@@ -0,0 +1,104 @@
++# vim:set noet ts=4:
++#
++# ibus - The Input Bus
++#
++# Copyright (C) 2011 Takao Fujiwara <takao.fujiwara1 at gmail.com>
++# Copyright (c) 2011 Peng Huang <shawn.p.huang at gmail.com>
++# Copyright (c) 2011 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
++
++libibus = $(top_builddir)/src/libibus- at IBUS_API_VERSION@.la
++
++INCLUDES = \
++        -I$(top_srcdir) \
++        -I$(top_srcdir)/src \
++	-DIBUS_LOCALEDIR=\"$(datadir)/locale\" \
++	-DLIBEXECDIR=\""$(libexecdir)"\" \
++        $(NULL)
++
++noinst_PROGRAMS = $(TESTS)
++libexec_PROGRAMS =
++EXTRA_DIST =
++DISTCLEANFILES =
++
++if ENABLE_XKB
++libexec_PROGRAMS += ibus-xkb
++ibus_xkb_SOURCES = \
++	ibus-xkb-main.c \
++	xkblib.h \
++	xkblib.c \
++	$(NULL)
++ibus_xkb_CFLAGS = \
++	@XKB_CFLAGS@ \
++	@X11_CFLAGS@ \
++	@GLIB2_CFLAGS@ \
++	$(NULL)
++ibus_xkb_LDADD = \
++	@XKB_LIBS@ \
++	@X11_LIBS@ \
++	@GLIB2_LIBS@ \
++	$(libibus) \
++	$(NULL)
++
++libexec_PROGRAMS += ibus-engine-xkb
++ibus_engine_xkb_SOURCES = \
++        ibus-engine-xkb-main.c \
++        ibus-engine-xkb-main.h \
++        xkbxml.c \
++        xkbxml.h \
++        $(NULL)
++ibus_engine_xkb_CFLAGS = \
++	@GLIB2_CFLAGS@ \
++	@GOBJECT2_CFLAGS@ \
++	@GCONF_CFLAGS@ \
++        $(NULL)
++ibus_engine_xkb_LDADD = \
++	@GLIB2_LIBS@ \
++	@GOBJECT2_LIBS@ \
++	@GCONF_LIBS@ \
++	$(libibus) \
++        $(NULL)
++
++xkblayoutdir = $(datadir)/ibus/component
++xkblayout_in_files = xkblayout.xml.in
++xkblayout_DATA = $(xkblayout_in_files:.xml.in=.xml)
++
++xkblayoutconfigdir = $(datadir)/ibus/xkb
++xkblayoutconfig_in_files = xkblayoutconfig.xml.in
++xkblayoutconfig_DATA = $(xkblayoutconfig_in_files:.xml.in=.xml)
++
++%.xml : %.xml.in
++	@sed -e "s|\@libexecdir\@|$(libexecdir)|g" \
++	     -e "s|\@datadir\@|$(datadir)|g" \
++	     -e "s|\@XKB_PRELOAD_LAYOUTS\@|$(XKB_PRELOAD_LAYOUTS)|g" \
++	$< > $@
++
++INCLUDES += \
++	-DXKBLAYOUTCONFIG_FILE=\""$(xkblayoutconfigdir)/$(xkblayoutconfig_DATA)"\" \
++	$(NULL)
++
++EXTRA_DIST += \
++        $(xkblayout_in_files) \
++        $(xkblayoutconfig_in_files) \
++        $(NULL)
++
++DISTCLEANFILES += \
++        $(xkblayout_DATA) \
++        $(xkblayoutconfig_DATA) \
++        $(NULL)
++
++endif
+diff --git a/xkb/ibus-engine-xkb-main.c b/xkb/ibus-engine-xkb-main.c
+new file mode 100644
+index 0000000..5d748cc
+--- /dev/null
++++ b/xkb/ibus-engine-xkb-main.c
+@@ -0,0 +1,397 @@
++/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
++/* vim:set et sts=4: */
++/* bus - The Input Bus
++ * Copyright (C) 2011 Takao Fujiwara <takao.fujiwara1 at gmail.com>
++ * Copyright (C) 2011 Peng Huang <shawn.p.huang at gmail.com>
++ * Copyright (C) 2011 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 library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <gconf/gconf-client.h>
++#include <ibus.h>
++#include <stdlib.h>
++
++#ifdef ENABLE_NLS
++#include <locale.h>
++#endif
++
++#include "ibus-engine-xkb-main.h"
++#include "xkbxml.h"
++
++#define IBUS_TYPE_XKB_ENGINE (ibus_xkb_engine_get_type ())
++
++static IBusBus *bus = NULL;
++static IBusFactory *factory = NULL;
++static IBusEngineClass *parent_class = NULL;
++static gboolean ibus = FALSE;
++static gboolean xml = FALSE;
++
++static const GOptionEntry entries[] =
++{
++    { "ibus", 'i', 0, G_OPTION_ARG_NONE, &ibus, "component is executed by ibus", NULL },
++    { "xml", 'x', 0, G_OPTION_ARG_NONE, &xml, "print component xml", NULL },
 +    { NULL },
 +};
 +
@@ -2808,16 +3466,16 @@ index 0000000..e1861e8
 +}
 diff --git a/xkb/ibus-engine-xkb-main.h b/xkb/ibus-engine-xkb-main.h
 new file mode 100644
-index 0000000..8007631
+index 0000000..c17c857
 --- /dev/null
 +++ b/xkb/ibus-engine-xkb-main.h
 @@ -0,0 +1,46 @@
 +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 +/* vim:set et sts=4: */
 +/* bus - The Input Bus
-+ * Copyright (C) 2010 Takao Fujiwara <takao.fujiwara1 at gmail.com>
-+ * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang at gmail.com>
-+ * Copyright (C) 2008-2010 Red Hat, Inc.
++ * Copyright (C) 2011 Takao Fujiwara <takao.fujiwara1 at gmail.com>
++ * Copyright (C) 2011 Peng Huang <shawn.p.huang at gmail.com>
++ * Copyright (C) 2011 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
@@ -2860,16 +3518,16 @@ index 0000000..8007631
 +#endif
 diff --git a/xkb/ibus-xkb-main.c b/xkb/ibus-xkb-main.c
 new file mode 100644
-index 0000000..9db7d0a
+index 0000000..ef57553
 --- /dev/null
 +++ b/xkb/ibus-xkb-main.c
-@@ -0,0 +1,105 @@
+@@ -0,0 +1,112 @@
 +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 +/* vim:set et sts=4: */
 +/* bus - The Input Bus
-+ * Copyright (C) 2010 Takao Fujiwara <takao.fujiwara1 at gmail.com>
-+ * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang at gmail.com>
-+ * Copyright (C) 2008-2010 Red Hat, Inc.
++ * Copyright (C) 2011 Takao Fujiwara <takao.fujiwara1 at gmail.com>
++ * Copyright (C) 2011 Peng Huang <shawn.p.huang at gmail.com>
++ * Copyright (C) 2011 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
@@ -2902,9 +3560,11 @@ index 0000000..9db7d0a
 +#include "xkblib.h"
 +
 +static gboolean get_layout = FALSE;
++static gboolean get_group = FALSE;
 +static gchar *layout = NULL;
 +static gchar *model = NULL;
 +static gchar *option = NULL;
++static int group = 0;
 +
 +static const GOptionEntry entries[] =
 +{
@@ -2913,6 +3573,7 @@ index 0000000..9db7d0a
 +    { "layout", 'l', 0, G_OPTION_ARG_STRING, &layout, N_("Set xkb layout"), "layout" },
 +    { "model", 'm', 0, G_OPTION_ARG_STRING, &model, N_("Set xkb model"), "model" },
 +    { "option", 'o', 0, G_OPTION_ARG_STRING, &option, N_("Set xkb option"), "option" },
++    { "get-group", 'G', 0, G_OPTION_ARG_NONE, &get_group, N_("Get current xkb state"), NULL },
 +    { NULL },
 +};
 +
@@ -2964,6 +3625,10 @@ index 0000000..9db7d0a
 +        g_free (model);
 +        g_free (option);
 +    }
++    if (get_group) {
++        group = ibus_xkb_get_current_group ();
++        g_printf ("group: %d\n", group);
++    }
 +
 +    ibus_xkb_finit ();
 +
@@ -3005,16 +3670,16 @@ index 0000000..b1212d1
 +</xkblayout>
 diff --git a/xkb/xkblib.c b/xkb/xkblib.c
 new file mode 100644
-index 0000000..640f783
+index 0000000..293cdaf
 --- /dev/null
 +++ b/xkb/xkblib.c
-@@ -0,0 +1,303 @@
+@@ -0,0 +1,327 @@
 +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 +/* vim:set et sts=4: */
 +/* bus - The Input Bus
-+ * Copyright (C) 2010 Takao Fujiwara <takao.fujiwara1 at gmail.com>
-+ * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang at gmail.com>
-+ * Copyright (C) 2008-2010 Red Hat, Inc.
++ * Copyright (C) 2011 Takao Fujiwara <takao.fujiwara1 at gmail.com>
++ * Copyright (C) 2011 Peng Huang <shawn.p.huang at gmail.com>
++ * Copyright (C) 2011 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
@@ -3292,7 +3957,7 @@ index 0000000..640f783
 +
 +    if (default_layouts == NULL) {
 +        g_warning ("Your system seems not to support XKB.");
-+        return NULL;
++        return FALSE;
 +    }
 +
 +    if (layouts == NULL || g_strcmp0 (layouts, "default") == 0) {
@@ -3312,18 +3977,42 @@ index 0000000..640f783
 +
 +    return retval;
 +}
++
++int
++ibus_xkb_get_current_group (void)
++{
++    Display *xdisplay = get_xdisplay (NULL);
++    XkbStateRec state;
++
++    if (default_layouts == NULL) {
++        g_warning ("Your system seems not to support XKB.");
++        return 0;
++    }
++
++    if (xdisplay == NULL) {
++        g_warning ("ibus-xkb is not initialized.");
++        return 0;
++    }
++
++    if (XkbGetState (xdisplay, XkbUseCoreKbd, &state) != Success) {
++        g_warning ("Could not get state");
++        return 0;
++    }
++
++    return state.group;
++}
 diff --git a/xkb/xkblib.h b/xkb/xkblib.h
 new file mode 100644
-index 0000000..09d506d
+index 0000000..15e5d18
 --- /dev/null
 +++ b/xkb/xkblib.h
-@@ -0,0 +1,40 @@
+@@ -0,0 +1,41 @@
 +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 +/* vim:set et sts=4: */
 +/* bus - The Input Bus
-+ * Copyright (C) 2010 Takao Fujiwara <takao.fujiwara1 at gmail.com>
-+ * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang at gmail.com>
-+ * Copyright (C) 2008-2010 Red Hat, Inc.
++ * Copyright (C) 2011 Takao Fujiwara <takao.fujiwara1 at gmail.com>
++ * Copyright (C) 2011 Peng Huang <shawn.p.huang at gmail.com>
++ * Copyright (C) 2011 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
@@ -3355,21 +4044,22 @@ index 0000000..09d506d
 +gboolean         ibus_xkb_set_layout             (const char *layouts,
 +                                                  const char *variants,
 +                                                  const char *options);
++int              ibus_xkb_get_current_group      (void);
 +
 +G_END_DECLS
 +#endif
 diff --git a/xkb/xkbxml.c b/xkb/xkbxml.c
 new file mode 100644
-index 0000000..f5582ff
+index 0000000..2ce7bcf
 --- /dev/null
 +++ b/xkb/xkbxml.c
-@@ -0,0 +1,696 @@
+@@ -0,0 +1,335 @@
 +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 +/* vim:set et sts=4: */
 +/* bus - The Input Bus
-+ * Copyright (C) 2010 Takao Fujiwara <takao.fujiwara1 at gmail.com>
-+ * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang at gmail.com>
-+ * Copyright (C) 2008-2010 Red Hat, Inc.
++ * Copyright (C) 2011 Takao Fujiwara <takao.fujiwara1 at gmail.com>
++ * Copyright (C) 2011 Peng Huang <shawn.p.huang at gmail.com>
++ * Copyright (C) 2011 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
@@ -3392,294 +4082,29 @@ index 0000000..f5582ff
 +
 +#include <glib.h>
 +
-+#include "xkbxml.h"
-+#include "ibus.h"
-+
-+#ifndef XKB_RULES_XML_FILE
-+#define XKB_RULES_XML_FILE "/usr/share/X11/xkb/rules/evdev.xml"
-+#endif
-+
-+#define IBUS_XKB_CONFIG_REGISTRY_GET_PRIVATE(o)  \
-+   (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_XKB_CONFIG_REGISTRY, IBusXKBConfigRegistryPrivate))
-+#define IBUS_XKB_LAYOUT_CONFIG_GET_PRIVATE(o)  \
-+   (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_XKB_LAYOUT_CONFIG, IBusXKBLayoutConfigPrivate))
-+
-+typedef struct _IBusXKBConfigRegistryPrivate IBusXKBConfigRegistryPrivate;
-+typedef struct _IBusXKBLayoutConfigPrivate IBusXKBLayoutConfigPrivate;
-+
-+enum {
-+    PROP_0,
-+    PROP_SYSTEM_CONFIG_FILE,
-+};
-+
-+struct _IBusXKBConfigRegistryPrivate {
-+    GHashTable *layout_list;
-+    GHashTable *layout_lang;
-+    GHashTable *layout_desc;
-+    GHashTable *variant_desc;
-+};
-+
-+struct _IBusXKBLayoutConfigPrivate {
-+    gchar *system_config_file;
-+    GList *preload_layouts;
-+};
-+
-+/* functions prototype */
-+static void         ibus_xkb_config_registry_destroy
-+                                           (IBusXKBConfigRegistry *xkb_config);
-+static void         ibus_xkb_layout_config_destroy
-+                                           (IBusXKBLayoutConfig *xkb_layout_config);
-+
-+G_DEFINE_TYPE (IBusXKBConfigRegistry, ibus_xkb_config_registry, IBUS_TYPE_OBJECT)
-+G_DEFINE_TYPE (IBusXKBLayoutConfig, ibus_xkb_layout_config, IBUS_TYPE_OBJECT)
-+
-+static void
-+parse_xkb_xml_languagelist_node (IBusXKBConfigRegistryPrivate *priv,
-+                                 XMLNode *parent_node,
-+                                 const gchar *layout_name)
-+{
-+    XMLNode *node = parent_node;
-+    XMLNode *sub_node;
-+    GList *p;
-+    GList *lang_list = NULL;
-+
-+    g_assert (node != NULL);
-+    g_assert (layout_name != NULL);
-+    for (p = node->sub_nodes; p; p = p->next) {
-+        sub_node = (XMLNode *) p->data;
-+        if (g_strcmp0 (sub_node->name, "iso639Id") == 0) {
-+            lang_list = g_list_append (lang_list,
-+                                       (gpointer) g_strdup (sub_node->text));
-+            continue;
-+        }
-+    }
-+    if (lang_list == NULL) {
-+        /* some nodes have no lang */
-+        return;
-+    }
-+    if (g_hash_table_lookup (priv->layout_lang, layout_name) != NULL) {
-+        g_warning ("duplicated name %s exists", layout_name);
-+        return;
-+    }
-+    g_hash_table_insert (priv->layout_lang,
-+                         (gpointer) g_strdup (layout_name),
-+                         (gpointer) lang_list);
-+}
-+
-+static const gchar *
-+parse_xkb_xml_configitem_node (IBusXKBConfigRegistryPrivate *priv,
-+                               XMLNode *parent_node)
-+{
-+    XMLNode *node = parent_node;
-+    XMLNode *sub_node;
-+    GList *p;
-+    gchar *name = NULL;
-+    gchar *description = NULL;
-+
-+    g_assert (node != NULL);
-+    for (p = node->sub_nodes; p; p = p->next) {
-+        sub_node = (XMLNode *) p->data;
-+        if (g_strcmp0 (sub_node->name, "name") == 0) {
-+            name = sub_node->text;
-+            continue;
-+        }
-+        if (g_strcmp0 (sub_node->name, "description") == 0) {
-+            description = sub_node->text;
-+            continue;
-+        }
-+        if (g_strcmp0 (sub_node->name, "languageList") == 0) {
-+            if (name == NULL) {
-+                g_warning ("layout name is NULL in node %s", node->name);
-+                continue;
-+            }
-+            parse_xkb_xml_languagelist_node (priv, sub_node, name);
-+            continue;
-+        }
-+    }
-+    if (name == NULL) {
-+        g_warning ("No name in layout node");
-+        return NULL;
-+    }
-+    if (g_hash_table_lookup (priv->layout_desc, name) != NULL) {
-+        g_warning ("duplicated name %s exists", name);
-+        return name;
-+    }
-+    g_hash_table_insert (priv->layout_desc,
-+                         (gpointer) g_strdup (name),
-+                         (gpointer) g_strdup (description));
-+
-+    return name;
-+}
-+
-+static const gchar *
-+parse_xkb_xml_variant_configitem_node (IBusXKBConfigRegistryPrivate *priv,
-+                            XMLNode *parent_node,
-+                            const gchar *layout_name)
-+{
-+    XMLNode *node = parent_node;
-+    XMLNode *sub_node;
-+    GList *p;
-+    gchar *name = NULL;
-+    gchar *description = NULL;
-+    gchar *variant_lang_name = NULL;
-+
-+    g_assert (node != NULL);
-+    g_assert (layout_name != NULL);
-+    for (p = node->sub_nodes; p; p = p->next) {
-+        sub_node = (XMLNode *) p->data;
-+        if (g_strcmp0 (sub_node->name, "name") == 0) {
-+            name = sub_node->text;
-+            continue;
-+        }
-+        if (g_strcmp0 (sub_node->name, "description") == 0) {
-+            description = sub_node->text;
-+            continue;
-+        }
-+        if (g_strcmp0 (sub_node->name, "languageList") == 0) {
-+            if (name == NULL) {
-+                g_warning ("layout name is NULL in node %s", node->name);
-+                continue;
-+            }
-+            variant_lang_name = g_strdup_printf ("%s(%s)", layout_name, name);
-+            parse_xkb_xml_languagelist_node (priv, sub_node, variant_lang_name);
-+            g_free (variant_lang_name);
-+            continue;
-+        }
-+    }
-+    if (name == NULL) {
-+        g_warning ("No name in layout node");
-+        return NULL;
-+    }
-+    if (g_hash_table_lookup (priv->variant_desc, name) != NULL) {
-+        /* This is an expected case. */
-+        return name;
-+    }
-+    g_hash_table_insert (priv->variant_desc,
-+                         (gpointer) g_strdup (name),
-+                         (gpointer) g_strdup (description));
-+    return name;
-+}
-+
-+static const gchar *
-+parse_xkb_xml_variant_node (IBusXKBConfigRegistryPrivate *priv,
-+                            XMLNode *parent_node,
-+                            const gchar *layout_name)
-+{
-+    XMLNode *node = parent_node;
-+    XMLNode *sub_node;
-+    GList *p;
-+    const gchar *variant_name = NULL;
-+
-+    g_assert (node != NULL);
-+    g_assert (layout_name != NULL);
-+    for (p = node->sub_nodes; p; p = p->next) {
-+        sub_node = (XMLNode *) p->data;
-+        if (g_strcmp0 (sub_node->name, "configItem") == 0) {
-+            variant_name = parse_xkb_xml_variant_configitem_node (priv, sub_node, layout_name);
-+            continue;
-+        }
-+    }
-+    return variant_name;
-+}
-+
-+static GList *
-+parse_xkb_xml_variantlist_node (IBusXKBConfigRegistryPrivate *priv,
-+                                XMLNode *parent_node,
-+                                const gchar *layout_name,
-+                                GList *variant_list)
-+{
-+    XMLNode *node = parent_node;
-+    XMLNode *sub_node;
-+    GList *p;
-+    const gchar *variant_name = NULL;
-+
-+    g_assert (node != NULL);
-+    g_assert (layout_name != NULL);
-+    for (p = node->sub_nodes; p; p = p->next) {
-+        sub_node = (XMLNode *) p->data;
-+        if (g_strcmp0 (sub_node->name, "variant") == 0) {
-+            variant_name = parse_xkb_xml_variant_node (priv, sub_node, layout_name);
-+            if (variant_name != NULL) {
-+                variant_list = g_list_append (variant_list,
-+                                              (gpointer) g_strdup (variant_name));
-+            }
-+            continue;
-+        }
-+    }
-+    return variant_list;
-+}
++#include "xkbxml.h"
++#include "ibus.h"
 +
-+static void
-+parse_xkb_xml_layout_node (IBusXKBConfigRegistryPrivate *priv,
-+                           XMLNode *parent_node)
-+{
-+    XMLNode *node = parent_node;
-+    XMLNode *sub_node;
-+    GList *p;
-+    const gchar *name = NULL;
-+    GList *variant_list = NULL;
++#define IBUS_XKB_LAYOUT_CONFIG_GET_PRIVATE(o)  \
++   (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_XKB_LAYOUT_CONFIG, IBusXKBLayoutConfigPrivate))
 +
-+    g_assert (node != NULL);
-+    for (p = node->sub_nodes; p; p = p->next) {
-+        sub_node = (XMLNode *) p->data;
-+        if (g_strcmp0 (sub_node->name, "configItem") == 0) {
-+            name = parse_xkb_xml_configitem_node (priv, sub_node);
-+            continue;
-+        }
-+        if (g_strcmp0 (sub_node->name, "variantList") == 0) {
-+            if (name == NULL) {
-+                g_warning ("layout name is NULL in node %s", node->name);
-+                continue;
-+            }
-+            variant_list = parse_xkb_xml_variantlist_node (priv, sub_node,
-+                                                           name,
-+                                                           variant_list);
-+            continue;
-+        }
-+    }
-+    if (g_hash_table_lookup (priv->layout_list, name) != NULL) {
-+        g_warning ("duplicated name %s exists", name);
-+        return;
-+    }
-+    g_hash_table_insert (priv->layout_list,
-+                         (gpointer) g_strdup (name),
-+                         (gpointer) variant_list);
-+}
++typedef struct _IBusXKBLayoutConfigPrivate IBusXKBLayoutConfigPrivate;
 +
-+static void
-+parse_xkb_xml_top_node (IBusXKBConfigRegistryPrivate *priv,
-+                        XMLNode *parent_node)
-+{
-+    XMLNode *node = parent_node;
-+    XMLNode *sub_node;
-+    GList *p;
++enum {
++    PROP_0,
++    PROP_SYSTEM_CONFIG_FILE,
++};
 +
-+    g_assert (priv != NULL);
-+    g_assert (node != NULL);
++struct _IBusXKBLayoutConfigPrivate {
++    gchar *system_config_file;
++    GList *preload_layouts;
++};
 +
-+    if (g_strcmp0 (node->name, "xkbConfigRegistry") != 0) {
-+        g_warning ("node has no xkbConfigRegistry name");
-+        return;
-+    }
-+    for (p = node->sub_nodes; p; p = p->next) {
-+        sub_node = (XMLNode *) p->data;
-+        if (g_strcmp0 (sub_node->name, "layoutList") == 0) {
-+            break;
-+        }
-+    }
-+    if (p == NULL) {
-+        g_warning ("xkbConfigRegistry node has no layoutList node");
-+        return;
-+    }
-+    node = sub_node;
-+    for (p = node->sub_nodes; p; p = p->next) {
-+        sub_node = (XMLNode *) p->data;
-+        if (g_strcmp0 (sub_node->name, "layout") == 0) {
-+            parse_xkb_xml_layout_node (priv, sub_node);
-+            continue;
-+        }
-+    }
-+}
++/* functions prototype */
++static void         ibus_xkb_layout_config_destroy
++                                           (IBusXKBLayoutConfig *xkb_layout_config);
++
++G_DEFINE_TYPE (IBusXKBLayoutConfig, ibus_xkb_layout_config, IBUS_TYPE_OBJECT)
 +
 +static void
 +free_lang_list (GList *list)
@@ -3693,35 +4118,6 @@ index 0000000..f5582ff
 +    g_list_free (list);
 +}
 +
-+static void
-+parse_xkb_config_registry_file (IBusXKBConfigRegistryPrivate *priv,
-+                                const gchar *file)
-+{
-+    XMLNode *node;
-+
-+    g_assert (file != NULL);
-+
-+    priv->layout_list = g_hash_table_new_full (g_str_hash,
-+                                               (GEqualFunc) g_str_equal,
-+                                               (GDestroyNotify) g_free,
-+                                               (GDestroyNotify) free_lang_list);
-+    priv->layout_desc = g_hash_table_new_full (g_str_hash,
-+                                               (GEqualFunc) g_str_equal,
-+                                               (GDestroyNotify) g_free,
-+                                               (GDestroyNotify) g_free);
-+    priv->layout_lang = g_hash_table_new_full (g_str_hash,
-+                                               (GEqualFunc) g_str_equal,
-+                                               (GDestroyNotify) g_free,
-+                                               (GDestroyNotify) free_lang_list);
-+    priv->variant_desc = g_hash_table_new_full (g_str_hash,
-+                                               (GEqualFunc) g_str_equal,
-+                                               (GDestroyNotify) g_free,
-+                                               (GDestroyNotify) g_free);
-+    node = ibus_xml_parse_file (file);
-+    parse_xkb_xml_top_node (priv, node);
-+    ibus_xml_free (node);
-+}
-+
 +static GList *
 +parse_xkblayoutconfig_file (gchar *path)
 +{
@@ -3794,47 +4190,6 @@ index 0000000..f5582ff
 +}
 +
 +static void
-+ibus_xkb_config_registry_init (IBusXKBConfigRegistry *xkb_config)
-+{
-+    IBusXKBConfigRegistryPrivate *priv;
-+    const gchar *file = XKB_RULES_XML_FILE;
-+
-+    priv = IBUS_XKB_CONFIG_REGISTRY_GET_PRIVATE (xkb_config);
-+    parse_xkb_config_registry_file (priv, file);
-+}
-+
-+static void
-+ibus_xkb_config_registry_destroy (IBusXKBConfigRegistry *xkb_config)
-+{
-+    IBusXKBConfigRegistryPrivate *priv;
-+
-+    g_return_if_fail (xkb_config != NULL);
-+
-+    priv = IBUS_XKB_CONFIG_REGISTRY_GET_PRIVATE (xkb_config);
-+
-+    g_hash_table_destroy (priv->layout_list);
-+    priv->layout_list = NULL;
-+    g_hash_table_destroy (priv->layout_lang);
-+    priv->layout_lang= NULL;
-+    g_hash_table_destroy (priv->layout_desc);
-+    priv->layout_desc= NULL;
-+    g_hash_table_destroy (priv->variant_desc);
-+    priv->variant_desc = NULL;
-+
-+    IBUS_OBJECT_CLASS(ibus_xkb_config_registry_parent_class)->destroy (IBUS_OBJECT (xkb_config));
-+}
-+
-+static void
-+ibus_xkb_config_registry_class_init (IBusXKBConfigRegistryClass *klass)
-+{
-+    IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
-+
-+    g_type_class_add_private (klass, sizeof (IBusXKBConfigRegistryPrivate));
-+
-+    ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_xkb_config_registry_destroy;
-+}
-+
-+static void
 +ibus_xkb_layout_config_init (IBusXKBLayoutConfig *xkb_layout_config)
 +{
 +    IBusXKBLayoutConfigPrivate *priv;
@@ -3945,32 +4300,6 @@ index 0000000..f5582ff
 +                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 +}
 +
-+IBusXKBConfigRegistry *
-+ibus_xkb_config_registry_new (void)
-+{
-+    IBusXKBConfigRegistry *xkb_config;
-+
-+    xkb_config = IBUS_XKB_CONFIG_REGISTRY (g_object_new (IBUS_TYPE_XKB_CONFIG_REGISTRY, NULL));
-+    return xkb_config;
-+}
-+
-+#define TABLE_FUNC(field_name) const GHashTable *                       \
-+ibus_xkb_config_registry_get_##field_name  (IBusXKBConfigRegistry *xkb_config) \
-+{                                                                       \
-+    IBusXKBConfigRegistryPrivate *priv;                                 \
-+                                                                        \
-+    g_return_val_if_fail (xkb_config != NULL, NULL);                    \
-+    priv = IBUS_XKB_CONFIG_REGISTRY_GET_PRIVATE (xkb_config);           \
-+    return priv->field_name;                                            \
-+}
-+
-+TABLE_FUNC (layout_list)
-+TABLE_FUNC (layout_lang)
-+TABLE_FUNC (layout_desc)
-+TABLE_FUNC (variant_desc)
-+
-+#undef TABLE_FUNC
-+
 +IBusComponent *
 +ibus_xkb_component_new (void)
 +{
@@ -4062,16 +4391,16 @@ index 0000000..f5582ff
 +}
 diff --git a/xkb/xkbxml.h b/xkb/xkbxml.h
 new file mode 100644
-index 0000000..f4858fa
+index 0000000..56811ef
 --- /dev/null
 +++ b/xkb/xkbxml.h
-@@ -0,0 +1,189 @@
+@@ -0,0 +1,110 @@
 +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 +/* vim:set et sts=4: */
 +/* bus - The Input Bus
-+ * Copyright (C) 2010 Takao Fujiwara <takao.fujiwara1 at gmail.com>
-+ * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang at gmail.com>
-+ * Copyright (C) 2008-2010 Red Hat, Inc.
++ * Copyright (C) 2011 Takao Fujiwara <takao.fujiwara1 at gmail.com>
++ * Copyright (C) 2011 Peng Huang <shawn.p.huang at gmail.com>
++ * Copyright (C) 2011 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
@@ -4088,28 +4417,14 @@ index 0000000..f4858fa
 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 + * Boston, MA 02111-1307, USA.
 + */
-+#ifndef __IBUS_XKB_H_
-+#define __IBUS_XKB_H_
++#ifndef __XKBXML_H_
++#define __XKBXML_H_
 +
 +#include "ibus.h"
 +
 +/*
 + * Type macros.
 + */
-+/* define IBusXKBConfigRegistry macros */
-+#define IBUS_TYPE_XKB_CONFIG_REGISTRY                   \
-+    (ibus_xkb_config_registry_get_type ())
-+#define IBUS_XKB_CONFIG_REGISTRY(obj)                   \
-+    (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_XKB_CONFIG_REGISTRY, IBusXKBConfigRegistry))
-+#define IBUS_XKB_CONFIG_REGISTRY_CLASS(klass)           \
-+    (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_XKB_CONFIG_REGISTRY, IBusXKBConfigRegistryClass))
-+#define IBUS_IS_XKB_CONFIG_REGISTRY(obj)                \
-+    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_XKB_CONFIG_REGISTRY))
-+#define IBUS_IS_XKB_CONFIG_REGISTRY_CLASS(klass)        \
-+    (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_XKB_CONFIG_REGISTRY))
-+#define IBUS_XKB_CONFIG_REGISTRY_GET_CLASS(obj)         \
-+    (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_XKB_CONFIG_REGISTRY, IBusXKBConfigRegistryClass))
-+
 +/* define IBusXKBLayoutConfig macros */
 +#define IBUS_TYPE_XKB_LAYOUT_CONFIG                     \
 +    (ibus_xkb_layout_config_get_type ())
@@ -4126,23 +4441,9 @@ index 0000000..f4858fa
 +
 +G_BEGIN_DECLS
 +
-+typedef struct _IBusXKBConfigRegistry IBusXKBConfigRegistry;
-+typedef struct _IBusXKBConfigRegistryClass IBusXKBConfigRegistryClass;
 +typedef struct _IBusXKBLayoutConfig IBusXKBLayoutConfig;
 +typedef struct _IBusXKBLayoutConfigClass IBusXKBLayoutConfigClass;
 +
-+struct _IBusXKBConfigRegistry {
-+    IBusObject parent;
-+};
-+
-+struct _IBusXKBConfigRegistryClass {
-+    IBusObjectClass parent;
-+    /* signals */
-+    /*< private >*/
-+    /* padding */
-+    gpointer pdummy[8];
-+};
-+
 +struct _IBusXKBLayoutConfig {
 +    IBusObject parent;
 +};
@@ -4156,57 +4457,6 @@ index 0000000..f4858fa
 +};
 +
 +
-+GType            ibus_xkb_config_registry_get_type
-+                                                 (void);
-+/**
-+ * ibus_xkb_config_registry_new:
-+ * @returns: A newly allocated IBusXKBConfigRegistry
-+ *
-+ * New an IBusXKBConfigRegistry.
-+ */
-+IBusXKBConfigRegistry *
-+                 ibus_xkb_config_registry_new
-+                                                 (void);
-+/**
-+ * ibus_xkb_config_registry_get_layout_list:
-+ * @xkb_config: An IBusXKBConfigRegistry.
-+ * @returns: A const GHashTable
-+ *
-+ * a const GHashTable
-+ */
-+const GHashTable *
-+                 ibus_xkb_config_registry_get_layout_list
-+                                                 (IBusXKBConfigRegistry *xkb_config);
-+/**
-+ * ibus_xkb_config_registry_get_layout_lang:
-+ * @xkb_config: An IBusXKBConfigRegistry.
-+ * @returns: A const GHashTable
-+ *
-+ * a const GHashTable
-+ */
-+const GHashTable *
-+                 ibus_xkb_config_registry_get_layout_lang
-+                                                 (IBusXKBConfigRegistry *xkb_config);
-+/**
-+ * ibus_xkb_config_registry_get_layout_desc:
-+ * @xkb_config: An IBusXKBConfigRegistry.
-+ * @returns: A const GHashTable
-+ *
-+ * a const GHashTable
-+ */
-+const GHashTable *
-+                 ibus_xkb_config_registry_get_layout_desc
-+                                                 (IBusXKBConfigRegistry *xkb_config);
-+/**
-+ * ibus_xkb_config_registry_get_variant_desc:
-+ * @xkb_config: An IBusXKBConfigRegistry.
-+ * @returns: A const GHashTable
-+ *
-+ * a const GHashTable
-+ */
-+const GHashTable *
-+                 ibus_xkb_config_registry_get_variant_desc
-+                                                 (IBusXKBConfigRegistry *xkb_config);
 +/**
 + * ibus_xkb_component_new:
 + * @returns: A newly allocated IBusComponent.
diff --git a/ibus-HEAD.patch b/ibus-HEAD.patch
index c6a8da5..4be8960 100644
--- a/ibus-HEAD.patch
+++ b/ibus-HEAD.patch
@@ -226,3 +226,744 @@ index 0e9418e..39ad784 100644
 -- 
 1.7.4.4
 
+From d059132885d3c90647f08f3083e39daa9f82b700 Mon Sep 17 00:00:00 2001
+From: Ryo Onodera <onodera at clear-code.com>
+Date: Tue, 17 May 2011 20:07:40 +0900
+Subject: [PATCH] fix wrong forward key event signature
+
+---
+ ibus/engine.py            |    4 ++--
+ ibus/interface/iengine.py |    4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/ibus/engine.py b/ibus/engine.py
+index 8cbcee3..fe5dd98 100644
+--- a/ibus/engine.py
++++ b/ibus/engine.py
+@@ -114,8 +114,8 @@ class EngineBase(object.Object):
+         text = serializable.serialize_object(text)
+         return self.__proxy.CommitText(text)
+ 
+-    def forward_key_event(self, keyval, state):
+-        return self.__proxy.ForwardKeyEvent(keyval, state)
++    def forward_key_event(self, keyval, keycode, state):
++        return self.__proxy.ForwardKeyEvent(keyval, keycode, state)
+ 
+     def update_preedit_text(self, text, cursor_pos, visible, mode=common.IBUS_ENGINE_PREEDIT_CLEAR):
+         text = serializable.serialize_object(text)
+diff --git a/ibus/interface/iengine.py b/ibus/interface/iengine.py
+index 0e0f4ee..9e0d981 100644
+--- a/ibus/interface/iengine.py
++++ b/ibus/interface/iengine.py
+@@ -104,8 +104,8 @@ class IEngine(dbus.service.Object):
+     @signal(signature="v")
+     def CommitText(self, text): pass
+ 
+-    @signal(signature="uu")
+-    def ForwardKeyEvent(self, keyval, state): pass
++    @signal(signature="uuu")
++    def ForwardKeyEvent(self, keyval, keycode, state): pass
+ 
+     @signal(signature="vubu")
+     def UpdatePreeditText(self, text, cursor_pos, visible, mode): pass
+-- 
+1.7.4.4
+
+From d3e750eab6db7035f494fcdb328b87b2923e33a2 Mon Sep 17 00:00:00 2001
+From: Yusuke Sato <yusukes at chromium.org>
+Date: Wed, 1 Jun 2011 23:37:14 +0900
+Subject: [PATCH] Send the new capabilities to ibus-daemon in
+ ibus_im_context_set_use_preedit.
+
+BUG=none
+TEST=none
+
+Review URL: http://codereview.appspot.com/4529103
+---
+ client/gtk2/ibusimcontext.c |    2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c
+index ebae09d..4a894b0 100644
+--- a/client/gtk2/ibusimcontext.c
++++ b/client/gtk2/ibusimcontext.c
+@@ -942,6 +942,8 @@ ibus_im_context_set_use_preedit (GtkIMContext *context, gboolean use_preedit)
+         else {
+             ibusimcontext->caps &= ~IBUS_CAP_PREEDIT_TEXT;
+         }
++        ibus_input_context_set_capabilities (ibusimcontext->ibuscontext,
++                                             ibusimcontext->caps);
+     }
+     gtk_im_context_set_use_preedit (ibusimcontext->slave, use_preedit);
+ }
+-- 
+1.7.4.4
+
+From 52425daa537a32bed1781958e1ef62dbf199ad8b Mon Sep 17 00:00:00 2001
+From: Peng Huang <shawn.p.huang at gmail.com>
+Date: Mon, 6 Jun 2011 09:30:27 -0400
+Subject: [PATCH] Fix Python input context binding.
+
+Export "forward-key-event" and "delete-surrounding-text" signals to Python; clear __needs_surrounding_text property on "enabled" and "disabled" signals.
+
+BUG=none
+TEST=briefly tested, at least I don't see any regression
+
+Review URL: http://codereview.appspot.com/4437062
+---
+ ibus/inputcontext.py            |   26 +++++++++++++++++++++++++-
+ ibus/interface/iinputcontext.py |    3 +++
+ 2 files changed, 28 insertions(+), 1 deletions(-)
+
+diff --git a/ibus/inputcontext.py b/ibus/inputcontext.py
+index d143727..ceeb56d 100644
+--- a/ibus/inputcontext.py
++++ b/ibus/inputcontext.py
+@@ -116,6 +116,16 @@ class InputContext(object.Object):
+             gobject.TYPE_NONE,
+             ()
+         ),
++        "forward-key-event" : (
++            gobject.SIGNAL_RUN_LAST,
++            gobject.TYPE_NONE,
++            (gobject.TYPE_UINT, gobject.TYPE_UINT, gobject.TYPE_UINT)
++        ),
++        "delete-surrounding-text" : (
++            gobject.SIGNAL_RUN_LAST,
++            gobject.TYPE_NONE,
++            (gobject.TYPE_INT, gobject.TYPE_UINT)
++        ),
+     }
+ 
+     def __init__(self, bus, path, watch_signals=False):
+@@ -142,8 +152,14 @@ 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("Enabled",             lambda *args: self.emit("enabled"))
++        m = self.__context.connect_to_signal("ForwardKeyEvent",            lambda *args: self.emit("forward-key-event", *args))
++        self.__signal_matches.append(m)
++        m = self.__context.connect_to_signal("DeleteSurroundingText",            lambda *args: self.emit("delete-surrounding-text", *args))
+         self.__signal_matches.append(m)
+         m = self.__context.connect_to_signal("Disabled",            lambda *args: self.emit("disabled"))
+         self.__signal_matches.append(m)
+@@ -168,6 +184,14 @@ 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)
+diff --git a/ibus/interface/iinputcontext.py b/ibus/interface/iinputcontext.py
+index 2db1c9b..1d3cd2a 100644
+--- a/ibus/interface/iinputcontext.py
++++ b/ibus/interface/iinputcontext.py
+@@ -95,6 +95,9 @@ class IInputContext(dbus.service.Object):
+     @signal(signature="uuu")
+     def ForwardKeyEvent(self, keyval, keycode, state): pass
+ 
++    @signal(signature="iu")
++    def DeleteSurroundingText(self, offset_from_cursor, nchars): pass
++
+     @signal(signature="vub")
+     def UpdatePreeditText(self, text, cursor_pos, visible): pass
+ 
+-- 
+1.7.4.4
+
+From 59ce675e335e599ed18d74ab8849b9a5fe75d4be Mon Sep 17 00:00:00 2001
+From: Peng Huang <shawn.p.huang at gmail.com>
+Date: Mon, 13 Jun 2011 13:18:29 -0400
+Subject: [PATCH] Fix some race condition between idle and timeout
+ events. Also fix a memory leak.
+
+BUG=http://crosbug.com/16387
+TEST=Linux desktop
+
+Review URL: http://codereview.appspot.com/4568072
+---
+ bus/engineproxy.c |   46 ++++++++++++++++++++++++++++++----------------
+ 1 files changed, 30 insertions(+), 16 deletions(-)
+
+diff --git a/bus/engineproxy.c b/bus/engineproxy.c
+index 0c6f45d..f74af12 100644
+--- a/bus/engineproxy.c
++++ b/bus/engineproxy.c
+@@ -603,7 +603,8 @@ bus_engine_proxy_new_internal (const gchar     *path,
+     g_assert (IBUS_IS_ENGINE_DESC (desc));
+     g_assert (G_IS_DBUS_CONNECTION (connection));
+ 
+-
++    GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
++                            G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES;
+     BusEngineProxy *engine =
+         (BusEngineProxy *) g_initable_new (BUS_TYPE_ENGINE_PROXY,
+                                            NULL,
+@@ -613,7 +614,7 @@ bus_engine_proxy_new_internal (const gchar     *path,
+                                            "g-interface-name",  IBUS_INTERFACE_ENGINE,
+                                            "g-object-path",     path,
+                                            "g-default-timeout", g_gdbus_timeout,
+-                                           "g-flags",           G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
++                                           "g-flags",           flags,
+                                            NULL);
+     const gchar *layout = ibus_engine_desc_get_layout (desc);
+     if (layout != NULL && layout[0] != '\0') {
+@@ -638,24 +639,33 @@ static void
+ engine_proxy_new_data_free (EngineProxyNewData *data)
+ {
+     if (data->simple != NULL) {
+-        if (data->handler_id != 0)
+-            g_signal_handler_disconnect (data->component, data->handler_id);
+         g_object_unref (data->simple);
+     }
+ 
+-    if (data->component != NULL)
++    if (data->desc != NULL) {
++        g_object_unref (data->desc);
++    }
++
++    if (data->component != NULL) {
++        if (data->handler_id != 0) {
++            g_signal_handler_disconnect (data->component, data->handler_id);
++        }
+         g_object_unref (data->component);
++    }
+ 
+-    if (data->factory != NULL)
++    if (data->factory != NULL) {
+         g_object_unref (data->factory);
++    }
+ 
+-    if (data->timeout_id != 0)
++    if (data->timeout_id != 0) {
+         g_source_remove (data->timeout_id);
++    }
+ 
+     if (data->cancellable != NULL) {
+-        if (data->cancelled_handler_id != 0)
++        if (data->cancelled_handler_id != 0) {
+             g_cancellable_disconnect (data->cancellable,
+-                data->cancelled_handler_id);
++                                      data->cancelled_handler_id);
++        }
+         g_object_unref (data->cancellable);
+     }
+ 
+@@ -772,7 +782,8 @@ timeout_cb (EngineProxyNewData *data)
+ /**
+  * cancelled_cb:
+  *
+- * A callback function to be called when someone calls g_cancellable_cancel() for the cancellable object for bus_engine_proxy_new.
++ * A callback function to be called when someone calls g_cancellable_cancel()
++ * for the cancellable object for bus_engine_proxy_new.
+  * Call the GAsyncReadyCallback.
+  */
+ static gboolean
+@@ -793,8 +804,12 @@ static void
+ cancelled_cb (GCancellable       *cancellable,
+               EngineProxyNewData *data)
+ {
+-    /* Cancel the bus_engine_proxy_new() in idle to avoid deadlock */
+-    g_idle_add ((GSourceFunc) cancelled_idle_cb, data);
++    /* Cancel the bus_engine_proxy_new() in idle to avoid deadlock.
++     * And use HIGH priority to avoid timeout event happening before
++     * idle callback. */
++    g_idle_add_full (G_PRIORITY_HIGH,
++                    (GSourceFunc) cancelled_idle_cb,
++                    data, NULL);
+ }
+ 
+ void
+@@ -831,13 +846,12 @@ bus_engine_proxy_new (IBusEngineDesc      *desc,
+     data->simple = simple;
+     data->timeout = timeout;
+ 
+-    g_object_set_data ((GObject *)data->simple, "EngineProxyNewData", data);
+-
+     data->factory = bus_component_get_factory (data->component);
+ 
+     if (data->factory == NULL) {
+-        /* The factory is not ready yet. Create the factory first, and wait for the "notify::factory" signal.
+-         * In the handler of "notify::factory", we'll create the engine proxy. */
++        /* The factory is not ready yet. Create the factory first, and wait for
++         * the "notify::factory" signal. In the handler of "notify::factory",
++         * we'll create the engine proxy. */
+         data->handler_id = g_signal_connect (data->component,
+                                              "notify::factory",
+                                              G_CALLBACK (notify_factory_cb),
+-- 
+1.7.4.4
+
+From fc9dedec30f724e91e7b3bb9111177e96b58ee43 Mon Sep 17 00:00:00 2001
+From: Peng Huang <shawn.p.huang at gmail.com>
+Date: Wed, 15 Jun 2011 10:38:17 -0400
+Subject: [PATCH] Add IBUS_ERROR domain and reply IBUS_ERROR_NO_ENGINE
+ in org.freedesktop.IBus.InputContext.GetEngine
+
+BUG=None
+TEST=Manually
+
+Review URL: http://codereview.appspot.com/4528140
+---
+ bus/inputcontext.c                |    7 ++++-
+ src/Makefile.am                   |    2 +
+ src/ibus.h                        |    1 +
+ src/ibuserror.c                   |   41 +++++++++++++++++++++++++++++++++
+ src/ibuserror.h                   |   46 +++++++++++++++++++++++++++++++++++++
+ src/ibusinputcontext.c            |   15 +++++++++--
+ src/ibusshare.c                   |    1 +
+ src/ibustypes.h                   |    9 +++++++
+ src/tests/ibus-gi-inputcontext.py |   34 +++++++++++++++++++++++++++
+ 9 files changed, 151 insertions(+), 5 deletions(-)
+ create mode 100644 src/ibuserror.c
+ create mode 100644 src/ibuserror.h
+ create mode 100755 src/tests/ibus-gi-inputcontext.py
+
+diff --git a/bus/inputcontext.c b/bus/inputcontext.c
+index bad90ec..1567c5f 100644
+--- a/bus/inputcontext.c
++++ b/bus/inputcontext.c
+@@ -1040,8 +1040,11 @@ _ic_get_engine (BusInputContext       *context,
+                         g_variant_new ("(v)", ibus_serializable_serialize ((IBusSerializable *)desc)));
+     }
+     else {
+-        g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
+-                        "Input context does not have engine.");
++        g_dbus_method_invocation_return_error (
++                invocation,
++                IBUS_ERROR,
++                IBUS_ERROR_NO_ENGINE,
++                "Input context does not have engine.");
+     }
+ }
+ 
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 632fc72..a53bd23 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -70,6 +70,7 @@ ibus_sources =              \
+     ibusservice.c           \
+     ibusfactory.c           \
+     ibusengine.c            \
++    ibuserror.c				\
+     ibustext.c              \
+     ibuskeymap.c            \
+     ibusattribute.c         \
+@@ -114,6 +115,7 @@ ibus_headers =              \
+     ibusservice.h           \
+     ibusfactory.h           \
+     ibusengine.h            \
++    ibuserror.h				\
+     ibustext.h              \
+     ibuskeymap.h            \
+     ibusattribute.h         \
+diff --git a/src/ibus.h b/src/ibus.h
+index 8df7160..c408f3d 100644
+--- a/src/ibus.h
++++ b/src/ibus.h
+@@ -35,6 +35,7 @@
+ #include <ibusservice.h>
+ #include <ibusfactory.h>
+ #include <ibusengine.h>
++#include <ibuserror.h>
+ #include <ibusproperty.h>
+ #include <ibusproplist.h>
+ #include <ibuslookuptable.h>
+diff --git a/src/ibuserror.c b/src/ibuserror.c
+new file mode 100644
+index 0000000..c50c164
+--- /dev/null
++++ b/src/ibuserror.c
+@@ -0,0 +1,41 @@
++/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
++/* vim:set et sts=4: */
++/* ibus - The Input Bus
++ * Copyright (C) 2011 Peng Huang <shawn.p.huang at gmail.com>
++ *
++ * 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 library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++#include "ibuserror.h"
++
++#include <gio/gio.h>
++#include "ibustypes.h"
++
++static const GDBusErrorEntry ibus_error_entries[] =
++{
++    { IBUS_ERROR_NO_ENGINE,         "org.freedesktop.IBus.Error.NoEngine" },
++};
++
++GQuark
++ibus_error_quark (void)
++{
++    static volatile gsize quark_volatile = 0;
++    g_dbus_error_register_error_domain ("ibus-error-quark",
++                                        &quark_volatile,
++                                        ibus_error_entries,
++                                        G_N_ELEMENTS (ibus_error_entries));
++    return (GQuark) quark_volatile;
++}
+diff --git a/src/ibuserror.h b/src/ibuserror.h
+new file mode 100644
+index 0000000..75c64b9
+--- /dev/null
++++ b/src/ibuserror.h
+@@ -0,0 +1,46 @@
++/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
++/* vim:set et sts=4: */
++/* ibus - The Input Bus
++ * Copyright (C) 2011 Peng Huang <shawn.p.huang at gmail.com>
++ *
++ * 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 library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++#if !defined (__IBUS_H_INSIDE__) && !defined (IBUS_COMPILATION)
++#error "Only <ibus.h> can be included directly"
++#endif
++
++/**
++ * SECTION: ibusshare
++ * @short_description: Shared utility functions and definition.
++ * @stability: Stable
++ *
++ * This file defines some utility functions and definition
++ * which are shared among ibus component and services.
++ */
++
++#ifndef __IBUS_ERROR_H_
++#define __IBUS_ERROR_H_
++
++#include <glib.h>
++
++G_BEGIN_DECLS
++
++#define IBUS_ERROR ibus_error_quark()
++GQuark ibus_error_quark (void);
++
++G_END_DECLS
++#endif
+diff --git a/src/ibusinputcontext.c b/src/ibusinputcontext.c
+index e6f97e8..78d454e 100644
+--- a/src/ibusinputcontext.c
++++ b/src/ibusinputcontext.c
+@@ -27,6 +27,7 @@
+ #include "ibusattribute.h"
+ #include "ibuslookuptable.h"
+ #include "ibusproplist.h"
++#include "ibuserror.h"
+ 
+ #define IBUS_INPUT_CONTEXT_GET_PRIVATE(o)  \
+    (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_INPUT_CONTEXT, IBusInputContextPrivate))
+@@ -1164,7 +1165,7 @@ IBusEngineDesc *
+ ibus_input_context_get_engine (IBusInputContext *context)
+ {
+     g_assert (IBUS_IS_INPUT_CONTEXT (context));
+-    GVariant *result;
++    GVariant *result = NULL;
+     GError *error = NULL;
+     result = g_dbus_proxy_call_sync ((GDBusProxy *) context,
+                                      "GetEngine",               /* method_name */
+@@ -1174,9 +1175,17 @@ ibus_input_context_get_engine (IBusInputContext *context)
+                                      NULL,                      /* cancellable */
+                                      &error                     /* error */
+                                      );
+-
+     if (result == NULL) {
+-        g_warning ("%s.GetEngine: %s", IBUS_INTERFACE_INPUT_CONTEXT, error->message);
++        if (g_error_matches (error, IBUS_ERROR, IBUS_ERROR_NO_ENGINE)) {
++            g_debug ("%s.GetEngine: %s",
++                     IBUS_INTERFACE_INPUT_CONTEXT,
++                     error->message);
++        }
++        else {
++            g_warning ("%s.GetEngine: %s",
++                       IBUS_INTERFACE_INPUT_CONTEXT,
++                       error->message);
++        }
+         g_error_free (error);
+         return NULL;
+     }
+diff --git a/src/ibusshare.c b/src/ibusshare.c
+index 1b8ae2a..19f9f65 100644
+--- a/src/ibusshare.c
++++ b/src/ibusshare.c
+@@ -318,6 +318,7 @@ void
+ ibus_init (void)
+ {
+     g_type_init ();
++    IBUS_ERROR;
+     IBUS_TYPE_TEXT;
+     IBUS_TYPE_ATTRIBUTE;
+     IBUS_TYPE_ATTR_LIST;
+diff --git a/src/ibustypes.h b/src/ibustypes.h
+index 6a31847..8146719 100644
+--- a/src/ibustypes.h
++++ b/src/ibustypes.h
+@@ -177,6 +177,15 @@ typedef enum {
+ } IBusBusRequestNameReply;
+ 
+ /**
++ * IBusError:
++ * @IBUS_ERROR_NO_ENGINE:
++ * There is no engine associated with input context.
++ */
++typedef enum {
++    IBUS_ERROR_NO_ENGINE,
++} IBusError;
++
++/**
+  * IBusRectangle:
+  * @x: x coordinate.
+  * @y: y coordinate.
+diff --git a/src/tests/ibus-gi-inputcontext.py b/src/tests/ibus-gi-inputcontext.py
+new file mode 100755
+index 0000000..80fb97b
+--- /dev/null
++++ b/src/tests/ibus-gi-inputcontext.py
+@@ -0,0 +1,34 @@
++#!/usr/bin/env python
++# vim:set et sts=4 sw=4:
++#
++# ibus - The Input Bus
++#
++# Copyright (c) 2011 Peng Huang <shawn.p.huang at gmail.com>
++#
++# 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
++
++
++import glib
++import gio
++from gi.repository import IBus
++IBus.init()
++main = glib.MainLoop()
++bus = IBus.Bus()
++ic = bus.create_input_context("ibus-test")
++ic.get_engine()
++ic.get_engine()
++ic.get_engine()
++ic.get_engine()
+-- 
+1.7.4.4
+
+From aec97ac090980dfcd7eeef55c1755f6cd3f87a01 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <daiki.ueno at gmail.com>
+Date: Sat, 18 Jun 2011 00:03:07 -0400
+Subject: [PATCH] Simplify surrounding-text initialization.
+
+Currently the immodule tries to retrieve surrounding-text unconditionally
+on focus_in and enabled.  These calls could be eliminated if engine were
+able to proclaim that it will need surrounding-text.
+
+This patch extends ibus_engine_get_surrounding_text() to allow this.
+Engines that need surrounding-text are expected to have:
+
+    /* Indicate we will use surrounding-text. */
+    ibus_engine_get_surrounding_text (engine, NULL, NULL);
+
+in their enable() method.  This would work because enable() is called before
+SetCapabilities DBus call.
+
+BUG=none
+TEST=manually with ibus-m17n, with the above change.
+
+Review URL: http://codereview.appspot.com/4613043
+Patch from Daiki Ueno <daiki.ueno at gmail.com>.
+---
+ client/gtk2/ibusimcontext.c |   23 +++++++++--------------
+ src/ibusengine.c            |   10 ++++++----
+ src/ibusengine.h            |    9 +++++++--
+ 3 files changed, 22 insertions(+), 20 deletions(-)
+
+diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c
+index ec764ef..a4e7a16 100644
+--- a/client/gtk2/ibusimcontext.c
++++ b/client/gtk2/ibusimcontext.c
+@@ -147,8 +147,7 @@ static gboolean _slave_delete_surroundin
+                                              gint                offset_from_cursor,
+                                              guint               nchars,
+                                              IBusIMContext      *context);
+-static void     _request_surrounding_text   (IBusIMContext      *context,
+-                                             gboolean            force);
++static void     _request_surrounding_text   (IBusIMContext      *context);
+ static void     _create_fake_input_context  (void);
+ 
+ 
+@@ -263,17 +262,13 @@ _process_key_event_done (GObject      *o
+ /* emit "retrieve-surrounding" glib signal of GtkIMContext, if
+  * context->caps has IBUS_CAP_SURROUNDING_TEXT and the current IBus
+  * engine needs surrounding-text.
+- *
+- * if "force" is TRUE, emit the signal regardless of whether the
+- * engine needs surrounding-text.
+  */
+ static void
+-_request_surrounding_text (IBusIMContext *context, gboolean force)
++_request_surrounding_text (IBusIMContext *context)
+ {
+-    if (context->enable &&
++    if (context && context->enable &&
+         (context->caps & IBUS_CAP_SURROUNDING_TEXT) != 0 &&
+-        (force ||
+-         ibus_input_context_needs_surrounding_text (context->ibuscontext))) {
++        ibus_input_context_needs_surrounding_text (context->ibuscontext)) {
+         gboolean return_value;
+         IDEBUG ("requesting surrounding text");
+         g_signal_emit (context, _signal_retrieve_surrounding_id, 0,
+@@ -368,9 +363,8 @@ _key_snooper_cb (GtkWidget   *widget,
+ 
+     } while (0);
+ 
+-    _request_surrounding_text (ibusimcontext, FALSE);
+-
+     if (ibusimcontext != NULL) {
++        _request_surrounding_text (ibusimcontext);
+         ibusimcontext->time = event->time;
+     }
+ 
+@@ -680,7 +674,7 @@ ibus_im_context_filter_keypress (GtkIMCo
+         if (ibusimcontext->client_window == NULL && event->window != NULL)
+             gtk_im_context_set_client_window ((GtkIMContext *)ibusimcontext, event->window);
+ 
+-        _request_surrounding_text (ibusimcontext, FALSE);
++        _request_surrounding_text (ibusimcontext);
+ 
+         if (ibusimcontext != NULL) {
+             ibusimcontext->time = event->time;
+@@ -763,7 +757,7 @@ ibus_im_context_focus_in (GtkIMContext *
+ 
+     /* retrieve the initial surrounding-text (regardless of whether
+      * the current IBus engine needs surrounding-text) */
+-    _request_surrounding_text (ibusimcontext, TRUE);
++    _request_surrounding_text (ibusimcontext);
+ 
+     g_object_add_weak_pointer ((GObject *) context,
+                                (gpointer *) &_focus_im_context);
+@@ -1000,7 +996,7 @@ _ibus_context_commit_text_cb (IBusInputC
+ 
+     g_signal_emit (ibusimcontext, _signal_commit_id, 0, text->text);
+ 
+-    _request_surrounding_text (ibusimcontext, FALSE);
++    _request_surrounding_text (ibusimcontext);
+ }
+ 
+ static gboolean
+@@ -1296,7 +1292,7 @@ _ibus_context_show_preedit_text_cb (IBus
+     g_signal_emit (ibusimcontext, _signal_preedit_start_id, 0);
+     g_signal_emit (ibusimcontext, _signal_preedit_changed_id, 0);
+ 
+-    _request_surrounding_text (ibusimcontext, FALSE);
++    _request_surrounding_text (ibusimcontext);
+ }
+ 
+ static void
+@@ -1323,7 +1319,7 @@ _ibus_context_enabled_cb (IBusInputConte
+ 
+     /* retrieve the initial surrounding-text (regardless of whether
+      * the current IBus engine needs surrounding-text) */
+-    _request_surrounding_text (ibusimcontext, TRUE);
++    _request_surrounding_text (ibusimcontext);
+ }
+ 
+ static void
+diff --git a/src/ibusengine.c b/src/ibusengine.c
+index f545bef..620d07f 100644
+--- a/src/ibusengine.c
++++ b/src/ibusengine.c
+@@ -1382,13 +1382,15 @@ ibus_engine_get_surrounding_text (IBusEngine   *engine,
+     IBusEnginePrivate *priv;
+ 
+     g_return_if_fail (IBUS_IS_ENGINE (engine));
+-    g_return_if_fail (text != NULL);
+-    g_return_if_fail (cursor_pos != NULL);
++    g_return_if_fail ((text != NULL && cursor_pos != NULL) ||
++                      (text == NULL && cursor_pos == NULL));
+ 
+     priv = IBUS_ENGINE_GET_PRIVATE (engine);
+ 
+-    *text = g_object_ref (priv->surrounding_text);
+-    *cursor_pos = priv->surrounding_cursor_pos;
++    if (text && cursor_pos) {
++        *text = g_object_ref (priv->surrounding_text);
++        *cursor_pos = priv->surrounding_cursor_pos;
++    }
+ 
+     /* tell the client that this engine will utilize surrounding-text
+      * feature, which causes periodical update.  Note that the client
+diff --git a/src/ibusengine.h b/src/ibusengine.h
+index 29b8f1d..6da342a 100644
+--- a/src/ibusengine.h
++++ b/src/ibusengine.h
+@@ -407,11 +407,16 @@ void ibus_engine_delete_surrounding_text(IBusEngine         *engine,
+ /**
+  * ibus_engine_get_surrounding_text:
+  * @engine: An IBusEngine.
+- * @text: Location to store surrounding text.
+- * @cursor_pos: Cursor position in characters in @text.
++ * @text: (allow-none): Location to store surrounding text.
++ * @cursor_pos: (allow-none): Cursor position in characters in @text.
+  *
+  * Get surrounding text.
+  *
++ * It is also used to tell the input-context that the engine will
++ * utilize surrounding-text.  In that case, it must be called in
++ * #IBusEngine::enable handler, with both @text and @cursor set to
++ * %NULL.
++ *
+  * @see_also #IBusEngine::set-surrounding-text
+  */
+ void ibus_engine_get_surrounding_text(IBusEngine         *engine,
+-- 
+1.7.4.4
+
diff --git a/ibus-xx-bridge-hotkey.patch b/ibus-xx-bridge-hotkey.patch
new file mode 100644
index 0000000..824dd81
--- /dev/null
+++ b/ibus-xx-bridge-hotkey.patch
@@ -0,0 +1,874 @@
+From a3a7b364410511b3a17f2b1566ba4c4c4f0de2cf Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1 at gmail.com>
+Date: Tue, 21 Jun 2011 17:00:54 +0900
+Subject: [PATCH] Add a bridge hotkey which use prev-next engines instead
+ of on-off.
+
+---
+ bus/Makefile.am            |   20 ++--
+ bus/ibusimpl.c             |  244 ++++++++++++++++++++++++++++----------
+ bus/registry.c             |   35 ++++++
+ configure.ac               |   31 +++++
+ data/Makefile.am           |    6 +-
+ data/ibus.schemas.in       |  286 --------------------------------------------
+ data/ibus.schemas.in.in    |  286 ++++++++++++++++++++++++++++++++++++++++++++
+ ibus/_config.py.in         |    6 +
+ ibus/inputcontext.py       |    4 +
+ src/Makefile.am            |    1 +
+ src/ibusbus.c              |    6 +
+ src/ibusbus.h              |    9 ++
+ src/ibusenginedesc.c       |    4 +
+ src/ibushotkey.c           |   11 ++
+ src/ibushotkey.h           |   11 ++
+ ui/gtk/panel.py            |   60 +++++++++-
+ xkb/Makefile.am            |    2 +
+ xkb/ibus-engine-xkb-main.c |    8 ++
+ xkb/xkbxml.c               |    8 +-
+ 19 files changed, 677 insertions(+), 361 deletions(-)
+ delete mode 100644 data/ibus.schemas.in
+ create mode 100644 data/ibus.schemas.in.in
+
+diff --git a/bus/Makefile.am b/bus/Makefile.am
+index 074b456..0efaa1b 100644
+--- a/bus/Makefile.am
++++ b/bus/Makefile.am
+@@ -29,15 +29,17 @@ INCLUDES =                \
+ 	-I$(top_builddir)/src \
+ 	$(NULL)
+ 
+-AM_CFLAGS =                        \
+-	@GLIB2_CFLAGS@                 \
+-	@GIO2_CFLAGS@                  \
+-	@GTHREAD2_CFLAGS@              \
+-	-DG_LOG_DOMAIN=\"IBUS\"        \
+-	-DPKGDATADIR=\"$(pkgdatadir)\" \
+-	-DLIBEXECDIR=\"$(libexecdir)\" \
+-	-DBINDIR=\"@bindir@\"          \
+-	$(INCLUDES)                    \
++AM_CFLAGS =                                                            \
++	@GLIB2_CFLAGS@                                                 \
++	@GIO2_CFLAGS@                                                  \
++	@GTHREAD2_CFLAGS@                                              \
++	-DG_LOG_DOMAIN=\"IBUS\"                                        \
++	-DPKGDATADIR=\"$(pkgdatadir)\"                                 \
++	-DLIBEXECDIR=\"$(libexecdir)\"                                 \
++	-DBINDIR=\"@bindir@\"                                          \
++	-DUSE_BRIDGE_HOTKEY=$(USE_BRIDGE_HOTKEY)                       \
++	-DDEFAULT_BRIDGE_ENGINE_NAME=\"$(DEFAULT_BRIDGE_ENGINE_NAME)\" \
++	$(INCLUDES)                                                    \
+ 	$(NULL)
+ AM_LDADD =                  \
+ 	@GOBJECT2_LIBS@         \
+diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c
+index 38d6d11..3b2d539 100644
+--- a/bus/ibusimpl.c
++++ b/bus/ibusimpl.c
+@@ -20,6 +20,10 @@
+  * Boston, MA 02111-1307, USA.
+  */
+ 
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
+ #include <unistd.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+@@ -79,6 +83,8 @@ struct _BusIBusImpl {
+     /* engine-specific hotkeys */
+     IBusHotkeyProfile *engines_hotkey_profile;
+     GHashTable      *hotkey_to_engines_map;
++
++    IBusEngineDesc *prev_hotkey_engine;
+ };
+ 
+ struct _BusIBusImplClass {
+@@ -285,6 +291,30 @@ _panel_destroy_cb (BusPanelProxy *panel,
+     g_object_unref (panel);
+ }
+ 
++static IBusEngineDesc *
++_find_engine_desc_by_name (BusIBusImpl *ibus,
++                           const gchar *engine_name)
++{
++    IBusEngineDesc *desc = NULL;
++    GList *p;
++
++    /* find engine in registered engine list */
++    for (p = ibus->register_engine_list; p != NULL; p = p->next) {
++        desc = (IBusEngineDesc *) p->data;
++        if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
++            return desc;
++    }
++
++    /* find engine in preload engine list */
++    for (p = ibus->engine_list; p != NULL; p = p->next) {
++        desc = (IBusEngineDesc *) p->data;
++        if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
++            return desc;
++    }
++
++    return NULL;
++}
++
+ static void
+ _config_set_value_done (GObject      *object,
+                         GAsyncResult *res,
+@@ -475,8 +505,17 @@ _set_preload_engines (BusIBusImpl *ibus,
+         g_variant_unref (value);
+     }
+ 
+-    g_list_foreach (engine_list, (GFunc) g_object_ref, NULL);
+     ibus->engine_list = engine_list;
++#if USE_BRIDGE_HOTKEY
++    if (_find_engine_desc_by_name (ibus, DEFAULT_BRIDGE_ENGINE_NAME) == NULL) {
++        IBusEngineDesc *engine = bus_registry_find_engine_by_name (ibus->registry,
++                                                                   DEFAULT_BRIDGE_ENGINE_NAME);
++        g_assert (engine != NULL);
++        engine_list = g_list_append (engine_list, engine);
++        ibus->engine_list = engine_list;
++    }
++#endif
++    g_list_foreach (engine_list, (GFunc) g_object_ref, NULL);
+ 
+     if (ibus->engine_list) {
+         BusComponent *component = bus_component_from_engine_desc ((IBusEngineDesc *) ibus->engine_list->data);
+@@ -1182,28 +1221,110 @@ _ibus_get_address (BusIBusImpl          
+                                            g_variant_new ("(s)", bus_server_get_address ()));
+ }
+ 
+-static IBusEngineDesc *
+-_find_engine_desc_by_name (BusIBusImpl *ibus,
+-                           const gchar *engine_name)
+-{
+-    IBusEngineDesc *desc = NULL;
+-    GList *p;
++/**
++ * _foreach_remove_engine_hotkey:
++ *
++ * Remove the engine-specific hot key of the engine, and update ibus->engines_hotkey_profile.
++ */
++gboolean
++_foreach_remove_engine_hotkey (gpointer        key,
++                               gpointer        value,
++                               gpointer        data)
++{
++    GQuark event = GPOINTER_TO_UINT (value);
++    struct _impl_and_desc {
++        BusIBusImpl    *ibus;
++        IBusEngineDesc *desc;
++    } *id = (struct _impl_and_desc *) data;
++    BusIBusImpl *ibus = id->ibus;
++    IBusEngineDesc *desc = id->desc;
++    GList *engine_list;
+ 
+-    /* find engine in registered engine list */
+-    for (p = ibus->register_engine_list; p != NULL; p = p->next) {
+-        desc = (IBusEngineDesc *) p->data;
+-        if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
+-            return desc;
++    g_assert (ibus != NULL);
++    g_assert (desc != NULL);
++
++    if (event == 0) {
++        return FALSE;
+     }
+ 
+-    /* find engine in preload engine list */
+-    for (p = ibus->engine_list; p != NULL; p = p->next) {
+-        desc = (IBusEngineDesc *) p->data;
+-        if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
+-            return desc;
++    engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
++                                       GUINT_TO_POINTER (event));
++
++    /* As we will rebuild the engines hotkey map whenever an engine was
++     * added or removed, we don't need to hold a reference of the engine
++     * here. */
++    if (engine_list && g_list_find (engine_list, desc) != NULL) {
++        engine_list = g_list_remove (engine_list, desc);
+     }
+ 
+-    return NULL;
++    /* We need to steal the value before adding it back, otherwise it will
++     * be destroyed. */
++    g_hash_table_steal (ibus->hotkey_to_engines_map, GUINT_TO_POINTER (event));
++
++    if (engine_list != NULL) {
++        g_hash_table_insert (ibus->hotkey_to_engines_map,
++                             GUINT_TO_POINTER (event), engine_list);
++    }
++
++    return FALSE;
++}
++
++/**
++ * _add_engine_hotkey_with_hotkeys:
++ *
++ * Check the engine-specific hot key of the engine, and update ibus->engines_hotkey_profile.
++ */
++static void
++_add_engine_hotkey_with_hotkeys (IBusEngineDesc *engine,
++                                 BusIBusImpl    *ibus,
++                                 const gchar    *hotkeys)
++{
++    gchar **hotkey_list;
++    gchar **p;
++    gchar *hotkey;
++    GList *engine_list;
++
++    GQuark event;
++    guint keyval;
++    guint modifiers;
++
++    g_assert (engine != NULL);
++    g_assert (hotkeys && *hotkeys);
++
++    hotkey_list = g_strsplit_set (hotkeys, ";,", 0);
++
++    for (p = hotkey_list; p && *p; ++p) {
++        hotkey = g_strstrip (*p);
++        if (!*hotkey || !ibus_key_event_from_string (hotkey, &keyval, &modifiers)) {
++            continue;
++        }
++
++        /* If the hotkey already exists, we won't need to add it again. */
++        event = ibus_hotkey_profile_lookup_hotkey (ibus->engines_hotkey_profile,
++                                                   keyval, modifiers);
++        if (event == 0) {
++            event = g_quark_from_string (hotkey);
++            ibus_hotkey_profile_add_hotkey (ibus->engines_hotkey_profile,
++                                            keyval, modifiers, event);
++        }
++
++        engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
++                                           GUINT_TO_POINTER (event));
++
++        /* As we will rebuild the engines hotkey map whenever an engine was
++         * added or removed, we don't need to hold a reference of the engine
++         * here. */
++        engine_list = g_list_append (engine_list, engine);
++
++        /* We need to steal the value before adding it back, otherwise it will
++         * be destroyed. */
++        g_hash_table_steal (ibus->hotkey_to_engines_map, GUINT_TO_POINTER (event));
++
++        g_hash_table_insert (ibus->hotkey_to_engines_map,
++                             GUINT_TO_POINTER (event), engine_list);
++    }
++
++    g_strfreev (hotkey_list);
+ }
+ 
+ /**
+@@ -1216,7 +1337,39 @@ _context_request_engine_cb (BusInputCont
+                             const gchar     *engine_name,
+                             BusIBusImpl     *ibus)
+ {
+-    return bus_ibus_impl_get_engine_desc (ibus, engine_name);
++    IBusEngineDesc *desc = bus_ibus_impl_get_engine_desc (ibus, engine_name);
++    struct _impl_and_desc {
++        BusIBusImpl    *ibus;
++        IBusEngineDesc *desc;
++    } id = {ibus, desc};
++
++#if USE_BRIDGE_HOTKEY
++    IBusEngineDesc *current_desc = NULL;
++    if (context) {
++        BusEngineProxy *engine = bus_input_context_get_engine (context);
++        if (engine != NULL) {
++            current_desc = bus_engine_proxy_get_desc (engine);
++        }
++    }
++    if (current_desc) {
++        ibus->prev_hotkey_engine = current_desc;
++    }
++    if (current_desc != NULL && desc != NULL &&
++        g_strcmp0 (ibus_engine_desc_get_name (current_desc),
++                   ibus_engine_desc_get_name (desc)) != 0 &&
++        g_strcmp0 (ibus_engine_desc_get_name (desc),
++                   DEFAULT_BRIDGE_ENGINE_NAME) == 0) {
++        const gchar *hotkeys = ibus_engine_desc_get_hotkeys (current_desc);
++        if (!hotkeys || !*hotkeys) {
++            hotkeys = "Control+space";
++        }
++        ibus_hotkey_profile_foreach_hotkey (ibus->engines_hotkey_profile,
++                                            _foreach_remove_engine_hotkey,
++                                            &id);
++        _add_engine_hotkey_with_hotkeys (desc, ibus, hotkeys);
++    }
++#endif
++    return desc;
+ }
+ 
+ /**
+@@ -2357,6 +2510,11 @@ bus_ibus_impl_filter_keyboard_shortcuts 
+          * 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. */
++#if USE_BRIDGE_HOTKEY
++        if (ibus->prev_hotkey_engine) {
++            new_engine_desc = ibus->prev_hotkey_engine;
++        }
++#else
+         GList *p = engine_list;
+         for (; p->next != NULL; p = p->next) {
+             if (current_engine_desc == (IBusEngineDesc *) p->data) {
+@@ -2364,9 +2522,14 @@ bus_ibus_impl_filter_keyboard_shortcuts 
+                 break;
+             }
+         }
++#endif
+ 
+         if (current_engine_desc != new_engine_desc) {
++            ibus->prev_hotkey_engine = current_engine_desc;
+             bus_ibus_impl_set_context_engine_from_desc (ibus, context, new_engine_desc);
++        } else {
++            g_warning ("The engine %s is registered twice in hotkeys",
++                       ibus_engine_desc_get_name (current_engine_desc));
+         }
+ 
+         return TRUE;
+@@ -2470,14 +2633,6 @@ static void
+ _add_engine_hotkey (IBusEngineDesc *engine, BusIBusImpl *ibus)
+ {
+     const gchar *hotkeys;
+-    gchar **hotkey_list;
+-    gchar **p;
+-    gchar *hotkey;
+-    GList *engine_list;
+-
+-    GQuark event;
+-    guint keyval;
+-    guint modifiers;
+ 
+     if (!engine) {
+         return;
+@@ -2489,40 +2644,7 @@ _add_engine_hotkey (IBusEngineDesc *engi
+         return;
+     }
+ 
+-    hotkey_list = g_strsplit_set (hotkeys, ";,", 0);
+-
+-    for (p = hotkey_list; p && *p; ++p) {
+-        hotkey = g_strstrip (*p);
+-        if (!*hotkey || !ibus_key_event_from_string (hotkey, &keyval, &modifiers)) {
+-            continue;
+-        }
+-
+-        /* If the hotkey already exists, we won't need to add it again. */
+-        event = ibus_hotkey_profile_lookup_hotkey (ibus->engines_hotkey_profile,
+-                                                   keyval, modifiers);
+-        if (event == 0) {
+-            event = g_quark_from_string (hotkey);
+-            ibus_hotkey_profile_add_hotkey (ibus->engines_hotkey_profile,
+-                                            keyval, modifiers, event);
+-        }
+-
+-        engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
+-                                           GUINT_TO_POINTER (event));
+-
+-        /* As we will rebuild the engines hotkey map whenever an engine was
+-         * added or removed, we don't need to hold a reference of the engine
+-         * here. */
+-        engine_list = g_list_append (engine_list, engine);
+-
+-        /* We need to steal the value before adding it back, otherwise it will
+-         * be destroyed. */
+-        g_hash_table_steal (ibus->hotkey_to_engines_map, GUINT_TO_POINTER (event));
+-
+-        g_hash_table_insert (ibus->hotkey_to_engines_map,
+-                             GUINT_TO_POINTER (event), engine_list);
+-    }
+-
+-    g_strfreev (hotkey_list);
++    _add_engine_hotkey_with_hotkeys (engine, ibus, hotkeys);
+ }
+ 
+ /**
+diff --git a/bus/registry.c b/bus/registry.c
+index bc6680d..f47f727 100644
+--- a/bus/registry.c
++++ b/bus/registry.c
+@@ -19,6 +19,11 @@
+  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+  * Boston, MA 02111-1307, USA.
+  */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
+ #include "registry.h"
+ #include <glib/gstdio.h>
+ #include <gio/gio.h>
+@@ -101,6 +106,9 @@ bus_registry_init (BusRegistry *registry)
+     registry->observed_paths = NULL;
+     registry->components = NULL;
+     registry->engine_table = g_hash_table_new (g_str_hash, g_str_equal);
++#if USE_BRIDGE_HOTKEY
++    gboolean has_default_engine = FALSE;
++#endif
+ 
+ #ifdef G_THREADS_ENABLED
+     /* If glib supports thread, we'll create a thread to monitor changes in IME
+@@ -145,12 +153,39 @@ bus_registry_init (BusRegistry *registry)
+         GList *p1;
+         for (p1 = engines; p1 != NULL; p1 = p1->next) {
+             IBusEngineDesc *desc = (IBusEngineDesc *) p1->data;
++#if USE_BRIDGE_HOTKEY
++            if (g_strcmp0 (ibus_engine_desc_get_name (desc),
++                           DEFAULT_BRIDGE_ENGINE_NAME) == 0) {
++                has_default_engine = TRUE;
++            }
++#endif
+             g_hash_table_insert (registry->engine_table,
+                                  (gpointer) ibus_engine_desc_get_name (desc),
+                                  desc);
+         }
+         g_list_free (engines);
+     }
++
++#if USE_BRIDGE_HOTKEY
++    if (has_default_engine == FALSE) {
++        bus_registry_remove_all (registry);
++        bus_registry_load (registry);
++        bus_registry_save_cache (registry);
++
++        for (p = registry->components; p != NULL; p = p->next) {
++            BusComponent *comp = (BusComponent *) p->data;
++            GList *engines = bus_component_get_engines (comp);
++            GList *p1;
++            for (p1 = engines; p1 != NULL; p1 = p1->next) {
++                IBusEngineDesc *desc = (IBusEngineDesc *) p1->data;
++                g_hash_table_insert (registry->engine_table,
++                                     (gpointer) ibus_engine_desc_get_name (desc),
++                                     desc);
++            }
++            g_list_free (engines);
++        }
++    }
++#endif
+ }
+ 
+ static void
+diff --git a/configure.ac b/configure.ac
+index 85e5e30..a6974d4 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -438,6 +438,34 @@ else
+     enable_surrounding_text="no (disabled, use --enable-surrounding-text to enable)"
+ fi
+ 
++# option for bridge hotkey
++AC_ARG_ENABLE(bridge-hotkey,
++    AS_HELP_STRING([--enable-bridge-hotkey],
++        [Enable bridge hotkey instead of ON/OFF hotkey]),
++    [enable_bridge_hotkey=$enableval],
++    [enable_bridge_hotkey=no]
++)
++
++if test x"$enable_bridge_hotkey" = x"yes"; then
++    USE_BRIDGE_HOTKEY=1
++    TRIGGER_HOTKEYS=""
++else
++    USE_BRIDGE_HOTKEY=0
++    TRIGGER_HOTKEYS="Control+space,Zenkaku_Hankaku,Alt+Kanji,Alt+grave,Hangul,Alt+Release+Alt_R"
++    enable_bridge_hotkey="no (disabled, use --enable-bridge-hotkey to enable)"
++fi
++AC_SUBST(USE_BRIDGE_HOTKEY)
++AC_SUBST(TRIGGER_HOTKEYS)
++
++# define default bridge engine name
++AC_ARG_WITH(bridge-engine,
++    AS_HELP_STRING([--with-bridge-engine[=bridge_engine_name]],
++        [Set bridge engine name in IM bridge hotkey. (default: xkb:layout:default)]),
++    [DEFAULT_BRIDGE_ENGINE_NAME=$with_bridge_engine],
++    [DEFAULT_BRIDGE_ENGINE_NAME="xkb:layout:default"]
++)
++AC_SUBST(DEFAULT_BRIDGE_ENGINE_NAME)
++
+ # check iso-codes
+ PKG_CHECK_MODULES(ISOCODES, [
+     iso-codes
+@@ -464,6 +492,7 @@ bus/Makefile
+ util/Makefile
+ util/IMdkit/Makefile
+ data/Makefile
++data/ibus.schemas.in
+ data/icons/Makefile
+ data/keymaps/Makefile
+ docs/Makefile
+@@ -512,5 +541,7 @@ Build options:
+   No snooper regexes        "$NO_SNOOPER_APPS"
+   Panel icon                "$IBUS_ICON_KEYBOARD"
+   Enable surrounding-text   $enable_surrounding_text
++  Enable bridge hotkey      $enable_bridge_hotkey
++  Default bridge engine     $DEFAULT_BRIDGE_ENGINE_NAME
+ ])
+ 
+diff --git a/data/Makefile.am b/data/Makefile.am
+index ba9f4bb..a909e5b 100644
+--- a/data/Makefile.am
++++ b/data/Makefile.am
+@@ -26,7 +26,8 @@ SUBDIRS = \
+ 	$(NULL)
+ 
+ schemasdir = $(GCONF_SCHEMA_FILE_DIR)
+-schemas_in_files = ibus.schemas.in
++schemas_in_in_files = ibus.schemas.in.in
++schemas_in_files = $(schemas_in_in_files:.schemas.in.in=.schemas.in)
+ schemas_DATA = $(schemas_in_files:.schemas.in=.schemas)
+ @INTLTOOL_SCHEMAS_RULE@
+ 
+@@ -41,11 +42,12 @@ if GCONF_SCHEMAS_INSTALL
+ endif
+ 
+ EXTRA_DIST = \
+-	$(schemas_in_files) \
++	$(schemas_in_in_files) \
+ 	$(NULL)
+ 
+ DISTCLEANFILES = \
+ 	$(schemas_DATA) \
++	$(schemas_in_files) \
+ 	$(NULL)
+ 
+ -include $(top_srcdir)/git.mk
+diff --git a/data/ibus.schemas.in b/data/ibus.schemas.in.in
+index 7ca4899..42d9297
+--- a/data/ibus.schemas.in
++++ b/data/ibus.schemas.in.in
+@@ -31,7 +31,7 @@
+       <owner>ibus</owner>
+       <type>list</type>
+       <list_type>string</list_type>
+-      <default>[Control+space,Zenkaku_Hankaku,Alt+Kanji,Alt+grave,Hangul,Alt+Release+Alt_R]</default>
++      <default>[@TRIGGER_HOTKEYS@]</default>
+       <locale name="C">
+         <short>Trigger shortcut keys</short>
+ 	    <long>The shortcut keys for turning input method on or off</long>
+diff --git a/ibus/_config.py.in b/ibus/_config.py.in
+index a830136..4c3c980 100644
+--- a/ibus/_config.py.in
++++ b/ibus/_config.py.in
+@@ -25,6 +25,8 @@ __all__ = (
+     "get_copyright",
+     "get_license",
+     "get_ICON_KEYBOARD",
++    "use_bridge_hotkey",
++    "DEFAULT_BRIDGE_ENGINE_NAME",
+     "ISOCODES_PREFIX",
+     "_"
+ )
+@@ -51,4 +53,8 @@ def get_ICON_KEYBOARD():
+         icon = 'ibus-keyboard'
+     return icon
+ 
++def use_bridge_hotkey():
++    return True if @USE_BRIDGE_HOTKEY@ == 1 else False
++
++DEFAULT_BRIDGE_ENGINE_NAME='@DEFAULT_BRIDGE_ENGINE_NAME@'
+ ISOCODES_PREFIX='@ISOCODES_PREFIX@'
+diff --git a/ibus/inputcontext.py b/ibus/inputcontext.py
+index ceeb56d..2694fa3 100644
+--- a/ibus/inputcontext.py
++++ b/ibus/inputcontext.py
+@@ -28,6 +28,7 @@ import sys
+ import gobject
+ import dbus
+ import dbus.lowlevel
++import _config
+ import object
+ import common
+ import serializable
+@@ -282,6 +283,9 @@ class InputContext(object.Object):
+     def set_engine(self, engine):
+         return self.__context.SetEngine(engine.name)
+ 
++    def set_bridge_engine(self):
++        return self.__context.SetEngine(_config.DEFAULT_BRIDGE_ENGINE_NAME)
++
+     def introspect(self):
+         return self.__context.Introspect()
+ 
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 6454522..443b0db 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -46,6 +46,7 @@ AM_CPPFLAGS =                                   \
+     -DIBUS_DATA_DIR=\"$(pkgdatadir)\"           \
+     -DIBUS_COMPILATION                          \
+     -DISOCODES_PREFIX=\"$(ISOCODES_PREFIX)\"    \
++    -DUSE_BRIDGE_HOTKEY=$(USE_BRIDGE_HOTKEY)    \
+     $(NULL)
+ 
+ # ibus library
+diff --git a/src/ibusbus.c b/src/ibusbus.c
+index 39ad784..5a8f9a9 100644
+--- a/src/ibusbus.c
++++ b/src/ibusbus.c
+@@ -1902,3 +1902,9 @@ ibus_bus_call_async (IBusBus            *bus,
+                             (GAsyncReadyCallback) ibus_bus_call_async_done,
+                             simple);
+ }
++
++gboolean
++ibus_bus_use_bridge_hotkey (IBusBus *bus)
++{
++    return (USE_BRIDGE_HOTKEY == 1) ? TRUE : FALSE;
++}
+diff --git a/src/ibusbus.h b/src/ibusbus.h
+index 77d3916..4bdf760 100644
+--- a/src/ibusbus.h
++++ b/src/ibusbus.h
+@@ -971,5 +971,14 @@ void         ibus_bus_set_watch_ibus_signal
+  */
+ IBusConfig  *ibus_bus_get_config        (IBusBus        *bus);
+ 
++/**
++ * ibus_bus_use_bridge_hotkey:
++ * @bus: An #IBusBus.
++ * @returns: %TRUE if @bus use bridge hotkey, %FALSE otherwise.
++ *
++ * Return %TRUE if @bus use bridge hotkey.
++ */
++gboolean     ibus_bus_use_bridge_hotkey (IBusBus *bus);
++
+ G_END_DECLS
+ #endif
+diff --git a/src/ibusenginedesc.c b/src/ibusenginedesc.c
+index d3800e1..a9e68be 100644
+--- a/src/ibusenginedesc.c
++++ b/src/ibusenginedesc.c
+@@ -233,7 +233,11 @@ ibus_engine_desc_class_init (IBusEngineDescClass *class)
+                     g_param_spec_string ("hotkeys",
+                         "description hotkeys",
+                         "The hotkeys of engine description",
++#if USE_BRIDGE_HOTKEY
++                        "Control+space",
++#else
+                         "",
++#endif
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ 
+     /**
+diff --git a/src/ibushotkey.c b/src/ibushotkey.c
+index 32f8338..bef7dfc 100644
+--- a/src/ibushotkey.c
++++ b/src/ibushotkey.c
+@@ -562,3 +562,14 @@ ibus_hotkey_profile_lookup_hotkey (IBusHotkeyProfile *profile,
+ 
+     return (GQuark) GPOINTER_TO_UINT (g_tree_lookup (priv->hotkeys, &hotkey));
+ }
++
++void
++ibus_hotkey_profile_foreach_hotkey (IBusHotkeyProfile *profile,
++                                    GTraverseFunc      func,
++                                    gpointer           user_data)
++{
++    IBusHotkeyProfilePrivate *priv;
++    priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile);
++
++    g_tree_foreach (priv->hotkeys, func, user_data);
++}
+diff --git a/src/ibushotkey.h b/src/ibushotkey.h
+index 9a341f6..92ec6af 100644
+--- a/src/ibushotkey.h
++++ b/src/ibushotkey.h
+@@ -179,5 +179,16 @@ GQuark           ibus_hotkey_profile_lookup_hotkey
+                                                  guint               keyval,
+                                                  guint               modifiers);
+ 
++/**
++ * ibus_hotkey_profile_foreach_hotkey:
++ * @profile: An IBusHotkeyProfile.
++ * @func: (scope call): A GTraverseFunc for g_tree_traverse.
++ * @user_data: A gpointer for g_tree_traverse.
++ */
++void             ibus_hotkey_profile_foreach_hotkey
++                                                (IBusHotkeyProfile  *profile,
++                                                 GTraverseFunc       func,
++                                                 gpointer            user_data);
++
+ G_END_DECLS
+ #endif
+diff --git a/ui/gtk/panel.py b/ui/gtk/panel.py
+index de64920..7f2edcd 100644
+--- a/ui/gtk/panel.py
++++ b/ui/gtk/panel.py
+@@ -133,6 +133,11 @@ class Panel(ibus.PanelBase):
+         # self.__bus.request_name(ibus.panel.IBUS_SERVICE_PANEL, 0)
+ 
+         # init xkb
++        self.__default_layout = 'default'
++        self.__default_model = 'default'
++        self.__default_option = 'default'
++        self.__disabled_engine = None
++
+         self.__xkblayout = ibus.XKBLayout(self.__config)
+         use_xkb = self.__config.get_value("general", "use_system_keyboard_layout", False)
+         if not use_xkb:
+@@ -142,11 +147,18 @@ class Panel(ibus.PanelBase):
+             value = 'default'
+         if value != 'default':
+             self.__xkblayout.set_default_layout(value)
++            if value.find('(') >= 0:
++                self.__default_layout = value.split('(')[0]
++                self.__default_model = value.split('(')[1].split(')')[0]
++            else:
++                self.__default_layout = value
++                self.__default_model = None
+         value = str(self.__config.get_value("general", "system_keyboard_option", ''))
+         if value == '':
+             value = 'default'
+         if value != 'default':
+             self.__xkblayout.set_default_option(value)
++            self.__default_option = value
+ 
+     def set_cursor_location(self, x, y, w, h):
+         self.__candidate_panel.set_cursor_location(x, y, w, h)
+@@ -233,6 +245,41 @@ class Panel(ibus.PanelBase):
+     def __set_im_name(self, name):
+         self.__language_bar.set_im_name(name)
+ 
++    def __set_default_layout_engine(self):
++        default_layout = self.__default_layout
++        default_model = self.__default_model
++        if default_layout == 'default':
++            default_layout = self.__xkblayout.get_default_layout()[0]
++            default_model = None
++        if default_model == 'default':
++            default_model = self.__xkblayout.get_default_layout()[1]
++        layouts = default_layout.split(',')
++        group = self.__xkblayout.get_group()
++        layout = layouts[group]
++        model = None
++        if default_model != None and default_model != '':
++            models = default_model.split(',')
++            if group < models.length:
++                model = models[group]
++        registry = ibus.XKBConfigRegistry()
++        langs = registry.get_layout_lang()[layout]
++        lang = 'en'
++        im_icon = layout[:2]
++        if langs != None:
++            im_icon = langs[0][:2]
++            lang = str(langs[0])
++        if self.__disabled_engine == None:
++            self.__disabled_engine = registry.engine_desc_new(lang,
++                                                              self.__default_layout,
++                                                              'Default Layout',
++                                                              default_model,
++                                                              None)
++        if self.__focus_ic != None:
++            prev_engine = self.__focus_ic.get_engine()
++        if prev_engine == None or \
++           prev_engine.name != self.__disabled_engine.name:
++            self.__focus_ic.set_bridge_engine()
++
+     def focus_in(self, ic):
+         self.reset()
+         self.__focus_ic = ibus.InputContext(self.__bus, ic)
+@@ -240,6 +287,9 @@ class Panel(ibus.PanelBase):
+         self.__language_bar.set_enabled(enabled)
+ 
+         if not enabled:
++            if ibus.use_bridge_hotkey():
++                self.__set_default_layout_engine()
++
+             self.__set_im_icon(ICON_KEYBOARD)
+             self.__set_im_name(None)
+             if self.__bus.get_use_sys_layout():
+@@ -453,7 +503,12 @@ class Panel(ibus.PanelBase):
+         size = gtk.icon_size_lookup(gtk.ICON_SIZE_MENU)
+         menu = gtk.Menu()
+         for i, engine in enumerate(engines):
+-            lang = ibus.get_language_name(engine.language)
++            language = engine.language
++            if ibus.use_bridge_hotkey() and \
++                engine.name == ibus.DEFAULT_BRIDGE_ENGINE_NAME and \
++                self.__disabled_engine != None:
++                language = self.__disabled_engine.language
++            lang = ibus.get_language_name(language)
+             item = gtk.ImageMenuItem("%s - %s" % (lang, engine.longname))
+             if current_engine and current_engine.name == engine.name:
+                 for widget in item.get_children():
+@@ -471,7 +526,8 @@ class Panel(ibus.PanelBase):
+         item.connect("activate", self.__im_menu_item_activate_cb, None)
+         if self.__focus_ic == None or not self.__focus_ic.is_enabled():
+             item.set_sensitive(False)
+-        menu.add(item)
++        if not ibus.use_bridge_hotkey():
++            menu.add(item)
+ 
+         menu.show_all()
+         menu.set_take_focus(False)
+diff --git a/xkb/Makefile.am b/xkb/Makefile.am
+index ad9cdd9..c4d5afb 100644
+--- a/xkb/Makefile.am
++++ b/xkb/Makefile.am
+@@ -28,6 +28,8 @@ INCLUDES = \
+         -I$(top_srcdir)/src \
+ 	-DIBUS_LOCALEDIR=\"$(datadir)/locale\" \
+ 	-DLIBEXECDIR=\""$(libexecdir)"\" \
++	-DUSE_BRIDGE_HOTKEY=$(USE_BRIDGE_HOTKEY) \
++	-DDEFAULT_BRIDGE_ENGINE_NAME=\"$(DEFAULT_BRIDGE_ENGINE_NAME)\" \
+         $(NULL)
+ 
+ noinst_PROGRAMS = $(TESTS)
+diff --git a/xkb/ibus-engine-xkb-main.c b/xkb/ibus-engine-xkb-main.c
+index 5d748cc..a80f349 100644
+--- a/xkb/ibus-engine-xkb-main.c
++++ b/xkb/ibus-engine-xkb-main.c
+@@ -288,6 +288,14 @@ print_component ()
+     layout_desc = (GHashTable *) ibus_xkb_config_registry_get_layout_desc (config_registry);
+     variant_desc = (GHashTable *) ibus_xkb_config_registry_get_variant_desc (config_registry);
+     component = ibus_xkb_component_new ();
++#if USE_BRIDGE_HOTKEY
++    engine = ibus_xkb_engine_desc_new ("en",
++                                       "default",
++                                       "Default Layout",
++                                       NULL,
++                                       NULL);
++    ibus_component_add_engine (component, engine);
++#endif
+     for (keys = g_hash_table_get_keys (layout_list); keys; keys = keys->next) {
+         if (keys->data == NULL) {
+             continue;
+diff --git a/xkb/xkbxml.c b/xkb/xkbxml.c
+index 2ce7bcf..de6648f 100644
+--- a/xkb/xkbxml.c
++++ b/xkb/xkbxml.c
+@@ -273,6 +273,7 @@ ibus_xkb_engine_desc_new (const gchar *lang,
+     gchar *longname = NULL;
+     gchar *desc = NULL;
+     gchar *engine_layout = NULL;
++    const gchar *icon = "ibus-engine";
+ 
+     g_return_val_if_fail (lang != NULL && layout != NULL, NULL);
+ 
+@@ -294,6 +295,11 @@ ibus_xkb_engine_desc_new (const gchar *lang,
+         desc = g_strdup_printf ("XKB %s keyboard layout", layout);
+         engine_layout = g_strdup (layout);
+     }
++#if USE_BRIDGE_HOTKEY
++    if (g_strcmp0 (name, DEFAULT_BRIDGE_ENGINE_NAME) == 0) {
++        icon = "input-keyboard-symbolic";
++    }
++#endif
+ 
+     engine = ibus_engine_desc_new (name,
+                                    longname,
+@@ -301,7 +307,7 @@ ibus_xkb_engine_desc_new (const gchar *lang,
+                                    lang,
+                                    "LGPL2.1",
+                                    "Takao Fujiwara <takao.fujiwara1 at gmail.com>",
+-                                   "ibus-engine",
++                                   icon,
+                                    engine_layout);
+ 
+     g_free (name);
+-- 
+1.7.4.4
+
diff --git a/ibus-xx-icon-symbol.patch b/ibus-xx-icon-symbol.patch
new file mode 100644
index 0000000..eb0802d
--- /dev/null
+++ b/ibus-xx-icon-symbol.patch
@@ -0,0 +1,331 @@
+From ec02d646dccd213e1309011160d9d73a26174044 Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1 at gmail.com>
+Date: Mon, 20 Jun 2011 19:10:21 +0900
+Subject: [PATCH] Add icon_symbol property in IBusEngineDesc.
+
+---
+ bus/engineproxy.c         |   22 +++++++++++++++
+ bus/ibusimpl.c            |   33 ++++++++++++++++++++++
+ bus/ibusimpl.h            |    4 +++
+ ibus/engine.py            |    3 ++
+ ibus/interface/iengine.py |    3 ++
+ src/ibusenginedesc.c      |   66 +++++++++++++++++++++++++++++++++++++++++++++
+ src/ibusenginedesc.h      |   10 +++++++
+ 7 files changed, 141 insertions(+), 0 deletions(-)
+
+diff --git a/bus/engineproxy.c b/bus/engineproxy.c
+index f74af12..5c0cbb2 100644
+--- a/bus/engineproxy.c
++++ b/bus/engineproxy.c
+@@ -591,6 +591,28 @@ bus_engine_proxy_g_signal (GDBusProxy  *proxy,
+         return;
+     }
+ 
++    if (g_strcmp0 (signal_name, "SetIconSymbol") == 0) {
++        const gchar *name = NULL;
++        gchar *icon_symbol = NULL;
++        GValue value = { 0, };
++
++        name = ibus_engine_desc_get_name (engine->desc);
++        g_return_if_fail (name != NULL);
++        g_variant_get (parameters, "(s)", &icon_symbol);
++        g_return_if_fail (icon_symbol != NULL);
++
++        g_value_init (&value, G_TYPE_STRING);
++        g_value_set_string (&value, icon_symbol);
++        g_object_set_property (G_OBJECT (engine->desc), "icon_symbol", &value);
++        g_value_unset (&value);
++
++        bus_ibus_impl_set_icon_symbol_with_engine_name (BUS_DEFAULT_IBUS,
++                                                        name,
++                                                        icon_symbol);
++        g_free (icon_symbol);
++        return;
++    }
++
+     g_return_if_reached ();
+ }
+ 
+diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c
+index b356b2c..38d6d11 100644
+--- a/bus/ibusimpl.c
++++ b/bus/ibusimpl.c
+@@ -2342,3 +2342,36 @@ bus_ibus_impl_get_focused_input_context (BusIBusImpl *ibus)
+ 
+     return ibus->focused_context;
+ }
++
++void
++bus_ibus_impl_set_icon_symbol_with_engine_name (BusIBusImpl *ibus,
++                                                const gchar *name,
++                                                const gchar *icon_symbol)
++{
++    IBusEngineDesc *desc = NULL;
++    GValue value = { 0, };
++
++    g_assert (BUS_IS_IBUS_IMPL (ibus));
++    g_assert (name != NULL);
++    g_assert (icon_symbol != NULL);
++
++    desc = bus_ibus_impl_get_engine_desc (ibus, name);
++
++    if (desc == NULL) {
++        return;
++    }
++
++    g_value_init (&value, G_TYPE_STRING);
++    g_value_set_string (&value, icon_symbol);
++    g_object_set_property (G_OBJECT (desc), "icon_symbol", &value);
++    g_value_unset (&value);
++
++    /* Update status icon.
++     * "enabled" signal is caught by ibus->panel and ibus->panel calls
++     * StateChanged dbus method. */
++    if (ibus->panel && ibus->focused_context) {
++        if (bus_input_context_is_enabled (ibus->focused_context)) {
++            bus_input_context_enable (ibus->focused_context);
++        }
++    }
++}
+diff --git a/bus/ibusimpl.h b/bus/ibusimpl.h
+index 42edbf8..4f37cbc 100644
+--- a/bus/ibusimpl.h
++++ b/bus/ibusimpl.h
+@@ -99,6 +99,10 @@ gboolean         bus_ibus_impl_is_embed_preedit_text
+                                                     (BusIBusImpl        *ibus);
+ BusInputContext *bus_ibus_impl_get_focused_input_context
+                                                     (BusIBusImpl        *ibus);
++void             bus_ibus_impl_set_icon_symbol_with_engine_name
++                                                    (BusIBusImpl        *ibus,
++                                                     const gchar        *name,
++                                                     const gchar        *icon_symbol);
+ 
+ G_END_DECLS
+ #endif
+diff --git a/ibus/engine.py b/ibus/engine.py
+index fe5dd98..e827408 100644
+--- a/ibus/engine.py
++++ b/ibus/engine.py
+@@ -176,6 +176,9 @@ class EngineBase(object.Object):
+         self.__proxy = None
+         super(EngineBase,self).do_destroy()
+ 
++    def set_icon_symbol(self, icon_symbol):
++        return self.__proxy.SetIconSymbol(icon_symbol)
++
+ 
+ class EngineProxy(interface.IEngine):
+     def __init__(self, engine, conn, object_path):
+diff --git a/ibus/interface/iengine.py b/ibus/interface/iengine.py
+index 9e0d981..7cefcdf 100644
+--- a/ibus/interface/iengine.py
++++ b/ibus/interface/iengine.py
+@@ -157,3 +157,6 @@ class IEngine(dbus.service.Object):
+ 
+     @signal()
+     def RequireSurroundingText(self): pass
++
++    @signal(signature="s")
++    def SetIconSymbol(self, icon_symbol): pass
+diff --git a/src/ibusenginedesc.c b/src/ibusenginedesc.c
+index ca5ef60..d3800e1 100644
+--- a/src/ibusenginedesc.c
++++ b/src/ibusenginedesc.c
+@@ -22,6 +22,7 @@
+ #include <stdlib.h>
+ #include "ibusenginedesc.h"
+ #include "ibusxml.h"
++#include "ibusenumtypes.h"
+ 
+ enum {
+     LAST_SIGNAL,
+@@ -39,6 +40,7 @@ enum {
+     PROP_LAYOUT,
+     PROP_RANK,
+     PROP_HOTKEYS,
++    PROP_ICON_SYMBOL,
+ };
+ 
+ 
+@@ -54,6 +56,7 @@ struct _IBusEngineDescPrivate {
+     gchar      *layout;
+     guint       rank;
+     gchar      *hotkeys;
++    gchar      *icon_symbol;
+ };
+ 
+ #define IBUS_ENGINE_DESC_GET_PRIVATE(o)  \
+@@ -232,6 +235,19 @@ ibus_engine_desc_class_init (IBusEngineDescClass *class)
+                         "The hotkeys of engine description",
+                         "",
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
++
++    /**
++     * IBusEngineDesc:icon_symbol:
++     *
++     * The symbol chars of engine description instead of icon image
++     */
++    g_object_class_install_property (gobject_class,
++                    PROP_ICON_SYMBOL,
++                    g_param_spec_string ("icon_symbol",
++                        "description icon_symbol",
++                        "The icon symbol chars of engine description",
++                        "",
++                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ }
+ 
+ static void
+@@ -249,6 +265,7 @@ ibus_engine_desc_init (IBusEngineDesc *desc)
+     desc->priv->layout = NULL;
+     desc->priv->rank = 0;
+     desc->priv->hotkeys = NULL;
++    desc->priv->icon_symbol = NULL;
+ }
+ 
+ static void
+@@ -263,6 +280,7 @@ ibus_engine_desc_destroy (IBusEngineDesc *desc)
+     g_free (desc->priv->icon);
+     g_free (desc->priv->layout);
+     g_free (desc->priv->hotkeys);
++    g_free (desc->priv->icon_symbol);
+ 
+     IBUS_OBJECT_CLASS (ibus_engine_desc_parent_class)->destroy (IBUS_OBJECT (desc));
+ }
+@@ -313,6 +331,10 @@ ibus_engine_desc_set_property (IBusEngineDesc *desc,
+         g_assert (desc->priv->hotkeys == NULL);
+         desc->priv->hotkeys = g_value_dup_string (value);
+         break;
++    case PROP_ICON_SYMBOL:
++        g_free (desc->priv->icon_symbol);
++        desc->priv->icon_symbol = g_value_dup_string (value);
++        break;
+     default:
+         G_OBJECT_WARN_INVALID_PROPERTY_ID (desc, prop_id, pspec);
+     }
+@@ -355,6 +377,9 @@ ibus_engine_desc_get_property (IBusEngineDesc *desc,
+     case PROP_HOTKEYS:
+         g_value_set_string (value, ibus_engine_desc_get_hotkeys (desc));
+         break;
++    case PROP_ICON_SYMBOL:
++        g_value_set_string (value, ibus_engine_desc_get_icon_symbol (desc));
++        break;
+     default:
+         G_OBJECT_WARN_INVALID_PROPERTY_ID (desc, prop_id, pspec);
+     }
+@@ -382,9 +407,28 @@ ibus_engine_desc_serialize (IBusEngineDesc  *desc,
+     g_variant_builder_add (builder, "u", desc->priv->rank);
+     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->hotkeys));
+ #undef NOTNULL
++
++    /* append extra properties */
++    GVariantBuilder array;
++    g_variant_builder_init (&array, G_VARIANT_TYPE ("a{sv}"));
++    g_variant_builder_add (&array, "{sv}", "icon_symbol", g_variant_new_string (desc->priv->icon_symbol));
++    g_variant_builder_add (builder, "v", g_variant_builder_end (&array));
++
+     return TRUE;
+ }
+ 
++static gboolean
++ibus_engine_desc_deserialize_property (IBusEngineDesc *desc,
++                                       const gchar    *name,
++                                       GVariant       *variant)
++{
++    if (g_strcmp0 (name, "icon_symbol") == 0) {
++        g_variant_get (variant, "s", &desc->priv->icon_symbol);
++        return TRUE;
++    }
++    return FALSE;
++}
++
+ static gint
+ ibus_engine_desc_deserialize (IBusEngineDesc *desc,
+                               GVariant       *variant)
+@@ -405,6 +449,23 @@ ibus_engine_desc_deserialize (IBusEngineDesc *desc,
+     g_variant_get_child (variant, retval++, "u", &desc->priv->rank);
+     g_variant_get_child (variant, retval++, "s", &desc->priv->hotkeys);
+ 
++    /* extract extra properties */
++    GVariantIter iter;
++    GVariant *child, *array;
++
++    g_variant_get_child (variant, retval++, "v", &array);
++    g_variant_iter_init (&iter, array);
++    while ((child = g_variant_iter_next_value (&iter))) {
++        gchar *name;
++        GVariant *value;
++        g_variant_get (child, "{sv}", &name, &value);
++        if (ibus_engine_desc_deserialize_property (desc, name, value))
++            retval++;
++        g_free (name);
++        g_variant_unref (value);
++        g_variant_unref (child);
++    }
++
+     return retval;
+ }
+ 
+@@ -428,6 +489,7 @@ ibus_engine_desc_copy (IBusEngineDesc       *dest,
+     dest->priv->layout           = g_strdup (src->priv->layout);
+     dest->priv->rank             = src->priv->rank;
+     dest->priv->hotkeys          = g_strdup (src->priv->hotkeys);
++    dest->priv->icon_symbol      = g_strdup (src->priv->icon_symbol);
+     return TRUE;
+ }
+ 
+@@ -465,6 +527,7 @@ ibus_engine_desc_output (IBusEngineDesc *desc,
+     OUTPUT_ENTRY_1(icon);
+     OUTPUT_ENTRY_1(layout);
+     OUTPUT_ENTRY_1(hotkeys);
++    OUTPUT_ENTRY_1(icon_symbol);
+     g_string_append_indent (output, indent + 1);
+     g_string_append_printf (output, "<rank>%u</rank>\n", desc->priv->rank);
+ #undef OUTPUT_ENTRY
+@@ -498,6 +561,7 @@ ibus_engine_desc_parse_xml_node (IBusEngineDesc *desc,
+         PARSE_ENTRY_1(icon);
+         PARSE_ENTRY_1(layout);
+         PARSE_ENTRY_1(hotkeys);
++        PARSE_ENTRY_1(icon_symbol);
+ #undef PARSE_ENTRY
+ #undef PARSE_ENTRY_1
+         if (g_strcmp0 (sub_node->name , "rank") == 0) {
+@@ -526,6 +590,7 @@ IBUS_ENGINE_DESC_GET_PROPERTY (icon, const gchar *)
+ IBUS_ENGINE_DESC_GET_PROPERTY (layout, const gchar *)
+ IBUS_ENGINE_DESC_GET_PROPERTY (rank, guint)
+ IBUS_ENGINE_DESC_GET_PROPERTY (hotkeys, const gchar *)
++IBUS_ENGINE_DESC_GET_PROPERTY (icon_symbol, const gchar *)
+ #undef IBUS_ENGINE_DESC_GET_PROPERTY
+ 
+ IBusEngineDesc *
+@@ -573,6 +638,7 @@ ibus_engine_desc_new_varargs (const gchar *first_property_name, ...)
+     g_assert (desc->priv->icon);
+     g_assert (desc->priv->layout);
+     g_assert (desc->priv->hotkeys);
++    g_assert (desc->priv->icon_symbol);
+ 
+     return desc;
+ }
+diff --git a/src/ibusenginedesc.h b/src/ibusenginedesc.h
+index 9718b15..e3194c3 100644
+--- a/src/ibusenginedesc.h
++++ b/src/ibusenginedesc.h
+@@ -249,6 +249,16 @@ guint            ibus_engine_desc_get_rank      (IBusEngineDesc *info);
+ const gchar     *ibus_engine_desc_get_hotkeys   (IBusEngineDesc *info);
+ 
+ /**
++ * ibus_engine_desc_get_icon_symbol:
++ * @info: An IBusEngineDesc
++ * @returns: icon_symbol property in IBusEngineDesc
++ *
++ * Return the icon_symbol property in IBusEngineDesc. It should not be freed.
++ */
++const gchar     *ibus_engine_desc_get_icon_symbol
++                                                (IBusEngineDesc *info);
++
++/**
+  * ibus_engine_desc_output:
+  * @info: An IBusEngineDesc
+  * @output: XML-formatted Input method engine description.
+-- 
+1.7.4.4
+
diff --git a/ibus-xx-setup-frequent-lang.patch b/ibus-xx-setup-frequent-lang.patch
index a019fa8..a65949e 100644
--- a/ibus-xx-setup-frequent-lang.patch
+++ b/ibus-xx-setup-frequent-lang.patch
@@ -1,6 +1,6 @@
-From 231285d6d9e1b0b868edb842b46c30974a5c517a Mon Sep 17 00:00:00 2001
+From 735a4d98ac057ded317dae9b85777ce56d8af0fd Mon Sep 17 00:00:00 2001
 From: fujiwarat <takao.fujiwara1 at gmail.com>
-Date: Wed, 25 May 2011 18:52:25 +0900
+Date: Mon, 20 Jun 2011 19:04:51 +0900
 Subject: [PATCH] Enable ibus-setup to show the frequently used languages
  only in IME list.
 
@@ -10,10 +10,10 @@ Subject: [PATCH] Enable ibus-setup to show the frequently used languages
  setup/main.py           |    1 +
  3 files changed, 300 insertions(+), 22 deletions(-)
 
-diff --git a/data/ibus.schemas.in b/data/ibus.schemas.in
-index 39922a0..2e33b2c 100644
---- a/data/ibus.schemas.in
-+++ b/data/ibus.schemas.in
+diff --git a/data/ibus.schemas.in.in b/data/ibus.schemas.in.in
+index d4334e1..5ef2ac2 100644
+--- a/data/ibus.schemas.in.in
++++ b/data/ibus.schemas.in.in
 @@ -239,6 +239,174 @@
        </locale>
      </schema>
@@ -413,10 +413,10 @@ index 7383177..bff2407 100644
          return self.__title
  
 diff --git a/setup/main.py b/setup/main.py
-index 9cdce02..5201139 100644
+index 192fb88..5a0170d 100644
 --- a/setup/main.py
 +++ b/setup/main.py
-@@ -226,6 +226,7 @@ class Setup(object):
+@@ -227,6 +227,7 @@ class Setup(object):
          button.connect("toggled", self.__checkbutton_preload_engine_mode_toggled_cb)
          self.__engines = self.__bus.list_engines()
          self.__combobox = self.__builder.get_object("combobox_engines")
diff --git a/ibus.spec b/ibus.spec
index 15a20f6..592d36b 100644
--- a/ibus.spec
+++ b/ibus.spec
@@ -13,7 +13,7 @@
 
 Name:       ibus
 Version:    1.3.99.20110419
-Release:    2%{?dist}
+Release:    3%{?dist}
 Summary:    Intelligent Input Bus for Linux OS
 License:    LGPLv2+
 Group:      System Environment/Libraries
@@ -21,14 +21,16 @@ URL:        http://code.google.com/p/ibus/
 Source0:    http://ibus.googlecode.com/files/%{name}-%{version}.tar.gz
 Source1:    xinput-ibus
 %if %have_gjsfile
-Source2:    http://fujiwara.fedorapeople.org/ibus/gnome-shell/gnome-shell-ibus-plugins-20110601.tar.bz2
+Source2:    http://fujiwara.fedorapeople.org/ibus/gnome-shell/gnome-shell-ibus-plugins-20110621.tar.bz2
 %endif
 Source3:    https://www.transifex.net/projects/p/ibus/resource/master/l/da/download/ibus_master_da.po
+Source4:    http://ueno.fedorapeople.org/ibus-indicator/ibus-indicator.tar.bz2
 Patch0:     ibus-HEAD.patch
-Patch1:     ibus-435880-surrounding-text.patch
-Patch2:     ibus-541492-xkb.patch
-Patch3:     ibus-530711-preload-sys.patch
-Patch4:     ibus-xx-setup-frequent-lang.patch
+Patch1:     ibus-530711-preload-sys.patch
+Patch2:     ibus-xx-icon-symbol.patch
+Patch3:     ibus-541492-xkb.patch
+Patch4:     ibus-xx-bridge-hotkey.patch
+Patch5:     ibus-xx-setup-frequent-lang.patch
 
 # Workaround for oxygen-gtk icon theme until bug 699103 is fixed.
 Patch91:    ibus-711632-fedora-fallback-icon.patch
@@ -121,6 +123,21 @@ Requires(post): glib2 >= %{glib_ver}
 %description gtk3
 This package contains ibus im module for gtk3
 
+%package gnome3
+Summary:    IBus gnome-shell-extension for GNOME3
+Group:      System Environment/Libraries
+Requires:   %{name} = %{version}-%{release}
+Requires:   %{name}-libs = %{version}-%{release}
+Requires:   gnome-shell
+
+%description gnome3
+This is a transitional package which allows users to try out new IBus
+GUI for GNOME3 in development.  Note that this package will be marked
+as obsolete once the integration has completed in the GNOME3 upstream.
+
+%description gnome3
+This package contains ibus im module for gtk3
+
 %package devel
 Summary:    Development tools for ibus
 Group:      Development/Libraries
@@ -150,18 +167,19 @@ sed -i \
   -e "s|Config.IBUS_XKB|'/usr/libexec/ibus-xkb'|" \
   -e "s|Config.HAVE_IBUS_XKB|true|" \
   js/ui/status/ibus/xkbLayout.js
+bzcat %SOURCE4 | tar xf -
 %endif
 cp %SOURCE3 po/da.po
 %patch0 -p1
-# start surrounding patch
-%patch1 -p1 -b .surrounding
 cp client/gtk2/ibusimcontext.c client/gtk3/ibusimcontext.c
-# end surrounding patch
+%patch1 -p1 -b .preload-sys
+%patch2 -p1 -b .icon-symbol
 %if %have_libxkbfile
-%patch2 -p1 -b .xkb
+%patch3 -p1 -b .xkb
 %endif
-%patch3 -p1 -b .preload-sys
-%patch4 -p1 -b .setup-frequent-lang
+mv data/ibus.schemas.in data/ibus.schemas.in.in
+%patch4 -p1 -b .bridge-key
+%patch5 -p1 -b .setup-frequent-lang
 
 %patch91 -p1 -b .fallback-icon
 
@@ -180,6 +198,7 @@ automake -a -c -f
     --disable-gtk-doc \
     --with-no-snooper-apps='gnome-do,Do.*,firefox.*,.*chrome.*,.*chromium.*' \
     --enable-surrounding-text \
+    --enable-bridge-hotkey \
     --enable-introspection
 
 # make -C po update-gmo
@@ -215,19 +234,11 @@ desktop-file-install --delete-original          \
   $RPM_BUILD_ROOT%{_datadir}/applications/*
 
 %if %have_gjsfile
-cp -R js/ui/status/ibus $RPM_BUILD_ROOT%{_datadir}/ibus/ui/gjs-g-s
-cat >> $RPM_BUILD_ROOT%{_datadir}/ibus/ui/gjs-g-s/README <<_EOF
-IBus Panel for GNOME-Shell
---------------------------
-
-This is an alpha version of IBus Panel for GNOME-Shell.
-These files under this directory are prepared for the test purpose.
-It is planned to integrate the files into gnome-shell finally.
-Please refer the installation:
-https://fedoraproject.org/wiki/I18N/InputMethods#GNOME-Shell
-Bug Report:
-https://bugzilla.redhat.com/show_bug.cgi?id=657165
-_EOF
+# https://bugzilla.redhat.com/show_bug.cgi?id=657165
+install -dm 755 $RPM_BUILD_ROOT%{_datadir}/gnome-shell
+cp -R js $RPM_BUILD_ROOT%{_datadir}/gnome-shell
+install -dm 755 $RPM_BUILD_ROOT%{_datadir}/gnome-shell/extensions
+cp -R ibus-indicator at example.com $RPM_BUILD_ROOT%{_datadir}/gnome-shell/extensions
 %endif
 
 # FIXME: no version number
@@ -323,6 +334,11 @@ fi
 %defattr(-,root,root,-)
 %{_libdir}/gtk-3.0/%{gtk3_binary_version}/immodules/im-ibus.so
 
+%files gnome3
+%defattr(-,root,root,-)
+%{_datadir}/gnome-shell/js/ui/status/ibus
+%{_datadir}/gnome-shell/extensions/ibus-indicator at example.com
+
 %files devel
 %defattr(-,root,root,-)
 %{_libdir}/lib*.so
@@ -337,9 +353,14 @@ fi
 %{_datadir}/gtk-doc/html/*
 
 %changelog
-* Wed Jun 08 2011 Takao Fujiwara <tfujiwar at redhat.com> - 1.3.99.20110419-2
+* Mon Jun 20 2011 Takao Fujiwara <tfujiwar at redhat.com> - 1.3.99.20110419-3
+- Updated ibus-HEAD.patch for upstream.
+- Removed ibus-435880-surrounding-text.patch as upstream.
 - Added ibus-711632-fedora-fallback-icon.patch
   Fixed SEGV with no icon in oxygen-gtk icon theme.
+- Added ibus-xx-icon-symbol.patch
+- Added ibus-xx-bridge-hotkey.patch
+- Added transitional ibus-gnome3 package.
 
 * Thu May 26 2011 Takao Fujiwara <tfujiwar at redhat.com> - 1.3.99.20110419-1
 - Updated to 1.3.99.20110419
diff --git a/sources b/sources
index a92cbb8..0b35584 100644
--- a/sources
+++ b/sources
@@ -1,3 +1,4 @@
 d4f2729fecb92ae6b41f26c770b1a772  ibus-1.3.99.20110419.tar.gz
-64e556364ee619d51e80397086b1d244  gnome-shell-ibus-plugins-20110601.tar.bz2
+ecd3a320faca906b1b8edaae1988f512  gnome-shell-ibus-plugins-20110621.tar.bz2
 698c90edf0f037488e1aa969804e891f  ibus_master_da.po
+23756d25109745bdc1c3a54db370d210  ibus-indicator.tar.bz2


More information about the scm-commits mailing list