public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/ibus] autotool: Generate simple.xml with denylist
@ 2026-05-31 2:07 Takao Fujiwara
0 siblings, 0 replies; only message in thread
From: Takao Fujiwara @ 2026-05-31 2:07 UTC (permalink / raw)
To: git-commits
A new commit has been pushed.
Repo : rpms/ibus
Branch : autotool
Commit : 97d0736b818ea976ec65682ff6407069d09e4ed1
Author : Takao Fujiwara <tfujiwar@redhat.com>
Date : 2020-08-21T13:03:13+09:00
Stats : +1500/-12 in 4 file(s)
URL : https://src.fedoraproject.org/rpms/ibus/c/97d0736b818ea976ec65682ff6407069d09e4ed1?branch=autotool
Log:
Generate simple.xml with denylist
- Tell Pango about the engine language in the candidate panel
- Add file list in registry file for Silverblue
---
diff --git a/.gitignore b/.gitignore
index 352772b..0119b7f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,3 +61,4 @@ ibus-1.3.6.tar.gz
/ibus-1.5.20.tar.gz
/ibus-1.5.21.tar.gz
/ibus-1.5.22.tar.gz
+/ibus-simple-1.5.22.20200821.xml.gz
diff --git a/ibus-HEAD.patch b/ibus-HEAD.patch
index 1ed4aac..3b145c5 100644
--- a/ibus-HEAD.patch
+++ b/ibus-HEAD.patch
@@ -597,3 +597,1490 @@ index b54ef817..59787a80 100644
--
2.24.1
+From 0da3cece88c8b94c0721aa7aca4f2d427aa22069 Mon Sep 17 00:00:00 2001
+From: Neil Shepperd <nshepperd@gmail.com>
+Date: Wed, 22 Jul 2020 15:31:29 +0900
+Subject: [PATCH 1/9] src: Skip parsing of compose sequence with invalid
+ keysyms
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Instead of continuing with the keysym defaulted to <Delete>, print a
+warning and skip the broken XCompose rule entirely. Fixes a bug where
+an ~/.XCompose file with a error breaks the delete key.
+
+Tested locally with the example from launchpad bug below:
+
+ <\> <)> : "☭" # HAMMER AND SICKLE
+
+This is incorrect syntax as neither <\> nor <)> are correct keysym
+names. Before this patch, ibus-daemon -v prints a warning, but
+pressing delete twice produces ☭ instead of its normal function. After
+this patch, ibus-daemon -v prints a slightly better warning, and the
+delete key is unaffected.
+
+BUG=https://github.com/ibus/ibus/issues/2130
+BUG=https://bugs.launchpad.net/ubuntu/+source/ibus/+bug/1849399
+---
+ src/ibuscomposetable.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/src/ibuscomposetable.c b/src/ibuscomposetable.c
+index 3f439134..c50be2b3 100644
+--- a/src/ibuscomposetable.c
++++ b/src/ibuscomposetable.c
+@@ -216,8 +216,12 @@ parse_compose_sequence (IBusComposeData *compose_data,
+ compose_data->sequence[n] = codepoint;
+ }
+
+- if (codepoint == IBUS_KEY_VoidSymbol)
+- g_warning ("Could not get code point of keysym %s", match);
++ if (codepoint == IBUS_KEY_VoidSymbol) {
++ g_warning ("Could not get code point of keysym %s: %s",
++ match, line);
++ g_free (match);
++ goto fail;
++ }
+ g_free (match);
+ n++;
+ }
+--
+2.24.1
+
+From 0ad5e9a6b6611b53c63e635e89b42e30e43ac701 Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Wed, 5 Aug 2020 19:50:02 +0900
+Subject: [PATCH 2/9] setup: Delete autostart setting
+
+BUG=https://github.com/ibus/ibus/pull/2224
+---
+ setup/main.py | 38 --------------------------------
+ setup/setup.ui | 59 --------------------------------------------------
+ 2 files changed, 97 deletions(-)
+
+diff --git a/setup/main.py b/setup/main.py
+index f6adb098..d5e2078c 100644
+--- a/setup/main.py
++++ b/setup/main.py
+@@ -398,13 +398,6 @@ class Setup(object):
+ self.__button_close = self.__builder.get_object("button_close")
+ self.__button_close.connect("clicked", Gtk.main_quit)
+
+- # auto start ibus
+- self.__checkbutton_auto_start = self.__builder.get_object(
+- "checkbutton_auto_start")
+- self.__checkbutton_auto_start.set_active(self.__is_auto_start())
+- self.__checkbutton_auto_start.connect("toggled",
+- self.__checkbutton_auto_start_toggled_cb)
+-
+ self.__init_hotkeys()
+ self.__init_panel()
+ self.__init_general()
+@@ -647,37 +640,6 @@ class Setup(object):
+ # set new value
+ model.set(iter, COLUMN_PRELOAD, data[DATA_PRELOAD])
+
+- def __is_auto_start(self):
+- link_file = path.join(GLib.get_user_config_dir(),
+- "autostart/ibus.desktop")
+- ibus_desktop = path.join(os.getenv("IBUS_PREFIX"),
+- "share/applications/ibus.desktop")
+-
+- if not path.exists(link_file):
+- return False
+- if not path.islink(link_file):
+- return False
+- if path.realpath(link_file) != ibus_desktop:
+- return False
+- return True
+-
+- def __checkbutton_auto_start_toggled_cb(self, button):
+- auto_start_dir = path.join(GLib.get_user_config_dir(), "autostart")
+- if not path.isdir(auto_start_dir):
+- os.makedirs(auto_start_dir)
+-
+- link_file = path.join(GLib.get_user_config_dir(),
+- "autostart/ibus.desktop")
+- ibus_desktop = path.join(os.getenv("IBUS_PREFIX"),
+- "share/applications/ibus.desktop")
+- # unlink file
+- try:
+- os.unlink(link_file)
+- except:
+- pass
+- if self.__checkbutton_auto_start.get_active():
+- os.symlink(ibus_desktop, link_file)
+-
+ def __sigusr1_cb(self, *args):
+ self.__window.present()
+
+diff --git a/setup/setup.ui b/setup/setup.ui
+index 56453054..250f43a0 100644
+--- a/setup/setup.ui
++++ b/setup/setup.ui
+@@ -1307,65 +1307,6 @@
+ <property name="orientation">vertical</property>
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+- <child>
+- <placeholder/>
+- </child>
+- <child>
+- <object class="GtkLabel" id="label5">
+- <property name="visible">True</property>
+- <property name="can_focus">False</property>
+- <property name="label" translatable="yes"><big><b>IBus</b></big>
+-<small>The intelligent input bus</small>
+-Homepage: https://github.com/ibus/ibus/wiki
+-
+-
+-
+-</property>
+- <property name="use_markup">True</property>
+- <property name="justify">center</property>
+- </object>
+- <packing>
+- <property name="expand">True</property>
+- <property name="fill">True</property>
+- <property name="position">1</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkFrame" id="frame1">
+- <property name="can_focus">False</property>
+- <property name="no_show_all">True</property>
+- <property name="label_xalign">0</property>
+- <property name="shadow_type">none</property>
+- <child>
+- <object class="GtkCheckButton" id="checkbutton_auto_start">
+- <property name="label" translatable="yes">Start ibus on login</property>
+- <property name="use_action_appearance">False</property>
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="receives_default">False</property>
+- <property name="use_action_appearance">False</property>
+- <property name="use_underline">True</property>
+- <property name="halign">start</property>
+- <property name="draw_indicator">True</property>
+- <property name="margin_top">6</property>
+- <property name="margin_start">12</property>
+- </object>
+- </child>
+- <child type="label">
+- <object class="GtkLabel" id="label4">
+- <property name="visible">True</property>
+- <property name="can_focus">False</property>
+- <property name="label" translatable="yes"><b>Startup</b></property>
+- <property name="use_markup">True</property>
+- </object>
+- </child>
+- </object>
+- <packing>
+- <property name="expand">False</property>
+- <property name="fill">False</property>
+- <property name="position">2</property>
+- </packing>
+- </child>
+ </object>
+ <packing>
+ <property name="position">4</property>
+--
+2.24.1
+
+From 3f098dc51a718f3bd427873607dcd47865523dce Mon Sep 17 00:00:00 2001
+From: Aaron Muir Hamilton <aaron@correspondwith.me>
+Date: Tue, 18 Aug 2020 13:45:32 +0900
+Subject: [PATCH 3/9] ui/gtk3: Tell Pango about the engine language in the
+ candidate panel
+
+This helps Pango select the correct font variants for the engine
+language, which is especially important between languages based on han
+characters which have wildly different forms of the same character.
+
+BUG=https://github.com/ibus/ibus/issues/2238
+---
+ ui/gtk3/candidatearea.vala | 7 +++++++
+ ui/gtk3/candidatepanel.vala | 9 +++++++++
+ ui/gtk3/panel.vala | 2 ++
+ 3 files changed, 18 insertions(+)
+
+diff --git a/ui/gtk3/candidatearea.vala b/ui/gtk3/candidatearea.vala
+index b22ab5da..0ab41217 100644
+--- a/ui/gtk3/candidatearea.vala
++++ b/ui/gtk3/candidatearea.vala
+@@ -32,6 +32,8 @@ class CandidateArea : Gtk.Box {
+ private bool m_show_cursor;
+ private ThemedRGBA m_rgba;
+
++ private Pango.Attribute m_language_attribute;
++
+ private const string LABELS[] = {
+ "1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.",
+ "9.", "0.", "a.", "b.", "c.", "d.", "e.", "f."
+@@ -102,6 +104,10 @@ class CandidateArea : Gtk.Box {
+ m_labels[i].set_text(LABELS[i]);
+ }
+
++ public void set_language(Pango.Attribute language_attribute) {
++ m_language_attribute = language_attribute.copy();
++ }
++
+ public void set_candidates(IBus.Text[] candidates,
+ uint focus_candidate = 0,
+ bool show_cursor = true) {
+@@ -115,6 +121,7 @@ class CandidateArea : Gtk.Box {
+ bool visible = false;
+ if (i < candidates.length) {
+ Pango.AttrList attrs = get_pango_attr_list_from_ibus_text(candidates[i]);
++ attrs.change(m_language_attribute.copy());
+ if (i == focus_candidate && show_cursor) {
+ Pango.Attribute pango_attr = Pango.attr_foreground_new(
+ (uint16)(m_rgba.selected_fg.red * uint16.MAX),
+diff --git a/ui/gtk3/candidatepanel.vala b/ui/gtk3/candidatepanel.vala
+index 8994cdb9..57544df3 100644
+--- a/ui/gtk3/candidatepanel.vala
++++ b/ui/gtk3/candidatepanel.vala
+@@ -34,6 +34,8 @@ public class CandidatePanel : Gtk.Box{
+
+ private Gdk.Rectangle m_cursor_location;
+
++ private Pango.Attribute m_language_attribute;
++
+ public signal void cursor_up();
+ public signal void cursor_down();
+ public signal void page_up();
+@@ -112,8 +114,14 @@ public class CandidatePanel : Gtk.Box{
+ m_candidate_area.set_labels(labels);
+ }
+
++ public void set_language(Pango.Attribute language_attribute) {
++ m_candidate_area.set_language(language_attribute);
++ m_language_attribute = language_attribute.copy();
++ }
++
+ private void set_attributes(Gtk.Label label, IBus.Text text) {
+ Pango.AttrList attrs = get_pango_attr_list_from_ibus_text(text);
++ attrs.change(m_language_attribute.copy());
+
+ Gtk.StyleContext context = label.get_style_context();
+ Gdk.RGBA color;
+@@ -154,6 +162,7 @@ public class CandidatePanel : Gtk.Box{
+ if (text != null) {
+ m_aux_label.set_text(text.get_text());
+ Pango.AttrList attrs = get_pango_attr_list_from_ibus_text(text);
++ attrs.change(m_language_attribute.copy());
+ m_aux_label.set_attributes(attrs);
+ m_aux_label.show();
+ } else {
+diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
+index 680c86ed..8d9f5cc0 100644
+--- a/ui/gtk3/panel.vala
++++ b/ui/gtk3/panel.vala
+@@ -822,6 +822,8 @@ class Panel : IBus.PanelService {
+ if (!m_use_system_keyboard_layout)
+ m_xkblayout.set_layout(engine);
+
++ m_candidate_panel.set_language(new Pango.AttrLanguage(Pango.Language.from_string(engine.get_language())));
++
+ engine_contexts_insert(engine);
+ }
+
+--
+2.24.1
+
+From 79a09f1e75357a9f1b38e80717a59c19cca1645e Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Tue, 18 Aug 2020 13:45:38 +0900
+Subject: [PATCH 4/9] setup: Add use-glyph-from-engine-lang
+
+The setting can revert the previous setting to choose glpyhs
+with the current locale on lookup window instead of the engine's language.
+
+BUG=https://github.com/ibus/ibus/issues/2238
+---
+ data/dconf/org.freedesktop.ibus.gschema.xml | 9 ++++
+ setup/main.py | 7 +++
+ setup/setup.ui | 49 +++++++++++++++++++++
+ ui/gtk3/panel.vala | 26 ++++++++++-
+ 4 files changed, 89 insertions(+), 2 deletions(-)
+
+diff --git a/data/dconf/org.freedesktop.ibus.gschema.xml b/data/dconf/org.freedesktop.ibus.gschema.xml
+index 7ae8f0f6..11a179a6 100644
+--- a/data/dconf/org.freedesktop.ibus.gschema.xml
++++ b/data/dconf/org.freedesktop.ibus.gschema.xml
+@@ -165,6 +165,15 @@
+ <summary>Custom font</summary>
+ <description>Custom font name for language panel</description>
+ </key>
++ <key name="use-glyph-from-engine-lang" type="b">
++ <default>true</default>
++ <summary>Choose glyphs with input method's language on candidate window</summary>
++ <description>Some code points have the different glyphs and Pango
++ determines the glyphs from the language attribute.
++ Pango chooses glyphs from the IBus engine's language
++ if the value is true and choose them from the desktop
++ locale if the value is false.</description>
++ </key>
+ <child name="emoji" schema="org.freedesktop.ibus.panel.emoji"/>
+ </schema>
+ <schema id="org.freedesktop.ibus.panel.emoji" path="/desktop/ibus/panel/emoji/">
+diff --git a/setup/main.py b/setup/main.py
+index d5e2078c..8c8d7a47 100644
+--- a/setup/main.py
++++ b/setup/main.py
+@@ -212,6 +212,13 @@ class Setup(object):
+ 'active',
+ Gio.SettingsBindFlags.DEFAULT)
+
++ self.__checkbutton_glyph_from_engine_lang = self.__builder.get_object(
++ "checkbutton_use_glyph_from_engine_lang")
++ self.__settings_panel.bind('use-glyph-from-engine-lang',
++ self.__checkbutton_glyph_from_engine_lang,
++ 'active',
++ Gio.SettingsBindFlags.DEFAULT)
++
+ def __init_general(self):
+ # embed preedit text
+ self.__checkbutton_embed_preedit_text = self.__builder.get_object(
+diff --git a/setup/setup.ui b/setup/setup.ui
+index 250f43a0..a15b9083 100644
+--- a/setup/setup.ui
++++ b/setup/setup.ui
+@@ -1286,6 +1286,55 @@
+ <property name="position">1</property>
+ </packing>
+ </child>
++ <child>
++ <object class="GtkFrame" id="frame1">
++ <property name="visible">True</property>
++ <property name="can_focus">False</property>
++ <property name="label_xalign">0</property>
++ <property name="shadow_type">none</property>
++ <child>
++ <object class="GtkBox" id="vbox10">
++ <property name="orientation">vertical</property>
++ <property name="visible">True</property>
++ <property name="can_focus">False</property>
++ <property name="spacing">6</property>
++ <property name="margin_top">6</property>
++ <property name="margin_start">24</property>
++ <child>
++ <object class="GtkCheckButton" id="checkbutton_use_glyph_from_engine_lang">
++ <property name="label" translatable="yes">Choose glyphs with input method's language on candidate window</property>
++ <property name="use_action_appearance">False</property>
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="receives_default">False</property>
++ <property name="tooltip_text" translatable="yes">Choose glyphs with the input method's language on the candidate window for the duplicated code points</property>
++ <property name="use_action_appearance">False</property>
++ <property name="halign">start</property>
++ <property name="draw_indicator">True</property>
++ </object>
++ <packing>
++ <property name="expand">False</property>
++ <property name="fill">False</property>
++ <property name="position">0</property>
++ </packing>
++ </child>
++ </object>
++ </child>
++ <child type="label">
++ <object class="GtkLabel" id="label20">
++ <property name="visible">True</property>
++ <property name="can_focus">False</property>
++ <property name="label" translatable="yes"><b>Fonts</b></property>
++ <property name="use_markup">True</property>
++ </object>
++ </child>
++ </object>
++ <packing>
++ <property name="expand">False</property>
++ <property name="fill">False</property>
++ <property name="position">2</property>
++ </packing>
++ </child>
+ </object>
+ <packing>
+ <property name="position">3</property>
+diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
+index 8d9f5cc0..dc98e722 100644
+--- a/ui/gtk3/panel.vala
++++ b/ui/gtk3/panel.vala
+@@ -47,6 +47,7 @@ class Panel : IBus.PanelService {
+ private string m_current_context_path = "";
+ private string m_real_current_context_path = "";
+ private bool m_use_global_engine = true;
++ private bool m_use_engine_lang = true;
+ private CandidatePanel m_candidate_panel;
+ private Switcher m_switcher;
+ private uint m_switcher_focus_set_engine_id;
+@@ -197,6 +198,15 @@ class Panel : IBus.PanelService {
+ ref m_css_provider);
+ });
+
++ m_settings_panel.changed["use-glyph-from-engine-lang"].connect((key) =>
++ {
++ m_use_engine_lang = m_settings_panel.get_boolean(
++ "use-glyph-from-engine-lang");
++ var engine = m_bus.get_global_engine();
++ if (engine != null)
++ set_language_from_engine(engine);
++ });
++
+ m_settings_panel.changed["show-icon-on-systray"].connect((key) => {
+ set_show_icon_on_systray();
+ });
+@@ -732,6 +742,8 @@ class Panel : IBus.PanelService {
+ set_use_system_keyboard_layout();
+ set_use_global_engine();
+ set_use_xmodmap();
++ m_use_engine_lang = m_settings_panel.get_boolean(
++ "use-glyph-from-engine-lang");
+ update_engines(m_settings_general.get_strv("preload-engines"),
+ m_settings_general.get_strv("engines-order"));
+ BindingCommon.unbind_switch_shortcut(
+@@ -801,6 +813,17 @@ class Panel : IBus.PanelService {
+ m_engine_contexts.replace(m_current_context_path, engine);
+ }
+
++ private void set_language_from_engine(IBus.EngineDesc engine) {
++ if (m_use_engine_lang) {
++ m_candidate_panel.set_language(new Pango.AttrLanguage(
++ Pango.Language.from_string(engine.get_language())));
++ } else {
++ m_candidate_panel.set_language(new Pango.AttrLanguage(
++ Pango.Language.from_string(null)));
++ }
++
++ }
++
+ private void set_engine(IBus.EngineDesc engine) {
+ if (m_property_icon_delay_time_id > 0) {
+ GLib.Source.remove(m_property_icon_delay_time_id);
+@@ -822,8 +845,7 @@ class Panel : IBus.PanelService {
+ if (!m_use_system_keyboard_layout)
+ m_xkblayout.set_layout(engine);
+
+- m_candidate_panel.set_language(new Pango.AttrLanguage(Pango.Language.from_string(engine.get_language())));
+-
++ set_language_from_engine(engine);
+ engine_contexts_insert(engine);
+ }
+
+--
+2.24.1
+
+From 508527daaf90901b6a7fa062372516640f88aa75 Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Fri, 21 Aug 2020 09:07:39 +0900
+Subject: [PATCH 6/9] engine: Generate simple.xml with denylist
+
+simple.xml was generated by allowlist (whitelist) and it will be
+done by denylist (blacklist).
+
+BUG=https://github.com/ibus/ibus/issues/2153
+---
+ engine/Makefile.am | 20 ++-
+ engine/denylist.txt | 27 ++++
+ engine/gensimple.py | 367 ++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 407 insertions(+), 7 deletions(-)
+ create mode 100644 engine/denylist.txt
+ create mode 100755 engine/gensimple.py
+
+diff --git a/engine/Makefile.am b/engine/Makefile.am
+index 86f0e2b8..ca405496 100644
+--- a/engine/Makefile.am
++++ b/engine/Makefile.am
+@@ -4,6 +4,7 @@
+ #
+ # Copyright (c) 2010-2016, Google Inc. All rights reserved.
+ # Copyright (c) 2007-2016 Peng Huang <shawn.p.huang@gmail.com>
++# Copyright (c) 2013-2020 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ #
+ # This library is free software; you can redistribute it and/or
+ # modify it under the terms of the GNU Lesser General Public
+@@ -78,20 +79,25 @@ component_DATA = \
+
+ componentdir = $(pkgdatadir)/component
+
+-CLEANFILES = \
++MAINTAINERCLEANFILES = \
+ simple.xml \
+ $(NULL)
+
+ EXTRA_DIST = \
++ gensimple.py \
+ iso639converter.py \
+- simple.xml.in \
++ simple.xml \
+ $(NULL)
+
+-simple.xml: simple.xml.in
+- $(AM_V_GEN) sed \
+- -e 's|@VERSION[@]|$(VERSION)|g' \
+- -e 's|@libexecdir[@]|$(libexecdir)|g' $< > $@.tmp && \
+- mv $@.tmp $@
++simple.xml:
++ $(srcdir)/gensimple.py \
++ --input=$(datarootdir)/X11/xkb/rules/evdev.xml \
++ --output=$@ \
++ --version=$(VERSION).`date '+%Y%m%d'` \
++ --exec-path=$(libexecdir)/ibus-engine-simple \
++ --iso-path=$(datarootdir)/xml/iso-codes/iso_639.xml \
++ --first-language \
++ $(NULL)
+
+ $(libibus):
+ $(MAKE) -C $(top_builddir)/src
+diff --git a/engine/denylist.txt b/engine/denylist.txt
+new file mode 100644
+index 00000000..e4cd0473
+--- /dev/null
++++ b/engine/denylist.txt
+@@ -0,0 +1,27 @@
++# vim:set fileencoding=utf-8 et sts=4 sw=4:
++#
++# ibus - Intelligent Input Bus for Linux / Unix OS
++#
++# Copyright © 2020 Takao Fujiwara <takao.fujiwara1@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.1 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, see <http://www.gnu.org/licenses/>.
++
++# This file is a deny list (black list) and used by gensimple.py.
++# gensimple.py generates the engine list with evdev.xml and if an engine name
++# is matched with any entries in this file, the engine is excluded from the
++# engine list.
++# Asterisk(*) character can be used to match any engines.
++# E.g. xkb:cn:*:* excludes xkb:cn::zho and xkb:cn:mon_trad:mvf
++xkb:cn:*:*
++xkb:nec_vndr/jp:*:*
+diff --git a/engine/gensimple.py b/engine/gensimple.py
+new file mode 100755
+index 00000000..dc4ccf12
+--- /dev/null
++++ b/engine/gensimple.py
+@@ -0,0 +1,367 @@
++#!/usr/bin/python
++# vim:set fileencoding=utf-8 et sts=4 sw=4:
++#
++# ibus - Intelligent Input Bus for Linux / Unix OS
++#
++# Copyright © 2020 Takao Fujiwara <takao.fujiwara1@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.1 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, see <http://www.gnu.org/licenses/>.
++
++
++# This script generates simple.xml with /usr/share/X11/xkb/rules/evdev.xml,
++# /usr/share/xml/iso-codes/iso_639.xml and denylist.txt
++
++
++from xml.dom import minidom
++from xml.sax import make_parser as sax_make_parser
++from xml.sax.handler import feature_namespaces as sax_feature_namespaces
++from xml.sax.saxutils import XMLFilterBase, XMLGenerator, escape
++from xml.sax.xmlreader import AttributesImpl
++from xml.sax._exceptions import SAXParseException
++
++import codecs
++import getopt
++import io
++import os
++import sys
++
++VERSION='0.1'
++EVDEV_XML = '/usr/share/X11/xkb/rules/evdev.xml'
++EXEC_PATH='/usr/lib/ibus-engine-simple'
++ISO_PATH='/usr/share/xml/iso-codes/iso_639.xml'
++PY3K = sys.version_info >= (3, 0)
++
++if PY3K:
++ from io import StringIO
++else:
++ # io.StringIO does not work with XMLGenerator
++ from cStringIO import StringIO
++ # iso_639.xml includes UTF-8
++ reload(sys)
++ sys.setdefaultencoding('utf-8')
++
++def usage(prgname):
++ print('''\
++%s Version %s
++Usage:
++ %s [OPTION...]
++
++Options:
++ -h, --help Show this message
++ -i, --input=EVDEV_XML Load EVDEV_XML file (default is:
++ %s)
++ -o, --output=FILE Output FILE (default is stdout)
++ -V, --version=VERSION Set IBus VERSION (default is %s)
++ -e, --exec-path=EXEC_PATH Set EXEC_PATH file (default is:
++ %s)
++ -I, --iso-path=ISO_PATH Load ISO_PATH file (default is:
++ %s)
++ -1, --first-language Pull first language only in language list
++''' % (prgname, VERSION, prgname, EVDEV_XML, VERSION, EXEC_PATH, ISO_PATH))
++
++
++class EvdevXML(XMLFilterBase):
++ def __init__(self, parser=None, downstream=None, iso639=None,
++ denylist=None, author=None, first=False):
++ XMLFilterBase.__init__(self, parser)
++ self.__downstream = downstream
++ self.__iso639 = iso639
++ self.__denylist = denylist
++ self.__author = author
++ self.__first = first
++ self.__is_layout = False
++ self.__is_description = False
++ self.__is_config_item = False
++ self.__is_variant = False
++ self.__is_iso639 = False
++ self.__is_name = False
++ self.__layout = ''
++ self.__description = ''
++ self.__variant = ''
++ self.__list_iso639 = []
++ def startDocument(self):
++ if self.__downstream:
++ self.__downstream.startDocument()
++ self.__downstream.startElement('engines', AttributesImpl({}))
++ def endDocument(self):
++ if self.__downstream:
++ self.__downstream.endElement('engines')
++ self.__downstream.endDocument()
++ def startElement(self, name, attrs):
++ if name == 'layout':
++ self.__is_layout = True
++ elif name == 'description':
++ self.__is_description = True
++ elif name == 'configItem':
++ self.__is_config_item = True
++ elif name == 'languageList':
++ self.__list_iso639 = []
++ elif name == 'iso639Id':
++ self.__is_iso639 = True
++ elif name == 'variant':
++ self.__is_variant = True
++ elif name == 'name':
++ self.__is_name = True
++ def endElement(self, name):
++ if name == 'layout':
++ self.__is_layout = False
++ self.__layout = ''
++ self.__description = ''
++ self.__variant = ''
++ self.__list_iso639 = []
++ elif name == 'description':
++ self.__is_description = False
++ elif name == 'configItem':
++ self.save()
++ self.__is_config_item = False
++ elif name == 'iso639Id':
++ self.__is_iso639 = False
++ elif name == 'variant':
++ self.__is_variant = False
++ elif name == 'name':
++ self.__is_name = False
++ def characters(self, text):
++ if self.__is_description:
++ self.__description = text
++ elif self.__is_name:
++ if self.__is_variant and self.__is_config_item:
++ self.__variant = text
++ elif self.__is_layout and self.__is_config_item:
++ self.__layout = text
++ elif self.__is_iso639:
++ self.__list_iso639.append(text)
++ def save(self):
++ if not self.__downstream:
++ return
++ for iso in self.__list_iso639:
++ do_deny = False
++ for [xkb, layout, variant, lang] in self.__denylist:
++ if xkb == 'xkb' \
++ and ( layout == self.__layout or layout == '*' ) \
++ and ( variant == self.__variant or variant == '*' ) \
++ and ( lang == iso or variant == '*' ):
++ do_deny = True
++ break
++ if do_deny:
++ continue
++ self.__downstream.startElement('engine', AttributesImpl({}))
++ self.__downstream.startElement('name', AttributesImpl({}))
++ name = 'xkb:%s:%s:%s' % (
++ self.__layout,
++ self.__variant,
++ iso
++ )
++ self.__downstream.characters(name)
++ self.__downstream.endElement('name')
++ self.__downstream.startElement('language', AttributesImpl({}))
++ iso639_1 = self.__iso639.code2to1(iso)
++ if iso639_1 != None:
++ iso = iso639_1
++ self.__downstream.characters(iso)
++ self.__downstream.endElement('language')
++ self.__downstream.startElement('license', AttributesImpl({}))
++ self.__downstream.characters('GPL')
++ self.__downstream.endElement('license')
++ if self.__author != None:
++ self.__downstream.startElement('author', AttributesImpl({}))
++ self.__downstream.characters(self.__author)
++ self.__downstream.endElement('author')
++ self.__downstream.startElement('layout', AttributesImpl({}))
++ self.__downstream.characters(self.__layout)
++ self.__downstream.endElement('layout')
++ self.__downstream.startElement('longname', AttributesImpl({}))
++ self.__downstream.characters(self.__description)
++ self.__downstream.endElement('longname')
++ self.__downstream.startElement('description', AttributesImpl({}))
++ self.__downstream.characters(self.__description)
++ self.__downstream.endElement('description')
++ self.__downstream.startElement('icon', AttributesImpl({}))
++ self.__downstream.characters('ibus-keyboard')
++ self.__downstream.endElement('icon')
++ self.__downstream.startElement('rank', AttributesImpl({}))
++ if self.__variant == '':
++ self.__downstream.characters('50')
++ else:
++ self.__downstream.characters('1')
++ self.__downstream.endElement('rank')
++ self.__downstream.endElement('engine')
++ if self.__first:
++ break
++
++
++class GenerateEngineXML():
++ _NAME = 'org.freedesktop.IBus.Simple'
++ _DESCRIPTION = 'A table based simple engine'
++ _AUTHOR = 'Peng Huang <shawn.p.huang@gmail.com>'
++ _HOMEPAGE = 'https://github.com/ibus/ibus/wiki'
++ _DOMAIN = 'ibus'
++ def __init__(self, path, iso639=None, denylist='', version='', exec='',
++ first=False):
++ self.__path = path
++ self.__iso639 = iso639
++ self.__denylist = denylist
++ self.__version = version
++ self.__exec = exec
++ self.__first = first
++ self.__result = StringIO()
++ downstream = XMLGenerator(self.__result, 'utf-8')
++ self.__load(downstream)
++
++ def __load(self, downstream=None):
++ parser = sax_make_parser()
++ parser.setFeature(sax_feature_namespaces, 0)
++ self.__handler = EvdevXML(parser,
++ downstream,
++ self.__iso639,
++ self.__denylist,
++ self._AUTHOR,
++ self.__first)
++ parser.setContentHandler(self.__handler)
++ f = codecs.open(self.__path, 'r', encoding='utf-8')
++ try:
++ parser.parse(f)
++ except SAXParseException:
++ print('Error: Invalid file format: %s' % path)
++ finally:
++ f.close()
++ def write(self, output=None):
++ if output != None:
++ od = codecs.open(output, 'w', encoding='utf-8')
++ else:
++ if PY3K:
++ od = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
++ else:
++ od = codecs.getwriter('utf-8')(sys.stdout)
++ contents = self.__result.getvalue()
++ index = contents.find('<engines>')
++ if index >= 0:
++ author = escape(self._AUTHOR)
++ contents = '%s<component><name>%s</name>\
++<description>%s</description><exec>%s</exec><version>%s</version>\
++<author>%s</author><license>%s</license><homepage>%s</homepage>\
++<textdomain>%s</textdomain>%s</component>' % (
++ contents[:index],
++ self._NAME, self._DESCRIPTION,
++ self.__exec, self.__version, author, 'GPL',
++ self._HOMEPAGE, self._DOMAIN, contents[index:] )
++ parsed = minidom.parseString(contents)
++ # format with indent and encoding attribute in header
++ xml = parsed.toprettyxml(indent=' ', encoding='utf-8')
++ # convert byte to str
++ od.write(str(xml, 'utf-8'))
++ #od.write(contents)
++
++
++class ISO639XML(XMLFilterBase):
++ def __init__(self, parser=None):
++ self.__code2to1 = {}
++ self.__codetoname = {}
++ XMLFilterBase.__init__(self, parser)
++ def startElement(self, name, attrs):
++ if name != 'iso_639_entry':
++ return
++ n = attrs.get('name')
++ iso639_1 = attrs.get('iso_639_1_code')
++ iso639_2b = attrs.get('iso_639_2B_code')
++ iso639_2t = attrs.get('iso_639_2T_code')
++ if iso639_1 != None:
++ self.__codetoname[iso639_1] = n
++ if iso639_2b != None:
++ self.__code2to1[iso639_2b] = iso639_1
++ self.__codetoname[iso639_2b] = n
++ if iso639_2t != None and iso639_2b != iso639_2t:
++ self.__code2to1[iso639_2t] = iso639_1
++ self.__codetoname[iso639_2t] = n
++ def code2to1(self, iso639_2):
++ try:
++ return self.__code2to1[iso639_2]
++ except KeyError:
++ return None
++
++
++def parse_iso639(path):
++ f = codecs.open(path, 'r', encoding='utf-8')
++ parser = sax_make_parser()
++ parser.setFeature(sax_feature_namespaces, 0)
++ handler = ISO639XML(parser)
++ parser.setContentHandler(handler)
++ try:
++ parser.parse(f)
++ except SAXParseException:
++ print('Error: Invalid file format: %s' % path)
++ finally:
++ f.close()
++ return handler
++
++
++def parse_denylist(denyfile):
++ denylist = []
++ f = codecs.open(denyfile, 'r', encoding='utf-8')
++ for line in f.readlines():
++ if line == '\n' or line[0] == '#':
++ continue
++ line = line.rstrip()
++ entry = line.split(':')
++ if len(entry) != 4:
++ print('WARNING: format error: \'%s\' against \'%s\'' \
++ % (line, 'xkb:layout:variant:lang'))
++ continue
++ denylist.append(entry)
++ f.close()
++ return denylist
++
++
++if __name__ == '__main__':
++ prgname = os.path.basename(sys.argv[0])
++ mydir = os.path.dirname(sys.argv[0])
++ try:
++ opts, args = getopt.getopt(sys.argv[1:],
++ 'hi:o:V:e:I:1',
++ ['help', 'input=', 'output=', 'version=',
++ 'exec-path=', 'iso-path=',
++ 'first-language'])
++ except getopt.GetoptError as err:
++ print(err)
++ usage(prgname)
++ sys.exit(2)
++ if len(args) > 0:
++ usage(prgname)
++ sys.exit(2)
++ input = EVDEV_XML
++ output = None
++ version=VERSION
++ exec_path=EXEC_PATH
++ iso_path=ISO_PATH
++ first=False
++ for opt, arg in opts:
++ if opt in ('-h', '--help'):
++ usage(prgname)
++ sys.exit()
++ elif opt in ('-i', '--input'):
++ input = arg
++ elif opt in ('-o', '--output'):
++ output = arg
++ elif opt in ('-V', '--version'):
++ version = arg
++ elif opt in ('-e', '--exec-path'):
++ exec_path = arg
++ elif opt in ('-I', '--iso-path'):
++ iso_path = arg
++ elif opt in ('-1', '--first-langauge'):
++ first=True
++
++ iso639 = parse_iso639(iso_path)
++ denylist = parse_denylist('%s/%s' % ( mydir, 'denylist.txt'))
++ xml = GenerateEngineXML(input, iso639, denylist, version, exec_path, first)
++ xml.write(output)
+--
+2.24.1
+
+From 6879879002af47d49d8740ca383a048d2ac8e904 Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Fri, 21 Aug 2020 09:15:14 +0900
+Subject: [PATCH 8/9] src/tests: Fix runtest with simple.xml
+
+Now simple.xml.in is replaced with simple.xml and modify runtest
+to copy simple.xml.
+
+BUG=https://github.com/ibus/ibus/issues/2153
+---
+ src/tests/runtest | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/src/tests/runtest b/src/tests/runtest
+index a6e4194b..11bcc6c2 100755
+--- a/src/tests/runtest
++++ b/src/tests/runtest
+@@ -91,6 +91,19 @@ func_copy_component () {
+ fi
+ }
+
++func_copy_simple_xml () {
++ file=$1
++ base=`func_basename $file`
++ libexecdir=`func_dirname $file`
++ # top_srcdir != top_builddir in make dist
++ libexecdir=`echo "$libexecdir" | sed -e "s|$top_srcdir|$top_builddir|"`
++ if test -f $file; then
++ mkdir -p components
++ sed "s|\(<exec>\).*\(/ibus-engine-simple</exec>\)|\1$libexecdir\2|" \
++ < $file > components/$base
++ fi
++}
++
+ trap 'func_cleanup $tstdir' 1 2 3 15
+
+ tst=$1; shift
+@@ -127,7 +140,7 @@ run_test_case()
+ exit -1
+ fi
+ # func_copy_component replaces s/$top_srcdir/%top_builddir/
+- func_copy_component "../$top_srcdir/engine/simple.xml"
++ func_copy_simple_xml "../$top_srcdir/engine/simple.xml"
+ func_copy_component "../$top_srcdir/conf/memconf/memconf.xml"
+
+ IBUS_COMPONENT_PATH=$PWD/components
+--
+2.24.1
+
+From 59b902a809ed628bb4d5bbad2b8bcb79a8a23208 Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Fri, 21 Aug 2020 09:46:46 +0900
+Subject: [PATCH 9/9] src: Add file list in registry file
+
+Under Fedora Silverblue, st_mtime in /usr/share/ibus/component is
+1 Jan 1970 even if ibus engines are installed and ibus-daemon
+cannot detect new engines.
+Now IBusObservedPath saves hashed file list besides st_mtime of
+the compnent directory to detect the installed engines newly.
+
+BUG=https://github.com/ibus/ibus/issues/2132
+---
+ src/ibuscomponent.c | 9 +-
+ src/ibusobservedpath.c | 277 ++++++++++++++++++++++++++++++++++++-----
+ src/ibusregistry.c | 6 +-
+ 3 files changed, 254 insertions(+), 38 deletions(-)
+
+diff --git a/src/ibuscomponent.c b/src/ibuscomponent.c
+index 9837f47c..1404ada0 100644
+--- a/src/ibuscomponent.c
++++ b/src/ibuscomponent.c
+@@ -2,7 +2,8 @@
+ /* vim:set et sts=4: */
+ /* bus - The Input Bus
+ * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
+- * Copyright (C) 2008-2019 Red Hat, Inc.
++ * Copyright (C) 2020 Takao Fujiwara <takao.fujiwara1@gmail.com>
++ * Copyright (C) 2008-2020 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
+@@ -499,11 +500,7 @@ ibus_component_output (IBusComponent *component,
+
+ for (p = component->priv->observed_paths; p != NULL; p = p->next ) {
+ IBusObservedPath *path = (IBusObservedPath *) p->data;
+-
+- g_string_append_indent (output, indent + 2);
+- g_string_append_printf (output, "<path mtime=\"%ld\" >%s</path>\n",
+- path->mtime,
+- path->path);
++ ibus_observed_path_output (path, output, indent + 2);
+ }
+
+ g_string_append_indent (output, indent + 1);
+diff --git a/src/ibusobservedpath.c b/src/ibusobservedpath.c
+index 5b79f1fe..42192431 100644
+--- a/src/ibusobservedpath.c
++++ b/src/ibusobservedpath.c
+@@ -2,7 +2,8 @@
+ /* vim:set et sts=4: */
+ /* ibus - The Input IBus
+ * Copyright (C) 2008-2015 Peng Huang <shawn.p.huang@gmail.com>
+- * Copyright (C) 2008-2019 Red Hat, Inc.
++ * Copyright (C) 2020 Takao Fujiwara <takao.fujiwara1@gmail.com>
++ * Copyright (C) 2008-2020 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
+@@ -30,9 +31,9 @@ enum {
+ };
+
+
+-/* IBusObservedPathPriv */
++/* IBusObservedPathPrivate */
+ struct _IBusObservedPathPrivate {
+- gpointer pad;
++ guint *file_hash_list;
+ };
+ typedef struct _IBusObservedPathPrivate IBusObservedPathPrivate;
+
+@@ -52,7 +53,9 @@ static gboolean ibus_observed_path_copy (IBusObservedPath *des
+ static gboolean ibus_observed_path_parse_xml_node (IBusObservedPath *path,
+ XMLNode *node);
+
+-G_DEFINE_TYPE (IBusObservedPath, ibus_observed_path, IBUS_TYPE_SERIALIZABLE)
++G_DEFINE_TYPE_WITH_PRIVATE (IBusObservedPath,
++ ibus_observed_path,
++ IBUS_TYPE_SERIALIZABLE)
+
+ static void
+ ibus_observed_path_class_init (IBusObservedPathClass *class)
+@@ -84,7 +87,9 @@ static gboolean
+ ibus_observed_path_serialize (IBusObservedPath *path,
+ GVariantBuilder *builder)
+ {
++ IBusObservedPathPrivate *priv = IBUS_OBSERVED_PATH_GET_PRIVATE (path);
+ gboolean retval;
++ guint i;
+
+ retval = IBUS_SERIALIZABLE_CLASS (ibus_observed_path_parent_class)->
+ serialize ((IBusSerializable *)path, builder);
+@@ -93,6 +98,15 @@ ibus_observed_path_serialize (IBusObservedPath *path,
+ g_variant_builder_add (builder, "s", path->path);
+ g_variant_builder_add (builder, "x", path->mtime);
+
++ if (!priv->file_hash_list) {
++ g_variant_builder_add (builder, "u", 0);
++ return TRUE;
++ }
++ for (i = 0; priv->file_hash_list[i]; i++);
++ g_variant_builder_add (builder, "u", i);
++ for (i = 0; priv->file_hash_list[i]; i++)
++ g_variant_builder_add (builder, "u", priv->file_hash_list[i]);
++
+ return TRUE;
+ }
+
+@@ -100,7 +114,9 @@ static gint
+ ibus_observed_path_deserialize (IBusObservedPath *path,
+ GVariant *variant)
+ {
++ IBusObservedPathPrivate *priv = IBUS_OBSERVED_PATH_GET_PRIVATE (path);
+ gint retval;
++ guint i, length = 0;
+
+ retval = IBUS_SERIALIZABLE_CLASS (ibus_observed_path_parent_class)->
+ deserialize ((IBusSerializable *)path, variant);
+@@ -109,6 +125,15 @@ ibus_observed_path_deserialize (IBusObservedPath *path,
+ ibus_g_variant_get_child_string (variant, retval++, &path->path);
+ g_variant_get_child (variant, retval++, "x", &path->mtime);
+
++ if (g_variant_n_children (variant) < retval + 2)
++ return retval;
++ g_variant_get_child (variant, retval++, "u", &length);
++ if (!length)
++ return retval;
++ priv->file_hash_list = g_new0 (guint, length + 1);
++ for (i = 0; i < length; i++)
++ g_variant_get_child (variant, retval++, "u", &priv->file_hash_list[i]);
++
+ return retval;
+ }
+
+@@ -116,14 +141,27 @@ static gboolean
+ ibus_observed_path_copy (IBusObservedPath *dest,
+ const IBusObservedPath *src)
+ {
++ IBusObservedPathPrivate *dest_priv = IBUS_OBSERVED_PATH_GET_PRIVATE (dest);
++ IBusObservedPathPrivate *src_priv =
++ IBUS_OBSERVED_PATH_GET_PRIVATE ((IBusObservedPath *)src);
+ gboolean retval;
++ guint i;
+
+- retval = IBUS_SERIALIZABLE_CLASS (ibus_observed_path_parent_class)->copy ((IBusSerializable *)dest, (IBusSerializable *)src);
++ retval = IBUS_SERIALIZABLE_CLASS (ibus_observed_path_parent_class)->
++ copy ((IBusSerializable *)dest, (IBusSerializable *)src);
+ g_return_val_if_fail (retval, FALSE);
+
+ dest->path = g_strdup (src->path);
+ dest->mtime = src->mtime;
+
++ g_clear_pointer (&dest_priv->file_hash_list, g_free);
++ if (!src_priv->file_hash_list)
++ return TRUE;
++ for (i = 0; src_priv->file_hash_list[i]; i++);
++ dest_priv->file_hash_list = g_new0 (guint, i + 1);
++ for (i = 0; src_priv->file_hash_list[i]; i++)
++ dest_priv->file_hash_list[i] = src_priv->file_hash_list[i];
++
+ return TRUE;
+ }
+
+@@ -137,23 +175,48 @@ ibus_observed_path_copy (IBusObservedPath *dest,
+
+ void
+ ibus_observed_path_output (IBusObservedPath *path,
+- GString *output,
+- gint indent)
++ GString *output,
++ gint indent)
+ {
++ IBusObservedPathPrivate *priv = IBUS_OBSERVED_PATH_GET_PRIVATE (path);
++ guint i;
++
+ g_assert (IBUS_IS_OBSERVED_PATH (path));
+ g_assert (output);
+
+- g_string_append_indent (output, indent);
+- g_string_append_printf (output, "<path mtime=\"%ld\" >%s</path>\n",
+- path->mtime,
+- path->path);
++ if (!priv->file_hash_list) {
++ g_string_append_indent (output, indent);
++ g_string_append_printf (output, "<path mtime=\"%ld\" >%s</path>\n",
++ path->mtime,
++ path->path);
++ } else {
++ g_string_append_indent (output, indent);
++ g_string_append_printf (
++ output,
++ "<path mtime=\"%ld\" type=\"dir\" path=\"%s\">\n",
++ path->mtime,
++ path->path);
++ for (i = 0; priv->file_hash_list[i]; i++) {
++ g_string_append_indent (output, indent + 1);
++ g_string_append_printf (output, "<file hash=\"%u\" />\n",
++ priv->file_hash_list[i]);
++ }
++ g_string_append_indent (output, indent);
++ g_string_append_printf (output, "</path>\n");
++ }
+ }
+
+ gboolean
+ ibus_observed_path_check_modification (IBusObservedPath *path)
+ {
++ IBusObservedPathPrivate *priv = IBUS_OBSERVED_PATH_GET_PRIVATE (path);
+ gchar *real_path = NULL;
+ struct stat buf;
++ gboolean retval = FALSE;
++ GDir *dir = NULL;
++ const gchar *name;
++ guint i = 0;
++ guint file_num = 0;
+
+ g_assert (IBUS_IS_OBSERVED_PATH (path));
+
+@@ -169,11 +232,71 @@ ibus_observed_path_check_modification (IBusObservedPath *path)
+ buf.st_mtime = 0;
+ }
+
+- g_free (real_path);
+
+- if (path->mtime == buf.st_mtime)
+- return FALSE;
+- return TRUE;
++ if (path->mtime != buf.st_mtime) {
++ retval = TRUE;
++ goto end_check_modification;
++ }
++
++ /* If an ibus engine is installed, normal file system updates
++ * the directory mtime of "/usr/share/ibus/component" and
++ * path->mtime of the cache file and buf.st_mtime of the current directory
++ * could have the different values.
++ *
++ * But under a special file system, the buf.st_mtime is not updated
++ * even if an ibus engine is installed, likes Fedora Silverblue
++ * and ibus_observed_path_check_modification() could not detect
++ * the installed ibus engines.
++ * Now path->priv->file_hash_list reserves the hash list of the files
++ * in the observed directory and if a new ibus engine is installed,
++ * the hash of the compose file does not exists in the cache's
++ * file_hash_list and ibus-daemon regenerate the cache successfully.
++ */
++ if (!priv->file_hash_list) {
++ /* If the cache version is old, ibus_registry_load_cache() returns
++ * FALSE and ibus_registry_check_modification() and this are not
++ * called.
++ * If the cache version is the latest, the cache file includes the
++ * filled file_hash_list for directories with ibus_observed_path_new()
++ * when the cache was generated.
++ * Then if file_hash_list is null, it's a simple file in ibus
++ * components and return here simply.
++ */
++ goto end_check_modification;
++ }
++ dir = g_dir_open (real_path, 0, NULL);
++ g_return_val_if_fail (dir, FALSE);
++
++ while ((name = g_dir_read_name (dir)) != NULL) {
++ guint current_hash;
++ gboolean has_file = FALSE;
++
++ if (!g_str_has_suffix (name, ".xml"))
++ continue;
++ current_hash = g_str_hash (name);
++ for (i = 0; priv->file_hash_list[i]; i++) {
++ if (current_hash == priv->file_hash_list[i]) {
++ has_file = TRUE;
++ break;
++ }
++ }
++ if (!has_file) {
++ retval = TRUE;
++ goto end_check_modification;
++ }
++ file_num++;
++ }
++ if (!retval) {
++ for (i = 0; priv->file_hash_list[i]; i++);
++ if (file_num != i)
++ retval = TRUE;
++ }
++
++end_check_modification:
++ if (dir)
++ g_dir_close (dir);
++ g_free (real_path);
++ return retval;
+ }
+
+ static void
+@@ -224,7 +347,7 @@ ibus_observed_path_traverse (IBusObservedPath *path,
+ paths = g_list_append (paths, sub);
+ paths = g_list_concat (paths,
+ ibus_observed_path_traverse (sub, dir_only));
+- } else if (!dir_only) {
++ } else if (sub->is_exist && !dir_only) {
+ paths = g_list_append (paths, sub);
+ }
+ }
+@@ -233,36 +356,102 @@ ibus_observed_path_traverse (IBusObservedPath *path,
+ return paths;
+ }
+
++
++static gboolean
++ibus_observed_path_parse_file (IBusObservedPath *path,
++ XMLNode *node,
++ int *nth)
++{
++ IBusObservedPathPrivate *priv = IBUS_OBSERVED_PATH_GET_PRIVATE (path);
++ gchar **attr;
++
++ for (attr = node->attributes; attr[0]; attr += 2) {
++ guint hash = 0;
++
++ if (g_strcmp0 (*attr, "hash") == 0)
++ hash = atol (attr[1]);
++ else if (g_strcmp0 (*attr, "name") == 0)
++ hash = g_str_hash (attr[1]);
++ if (hash) {
++ if (!priv->file_hash_list) {
++ *nth = 0;
++ priv->file_hash_list = g_new0 (guint, *nth + 2);
++ } else {
++ priv->file_hash_list = g_renew (guint, priv->file_hash_list,
++ *nth + 2);
++ }
++ priv->file_hash_list[*nth] = hash;
++ priv->file_hash_list[*nth + 1] = 0;
++ *nth += 1;
++ continue;
++ }
++ g_warning ("Unkonwn attribute %s", attr[0]);
++ }
++
++ return TRUE;
++}
++
++
+ static gboolean
+ ibus_observed_path_parse_xml_node (IBusObservedPath *path,
+ XMLNode *node)
+ {
++ gchar **attr;
++ const gchar *full_path = node->text;
++ GList *p;
++ int i = 0;
++
+ g_assert (IBUS_IS_OBSERVED_PATH (path));
+ g_assert (node);
+
+- if (G_UNLIKELY (g_strcmp0 (node->name, "path") != 0)) {
++ if (G_UNLIKELY (g_strcmp0 (node->name, "path") != 0))
+ return FALSE;
++
++ for (attr = node->attributes; attr[0]; attr += 2) {
++ if (g_strcmp0 (*attr, "mtime") == 0) {
++ path->mtime = atol (attr[1]);
++ continue;
++ }
++ if (g_strcmp0 (*attr, "path") == 0) {
++ full_path = attr[1];
++ continue;
++ }
++ if (g_strcmp0 (*attr, "type") == 0) {
++ if (!g_strcmp0 (attr[1], "dir"))
++ path->is_dir = TRUE;
++ else if (!g_strcmp0 (attr[1], "file"))
++ path->is_dir = FALSE;
++ else
++ g_warning ("The type attribute can be \"dir\" or \"file\".");
++ continue;
++ }
++ g_warning ("Unkonwn attribute %s", attr[0]);
+ }
+
+- if (node->text[0] == '~' && node->text[1] != G_DIR_SEPARATOR) {
+- g_warning ("Invalid path \"%s\"", node->text);
++ if (full_path[0] == '~' && full_path[1] != G_DIR_SEPARATOR) {
++ g_warning ("Invalid path \"%s\"", full_path);
+ return FALSE;
+ }
+
+- path->path = g_strdup (node->text);
++ path->path = g_strdup (full_path);
+
+- gchar **attr;
+- for (attr = node->attributes; attr[0]; attr += 2) {
+- if (g_strcmp0 (*attr, "mtime") == 0) {
+- path->mtime = atol (attr[1]);
++ if (!path->is_dir)
++ return TRUE;
++
++ for (i = 0, p = node->sub_nodes; p != NULL; p = p->next) {
++ XMLNode *sub_node = (XMLNode *)p->data;
++
++ if (G_UNLIKELY (g_strcmp0 (sub_node->name, "file") != 0)) {
++ g_warning ("Unkonwn tag %s", sub_node->name);
+ continue;
+ }
+- g_warning ("Unkonwn attribute %s", attr[0]);
++ ibus_observed_path_parse_file (path, sub_node, &i);
+ }
+
+ return TRUE;
+ }
+
++
+ IBusObservedPath *
+ ibus_observed_path_new_from_xml_node (XMLNode *node,
+ gboolean fill_stat)
+@@ -288,16 +477,46 @@ IBusObservedPath *
+ ibus_observed_path_new (const gchar *path,
+ gboolean fill_stat)
+ {
+- g_assert (path);
+-
+ IBusObservedPath *op;
++ IBusObservedPathPrivate *priv;
++ GList *file_list, *l;
++ guint i = 0;
+
++ g_assert (path);
+ op = (IBusObservedPath *) g_object_new (IBUS_TYPE_OBSERVED_PATH, NULL);
+ op->path = g_strdup (path);
+
+- if (fill_stat) {
+- ibus_observed_path_fill_stat (op);
++ priv = IBUS_OBSERVED_PATH_GET_PRIVATE (op);
++ l = file_list = ibus_observed_path_traverse (op, FALSE);
++ for (; l; l = l->next) {
++ IBusObservedPath *sub = l->data;
++ const gchar *file = NULL;
++
++ g_return_val_if_fail (sub && sub->path, op);
++
++ file = sub->path;
++ if (!g_str_has_suffix (file, ".xml"))
++ continue;
++ if (g_str_has_prefix (file, path)) {
++ file += strlen (path);
++ if (*file == '/')
++ file++;
++ /* Ignore sub directories */
++ if (strchr (file, '/'))
++ continue;
++ }
++ if (!i)
++ priv->file_hash_list = g_new0 (guint, i + 2);
++ else
++ priv->file_hash_list = g_renew (guint, priv->file_hash_list, i + 2);
++ priv->file_hash_list[i] = g_str_hash (file);
++ priv->file_hash_list[i + 1] = 0;
++ ++i;
+ }
++ g_list_free_full (file_list, (GDestroyNotify)ibus_observed_path_destroy);
++
++ if (fill_stat)
++ ibus_observed_path_fill_stat (op);
+
+ return op;
+ }
+diff --git a/src/ibusregistry.c b/src/ibusregistry.c
+index 43990d5f..3386a5d1 100644
+--- a/src/ibusregistry.c
++++ b/src/ibusregistry.c
+@@ -2,8 +2,8 @@
+ /* vim:set et sts=4: */
+ /* bus - The Input Bus
+ * Copyright (C) 2015 Peng Huang <shawn.p.huang@gmail.com>
+- * Copyright (C) 2015-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
+- * Copyright (C) 2015-2019 Red Hat, Inc.
++ * Copyright (C) 2015-2020 Takao Fujiwara <takao.fujiwara1@gmail.com>
++ * Copyright (C) 2015-2020 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,7 +29,7 @@
+ #include "ibusregistry.h"
+
+ #define IBUS_CACHE_MAGIC 0x49425553 /* "IBUS" */
+-#define IBUS_CACHE_VERSION 0x00010512
++#define IBUS_CACHE_VERSION 0x00010522
+
+ enum {
+ CHANGED,
+--
+2.24.1
+
diff --git a/ibus.spec b/ibus.spec
index fa09803..38fe2f7 100644
--- a/ibus.spec
+++ b/ibus.spec
@@ -7,12 +7,6 @@
%global with_pkg_config %(pkg-config --version >/dev/null 2>&1 && echo -n "1" || echo -n "0")
-%if (0%{?fedora} > 21 || 0%{?rhel} > 7)
-%global with_kde5 1
-%else
-%global with_kde5 0
-%endif
-
%global ibus_api_version 1.0
# for bytecompile in %%{_datadir}/ibus/setup
@@ -32,13 +26,14 @@
Name: ibus
Version: 1.5.22
-Release: 11%{?dist}
+Release: 12%{?dist}
Summary: Intelligent Input Bus for Linux OS
License: LGPLv2+
URL: https://github.com/ibus/%name/wiki
Source0: https://github.com/ibus/%name/releases/download/%{version}/%{name}-%{version}.tar.gz
Source1: %{name}-xinput
Source2: %{name}.conf.5
+Source3: %{name}-simple-1.5.22.20200821.xml.gz
# Patch0: %%{name}-HEAD.patch
Patch0: %{name}-HEAD.patch
# Under testing #1349148 #1385349 #1350291 #1406699 #1432252 #1601577
@@ -71,9 +66,7 @@ BuildRequires: vala
BuildRequires: iso-codes-devel
BuildRequires: libnotify-devel
BuildRequires: wayland-devel
-%if %with_kde5
BuildRequires: qt5-qtbase-devel
-%endif
BuildRequires: cldr-emoji-annotation
BuildRequires: unicode-emoji
BuildRequires: unicode-ucd
@@ -254,6 +247,10 @@ the functionality of the installed %{name} package.
# cp client/gtk2/ibusimcontext.c client/gtk3/ibusimcontext.c || :
# cp client/gtk2/ibusim.c client/gtk3/ibusim.c || :
cp client/gtk2/ibusim.c client/gtk3/ibusim.c || :
+cd engine
+cp %{SOURCE3} simple.xml.gz
+gunzip simple.xml.gz
+cd ..
# prep test
@@ -285,9 +282,6 @@ autoreconf -f -i -v
--enable-python-library \
%endif
--enable-wayland \
-%if ! %with_kde5
- --disable-appindicator \
-%endif
--enable-introspection \
--enable-install-tests \
%{nil}
@@ -464,6 +458,11 @@ dconf update || :
%{_datadir}/installed-tests/ibus
%changelog
+* Fri Aug 21 2020 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.22-12
+- Generate simple.xml with denylist
+- Tell Pango about the engine language in the candidate panel
+- Add file list in registry file for Silverblue
+
* Tue Jul 28 2020 Adam Jackson <ajax@redhat.com> - 1.5.22-11
- Require setxkbmap not xorg-x11-xkb-utils
diff --git a/sources b/sources
index 2691b3b..4629f12 100644
--- a/sources
+++ b/sources
@@ -1 +1,2 @@
SHA512 (ibus-1.5.22.tar.gz) = 0abe89acc6da8cea484a6b9f807c08e94869072f374f9e8f4541a426636f818f1c3cb8b9237f97245771f9e4bf19184983d8ac924177dc4824ca6e8b5304425d
+SHA512 (ibus-simple-1.5.22.20200821.xml.gz) = f7532078bd409da0742538745d5d03942dd738a9bea935f75c9c0d74ad9891ff62fe7982a7c64ab957079583a12316d593f7f05534fa78a5c741eb5fb19f9da7
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-05-31 2:07 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-31 2:07 [rpms/ibus] autotool: Generate simple.xml with denylist Takao Fujiwara
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox