Blob Blame History Raw
From f33e19bec6ab7d1a6133894c86fdeb5a81ce11f1 Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com>
Date: Wed, 1 Oct 2014 16:21:02 +0900
Subject: [PATCH] Fix to lose a focus when move the focus from the delayed
 focus-in/out.

Some applications likes google-chrome URL entry could have the delayed
focus-in and focus-out events and ibus fails to get the new focus.

BUG=rhbz#919863, rhbz#1136623

Review URL: https://codereview.appspot.com/7725045
---
 bus/inputcontext.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/bus/inputcontext.c b/bus/inputcontext.c
index b7e1ff8..d9924a1 100644
--- a/bus/inputcontext.c
+++ b/bus/inputcontext.c
@@ -773,6 +773,34 @@ _ic_process_key_event  (BusInputContext       *context,
         }
     }
 
+    /* If I move the focus from the URL entry box of google-chrome
+     * to the text buffer of gnome-terminal,
+     * focus-in/focus-out of google-chrome is caused after
+     * focus-in of gonme-terminal and gnome-terminal loses the focus.
+     * The following focus events are received in ibusimcontext:
+     * 1) (gnome-terminal:445): IBUS-WARNING **: 15:32:36:717  focus_in
+     * 2) (google-chrome:495): IBUS-WARNING **: 15:32:36:866  focus_out
+     * 3) (google-chrome:495): IBUS-WARNING **: 15:32:36:875  focus_in
+     * 4) (google-chrome:495): IBUS-WARNING **: 15:32:36:890  focus_out
+     * In 2), Just return because focused_context is not google-chrome.
+     * In 3), focused_context is changed from gnome-terminal to google-chrome
+     * In 4), focused_context is changed from google-chrome to faked_context.
+     *
+     * It seems google-chrome has a popup window of the prediction of URL
+     * and async focus-in/focus-out.
+     */
+    if (context->has_focus && context->engine == NULL &&
+        context->fake == FALSE) {
+        BusInputContext *focused_context =
+                bus_ibus_impl_get_focused_input_context (BUS_DEFAULT_IBUS);
+
+        if (focused_context != NULL && context != focused_context &&
+            (context->capabilities & IBUS_CAP_FOCUS) != 0) {
+            context->has_focus = FALSE;
+            bus_input_context_focus_in (context);
+        }
+    }
+
     /* ignore key events, if it is a fake input context */
     if (context->has_focus && context->engine && context->fake == FALSE) {
         bus_engine_proxy_process_key_event (context->engine,
-- 
1.8.5.3

From bb818e438599f080a0cffb0b7573d9a646cf3b1a Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com>
Date: Tue, 28 Oct 2014 11:28:46 +0900
Subject: [PATCH] Fix not to SEGV ibus-ui-gtk3 with wrong 'preload-engines'
 value.

Fedora internal patch could save engines from the result of
'setxkbmap -query' but they do not exist in simple.xml likes
'xkb:cn::chi' while now the current implementation converts
those engines to 'xkb:us::eng'.

BUG=https://code.google.com/p/ibus/issues/detail?id=1744
TEST=ui/gtk3

Review URL: https://codereview.appspot.com/158640043
---
 ui/gtk3/panel.vala | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
index 76cea23..7b99fdf 100644
--- a/ui/gtk3/panel.vala
+++ b/ui/gtk3/panel.vala
@@ -790,6 +790,15 @@ class Panel : IBus.PanelService {
 
         var engines = m_bus.get_engines_by_names(names);
 
+        /* Fedora internal patch could save engines not in simple.xml
+         * likes 'xkb:cn::chi'.
+         */
+        if (engines.length == 0) {
+            names =  {"xkb:us::eng"};
+            m_settings_general.set_strv("preload-engines", names);
+            engines = m_bus.get_engines_by_names(names);
+	}
+
         if (m_engines.length == 0) {
             m_engines = engines;
             switch_engine(0, true);
-- 
1.8.5.3

From e2507263817926ceb97511da3d617934d4b73443 Mon Sep 17 00:00:00 2001
From: Osamu Aoki <osamu@debian.org>
Date: Thu, 13 Nov 2014 11:23:38 +0900
Subject: [PATCH] ibus-setup tries C since en_US.UTF-8 is not installed in
 Debian by default.

BUG=https://code.google.com/p/ibus/issues/detail?id=1747
TEST=setup

Review URL: https://codereview.appspot.com/166420043
Patch from Osamu Aoki <osamu@debian.org>.
---
 setup/enginecombobox.py |  2 +-
 setup/enginedialog.py   | 13 +++++++++----
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/setup/enginecombobox.py b/setup/enginecombobox.py
index 2a2a677..199ed96 100644
--- a/setup/enginecombobox.py
+++ b/setup/enginecombobox.py
@@ -78,7 +78,7 @@ class EngineComboBox(Gtk.ComboBox):
         keys.sort(key=functools.cmp_to_key(locale.strcoll))
         loc = locale.getlocale()[0]
         # None on C locale
-        if loc == None:
+        if loc == None or loc == 'C':
             loc = 'en_US'
         current_lang = IBus.get_language_name(loc)
         # move current language to the first place
diff --git a/setup/enginedialog.py b/setup/enginedialog.py
index 8a56901..2b179ad 100644
--- a/setup/enginedialog.py
+++ b/setup/enginedialog.py
@@ -325,21 +325,26 @@ class EngineDialog(Gtk.Dialog):
 
             # Retrieve Untranslated language names.
             backup_locale = locale.setlocale(locale.LC_ALL, None)
-            try:
-                locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
+            def __set_untrans_with_locale(en_locale):
+                locale.setlocale(locale.LC_ALL, en_locale)
                 untrans = IBus.get_language_name(e.get_language())
                 if untrans == None:
                     untrans = ''
                 self.__untrans_for_lang[l] = untrans
+            try:
+                __set_untrans_with_locale('en_US.UTF-8')
             except locale.Error:
-                pass
+                try:
+                    __set_untrans_with_locale('C')
+                except locale.Error:
+                    pass
             locale.setlocale(locale.LC_ALL, backup_locale)
 
         keys = list(self.__engines_for_lang.keys())
         keys.sort(key=functools.cmp_to_key(locale.strcoll))
         loc = locale.getlocale()[0]
         # None on C locale
-        if loc == None:
+        if loc == None or loc == 'C':
             loc = 'en_US'
         current_lang = IBus.get_language_name(loc)
         # move current language to the first place
-- 
1.8.5.3

From de3541d2a26c673f27c068559f6d363064e03760 Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com>
Date: Thu, 13 Nov 2014 11:28:43 +0900
Subject: [PATCH] Remove "Release" modifiers key on ibus-setup.

BUG=https://code.google.com/p/ibus/issues/detail?id=1748
TEST=setup

Review URL: https://codereview.appspot.com/167570043
---
 setup/keyboardshortcut.py | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/setup/keyboardshortcut.py b/setup/keyboardshortcut.py
index 91595f7..86463cb 100644
--- a/setup/keyboardshortcut.py
+++ b/setup/keyboardshortcut.py
@@ -105,20 +105,16 @@ class KeyboardShortcutSelection(Gtk.Box):
                                         Gtk.CheckButton.new_with_mnemonic("_Hyper"),
                                         Gdk.ModifierType.HYPER_MASK))
         # <CapsLock> is not parsed by gtk_accelerator_parse()
-        # FIXME: Need to check if ibus gtk panel can enable <Release>.
-        self.__modifier_buttons.append(("Release",
-                                        Gtk.CheckButton.new_with_mnemonic("_Release"),
-                                        Gdk.ModifierType.RELEASE_MASK))
+        # <Release> is not supported by XIGrabKeycode()
         for name, button, mask in self.__modifier_buttons:
             button.connect("toggled", self.__modifier_button_toggled_cb, name)
 
         table.attach(self.__modifier_buttons[0][1], 0, 1, 0, 1)
         table.attach(self.__modifier_buttons[1][1], 1, 2, 0, 1)
         table.attach(self.__modifier_buttons[2][1], 2, 3, 0, 1)
-        table.attach(self.__modifier_buttons[3][1], 3, 4, 0, 1)
-        table.attach(self.__modifier_buttons[4][1], 0, 1, 1, 2)
-        table.attach(self.__modifier_buttons[5][1], 1, 2, 1, 2)
-        table.attach(self.__modifier_buttons[6][1], 2, 3, 1, 2)
+        table.attach(self.__modifier_buttons[3][1], 0, 1, 1, 2)
+        table.attach(self.__modifier_buttons[4][1], 1, 2, 1, 2)
+        table.attach(self.__modifier_buttons[5][1], 2, 3, 1, 2)
         hbox.pack_start(table, True, True, 4)
         self.pack_start(hbox, False, True, 4)
 
-- 
1.8.5.3

From a7abce698f40e60275c46f05967e8cc369769e4b Mon Sep 17 00:00:00 2001
From: Peng Wu <alexepico@gmail.com>
Date: Wed, 19 Nov 2014 18:10:05 +0900
Subject: [PATCH] Fixes ibus_engine_update_lookup_table_fast method

gnome shell needs the previous page and next page
to correctly show the page up/down arrows,
send three pages instead of one page.

URL: https://bugzilla.gnome.org/show_bug.cgi?id=703020

BUG=

Review URL: https://codereview.appspot.com/164540045
Patch from Peng Wu <alexepico@gmail.com>.
---
 src/ibusengine.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/src/ibusengine.c b/src/ibusengine.c
index 53d57df..4758f82 100644
--- a/src/ibusengine.c
+++ b/src/ibusengine.c
@@ -1422,12 +1422,17 @@ ibus_engine_update_lookup_table_fast (IBusEngine        *engine,
                                       IBusLookupTable   *table,
                                       gboolean           visible)
 {
+    /* Note: gnome shell needs the previous page and next page
+       to correctly show the page up/down arrows,
+       send three pages instead of one page. */
+
     g_return_if_fail (IBUS_IS_ENGINE (engine));
     g_return_if_fail (IBUS_IS_LOOKUP_TABLE (table));
 
     IBusLookupTable *new_table;
     IBusText *text;
     gint page_begin;
+    gint cursor_pos;
     gint i;
 
     if (table->candidates->len < table->page_size << 2) {
@@ -1436,19 +1441,31 @@ ibus_engine_update_lookup_table_fast (IBusEngine        *engine,
     }
 
     page_begin = (table->cursor_pos / table->page_size) * table->page_size;
+    cursor_pos = ibus_lookup_table_get_cursor_in_page (table);
+
+    if (table->cursor_pos >= table->page_size) {
+        /* has previous page, adjust the value. */
+        page_begin -= table->page_size;
+        cursor_pos += table->page_size;
+    }
 
-    new_table = ibus_lookup_table_new (table->page_size, 0, table->cursor_visible, table->round);
+    new_table = ibus_lookup_table_new
+        (table->page_size, 0, table->cursor_visible, table->round);
 
-    for (i = page_begin; i < page_begin + table->page_size && i < table->candidates->len; i++) {
-        ibus_lookup_table_append_candidate (new_table, ibus_lookup_table_get_candidate (table, i));
+    /* '3' means the previous page, current page and next page. */
+    for (i = page_begin; i < page_begin + 3 * table->page_size &&
+             i < table->candidates->len; i++) {
+        ibus_lookup_table_append_candidate
+            (new_table, ibus_lookup_table_get_candidate (table, i));
     }
 
     for (i = 0; (text = ibus_lookup_table_get_label (table, i)) != NULL; i++) {
         ibus_lookup_table_append_label (new_table, text);
     }
 
-    ibus_lookup_table_set_cursor_pos (new_table, ibus_lookup_table_get_cursor_in_page (table));
-    ibus_lookup_table_set_orientation (new_table, ibus_lookup_table_get_orientation (table));
+    ibus_lookup_table_set_cursor_pos (new_table, cursor_pos);
+    ibus_lookup_table_set_orientation
+        (new_table, ibus_lookup_table_get_orientation (table));
 
     ibus_engine_update_lookup_table (engine, new_table, visible);
 
-- 
1.8.5.3

From f69ddc3952971c5599c92aee3dc1de6017d07f3c Mon Sep 17 00:00:00 2001
From: Peng Wu <alexepico@gmail.com>
Date: Fri, 5 Dec 2014 11:41:08 +0900
Subject: [PATCH] Fixes ibus_keyval_name method in c++ binding

Add G_BEGIN_DECLS and G_END_DECLS macros in src/ibuskeys.h

BUG=

Review URL: https://codereview.appspot.com/185850043
Patch from Peng Wu <alexepico@gmail.com>.
---
 src/ibuskeys.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/ibuskeys.h b/src/ibuskeys.h
index 6acb0d6..7969929 100644
--- a/src/ibuskeys.h
+++ b/src/ibuskeys.h
@@ -29,6 +29,7 @@
 
 #include <glib.h>
 
+G_BEGIN_DECLS
 /**
  * ibus_keyval_name:
  * @keyval: Key symbol.
@@ -73,4 +74,5 @@ guint            ibus_unicode_to_keyval (gunichar        wc);
  **/
 gunichar         ibus_keyval_to_unicode (guint           keyval);
 
+G_END_DECLS
 #endif // __IBUS_KEYS_H_
-- 
1.8.5.3

From 097715746da0f56b8b8c3ddae2da3442032bff0c Mon Sep 17 00:00:00 2001
From: Rui Matos <tiagomatos@gmail.com>
Date: Fri, 5 Dec 2014 20:25:44 +0900
Subject: [PATCH] Carry current context content type into fake context when
 switching

When focus moves out of a context to the fake context we should keep
the content type properties as they were in the focused out context.

This allows panel implementations to show the proper UI while input
focus moves away temporarily from a text entry.

E.g. a password entry is focused and the user clicks on the panel
UI. At this point ibus switches the currently focused context to the
fake context and emits set-content-type with the fake context
properties which are empty and thus the panel reacts to it. This isn't
the intended behavior though since, from a user POV, the password
entry is still the context that will be getting text input when the
panel UI gets dismissed.

R=shawn.p.huang@gmail.com
BUG=https://bugzilla.gnome.org/show_bug.cgi?id=730628

Review URL: https://codereview.appspot.com/176260043
Patch from Rui Matos <tiagomatos@gmail.com>.
---
 bus/ibusimpl.c     |  6 ++++
 bus/inputcontext.c | 91 +++++++++++++++++++++++++++++++++---------------------
 bus/inputcontext.h | 10 ++++++
 3 files changed, 72 insertions(+), 35 deletions(-)

diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c
index dd254e2..61f6649 100644
--- a/bus/ibusimpl.c
+++ b/bus/ibusimpl.c
@@ -620,6 +620,8 @@ bus_ibus_impl_set_focused_context (BusIBusImpl     *ibus,
     }
 
     BusEngineProxy *engine = NULL;
+    guint purpose = 0;
+    guint hints = 0;
 
     if (ibus->focused_context) {
         if (ibus->use_global_engine) {
@@ -634,12 +636,16 @@ bus_ibus_impl_set_focused_context (BusIBusImpl     *ibus,
         if (ibus->panel != NULL)
             bus_panel_proxy_focus_out (ibus->panel, ibus->focused_context);
 
+        bus_input_context_get_content_type (ibus->focused_context,
+                                            &purpose, &hints);
         g_object_unref (ibus->focused_context);
         ibus->focused_context = NULL;
     }
 
     if (context == NULL && ibus->use_global_engine) {
         context = ibus->fake_context;
+        if (context)
+            bus_input_context_set_content_type (context, purpose, hints);
     }
 
     if (context) {
diff --git a/bus/inputcontext.c b/bus/inputcontext.c
index d9924a1..ea77102 100644
--- a/bus/inputcontext.c
+++ b/bus/inputcontext.c
@@ -1151,6 +1151,47 @@ bus_input_context_service_method_call (IBusService            *service,
     g_return_if_reached ();
 }
 
+static void
+_ic_set_content_type (BusInputContext *context,
+                      GVariant        *value)
+{
+    guint purpose = 0;
+    guint hints = 0;
+
+    g_variant_get (value, "(uu)", &purpose, &hints);
+    if (purpose != context->purpose || hints != context->hints) {
+        GError *error;
+        gboolean retval;
+
+        context->purpose = purpose;
+        context->hints = hints;
+
+        if (context->has_focus && context->engine)
+            bus_engine_proxy_set_content_type (context->engine,
+                                               purpose,
+                                               hints);
+
+        if (context->has_focus) {
+            g_signal_emit (context,
+                           context_signals[SET_CONTENT_TYPE],
+                           0,
+                           context->purpose,
+                           context->hints);
+        }
+
+        error = NULL;
+        retval = bus_input_context_property_changed (context,
+                                                     "ContentType",
+                                                     value,
+                                                     &error);
+        if (!retval) {
+            g_warning ("Failed to emit PropertiesChanged signal: %s",
+                       error->message);
+            g_error_free (error);
+        }
+    }
+}
+
 static gboolean
 bus_input_context_service_set_property (IBusService     *service,
                                         GDBusConnection *connection,
@@ -1175,41 +1216,7 @@ bus_input_context_service_set_property (IBusService     *service,
 
     if (g_strcmp0 (property_name, "ContentType") == 0) {
         BusInputContext *context = (BusInputContext *) service;
-        guint purpose = 0;
-        guint hints = 0;
-
-        g_variant_get (value, "(uu)", &purpose, &hints);
-        if (purpose != context->purpose || hints != context->hints) {
-            GError *error;
-            gboolean retval;
-
-            context->purpose = purpose;
-            context->hints = hints;
-
-            if (context->has_focus && context->engine)
-                bus_engine_proxy_set_content_type (context->engine,
-                                                   purpose,
-                                                   hints);
-
-            if (context->has_focus) {
-                g_signal_emit (context,
-                               context_signals[SET_CONTENT_TYPE],
-                               0,
-                               context->purpose,
-                               context->hints);
-            }
-
-            error = NULL;
-            retval = bus_input_context_property_changed (context,
-                                                         "ContentType",
-                                                         value,
-                                                         &error);
-            if (!retval) {
-                g_warning ("Failed to emit PropertiesChanged signal: %s",
-                           error->message);
-                g_error_free (error);
-            }
-        }
+        _ic_set_content_type (context, value);
         return TRUE;
     }
 
@@ -2521,3 +2528,17 @@ bus_input_context_get_content_type (BusInputContext *context,
     *purpose = context->purpose;
     *hints = context->hints;
 }
+
+void
+bus_input_context_set_content_type (BusInputContext *context,
+                                    guint            purpose,
+                                    guint            hints)
+{
+    GVariant *value;
+
+    g_assert (BUS_IS_INPUT_CONTEXT (context));
+
+    value = g_variant_ref_sink (g_variant_new ("(uu)", purpose, hints));
+    _ic_set_content_type (context, value);
+    g_variant_unref (value);
+}
diff --git a/bus/inputcontext.h b/bus/inputcontext.h
index f282fae..258f501 100644
--- a/bus/inputcontext.h
+++ b/bus/inputcontext.h
@@ -250,5 +250,15 @@ void                 bus_input_context_get_content_type
                                                  guint              *purpose,
                                                  guint              *hints);
 
+/**
+ * bus_input_context_set_content_type:
+ * @purpose: Input purpose.
+ * @hints: Input hints.
+ */
+void                 bus_input_context_set_content_type
+                                                (BusInputContext *context,
+                                                 guint            purpose,
+                                                 guint            hints);
+
 G_END_DECLS
 #endif
-- 
1.8.5.3

From 8f471ce138a9dc10ab5b1e0c716bb48ca36fe12a Mon Sep 17 00:00:00 2001
From: Doug Rintoul <doug_rintoul@sil.org>
Date: Mon, 8 Dec 2014 12:52:00 +0900
Subject: [PATCH] Show language rather than layout in xkb panel icon

BUG=https://code.google.com/p/ibus/issues/detail?id=1753
TEST=ui/gtk3/ibus-ui-gtk3

Review URL: https://codereview.appspot.com/184840043
Patch from Doug Rintoul <doug_rintoul@sil.org>.
---
 ui/gtk3/panel.vala    |  8 ++++----
 ui/gtk3/switcher.vala | 42 ++++++++++++++++++------------------------
 2 files changed, 22 insertions(+), 28 deletions(-)

diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
index 7b99fdf..4e02140 100644
--- a/ui/gtk3/panel.vala
+++ b/ui/gtk3/panel.vala
@@ -1135,16 +1135,16 @@ class Panel : IBus.PanelService {
         if (icon_name[0] == '/')
             m_status_icon.set_from_file(icon_name);
         else {
-            string symbol = null;
+            string language = null;
 
             if (engine != null) {
                 var name = engine.get_name();
                 if (name.length >= 4 && name[0:4] == "xkb:")
-                    symbol = m_switcher.get_xkb_symbol(engine);
+                    language = m_switcher.get_xkb_language(engine);
             }
 
-            if (symbol != null) {
-                Gdk.Pixbuf pixbuf = create_icon_pixbuf_with_string(symbol);
+            if (language != null) {
+                Gdk.Pixbuf pixbuf = create_icon_pixbuf_with_string(language);
                 m_status_icon.set_from_pixbuf(pixbuf);
             } else {
                 var theme = Gtk.IconTheme.get_default();
diff --git a/ui/gtk3/switcher.vala b/ui/gtk3/switcher.vala
index 7601d80..476b159 100644
--- a/ui/gtk3/switcher.vala
+++ b/ui/gtk3/switcher.vala
@@ -21,8 +21,6 @@
  */
 
 class Switcher : Gtk.Window {
-    private const int DESC_LABEL_MAX_LEN = 20;
-
     private class IBusEngineButton : Gtk.Button {
         public IBusEngineButton(IBus.EngineDesc engine, Switcher switcher) {
             GLib.Object();
@@ -38,14 +36,14 @@ class Switcher : Gtk.Window {
                 icon.set_valign(Gtk.Align.CENTER);
                 add(icon);
             } else {
-                var symbol = switcher.get_xkb_symbol(engine);
+                var language = switcher.get_xkb_language(engine);
 
-                Gtk.Label label = new Gtk.Label(symbol);
+                Gtk.Label label = new Gtk.Label(language);
                 label.set_halign(Gtk.Align.CENTER);
                 label.set_valign(Gtk.Align.CENTER);
-                string symbol_font = "Monospace Bold 16";
+                string language_font = "Monospace Bold 16";
                 string markup = "<span font=\"%s\">%s</span>".
-                        printf(symbol_font, symbol);
+                        printf(language_font, language);
 
                 label.set_markup(markup);
 
@@ -89,7 +87,7 @@ class Switcher : Gtk.Window {
     private uint m_popup_delay_time_id = 0;
     private int m_root_x;
     private int m_root_y;
-    private GLib.HashTable<string, string> m_xkb_symbols =
+    private GLib.HashTable<string, string> m_xkb_languages =
             new GLib.HashTable<string, string>(GLib.str_hash,
                                                GLib.str_equal);
 
@@ -268,10 +266,6 @@ class Switcher : Gtk.Window {
                 return true;
             });
 
-            if (longname.length > DESC_LABEL_MAX_LEN) {
-                longname = longname[0:DESC_LABEL_MAX_LEN];
-            }
-
             button.longname = longname;
             m_label.set_label(longname);
 
@@ -429,37 +423,37 @@ class Switcher : Gtk.Window {
         m_popup_delay_time = popup_delay_time;
     }
 
-    public string get_xkb_symbol(IBus.EngineDesc engine) {
+    public string get_xkb_language(IBus.EngineDesc engine) {
         var name = engine.get_name();
 
         assert(name[0:4] == "xkb:");
 
-        var symbol = m_xkb_symbols[name];
+        var language = m_xkb_languages[name];
 
-        if (symbol != null)
-            return symbol;
+        if (language != null)
+            return language;
 
-        var layout = engine.get_layout();
+        language = engine.get_language();
 
         /* Maybe invalid layout */
-        if (layout.length < 2)
-            return layout;
+        if (language.length < 2)
+            return language;
 
-        symbol = layout[0:2].up();
+        language = language[0:2].up();
 
         int index = 0;
 
-        foreach (var saved_symbol in m_xkb_symbols.get_values()) {
-            if (symbol == saved_symbol[0:2])
+        foreach (var saved_language in m_xkb_languages.get_values()) {
+            if (language == saved_language[0:2])
                 index++;
         }
 
         if (index > 0) {
             unichar u = 0x2081 + index;
-            symbol = "%s%s".printf(symbol, u.to_string());
+            language = "%s%s".printf(language, u.to_string());
         }
 
-        m_xkb_symbols.insert(name, symbol);
-        return symbol;
+        m_xkb_languages.insert(name, language);
+        return language;
     }
 }
-- 
1.8.5.3

From 576ebc3633aa1fb3076ffac031255c3da4e2cd09 Mon Sep 17 00:00:00 2001
From: Klemens Baum <klemensbaum@gmail.com>
Date: Thu, 18 Dec 2014 16:27:23 +0900
Subject: [PATCH] IMdkit: Track window property offsets correctly

The XIM specification requires that XIM tranports over 20 bytes in size
be transferred via window properties. The sender calls XChangeProperty
with PropModeAppend, and instructs the recipient via ClientMessage to
call XGetWindowProperty with delete set to True.

Naive implementations exhibit a race condition because the receiver
could have written more data in the meantime, and XGetWindowProperty
only deletes the property when bytes_after_return is zero. If
bytes_after_return is non-zero, it is necessary to use an offset when
reading from the property again.

To ensure that the property data does not grow indefinitely, Xlib
recycles 21 Atoms in round-robin fashion. Because the XIM specification
does not limit the number of Atom names of the form "_clientXXX" to be
used for data transfer over window properties, an XIM server should be
able to keep of track any number of Atoms, remembering the offset into
each property.

This patch implements correct tracking of property offsets.

Signed-off-by: Klemens Baum <klemensbaum@gmail.com>
Reviewed-by: Keith Packard <keithp@keithp.com>

rhbz#1175595
BUG=https://code.google.com/p/ibus/issues/detail?id=1751
TEST=client/x11/ibus-x11

Review URL: https://codereview.appspot.com/176190044
Patch from Klemens Baum <klemensbaum@gmail.com>.
---
 util/IMdkit/Makefile.am       |  5 ++-
 util/IMdkit/Xi18n.h           | 23 +++++++++--
 util/IMdkit/i18nOffsetCache.c | 89 +++++++++++++++++++++++++++++++++++++++++++
 util/IMdkit/i18nUtil.c        |  9 +++--
 util/IMdkit/i18nX.c           | 73 ++++++++++++++++++-----------------
 5 files changed, 154 insertions(+), 45 deletions(-)
 create mode 100644 util/IMdkit/i18nOffsetCache.c

diff --git a/util/IMdkit/Makefile.am b/util/IMdkit/Makefile.am
index e3946d7..6cbb908 100644
--- a/util/IMdkit/Makefile.am
+++ b/util/IMdkit/Makefile.am
@@ -2,8 +2,8 @@
 #
 # ibus - The Input Bus
 #
-# Copyright (c) 2007-2010 Peng Huang <shawn.p.huang@gmail.com>
-# Copyright (c) 2007-2010 Red Hat, Inc.
+# Copyright (c) 2007-2014 Peng Huang <shawn.p.huang@gmail.com>
+# Copyright (c) 2007-2014 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
@@ -29,6 +29,7 @@ libIMdkit_la_SOURCES = \
 	i18nIc.c \
 	i18nIMProto.c \
 	i18nMethod.c \
+	i18nOffsetCache.c \
 	i18nPtHdr.c \
 	i18nUtil.c \
 	i18nX.c \
diff --git a/util/IMdkit/Xi18n.h b/util/IMdkit/Xi18n.h
index 484cc62..e1d24d5 100644
--- a/util/IMdkit/Xi18n.h
+++ b/util/IMdkit/Xi18n.h
@@ -1,7 +1,9 @@
 /******************************************************************
  
-         Copyright 1994, 1995 by Sun Microsystems, Inc.
-         Copyright 1993, 1994 by Hewlett-Packard Company
+         Copyright (C) 1994-1995 Sun Microsystems, Inc.
+         Copyright (C) 1993-1994 Hewlett-Packard Company
+         Copyright (C) 2014 Peng Huang <shawn.p.huang@gmail.com>
+         Copyright (C) 2014 Red Hat, Inc.
  
 Permission to use, copy, modify, distribute, and sell this software
 and its documentation for any purpose is hereby granted without fee,
@@ -45,6 +47,7 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #define XIM_EXT_MOVE				(0x33)
 #define COMMON_EXTENSIONS_NUM   		3
 
+#include <stddef.h>
 #include <stdlib.h>
 #include "IMdkit.h"
 
@@ -138,6 +141,19 @@ typedef struct
     char	*name;
 } XIMExt;
 
+typedef struct
+{
+    Atom key;
+    unsigned long offset;
+} Xi18nAtomOffsetPair;
+
+typedef struct
+{
+    size_t capacity;
+    size_t size;
+    Xi18nAtomOffsetPair *data;
+} Xi18nOffsetCache;
+
 typedef struct _Xi18nClient
 {
     int		connect_id;
@@ -149,8 +165,7 @@ typedef struct _Xi18nClient
      */
     int		sync;
     XIMPending  *pending;
-    /* property offset to read next data */
-    long        property_offset;
+    Xi18nOffsetCache offset_cache;
     void *trans_rec;		/* contains transport specific data  */
     struct _Xi18nClient *next;
 } Xi18nClient;
diff --git a/util/IMdkit/i18nOffsetCache.c b/util/IMdkit/i18nOffsetCache.c
new file mode 100644
index 0000000..c952d5b
--- /dev/null
+++ b/util/IMdkit/i18nOffsetCache.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 Peng Huang <shawn.p.huang@gmail.com>
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this
+ * software and its documentation for any purpose is hereby granted
+ * without fee, provided that the above copyright notice appear in
+ * all copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of
+ * the copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ * THIS SOFTWARE.
+ *
+ * Author: Klemens Baum <klemensbaum@gmail.com>
+ */
+
+#include <X11/Xlib.h>
+#include <stddef.h>
+#include "IMdkit.h"
+#include "Xi18n.h"
+
+/*
+ * The XIM specification does not limit the number of window properties
+ * that can be used to transfer data, but Xlib uses the atom strings
+ * _client0 through _client20.
+ *
+ * So use that as a sensible initial size for the offset cache.
+ */
+#define INITIAL_OFFSET_CACHE_CAPACITY 21
+#define OFFSET_CACHE_GROWTH_FACTOR 2
+
+void _Xi18nInitOffsetCache (Xi18nOffsetCache *offset_cache)
+{
+    offset_cache->size = 0;
+    offset_cache->capacity = INITIAL_OFFSET_CACHE_CAPACITY;
+    offset_cache->data = (Xi18nAtomOffsetPair *) malloc (
+        INITIAL_OFFSET_CACHE_CAPACITY * sizeof (Xi18nAtomOffsetPair));
+}
+
+unsigned long _Xi18nLookupPropertyOffset (Xi18nOffsetCache *offset_cache,
+                                          Atom key)
+{
+    Xi18nAtomOffsetPair *data = offset_cache->data;
+    size_t i;
+
+    for (i = 0; i < offset_cache->size; ++i) {
+        if (data[i].key == key) {
+            return data[i].offset;
+        }
+    }
+
+    return 0;
+}
+
+void _Xi18nSetPropertyOffset (Xi18nOffsetCache *offset_cache, Atom key,
+                              unsigned long offset)
+{
+    Xi18nAtomOffsetPair *data = offset_cache->data;
+    size_t i;
+
+    for (i = 0; i < offset_cache->size; ++i) {
+        if (data[i].key == key) {
+            data[i].offset = offset;
+            return;
+        }
+    }
+
+    if (++offset_cache->size > offset_cache->capacity) {
+        offset_cache->capacity *= OFFSET_CACHE_GROWTH_FACTOR;
+        offset_cache->data = data = (Xi18nAtomOffsetPair *) realloc (data,
+                offset_cache->capacity * sizeof (Xi18nAtomOffsetPair));
+    }
+
+    data[i].key = key;
+    data[i].offset = offset;
+}
+
diff --git a/util/IMdkit/i18nUtil.c b/util/IMdkit/i18nUtil.c
index c07de48..6557bd1 100644
--- a/util/IMdkit/i18nUtil.c
+++ b/util/IMdkit/i18nUtil.c
@@ -1,7 +1,9 @@
 /******************************************************************
  
-         Copyright 1994, 1995 by Sun Microsystems, Inc.
-         Copyright 1993, 1994 by Hewlett-Packard Company
+         Copyright (C) 1994-1995 Sun Microsystems, Inc.
+         Copyright (C) 1993-1994 Hewlett-Packard Company
+         Copyright (C) 2014 Peng Huang <shawn.p.huang@gmail.com>
+         Copyright (C) 2014 Red Hat, Inc.
  
 Permission to use, copy, modify, distribute, and sell this software
 and its documentation for any purpose is hereby granted without fee,
@@ -36,6 +38,7 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include "XimFunc.h"
 
 Xi18nClient *_Xi18nFindClient (Xi18n, CARD16);
+void _Xi18nInitOffsetCache (Xi18nOffsetCache *);
 
 int
 _Xi18nNeedSwap (Xi18n i18n_core, CARD16 connect_id)
@@ -70,7 +73,7 @@ Xi18nClient *_Xi18nNewClient(Xi18n i18n_core)
     client->sync = False;
     client->byte_order = '?'; 	/* initial value */
     memset (&client->pending, 0, sizeof (XIMPending *));
-    client->property_offset = 0;
+    _Xi18nInitOffsetCache (&client->offset_cache);
     client->next = i18n_core->address.clients;
     i18n_core->address.clients = client;
 
diff --git a/util/IMdkit/i18nX.c b/util/IMdkit/i18nX.c
index 0a54058..8385aba 100644
--- a/util/IMdkit/i18nX.c
+++ b/util/IMdkit/i18nX.c
@@ -1,7 +1,9 @@
 /******************************************************************
  
-         Copyright 1994, 1995 by Sun Microsystems, Inc.
-         Copyright 1993, 1994 by Hewlett-Packard Company
+         Copyright (C) 1994-1995 Sun Microsystems, Inc.
+         Copyright (C) 1993-1994 Hewlett-Packard Company
+         Copyright (C) 2014 Peng Huang <shawn.p.huang@gmail.com>
+         Copyright (C) 2014 Red Hat, Inc.
  
 Permission to use, copy, modify, distribute, and sell this software
 and its documentation for any purpose is hereby granted without fee,
@@ -29,6 +31,7 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  
 ******************************************************************/
 
+#include <stddef.h>
 #include <limits.h>
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
@@ -38,12 +41,14 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include "Xi18nX.h"
 #include "XimFunc.h"
 
-extern Xi18nClient *_Xi18nFindClient(Xi18n, CARD16);
-extern Xi18nClient *_Xi18nNewClient(Xi18n);
-extern void _Xi18nDeleteClient(Xi18n, CARD16);
-static Bool WaitXConnectMessage(Display*, Window,
-                                XEvent*, XPointer);
-static Bool WaitXIMProtocol(Display*, Window, XEvent*, XPointer);
+extern Xi18nClient *_Xi18nFindClient (Xi18n, CARD16);
+extern Xi18nClient *_Xi18nNewClient (Xi18n);
+extern void _Xi18nDeleteClient (Xi18n, CARD16);
+extern unsigned long _Xi18nLookupPropertyOffset (Xi18nOffsetCache *, Atom);
+extern void _Xi18nSetPropertyOffset (Xi18nOffsetCache *, Atom, unsigned long);
+static Bool WaitXConnectMessage (Display*, Window,
+                                 XEvent*, XPointer);
+static Bool WaitXIMProtocol (Display*, Window, XEvent*, XPointer);
 
 static XClient *NewXClient (Xi18n i18n_core, Window new_client)
 {
@@ -129,7 +134,6 @@ static unsigned char *ReadXIMMessage (XIMS ims,
     else if (ev->format == 32) {
         /* ClientMessage and WindowProperty */
         unsigned long length = (unsigned long) ev->data.l[0];
-        unsigned long get_length;
         Atom atom = (Atom) ev->data.l[1];
         int return_code;
         Atom actual_type_ret;
@@ -137,21 +141,28 @@ static unsigned char *ReadXIMMessage (XIMS ims,
         unsigned long bytes_after_ret;
         unsigned char *prop;
         unsigned long nitems;
-
-        /* Round up length to next 4 byte value. */
-        get_length = length + 3;
-        if (get_length > LONG_MAX)
-            get_length = LONG_MAX;
-        get_length /= 4;
-        if (get_length == 0) {
-            fprintf(stderr, "%s: invalid length 0\n", __func__);
+        Xi18nOffsetCache *offset_cache = &client->offset_cache;
+        unsigned long offset;
+        unsigned long end;
+        unsigned long long_begin;
+        unsigned long long_end;
+
+        if (length == 0) {
+            fprintf (stderr, "%s: invalid length 0\n", __func__);
             return NULL;
         }
+
+        offset = _Xi18nLookupPropertyOffset (offset_cache, atom);
+        end = offset + length;
+
+        /* The property data is retrieved in 32-bit chunks */
+        long_begin = offset / 4;
+        long_end = (end + 3) / 4;
         return_code = XGetWindowProperty (i18n_core->address.dpy,
                                           x_client->accept_win,
                                           atom,
-                                          client->property_offset / 4,
-                                          get_length,
+                                          long_begin,
+                                          long_end - long_begin,
                                           True,
                                           AnyPropertyType,
                                           &actual_type_ret,
@@ -162,32 +173,22 @@ static unsigned char *ReadXIMMessage (XIMS ims,
         if (return_code != Success || actual_format_ret == 0 || nitems == 0) {
             if (return_code == Success)
                 XFree (prop);
-            client->property_offset = 0;
+            fprintf (stderr,
+                    "(XIM-IMdkit) ERROR: XGetWindowProperty failed.\n"
+                    "Protocol data is likely to be inconsistent.\n");
+            _Xi18nSetPropertyOffset (offset_cache, atom, 0);
             return (unsigned char *) NULL;
         }
         /* Update the offset to read next time as needed */
         if (bytes_after_ret > 0)
-            client->property_offset += length;
+            _Xi18nSetPropertyOffset (offset_cache, atom, offset + length);
         else
-            client->property_offset = 0;
-        switch (actual_format_ret) {
-        case 8:
-        case 16:
-        case 32:
-            length = nitems * actual_format_ret / 8;
-            break;
-        default:
-            fprintf(stderr, "%s: unknown property return format: %d\n",
-                        __func__, actual_format_ret);
-            XFree(prop);
-            client->property_offset = 0;
-            return NULL;
-        }
+            _Xi18nSetPropertyOffset (offset_cache, atom, 0);
         /* if hit, it might be an error */
         if ((p = (unsigned char *) malloc (length)) == NULL)
             return (unsigned char *) NULL;
 
-        memmove (p, prop, length);
+        memcpy (p, prop + (offset % 4), length);
         XFree (prop);
     }
     return (unsigned char *) p;
-- 
2.1.0

From bfa4d75bac29f77828e4ed38ebec6af2e6d96144 Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com>
Date: Mon, 2 Feb 2015 16:15:37 +0900
Subject: [PATCH] Release registry observed_paths and components if they are 
 broken

Registry caches might be broken in a disk.
---
 src/ibusregistry.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/src/ibusregistry.c b/src/ibusregistry.c
index 2830a08..8e9ada9 100644
--- a/src/ibusregistry.c
+++ b/src/ibusregistry.c
@@ -1,9 +1,9 @@
 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 /* vim:set et sts=4: */
 /* bus - The Input Bus
- * Copyright (C) 2013 Peng Huang <shawn.p.huang@gmail.com>
- * Copyright (C) 2013 Takao Fujiwara <takao.fujiwara1@gmail.com>
- * Copyright (C) 2013 Red Hat, Inc.
+ * Copyright (C) 2015 Peng Huang <shawn.p.huang@gmail.com>
+ * Copyright (C) 2015 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2015 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
@@ -374,12 +374,26 @@ ibus_registry_check_modification (IBusRegistry *registry)
     g_assert (IBUS_IS_REGISTRY (registry));
 
     for (p = registry->priv->observed_paths; p != NULL; p = p->next) {
+        if (!IBUS_IS_OBSERVED_PATH (p->data)) {
+            g_warning ("The registry cache of observed_paths might be " \
+                       "broken and have to generate the cache again.");
+            g_list_free_full (registry->priv->observed_paths, g_object_unref);
+            registry->priv->observed_paths = NULL;
+            return TRUE;
+        }
         if (ibus_observed_path_check_modification (
                     (IBusObservedPath *) p->data))
             return TRUE;
     }
 
     for (p = registry->priv->components; p != NULL; p = p->next) {
+        if (!IBUS_IS_COMPONENT (p->data)) {
+            g_warning ("The registry cache of components might be " \
+                       "broken and have to generate the cache again.");
+            g_list_free_full (registry->priv->components, g_object_unref);
+            registry->priv->components = NULL;
+            return TRUE;
+        }
         if (ibus_component_check_modification ((IBusComponent *) p->data))
             return TRUE;
     }
-- 
2.1.0