public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Takao Fujiwara <tfujiwar@redhat.com>
To: git-commits@fedoraproject.org
Subject: [rpms/ibus] autotool: Delete upstreamed patches
Date: Sun, 31 May 2026 02:07:57 GMT	[thread overview]
Message-ID: <178019327714.1.14866051828136667805.rpms-ibus-e9877b0a75da@fedoraproject.org> (raw)

A new commit has been pushed.

Repo   : rpms/ibus
Branch : autotool
Commit : e9877b0a75da53b799a87b1adb106e10658c05fb
Author : Takao Fujiwara <tfujiwar@redhat.com>
Date   : 2022-09-01T07:46:54+09:00
Stats  : +0/-4563 in 1 file(s)
URL    : https://src.fedoraproject.org/rpms/ibus/c/e9877b0a75da53b799a87b1adb106e10658c05fb?branch=autotool

Log:
Delete upstreamed patches

---
diff --git a/ibus-HEAD.patch b/ibus-HEAD.patch
deleted file mode 100644
index 94cfbfd..0000000
--- a/ibus-HEAD.patch
+++ /dev/null
@@ -1,4563 +0,0 @@
-From 17648f0522910480b6c5dd4f5356ca1f6c160bf5 Mon Sep 17 00:00:00 2001
-From: Carlos Garnacho <carlosg@gnome.org>
-Date: Tue, 29 Mar 2022 22:48:19 +0200
-Subject: [PATCH] src: Fix refcounting issues
-
-Commit 5a455b1ead attempted to fix both GLib warnings around
-floating references and other presumed refcounting issues. However
-it missed 2 kinds of bugs:
-
-- The places that take an IBusText created from a static string
-  were made to avoid freeing it afterwards, but the staticness refers
-  to the string content, not the object itself.
-- The places that are documented to emit signals on floating object
-  references used to do the following after signal emission:
-
-  if (g_object_is_floating (object))
-    g_object_unref (object)
-
-  And did possibly trigger GLib warnings were changed to:
-
-  if (g_object_is_floating (object))
-    g_object_sink_ref (object);
-  g_object_unref (object);
-
-  Which fixes the GLib warning for floating references, but do
-  unintendedly steal one reference away for non floating references.
-
-This commit is essentially a revert of commit 5a455b1ead, but
-addressing both things differently:
-
-- All label/tooltip/symbol IBusText properties in IBusProperty do
-  now always sink the reference of the stored object.
-
-- All places documented as maybe using objects with a floating reference
-  on signals changed to doing:
-
-  if (g_object_is_floating (object)) {
-    g_object_ref_sink (object);
-    g_object_unref (object);
-  }
-
-  So the floating reference is owned and unreferenced without warnings,
-  but already owned references are left unchanged.
-
-This addresses the possible GLib warnings, fixes the possible double
-unrefs happening on IBusText used in signals, and fixes the missing
-unrefs on IBusText objects created from static strings.
-
-BUG=https://github.com/ibus/ibus/issues/2393
-BUG=https://github.com/ibus/ibus/issues/2387
----
- src/ibusinputcontext.c | 35 +++++++++++++++++++++--------------
- src/ibusproperty.c     | 32 +++++++++++++++++---------------
- 2 files changed, 38 insertions(+), 29 deletions(-)
-
-diff --git a/src/ibusinputcontext.c b/src/ibusinputcontext.c
-index 4b27551b..7981de38 100644
---- a/src/ibusinputcontext.c
-+++ b/src/ibusinputcontext.c
-@@ -549,9 +549,10 @@ ibus_input_context_g_signal (GDBusProxy  *proxy,
-         g_variant_unref (variant);
-         g_signal_emit (context, context_signals[COMMIT_TEXT], 0, text);
- 
--        if (g_object_is_floating (text))
-+        if (g_object_is_floating (text)) {
-             g_object_ref_sink (text);
--        g_object_unref (text);
-+            g_object_unref (text);
-+        }
-         return;
-     }
-     if (g_strcmp0 (signal_name, "UpdatePreeditText") == 0) {
-@@ -569,9 +570,10 @@ ibus_input_context_g_signal (GDBusProxy  *proxy,
-                        cursor_pos,
-                        visible);
- 
--        if (g_object_is_floating (text))
-+        if (g_object_is_floating (text)) {
-             g_object_ref_sink (text);
--        g_object_unref (text);
-+            g_object_unref (text);
-+        }
-         return;
-     }
-     if (g_strcmp0 (signal_name, "UpdatePreeditTextWithMode") == 0) {
-@@ -592,9 +594,10 @@ ibus_input_context_g_signal (GDBusProxy  *proxy,
-                        visible,
-                        mode);
- 
--        if (g_object_is_floating (text))
-+        if (g_object_is_floating (text)) {
-             g_object_ref_sink (text);
--        g_object_unref (text);
-+            g_object_unref (text);
-+        }
-         return;
-     }
- 
-@@ -621,9 +624,10 @@ ibus_input_context_g_signal (GDBusProxy  *proxy,
-                        0,
-                        text,
-                        visible);
--        if (g_object_is_floating (text))
-+        if (g_object_is_floating (text)) {
-             g_object_ref_sink (text);
--        g_object_unref (text);
-+            g_object_unref (text);
-+        }
-         return;
-     }
- 
-@@ -640,9 +644,10 @@ ibus_input_context_g_signal (GDBusProxy  *proxy,
-                        0,
-                        table,
-                        visible);
--        if (g_object_is_floating (table))
-+        if (g_object_is_floating (table)) {
-             g_object_ref_sink (table);
--        g_object_unref (table);
-+            g_object_unref (table);
-+        }
-         return;
- 
-     }
-@@ -659,9 +664,10 @@ ibus_input_context_g_signal (GDBusProxy  *proxy,
-                        0,
-                        prop_list);
- 
--        if (g_object_is_floating (prop_list))
-+        if (g_object_is_floating (prop_list)) {
-             g_object_ref_sink (prop_list);
--        g_object_unref (prop_list);
-+            g_object_unref (prop_list);
-+        }
-         return;
-     }
- 
-@@ -673,9 +679,10 @@ ibus_input_context_g_signal (GDBusProxy  *proxy,
- 
-         g_signal_emit (context, context_signals[UPDATE_PROPERTY], 0, prop);
- 
--        if (g_object_is_floating (prop))
-+        if (g_object_is_floating (prop)) {
-             g_object_ref_sink (prop);
--        g_object_unref (prop);
-+            g_object_unref (prop);
-+        }
-         return;
-     }
- 
-diff --git a/src/ibusproperty.c b/src/ibusproperty.c
-index 6d4ed088..cd8a0e2a 100644
---- a/src/ibusproperty.c
-+++ b/src/ibusproperty.c
-@@ -336,20 +336,17 @@ ibus_property_destroy (IBusProperty *prop)
-     prop->priv->icon = NULL;
- 
-     if (prop->priv->label) {
--        if (!ibus_text_get_is_static (prop->priv->label))
--            g_object_unref (prop->priv->label);
-+        g_object_unref (prop->priv->label);
-         prop->priv->label = NULL;
-     }
- 
-     if (prop->priv->symbol) {
--        if (!ibus_text_get_is_static (prop->priv->symbol))
--            g_object_unref (prop->priv->symbol);
-+        g_object_unref (prop->priv->symbol);
-         prop->priv->symbol = NULL;
-     }
- 
-     if (prop->priv->tooltip) {
--        if (!ibus_text_get_is_static (prop->priv->tooltip))
--            g_object_unref (prop->priv->tooltip);
-+        g_object_unref (prop->priv->tooltip);
-         prop->priv->tooltip = NULL;
-     }
- 
-@@ -404,7 +401,7 @@ ibus_property_deserialize (IBusProperty *prop,
-     g_variant_get_child (variant, retval++, "u", &prop->priv->type);
- 
-     GVariant *subvar = g_variant_get_child_value (variant, retval++);
--    if (prop->priv->label && !ibus_text_get_is_static (prop->priv->label)) {
-+    if (prop->priv->label) {
-         g_object_unref (prop->priv->label);
-     }
-     prop->priv->label = IBUS_TEXT (ibus_serializable_deserialize (subvar));
-@@ -414,7 +411,7 @@ ibus_property_deserialize (IBusProperty *prop,
-     ibus_g_variant_get_child_string (variant, retval++, &prop->priv->icon);
- 
-     subvar = g_variant_get_child_value (variant, retval++);
--    if (prop->priv->tooltip && !ibus_text_get_is_static (prop->priv->tooltip)) {
-+    if (prop->priv->tooltip) {
-         g_object_unref (prop->priv->tooltip);
-     }
-     prop->priv->tooltip = IBUS_TEXT (ibus_serializable_deserialize (subvar));
-@@ -435,7 +432,7 @@ ibus_property_deserialize (IBusProperty *prop,
- 
-     /* Keep the serialized order for the compatibility when add new members. */
-     subvar = g_variant_get_child_value (variant, retval++);
--    if (prop->priv->symbol && !ibus_text_get_is_static (prop->priv->symbol)) {
-+    if (prop->priv->symbol) {
-         g_object_unref (prop->priv->symbol);
-     }
-     prop->priv->symbol = IBUS_TEXT (ibus_serializable_deserialize (subvar));
-@@ -567,7 +564,7 @@ ibus_property_set_label (IBusProperty *prop,
-     g_assert (IBUS_IS_PROPERTY (prop));
-     g_return_if_fail (label == NULL || IBUS_IS_TEXT (label));
- 
--    if (prop->priv->label && !ibus_text_get_is_static (prop->priv->label)) {
-+    if (prop->priv->label) {
-         g_object_unref (prop->priv->label);
-     }
- 
-@@ -575,8 +572,10 @@ ibus_property_set_label (IBusProperty *prop,
-         prop->priv->label = ibus_text_new_from_static_string ("");
-     }
-     else {
--        prop->priv->label = g_object_ref_sink (label);
-+        prop->priv->label = label;
-     }
-+
-+    g_object_ref_sink (prop->priv->label);
- }
- 
- void
-@@ -586,7 +585,7 @@ ibus_property_set_symbol (IBusProperty *prop,
-     g_assert (IBUS_IS_PROPERTY (prop));
-     g_return_if_fail (symbol == NULL || IBUS_IS_TEXT (symbol));
- 
--    if (prop->priv->symbol && !ibus_text_get_is_static (prop->priv->symbol)) {
-+    if (prop->priv->symbol) {
-         g_object_unref (prop->priv->symbol);
-     }
- 
-@@ -594,8 +593,10 @@ ibus_property_set_symbol (IBusProperty *prop,
-         prop->priv->symbol = ibus_text_new_from_static_string ("");
-     }
-     else {
--        prop->priv->symbol = g_object_ref_sink (symbol);
-+        prop->priv->symbol = symbol;
-     }
-+
-+    g_object_ref_sink (prop->priv->symbol);
- }
- 
- void
-@@ -615,7 +616,7 @@ ibus_property_set_tooltip (IBusProperty *prop,
-     g_assert (IBUS_IS_PROPERTY (prop));
-     g_assert (tooltip == NULL || IBUS_IS_TEXT (tooltip));
- 
--    if (prop->priv->tooltip && !ibus_text_get_is_static (prop->priv->tooltip)) {
-+    if (prop->priv->tooltip) {
-         g_object_unref (prop->priv->tooltip);
-     }
- 
-@@ -624,8 +625,9 @@ ibus_property_set_tooltip (IBusProperty *prop,
-     }
-     else {
-         prop->priv->tooltip = tooltip;
--        g_object_ref_sink (prop->priv->tooltip);
-     }
-+
-+    g_object_ref_sink (prop->priv->tooltip);
- }
- 
- void
--- 
-2.34.1
-
-From 1b5b9548ad418765717ce1fbdc70b3f3eaae67fc Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Mon, 14 Mar 2022 14:25:10 +0900
-Subject: [PATCH] client/gtk2: Revert CCedilla change for pt-BR
-
-gtk_im_context_simple_add_table() is deprecated in GTK4.
-I decide to delete gtk_im_context_simple_add_table() here because
-the change 03c9e591430c62354bbf26ef7bd4a2e6acfb7c8f is no longer needed
-because IBusEngineSimple has implemented to load pt_br compose key
-by locale
-
-BUG=chromium-os:11421
-BUG=http://codereview.appspot.com/3989060
----
- client/gtk2/ibusimcontext.c | 33 +--------------------------------
- 1 file changed, 1 insertion(+), 32 deletions(-)
-
-diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c
-index a5e5e792..e314ae98 100644
---- a/client/gtk2/ibusimcontext.c
-+++ b/client/gtk2/ibusimcontext.c
-@@ -2,7 +2,7 @@
- /* vim:set et sts=4: */
- /* ibus - The Input Bus
-  * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2015-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2015-2022 Takao Fujiwara <takao.fujiwara1@gmail.com>
-  * Copyright (C) 2008-2021 Red Hat, Inc.
-  *
-  * This library is free software; you can redistribute it and/or
-@@ -874,33 +874,6 @@ ibus_im_context_class_fini (IBusIMContextClass *class)
-     g_bus_unwatch_name (_daemon_name_watch_id);
- }
- 
--/* Copied from gtk+2.0-2.20.1/modules/input/imcedilla.c to fix crosbug.com/11421.
-- * Overwrite the original Gtk+'s compose table in gtk+-2.x.y/gtk/gtkimcontextsimple.c. */
--
--/* The difference between this and the default input method is the handling
-- * of C+acute - this method produces C WITH CEDILLA rather than C WITH ACUTE.
-- * For languages that use CCedilla and not acute, this is the preferred mapping,
-- * and is particularly important for pt_BR, where the us-intl keyboard is
-- * used extensively.
-- */
--static guint16 cedilla_compose_seqs[] = {
--#ifdef DEPRECATED_GDK_KEYSYMS
--  GDK_dead_acute,	GDK_C,	0,	0,	0,	0x00C7,	/* LATIN_CAPITAL_LETTER_C_WITH_CEDILLA */
--  GDK_dead_acute,	GDK_c,	0,	0,	0,	0x00E7,	/* LATIN_SMALL_LETTER_C_WITH_CEDILLA */
--  GDK_Multi_key,	GDK_apostrophe,	GDK_C,  0,      0,      0x00C7, /* LATIN_CAPITAL_LETTER_C_WITH_CEDILLA */
--  GDK_Multi_key,	GDK_apostrophe,	GDK_c,  0,      0,      0x00E7, /* LATIN_SMALL_LETTER_C_WITH_CEDILLA */
--  GDK_Multi_key,	GDK_C,  GDK_apostrophe,	0,      0,      0x00C7, /* LATIN_CAPITAL_LETTER_C_WITH_CEDILLA */
--  GDK_Multi_key,	GDK_c,  GDK_apostrophe,	0,      0,      0x00E7, /* LATIN_SMALL_LETTER_C_WITH_CEDILLA */
--#else
--  GDK_KEY_dead_acute,	GDK_KEY_C,	0,	0,	0,	0x00C7,	/* LATIN_CAPITAL_LETTER_C_WITH_CEDILLA */
--  GDK_KEY_dead_acute,	GDK_KEY_c,	0,	0,	0,	0x00E7,	/* LATIN_SMALL_LETTER_C_WITH_CEDILLA */
--  GDK_KEY_Multi_key,	GDK_KEY_apostrophe,	GDK_KEY_C,  0,      0,      0x00C7, /* LATIN_CAPITAL_LETTER_C_WITH_CEDILLA */
--  GDK_KEY_Multi_key,	GDK_KEY_apostrophe,	GDK_KEY_c,  0,      0,      0x00E7, /* LATIN_SMALL_LETTER_C_WITH_CEDILLA */
--  GDK_KEY_Multi_key,	GDK_KEY_C,  GDK_KEY_apostrophe,	0,      0,      0x00C7, /* LATIN_CAPITAL_LETTER_C_WITH_CEDILLA */
--  GDK_KEY_Multi_key,	GDK_KEY_c,  GDK_KEY_apostrophe,	0,      0,      0x00E7, /* LATIN_SMALL_LETTER_C_WITH_CEDILLA */
--#endif
--};
--
- static void
- ibus_im_context_init (GObject *obj)
- {
-@@ -936,10 +909,6 @@ ibus_im_context_init (GObject *obj)
- 
-     // Create slave im context
-     ibusimcontext->slave = gtk_im_context_simple_new ();
--    gtk_im_context_simple_add_table (GTK_IM_CONTEXT_SIMPLE (ibusimcontext->slave),
--                                     cedilla_compose_seqs,
--                                     4,
--                                     G_N_ELEMENTS (cedilla_compose_seqs) / (4 + 2));
- 
-     g_signal_connect (ibusimcontext->slave,
-                       "commit",
--- 
-2.34.1
-
-From 37900574934bb01cc31860ae3ae2f668e4360838 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Mon, 28 Mar 2022 23:18:58 +0900
-Subject: [PATCH] src/tests: Run ibus-daemon from CI even if GNOME desktop
-
-gnome-shell no longer launch ibus-daemon with IBus systemd file.
-This is a workaround to call ibus-daemon after GNOME fails to
-launch ibus-daemon
-
-BUG=https://gitlab.gnome.org/GNOME/gdm/-/issues/777
----
- src/tests/ibus-desktop-testing-runner.in | 38 +++++++++++++++++++++---
- 1 file changed, 34 insertions(+), 4 deletions(-)
-
-diff --git a/src/tests/ibus-desktop-testing-runner.in b/src/tests/ibus-desktop-testing-runner.in
-index 48528326..6b208345 100755
---- a/src/tests/ibus-desktop-testing-runner.in
-+++ b/src/tests/ibus-desktop-testing-runner.in
-@@ -55,6 +55,7 @@ GREEN='\033[0;32m'
- RED='\033[0;31m'
- NC='\033[0m'
- 
-+
- print_log()
- {
-     if [ x"$RESULT_LOG" != x ] ; then
-@@ -69,6 +70,7 @@ print_log()
-     fi
- }
- 
-+
- usage()
- {
-     $ECHO -e \
-@@ -95,6 +97,7 @@ usage()
- ""
- }
- 
-+
- parse_args()
- {
-     # This is GNU getopt. "sudo port getopt" in BSD?
-@@ -129,6 +132,7 @@ parse_args()
-     fi
- }
- 
-+
- init_desktop()
- {
-     if [ "$RESULT_LOG" != "" ] ; then
-@@ -207,6 +211,7 @@ _EOF
-     #export XDG_SEAT=seat0
- }
- 
-+
- run_dbus_daemon()
- {
-     # Use dbus-launch --exit-with-session later instead of --sh-syntax
-@@ -216,6 +221,7 @@ run_dbus_daemon()
-     export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$UID/bus"
- }
- 
-+
- init_gnome()
- {
-     # gsettings set command needs dconf-service with the same $DISPLAY
-@@ -258,6 +264,7 @@ init_gnome()
-     fi
- }
- 
-+
- run_desktop()
- {
-     echo "$DESKTOP_COMMAND" | grep gnome-session > /dev/null
-@@ -278,12 +285,28 @@ run_desktop()
-     $DESKTOP_COMMAND &
-     PID_GNOME_SESSION=$!
-     sleep 30
--    if [  $HAS_GNOME -ne 0 ] ; then
--        ibus-daemon --daemonize --verbose
--        sleep 3
--    fi
-+
-+    # gnome-shell 42 checks if org.freedesktop.IBus.session.GNOME.service
-+    # systemd file is available with org.freedesktop.systemd1.Manager.GetUnit
-+    # D-Bus method, which is provided by IBus 1.5.26, and if the file
-+    # is available, gnome-shell no longer launch ibus-daemon
-+    # because gnome-shell assumes gnome-session would launch ibus-daemon
-+    # with org.freedesktop.systemd1.Manager.StartUnit D-Bus method.
-+    # But actually gnome-session failed to launch ibus-daemon
-+    # because the IBus systemd file depends on gnome-session.target
-+    # but this CI launches gnome-session directly.
-+    #
-+    # So ibus-dameon is now always called here after gnome-shell fails to
-+    # launch ibus-daemon.
-+    # It may be better this CI launches GDM autologin to run gnome-session
-+    # with gnome-session.target systemd file.
-+    # But `systemctl start gdm` terminates the parent script forcibly
-+    # and the script cannot get the CI result.
-+    ibus-daemon --daemonize --verbose
-+    sleep 3
- }
- 
-+
- count_case_result()
- {
-     retval=$1
-@@ -298,6 +321,7 @@ count_case_result()
-     echo $pass $fail
- }
- 
-+
- echo_case_result()
- {
-     retval=$1
-@@ -311,6 +335,7 @@ echo_case_result()
-     fi
- }
- 
-+
- run_direct_test_cases()
- {
-     pass=0
-@@ -363,6 +388,7 @@ EOF_ENVS
-     echo $pass $fail
- }
- 
-+
- run_gnome_desktop_testing_runner()
- {
-     pass=0
-@@ -397,6 +423,7 @@ EOF
-     echo $pass $fail
- }
- 
-+
- run_test_suite()
- {
-     pass=0
-@@ -435,6 +462,7 @@ EOF_RUNNER
-     fi
- }
- 
-+
- finit()
- {
-     echo "# Killing left gnome-session and Xorg"
-@@ -451,6 +479,7 @@ finit()
-     echo "# Finished $PROGNAME testing"
- }
- 
-+
- main()
- {
-     parse_args "$@"
-@@ -470,5 +499,6 @@ main()
-     finit
- }
- 
-+
- # Need to enclose $@ with double quotes not to split the array.
- main "$@"
--- 
-2.34.1
-
-From b024ea8fcee6fe1a20570a6f80cc4f9f8f420706 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Wed, 20 Apr 2022 19:36:10 +0900
-Subject: [PATCH] ui/gtk3: Disable XKB engines in Plasma Wayland
-
-Currently ibus-ui-gtk3 runs the setxkbmap command internally to set
-the XKB keymaps from XKB engines but setxkbmap does not work in Wayland
-session.
-The IBus XKB engines are disabled at the moment in Plamsa Wayland
-and ibus-ui-gtk3 asks users to use systemsettings5.
-
-Will use libinput and libxkbcommon later but it would be better
-to implement IBus in Plamsa Wayland compositor.
-
-BUG=rhbz#2076596
----
- configure.ac        | 16 ++++++++++
- ui/gtk3/Makefile.am | 17 ++++++++++-
- ui/gtk3/panel.vala  | 74 +++++++++++++++++++++++++++++++++++++++++----
- 3 files changed, 100 insertions(+), 7 deletions(-)
-
-diff --git a/configure.ac b/configure.ac
-index a3cdb2da..79b9c11a 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -636,6 +636,21 @@ if test x"$enable_engine" = x"yes"; then
-     enable_engine="yes (enabled, use --disable-engine to disable)"
- fi
- 
-+# --disable-libnotify
-+AC_ARG_ENABLE(libnotify,
-+    AS_HELP_STRING([--disable-libnotify],
-+                   [Disable to link libnotify]),
-+    [enable_libnotify=$enableval],
-+    [enable_libnotify=yes]
-+)
-+AM_CONDITIONAL([ENABLE_LIBNOTIFY], [test x"$enable_libnotify" = x"yes"])
-+if test x"$enable_libnotify" = x"yes"; then
-+    PKG_CHECK_MODULES(LIBNOTIFY, [
-+        libnotify >= 0.7
-+    ])
-+    enable_libnotify="yes (enabled, use --disable-libnotify to disable)"
-+fi
-+
- PKG_CHECK_MODULES(XTEST,
-     [x11 xtst],
-     [enable_xtest=yes],
-@@ -871,6 +886,7 @@ Build options:
-   No snooper regexes            "$NO_SNOOPER_APPS"
-   Panel icon                    "$IBUS_ICON_KEYBOARD"
-   Enable surrounding-text       $enable_surrounding_text
-+  Enable libnotify              $enable_libnotify
-   Enable Emoji dict             $enable_emoji_dict
-   Unicode Emoji directory       $UNICODE_EMOJI_DIR
-   CLDR annotation directory     $EMOJI_ANNOTATION_DIR
-diff --git a/ui/gtk3/Makefile.am b/ui/gtk3/Makefile.am
-index ab379328..2a9cabde 100644
---- a/ui/gtk3/Makefile.am
-+++ b/ui/gtk3/Makefile.am
-@@ -3,7 +3,7 @@
- # ibus - The Input Bus
- #
- # Copyright (c) 2007-2015 Peng Huang <shawn.p.huang@gmail.com>
--# Copyright (c) 2015-2020 Takao Fujwiara <takao.fujiwara1@gmail.com>
-+# Copyright (c) 2015-2022 Takao Fujwiara <takao.fujiwara1@gmail.com>
- # Copyright (c) 2007-2020 Red Hat, Inc.
- #
- # This library is free software; you can redistribute it and/or
-@@ -81,6 +81,21 @@ AM_VALAFLAGS = \
- 	--target-glib="$(VALA_TARGET_GLIB_VERSION)" \
- 	$(NULL)
- 
-+if ENABLE_LIBNOTIFY
-+AM_CFLAGS += \
-+       @LIBNOTIFY_CFLAGS@ \
-+       $(NULL)
-+
-+AM_LDADD += \
-+       @LIBNOTIFY_LIBS@ \
-+       $(NULL)
-+
-+AM_VALAFLAGS += \
-+       --pkg=libnotify \
-+       -D ENABLE_LIBNOTIFY \
-+       $(NULL)
-+endif
-+
- if ENABLE_APPINDICATOR
- AM_VALAFLAGS += --define=INDICATOR
- endif
-diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
-index 07ce6524..bd70d7d2 100644
---- a/ui/gtk3/panel.vala
-+++ b/ui/gtk3/panel.vala
-@@ -73,6 +73,7 @@ class Panel : IBus.PanelService {
-     private string m_icon_prop_key = "";
-     private int m_property_icon_delay_time = 500;
-     private uint m_property_icon_delay_time_id;
-+    private bool m_is_wayland;
- #if INDICATOR
-     private bool m_is_kde = is_kde();
- #else
-@@ -93,6 +94,18 @@ class Panel : IBus.PanelService {
- 
-         m_bus = bus;
- 
-+#if USE_GDK_WAYLAND
-+        Gdk.set_allowed_backends("*");
-+        var display = Gdk.DisplayManager.get().open_display(null);
-+        Type instance_type = display.get_type();
-+        Type wayland_type = typeof(GdkWayland.Display);
-+        m_is_wayland = instance_type.is_a(wayland_type);
-+        Gdk.set_allowed_backends("x11");
-+#else
-+        m_is_wayland = false;
-+        warning("Checking Wayland is disabled");
-+#endif
-+
-         init_settings();
- 
-         // init ui
-@@ -553,6 +566,11 @@ class Panel : IBus.PanelService {
-         GLib.List<IBus.EngineDesc> im_engines =
-                 get_engines_from_locale(engines);
- 
-+        if (m_is_wayland) {
-+            if (xkb_engines.length() > 0)
-+                xkb_engines = new GLib.List<IBus.EngineDesc>();
-+        }
-+
-         string[] names = {};
-         foreach (unowned IBus.EngineDesc engine in xkb_engines)
-             names += engine.get_name();
-@@ -728,6 +746,32 @@ class Panel : IBus.PanelService {
-         inited_engines_order = false;
-     }
- 
-+    private void update_version_1_5_26() {
-+#if ENABLE_LIBNOTIFY
-+        if (!Notify.is_initted()) {
-+            Notify.init ("ibus");
-+        }
-+
-+        var notification = new Notify.Notification(
-+                _("IBus Attention"),
-+                _("Layout changes do not work in Plasma Wayland. " +
-+                  "Please use systemsettings5."),
-+                "ibus");
-+        notification.set_timeout(30 * 1000);
-+        notification.set_category("hotkey");
-+
-+        try {
-+            notification.show();
-+        } catch (GLib.Error e){
-+            warning (_("Layout changes do not work in Plasma Wayland. " +
-+                        "Please use systemsettings5."));
-+        }
-+#else
-+        warning (_("Layout changes do not work in Plasma Wayland. " +
-+                   "Please use systemsettings5."));
-+#endif
-+    }
-+
-     private void set_version() {
-         string prev_version = m_settings_general.get_string("version");
-         string current_version = null;
-@@ -735,6 +779,9 @@ class Panel : IBus.PanelService {
-         if (compare_versions(prev_version, "1.5.8") < 0)
-             update_version_1_5_8();
- 
-+        if (compare_versions(prev_version, "1.5.26") < 0)
-+            update_version_1_5_26();
-+
-         current_version = "%d.%d.%d".printf(IBus.MAJOR_VERSION,
-                                             IBus.MINOR_VERSION,
-                                             IBus.MICRO_VERSION);
-@@ -856,7 +903,7 @@ class Panel : IBus.PanelService {
-         m_icon_prop_key = "";
- 
-         // set xkb layout
--        if (!m_use_system_keyboard_layout)
-+        if (!m_use_system_keyboard_layout && !m_is_wayland)
-             m_xkblayout.set_layout(engine);
- 
-         set_language_from_engine(engine);
-@@ -960,17 +1007,25 @@ class Panel : IBus.PanelService {
-                                 string[]? order_names) {
-         string[]? engine_names = unowned_engine_names;
- 
--        if (engine_names == null || engine_names.length == 0)
--            engine_names = {"xkb:us::eng"};
-+        if (engine_names == null || engine_names.length == 0) {
-+            if (m_is_wayland)
-+                engine_names = {};
-+            else
-+                engine_names = {"xkb:us::eng"};
-+        }
- 
-         string[] names = {};
- 
-         foreach (var name in order_names) {
-+            if (m_is_wayland && name.has_prefix("xkb:"))
-+                continue;
-             if (name in engine_names)
-                 names += name;
-         }
- 
-         foreach (var name in engine_names) {
-+            if (m_is_wayland && name.has_prefix("xkb:"))
-+                continue;
-             if (name in names)
-                 continue;
-             names += name;
-@@ -1011,9 +1066,14 @@ class Panel : IBus.PanelService {
- 	}
- 
-         if (m_engines.length == 0) {
--            m_engines = engines;
--            switch_engine(0, true);
--            run_preload_engines(engines, 1);
-+            if (engines.length > 0) {
-+                m_engines = engines;
-+                switch_engine(0, true);
-+                run_preload_engines(engines, 1);
-+            } else {
-+                m_candidate_panel.set_language(new Pango.AttrLanguage(
-+                        Pango.Language.from_string(null)));
-+            }
-         } else {
-             var current_engine = m_engines[0];
-             m_engines = engines;
-@@ -1478,6 +1538,8 @@ class Panel : IBus.PanelService {
-         /* Do not change the order of m_engines during running switcher. */
-         if (m_switcher.is_running())
-             return;
-+        if (m_engines.length == 0)
-+            return;
- 
-         if (m_icon_type == IconType.INDICATOR) {
-             // Wait for the callback of the session bus.
--- 
-2.34.1
-
-From bca7bf0f97230806a26f53c798050408108cfb3d Mon Sep 17 00:00:00 2001
-From: Mike FABIAN <mfabian@redhat.com>
-Date: Wed, 25 May 2022 23:07:24 +0900
-Subject: [PATCH] data/dconf: Update xkb-latin-layouts in gschema
-
-Add more keyboard layouts which cannot produce ASCII to
-data/dconf/org.freedesktop.ibus.gschema.xml
-Remove "mal" and "mkd", there are no such layouts.
-
-BUG=https://github.com/ibus/ibus/issues/2404
----
- data/dconf/org.freedesktop.ibus.gschema.xml | 47 ++++++++++++++++++++-
- 1 file changed, 46 insertions(+), 1 deletion(-)
-
-diff --git a/data/dconf/org.freedesktop.ibus.gschema.xml b/data/dconf/org.freedesktop.ibus.gschema.xml
-index 516f7520..8b181d76 100644
---- a/data/dconf/org.freedesktop.ibus.gschema.xml
-+++ b/data/dconf/org.freedesktop.ibus.gschema.xml
-@@ -28,7 +28,52 @@
-       <description>The saved version number will be used to check the difference between the version of the previous installed ibus and one of the current ibus.</description>
-     </key>
-     <key name="xkb-latin-layouts" type="as">
--      <default>[ 'ara', 'bg', 'cz', 'dev', 'gr', 'gur', 'in', 'jp(kana)', 'mal', 'mkd', 'ru', 'ua' ]</default>
-+      <default>
-+        [ 'af', 'af(fa-olpc)', 'af(ps-olpc)', 'af(ps)', 'af(uz)',
-+        'af(uz-olpc)', 'am', 'am(eastern)', 'am(eastern-alt)',
-+        'am(phonetic)', 'am(phonetic-alt)', 'am(western)', 'ara',
-+        'ara(azerty)', 'ara(azerty_digits)', 'ara(buckwalter)',
-+        'ara(digits)', 'ara(qwerty)', 'ara(qwerty_digits)',
-+        'az(cyrillic)', 'bd', 'bd(probhat)', 'bg', 'bg(bas_phonetic)',
-+        'bg(phonetic)', 'brai', 'brai(left_hand)', 'brai(right_hand)',
-+        'bt', 'by', 'by(legacy)', 'ca(ike)', 'ca(multi-2gr)',
-+        'cn(tib)', 'cn(tib_asciinum)', 'cn(ug)', 'cz', 'cz(ucw)',
-+        'de(ru)', 'dev', 'et', 'fr(geo)', 'ge', 'ge(os)', 'gr',
-+        'gr(extended)', 'gr(nodeadkeys)', 'gr(polytonic)',
-+        'gr(simple)', 'gur', 'il', 'il(biblical)', 'il(lyx)',
-+        'il(phonetic)', 'in', 'in(ben)', 'in(ben_baishakhi)',
-+        'in(ben_bornona)', 'in(ben_gitanjali)', 'in(ben_inscript)',
-+        'in(ben_probhat)', 'in(bolnagri)', 'in(deva)', 'in(guj)',
-+        'in(guru)', 'in(hin-kagapa)', 'in(hin-wx)', 'in(jhelum)',
-+        'in(kan)', 'in(kan-kagapa)', 'in(mal)', 'in(mal_enhanced)',
-+        'in(mal_lalitha)', 'in(mar-kagapa)', 'in(ori)',
-+        'in(san-kagapa)', 'in(tam)', 'in(tam_tamilnet)',
-+        'in(tam_tamilnet_TAB)', 'in(tam_tamilnet_TSCII)',
-+        'in(tam_tamilnet_with_tam_nums)', 'in(tel)', 'in(tel-kagapa)',
-+        'in(urd-phonetic)', 'in(urd-phonetic3)', 'in(urd-winkeys)',
-+        'iq', 'ir', 'ir(pes_keypad)', 'jp(kana)', 'jp(mac)', 'kg',
-+        'kg(phonetic)', 'kh', 'kz', 'kz(kazrus)', 'kz(ruskaz)', 'la',
-+        'la(stea)', 'lk', 'lk(tam_TAB)', 'lk(tam_unicode)', 'ma',
-+        'ma(tifinagh)', 'ma(tifinagh-alt)',
-+        'ma(tifinagh-alt-phonetic)', 'ma(tifinagh-extended)',
-+        'ma(tifinagh-extended-phonetic)', 'ma(tifinagh-phonetic)',
-+        'me(cyrillic)', 'me(cyrillicalternatequotes)',
-+        'me(cyrillicyz)', 'mk', 'mk(nodeadkeys)', 'mm', 'mn', 'mv',
-+        'np', 'ph(capewell-dvorak-bay)', 'ph(capewell-qwerf2k6-bay)',
-+        'ph(colemak-bay)', 'ph(dvorak-bay)', 'ph(qwerty-bay)', 'pk',
-+        'pk(ara)', 'pk(snd)', 'pk(urd-crulp)', 'pk(urd-nla)',
-+        'pl(ru_phonetic_dvorak)', 'rs', 'rs(alternatequotes)',
-+        'rs(rue)', 'rs(yz)', 'ru', 'ru(bak)', 'ru(chm)', 'ru(cv)',
-+        'ru(dos)', 'ru(kom)', 'ru(legacy)', 'ru(mac)',
-+        'ru(os_legacy)', 'ru(os_winkeys)', 'ru(phonetic)',
-+        'ru(phonetic_winkeys)', 'ru(sah)', 'ru(srp)', 'ru(tt)',
-+        'ru(typewriter)', 'ru(typewriter-legacy)', 'ru(udm)',
-+        'ru(xal)', 'se(rus)', 'se(rus_nodeadkeys)', 'se(swl)', 'sy',
-+        'sy(syc)', 'sy(syc_phonetic)', 'th', 'th(pat)', 'th(tis)',
-+        'tj', 'tj(legacy)', 'tz', 'ua', 'ua(homophonic)',
-+        'ua(legacy)', 'ua(phonetic)', 'ua(rstu)', 'ua(rstu_ru)',
-+        'ua(typewriter)', 'ua(winkeys)', 'us(chr)', 'us(rus)', 'uz' ]
-+      </default>
-       <summary>Latin layouts which have no ASCII</summary>
-       <description>US layout is appended to the Latin layouts. variant can be omitted.</description>
-     </key>
--- 
-2.35.3
-
-From 16df64edadc21f50906e5442b73425b9256fbf65 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Wed, 25 May 2022 23:07:33 +0900
-Subject: [PATCH] src/tests: Add xkb-latin-layouts case
-
-BUG=https://github.com/ibus/ibus/issues/2404
----
- src/tests/Makefile.am       |  26 ++++++--
- src/tests/runtest           |   1 +
- src/tests/xkb-latin-layouts | 130 ++++++++++++++++++++++++++++++++++++
- 3 files changed, 150 insertions(+), 8 deletions(-)
- create mode 100755 src/tests/xkb-latin-layouts
-
-diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
-index f932f18f..ca5285bd 100644
---- a/src/tests/Makefile.am
-+++ b/src/tests/Makefile.am
-@@ -41,8 +41,9 @@ prog_ldadd =\
-     $(top_builddir)/src/libibus-@IBUS_API_VERSION@.la                   \
-     $(NULL)
- 
--noinst_PROGRAMS = $(TESTS)
--TESTS = \
-+noinst_PROGRAMS = $(TESTS_C)
-+noinst_SCRIPTS = $(TESTS_SCRIPT)
-+TESTS_C = \
-     ibus-bus                        \
-     ibus-config                     \
-     ibus-configservice              \
-@@ -56,16 +57,25 @@ TESTS = \
-     ibus-util                       \
-     $(NULL)
- 
-+TESTS_SCRIPT = \
-+    xkb-latin-layouts               \
-+    $(NULL)
-+
-+TESTS = \
-+    $(TESTS_C)                      \
-+    $(TESTS_SCRIPT)                 \
-+    $(NULL)
-+
- CLEANFILES =
- 
- if ENABLE_ENGINE
--TESTS += ibus-engine-switch
-+TESTS_C += ibus-engine-switch
- endif
- 
- if ENABLE_GTK3
--TESTS += ibus-compose
-+TESTS_C += ibus-compose
- if ENABLE_XTEST
--TESTS += ibus-keypress
-+TESTS_C += ibus-keypress
- endif
- endif
- 
-@@ -99,9 +109,10 @@ CLEANFILES += \
-     org.freedesktop.IBus.Desktop.Testing.desktop \
-     $(NULL)
- 
--test_execs_PROGRAMS = $(TESTS)
-+test_execs_PROGRAMS = $(TESTS_C)
-+test_execs_SCRIPTS = $(TESTS_SCRIPT)
- if ENABLE_GTK3
--test_execs_SCRIPTS = ibus-compose-locales
-+test_execs_SCRIPTS += ibus-compose-locales
- CLEANFILES += \
-     ibus-compose-locales \
-     $(NULL)
-@@ -138,6 +149,7 @@ ibus-desktop-testing-runner: ibus-desktop-testing-runner.in
- 
- EXTRA_DIST = \
-     $(test_metas_in) \
-+    $(TESTS_SCRIPT) \
-     runtest \
-     ibus-compose.emoji \
-     ibus-compose.env \
-diff --git a/src/tests/runtest b/src/tests/runtest
-index a6e4194b..a229140a 100755
---- a/src/tests/runtest
-+++ b/src/tests/runtest
-@@ -35,6 +35,7 @@ ibus-engine-switch
- ibus-compose
- ibus-keypress
- test-stress
-+xkb-latin-layouts
- "
- IBUS_SCHEMA_FILE='org.freedesktop.ibus.gschema.xml'
- GTK_QUERY_MODULE=gtk-query-immodules-3.0-32
-diff --git a/src/tests/xkb-latin-layouts b/src/tests/xkb-latin-layouts
-new file mode 100755
-index 00000000..f8dced6b
---- /dev/null
-+++ b/src/tests/xkb-latin-layouts
-@@ -0,0 +1,130 @@
-+#!/bin/bash
-+
-+PROGNAME=`basename $0`
-+VERSION=0.1
-+# POSIX sh has no 'echo -e'
-+: ${ECHO:='/usr/bin/echo'}
-+TMPDIR=
-+INSTALLED_SCHEMAS_DIR=
-+
-+
-+usage()
-+{
-+    $ECHO -e \
-+"This test runs setxkbmap command for gsettings xkb-latin-layouts value\n"     \
-+"$PROGNAME [OPTIONS…]\n"                                                       \
-+"\n"                                                                           \
-+"OPTIONS:\n"                                                                   \
-+"-h, --help                       This help\n"                                 \
-+"-v, --version                    Show version\n"                              \
-+"-D, --schemasdir=DIR             Load the latest schema file in DIR\n"        \
-+""
-+}
-+
-+
-+parse_args()
-+{
-+    # This is GNU getopt. "sudo port getopt" in BSD?
-+    ARGS=`getopt -o hD:Tv --long \
-+          help,schemasdir:,tap,version\
-+        -- "$@"`;
-+    eval set -- "$ARGS"
-+    while [ 1 ] ; do
-+        case "$1" in
-+        -h | --help )        usage; exit 0;;
-+        -D | --schemasdir )  INSTALLED_SCHEMAS_DIR="$2"; shift 2;;
-+        -T | --tap )         shift;; # ignore the option
-+        -v | --version )     $ECHO -e "$VERSION"; exit 0;;
-+        -- )                 shift; break;;
-+        * )                  shift;;
-+        esac
-+    done
-+}
-+
-+
-+init()
-+{
-+    set -e
-+
-+    # gnome-continuous doesn't have a machine-id set, which
-+    # breaks dbus-launch.  There's dbus-run-session which is
-+    # better, but not everyone has it yet.
-+    export DBUS_FATAL_WARNINGS=0
-+    export TMPDIR=$(mktemp -d --tmpdir="$PWD")
-+    export XDG_CONFIG_HOME="$TMPDIR/config"
-+    export XDG_CACHE_HOME="$TMPDIR/cache"
-+    export GSETTINGS_SCHEMA_DIR="$TMPDIR/schemas"
-+    mkdir -p $XDG_CONFIG_HOME $XDG_CACHE_HOME $GSETTINGS_SCHEMA_DIR
-+
-+    eval `dbus-launch --sh-syntax`
-+
-+    trap 'rm -rf $TMPDIR; kill $DBUS_SESSION_BUS_PID; setxkbmap -layout us' ERR
-+
-+    # in case that schema is not installed on the system
-+    glib-compile-schemas --targetdir "$GSETTINGS_SCHEMA_DIR" "$INSTALLED_SCHEMAS_DIR"
-+}
-+
-+
-+finit()
-+{
-+    # dbus-launch and gsettings run /usr/lib*/gvfsd-fuse $TMPDIR/cache/gvfs -f
-+    # via systemd since gvfs 1.45.90 in Fedora 33
-+    # and rm $TMPDIR could be failed until umount would be called.
-+    if [ -d $TMPDIR/cache/gvfs ] ; then
-+        umount $TMPDIR/cache/gvfs
-+    fi
-+    rm -rf $TMPDIR
-+
-+    kill $DBUS_SESSION_BUS_PID
-+    exit 0
-+}
-+
-+
-+test_xkb_keymaps()
-+{
-+    # Loop over top level schemas since "gsettings list-recursively" only
-+    # looks for direct children.
-+    xkb_latin_layouts=`gsettings get org.freedesktop.ibus.general xkb-latin-layouts`
-+    while read keymap ; do
-+        eval keymap="$keymap"
-+        HAS_VARIANT=$($ECHO "$keymap" | grep '(' 2> /dev/null) ||:
-+        if [ "x$HAS_VARIANT" != "x" ] ; then
-+            layout=$($ECHO "$keymap" | sed -e 's/\([^(]*\)([^)]*)/\1/')
-+            variant=$($ECHO "$keymap" | sed -e 's/[^(]*(\([^)]*\))/\1/')
-+            $ECHO setxkbmap -layout $layout -variant $variant
-+            setxkbmap -layout $layout -variant $variant
-+        else
-+            layout="$keymap"
-+            $ECHO setxkbmap -layout $layout
-+            setxkbmap -layout $layout
-+        fi
-+        if [ $? -ne 0 ] ; then
-+            $ECHO "Error in layout $layout variant $variant"
-+            setxkbmap -layout us
-+            exit 1
-+        fi
-+    done << EOF_READ_XKB
-+    `$ECHO $xkb_latin_layouts | sed -e 's/^\[//' -e 's/\]$//' | tr "," "\n"`
-+EOF_READ_XKB
-+
-+    setxkbmap -layout us
-+}
-+
-+
-+main()
-+{
-+    parse_args "$@"
-+
-+    if [ x"$INSTALLED_SCHEMAS_DIR" != x ] ; then
-+        init
-+    fi
-+
-+    test_xkb_keymaps
-+
-+    if [ x"$INSTALLED_SCHEMAS_DIR" != x ] ; then
-+        finit
-+    fi
-+}
-+
-+
-+main "$@"
--- 
-2.35.3
-
-From 233a3f4d4d3dc6782e74db5bf4e7c28fae729bc9 Mon Sep 17 00:00:00 2001
-From: Hollow Man <hollowman@opensuse.org>
-Date: Wed, 26 Jan 2022 09:35:11 +0800
-Subject: [PATCH 1/3] Add functionality to change IBus panel themes with
- available GTK themes
-
-To allow IBus to have their own control of themes.
-
-https://gitlab.gnome.org/GNOME/gnome-tweaks/-/blob/b9badc47b92dd73f8cedbd2efc66cbaf3ea25773/gtweak/tweaks/tweak_group_appearance.py#L69
-
-BUG=https://github.com/ibus/ibus/pull/2327
-
-Signed-off-by: Hollow Man <hollowman@opensuse.org>
----
- data/dconf/org.freedesktop.ibus.gschema.xml |  20 +++
- setup/main.py                               | 137 ++++++++++++++++++++
- setup/setup.ui                              |  97 +++++++++++++-
- ui/gtk3/bindingcommon.vala                  |  46 +++++++
- ui/gtk3/panel.vala                          |  18 +++
- ui/gtk3/panelbinding.vala                   |  18 +++
- 6 files changed, 335 insertions(+), 1 deletion(-)
-
-diff --git a/data/dconf/org.freedesktop.ibus.gschema.xml b/data/dconf/org.freedesktop.ibus.gschema.xml
-index 8b181d76..051f21a5 100644
---- a/data/dconf/org.freedesktop.ibus.gschema.xml
-+++ b/data/dconf/org.freedesktop.ibus.gschema.xml
-@@ -210,6 +210,26 @@
-       <summary>Custom font</summary>
-       <description>Custom font name for language panel</description>
-     </key>
-+    <key name="use-custom-theme" type="b">
-+      <default>false</default>
-+      <summary>Use custom theme</summary>
-+      <description>Use custom theme name for language panel</description>
-+    </key>
-+    <key name="custom-theme" type="s">
-+      <default>'Adwaita'</default>
-+      <summary>Custom theme</summary>
-+      <description>Custom theme name for language panel</description>
-+    </key>
-+    <key name="use-custom-icon" type="b">
-+      <default>false</default>
-+      <summary>Use custom icon</summary>
-+      <description>Use custom icon name for language panel</description>
-+    </key>
-+    <key name="custom-icon" type="s">
-+      <default>'Adwaita'</default>
-+      <summary>Custom icon</summary>
-+      <description>Custom icon 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>
-diff --git a/setup/main.py b/setup/main.py
-index 1b9056a6..71896693 100644
---- a/setup/main.py
-+++ b/setup/main.py
-@@ -29,6 +29,7 @@ import os
- import signal
- import sys
- import time
-+import glob
- 
- from gi import require_version as gi_require_version
- gi_require_version('GLib', '2.0')
-@@ -196,6 +197,79 @@ class Setup(object):
-                                    'sensitive',
-                                    Gio.SettingsBindFlags.GET)
- 
-+        # custom theme
-+        self.__model_custom_theme = self.__builder.get_object(
-+                "model_custom_theme")
-+        self.__combobox_custom_theme = self.__builder.get_object(
-+                "combobox_custom_theme")
-+        self.__checkbutton_custom_theme = self.__builder.get_object(
-+                "checkbutton_custom_theme")
-+
-+        def update_combobox_custom_theme(settings, key):
-+            theme_name_list = self.__init_available_gtk_themes()
-+            self.__model_custom_theme.clear()
-+            for name in theme_name_list:
-+                self.__model_custom_theme.append([name])
-+            current_theme = self.__settings_panel.get_string(key)
-+            try:
-+                current_theme_number = theme_name_list.index(current_theme)
-+            except ValueError:
-+                self.__settings_panel.reset(key)
-+                current_theme = self.__settings_panel.get_string(key)
-+                current_theme_number = theme_name_list.index(current_theme)
-+            self.__combobox_custom_theme.set_active(current_theme_number)
-+
-+        update_combobox_custom_theme(None, 'custom-theme')
-+        self.__settings_panel.bind('use-custom-theme',
-+                                   self.__checkbutton_custom_theme,
-+                                   'active',
-+                                   Gio.SettingsBindFlags.DEFAULT)
-+        self.__settings_panel.connect('changed::custom-theme',
-+                                   update_combobox_custom_theme)
-+        self.__settings_panel.bind('use-custom-theme',
-+                                   self.__combobox_custom_theme,
-+                                   'sensitive',
-+                                   Gio.SettingsBindFlags.DEFAULT)
-+        self.__combobox_custom_theme.connect("changed",
-+                                   self.__on_combobox_custom_theme_changed)
-+
-+
-+        # custom icon
-+        self.__model_custom_icon = self.__builder.get_object(
-+                "model_custom_icon")
-+        self.__combobox_custom_icon = self.__builder.get_object(
-+                "combobox_custom_icon")
-+        self.__checkbutton_custom_icon = self.__builder.get_object(
-+                "checkbutton_custom_icon")
-+
-+        def update_combobox_custom_icon(settings, key):
-+            icon_name_list = self.__init_available_gtk_icons()
-+            self.__model_custom_icon.clear()
-+            for name in icon_name_list:
-+                self.__model_custom_icon.append([name])
-+            current_icon = self.__settings_panel.get_string(key)
-+            try:
-+                current_icon_number = icon_name_list.index(current_icon)
-+            except ValueError:
-+                self.__settings_panel.reset(key)
-+                current_icon = self.__settings_panel.get_string(key)
-+                current_icon_number = icon_name_list.index(current_icon)
-+            self.__combobox_custom_icon.set_active(current_icon_number)
-+
-+        update_combobox_custom_icon(None, 'custom-icon')
-+        self.__settings_panel.bind('use-custom-icon',
-+                                   self.__checkbutton_custom_icon,
-+                                   'active',
-+                                   Gio.SettingsBindFlags.DEFAULT)
-+        self.__settings_panel.connect('changed::custom-icon',
-+                                   update_combobox_custom_icon)
-+        self.__settings_panel.bind('use-custom-icon',
-+                                   self.__combobox_custom_icon,
-+                                   'sensitive',
-+                                   Gio.SettingsBindFlags.DEFAULT)
-+        self.__combobox_custom_icon.connect("changed",
-+                                   self.__on_combobox_custom_icon_changed)
-+
-         # show icon on system tray
-         self.__checkbutton_show_icon_on_systray = self.__builder.get_object(
-                 "checkbutton_show_icon_on_systray")
-@@ -588,6 +662,69 @@ class Setup(object):
-             _("Use shortcut with shift to switch to the previous input method") 
-         entry.set_tooltip_text(tooltip)
- 
-+    def __init_available_gtk_themes(self):
-+        path_list = []
-+        path_list.append(os.path.join(GLib.get_home_dir(), ".themes"))
-+        path_list.append(os.path.join(GLib.get_user_data_dir(), "themes"))
-+        path_list.extend(list(map(lambda x: os.path.join(
-+            x, "themes"), GLib.get_system_data_dirs())))
-+        theme_name_list = []
-+        gtk_theme_path = []
-+        for path in path_list:
-+            gtk_theme_path.extend(glob.glob(path + "/*/gtk-*/gtk.css"))
-+            gtk_theme_path.extend(glob.glob(path + "/*/gtk-*/gtk-dark.css"))
-+        for path in gtk_theme_path:
-+            filename = os.path.basename(path)
-+            appendix = ""
-+            if filename == "gtk-dark.css":
-+                appendix = ":dark"
-+            theme_name_list.append(os.path.basename(
-+                os.path.dirname(os.path.dirname(path))) + appendix)
-+
-+        theme_name_list.extend([
-+            'Adwaita', 'Adwaita:dark',
-+            'HighContrast', 'HighContrastInverse'
-+        ])
-+        theme_name_list = list(set(theme_name_list))
-+        theme_name_list.sort()
-+
-+        return theme_name_list
-+
-+    def __on_combobox_custom_theme_changed(self, combobox):
-+        tree_iter = self.__combobox_custom_theme.get_active_iter()
-+        if tree_iter is not None:
-+            model = self.__combobox_custom_theme.get_model()
-+            theme_name = model[tree_iter][0]
-+            self.__settings_panel.set_string('custom-theme', theme_name)
-+
-+    def __init_available_gtk_icons(self):
-+        path_list = []
-+        path_list.append(os.path.join(GLib.get_home_dir(), ".icons"))
-+        path_list.append(os.path.join(GLib.get_user_data_dir(), "icons"))
-+        path_list.extend(list(map(lambda x: os.path.join(
-+            x, "icons"), GLib.get_system_data_dirs())))
-+        icon_name_list = []
-+        gtk_icon_path = []
-+        for path in path_list:
-+            gtk_icon_path.extend(glob.glob(path + "/*/index.theme"))
-+        for path in gtk_icon_path:
-+            dir = os.path.dirname(path)
-+            if not os.path.exists(os.path.join(dir, "cursors")):
-+                icon_name_list.append(os.path.basename(dir))
-+
-+        icon_name_list.extend(["Adwaita"])
-+        icon_name_list = list(set(icon_name_list))
-+        icon_name_list.sort()
-+
-+        return icon_name_list
-+
-+    def __on_combobox_custom_icon_changed(self, combobox):
-+        tree_iter = self.__combobox_custom_icon.get_active_iter()
-+        if tree_iter is not None:
-+            model = self.__combobox_custom_icon.get_model()
-+            icon_name = model[tree_iter][0]
-+            self.__settings_panel.set_string('custom-icon', icon_name)
-+
-     def __item_started_column_toggled_cb(self, cell, path_str, model):
- 
-         # get toggled iter
-diff --git a/setup/setup.ui b/setup/setup.ui
-index a15b9083..5a9804f9 100644
---- a/setup/setup.ui
-+++ b/setup/setup.ui
-@@ -55,6 +55,18 @@
-       </row>
-     </data>
-   </object>
-+  <object class="GtkListStore" id="model_custom_theme">
-+    <columns>
-+      <!-- column-name gchararray -->
-+      <column type="gchararray"/>
-+    </columns>
-+  </object>
-+  <object class="GtkListStore" id="model_custom_icon">
-+    <columns>
-+      <!-- column-name gchararray -->
-+      <column type="gchararray"/>
-+    </columns>
-+  </object>
-   <object class="GtkAdjustment" id="adjustment_emoji_partial_match">
-     <property name="value">3.0</property>
-     <property name="lower">1.0</property>
-@@ -1318,13 +1330,96 @@
-                             <property name="position">0</property>
-                           </packing>
-                         </child>
-+                        <child>
-+                          <object class="GtkGrid" id="table3">
-+                            <property name="visible">True</property>
-+                            <property name="can_focus">False</property>
-+                            <property name="column_spacing">12</property>
-+                            <property name="row_spacing">6</property>
-+                            <child>
-+                              <object class="GtkCheckButton" id="checkbutton_custom_theme">
-+                                <property name="label" translatable="yes">Use custom theme:</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="hexpand">True</property>
-+                              </object>
-+                              <packing>
-+                                <property name="left_attach">0</property>
-+                                <property name="top_attach">0</property>
-+                              </packing>
-+                            </child>
-+                            <child>
-+                              <object class="GtkComboBox" id="combobox_custom_theme">
-+                                <property name="visible">True</property>
-+                                <property name="can_focus">False</property>
-+                                <property name="model">model_custom_theme</property>
-+                                <property name="hexpand">True</property>
-+                                <child>
-+                                  <object class="GtkCellRendererText" id="renderer4"/>
-+                                  <attributes>
-+                                    <attribute name="text">0</attribute>
-+                                  </attributes>
-+                                </child>
-+                              </object>
-+                              <packing>
-+                                <property name="left_attach">1</property>
-+                                <property name="top_attach">0</property>
-+                              </packing>
-+                            </child>
-+                            <child>
-+                              <object class="GtkCheckButton" id="checkbutton_custom_icon">
-+                                <property name="label" translatable="yes">Use custom icon:</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>
-+                              </object>
-+                              <packing>
-+                                <property name="left_attach">0</property>
-+                                <property name="top_attach">1</property>
-+                              </packing>
-+                            </child>
-+                            <child>
-+                              <object class="GtkComboBox" id="combobox_custom_icon">
-+                                <property name="visible">True</property>
-+                                <property name="can_focus">False</property>
-+                                <property name="model">model_custom_icon</property>
-+                                <child>
-+                                  <object class="GtkCellRendererText" id="renderer5"/>
-+                                  <attributes>
-+                                    <attribute name="text">0</attribute>
-+                                  </attributes>
-+                                </child>
-+                              </object>
-+                              <packing>
-+                                <property name="left_attach">1</property>
-+                                <property name="top_attach">1</property>
-+                              </packing>
-+                            </child>
-+                          </object>
-+                          <packing>
-+                            <property name="expand">False</property>
-+                            <property name="fill">False</property>
-+                            <property name="position">1</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">&lt;b&gt;Fonts&lt;/b&gt;</property>
-+                        <property name="label" translatable="yes">&lt;b&gt;Font and Theme&lt;/b&gt;</property>
-                         <property name="use_markup">True</property>
-                       </object>
-                     </child>
-diff --git a/ui/gtk3/bindingcommon.vala b/ui/gtk3/bindingcommon.vala
-index 150d4c39..e825167b 100644
---- a/ui/gtk3/bindingcommon.vala
-+++ b/ui/gtk3/bindingcommon.vala
-@@ -212,4 +212,50 @@ class BindingCommon {
-                 css_provider,
-                 Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
-     }
-+
-+    public static void
-+    set_custom_theme(GLib.Settings? settings_panel) {
-+        if (settings_panel == null)
-+            return;
-+
-+        bool use_custom_theme = settings_panel.get_boolean("use-custom-theme");
-+        string custom_theme = settings_panel.get_string("custom-theme");
-+
-+        Gtk.Settings gtk_settings = Gtk.Settings.get_default();
-+
-+        if (use_custom_theme == false)
-+            custom_theme = "";
-+
-+        if (custom_theme == null || custom_theme == "") {
-+            gtk_settings.reset_property("gtk-theme-name");
-+            gtk_settings.reset_property("gtk-application-prefer-dark-theme");
-+        } else {
-+            string[] custom_theme_splitted = custom_theme.split(":");
-+            gtk_settings.gtk_theme_name = custom_theme_splitted[0];
-+            if (custom_theme_splitted.length == 2 &&
-+            custom_theme_splitted[1] == "dark")
-+                gtk_settings.gtk_application_prefer_dark_theme = true;
-+            else
-+                gtk_settings.gtk_application_prefer_dark_theme = false;
-+        }
-+    }
-+
-+    public static void
-+    set_custom_icon(GLib.Settings? settings_panel) {
-+        if (settings_panel == null)
-+            return;
-+
-+        bool use_custom_icon = settings_panel.get_boolean("use-custom-icon");
-+        string custom_icon = settings_panel.get_string("custom-icon");
-+
-+        Gtk.Settings gtk_settings = Gtk.Settings.get_default();
-+
-+        if (use_custom_icon == false)
-+            custom_icon = "";
-+
-+        if (custom_icon == null || custom_icon == "")
-+            gtk_settings.reset_property("gtk-icon-theme-name");
-+        else
-+            gtk_settings.gtk_icon_theme_name = custom_icon;
-+    }
- }
-diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
-index 61bfa1b6..101c2b3d 100644
---- a/ui/gtk3/panel.vala
-+++ b/ui/gtk3/panel.vala
-@@ -211,6 +211,22 @@ class Panel : IBus.PanelService {
-                                               ref m_css_provider);
-         });
- 
-+        m_settings_panel.changed["custom-theme"].connect((key) => {
-+                BindingCommon.set_custom_theme(m_settings_panel);
-+        });
-+
-+        m_settings_panel.changed["use-custom-theme"].connect((key) => {
-+                BindingCommon.set_custom_theme(m_settings_panel);
-+        });
-+
-+        m_settings_panel.changed["custom-icon"].connect((key) => {
-+                BindingCommon.set_custom_icon(m_settings_panel);
-+        });
-+
-+        m_settings_panel.changed["use-custom-icon"].connect((key) => {
-+                BindingCommon.set_custom_icon(m_settings_panel);
-+        });
-+
-         m_settings_panel.changed["use-glyph-from-engine-lang"].connect((key) =>
-         {
-                 m_use_engine_lang = m_settings_panel.get_boolean(
-@@ -816,6 +832,8 @@ class Panel : IBus.PanelService {
-         BindingCommon.set_custom_font(m_settings_panel,
-                                       null,
-                                       ref m_css_provider);
-+        BindingCommon.set_custom_theme(m_settings_panel);
-+        BindingCommon.set_custom_icon(m_settings_panel);
-         set_show_icon_on_systray();
-         set_lookup_table_orientation();
-         set_show_property_panel();
-diff --git a/ui/gtk3/panelbinding.vala b/ui/gtk3/panelbinding.vala
-index e63d93f2..3c516afd 100644
---- a/ui/gtk3/panelbinding.vala
-+++ b/ui/gtk3/panelbinding.vala
-@@ -270,6 +270,22 @@ class PanelBinding : IBus.PanelService {
-                                               ref m_css_provider);
-         });
- 
-+        m_settings_panel.changed["custom-theme"].connect((key) => {
-+                BindingCommon.set_custom_theme(m_settings_panel);
-+        });
-+
-+        m_settings_panel.changed["use-custom-theme"].connect((key) => {
-+                BindingCommon.set_custom_theme(m_settings_panel);
-+        });
-+
-+        m_settings_panel.changed["custom-icon"].connect((key) => {
-+                BindingCommon.set_custom_icon(m_settings_panel);
-+        });
-+
-+        m_settings_panel.changed["use-custom-icon"].connect((key) => {
-+                BindingCommon.set_custom_icon(m_settings_panel);
-+        });
-+
-         m_settings_emoji.changed["unicode-hotkey"].connect((key) => {
-                 set_emoji_hotkey();
-         });
-@@ -422,6 +438,8 @@ class PanelBinding : IBus.PanelService {
-         BindingCommon.set_custom_font(m_settings_panel,
-                                       m_settings_emoji,
-                                       ref m_css_provider);
-+        BindingCommon.set_custom_theme(m_settings_panel);
-+        BindingCommon.set_custom_icon(m_settings_panel);
-         set_emoji_favorites();
-         if (m_load_emoji_at_startup && !m_loaded_emoji)
-             set_emoji_lang();
--- 
-2.35.3
-
-From addab9fdc7f98c172b6fcb1e24faa133368bdaf3 Mon Sep 17 00:00:00 2001
-From: Hollow Man <hollowman@opensuse.org>
-Date: Wed, 26 Jan 2022 10:03:04 +0800
-Subject: [PATCH 2/3] Revert support for choosing GTK themes dark variant
-
-So that the theme list won't get too messy
-
-BUG=https://github.com/ibus/ibus/pull/2327
-
-Signed-off-by: Hollow Man <hollowman@opensuse.org>
----
- setup/main.py              | 10 ++--------
- ui/gtk3/bindingcommon.vala | 14 +++-----------
- 2 files changed, 5 insertions(+), 19 deletions(-)
-
-diff --git a/setup/main.py b/setup/main.py
-index 71896693..d0e05666 100644
---- a/setup/main.py
-+++ b/setup/main.py
-@@ -672,18 +672,12 @@ class Setup(object):
-         gtk_theme_path = []
-         for path in path_list:
-             gtk_theme_path.extend(glob.glob(path + "/*/gtk-*/gtk.css"))
--            gtk_theme_path.extend(glob.glob(path + "/*/gtk-*/gtk-dark.css"))
-         for path in gtk_theme_path:
--            filename = os.path.basename(path)
--            appendix = ""
--            if filename == "gtk-dark.css":
--                appendix = ":dark"
-             theme_name_list.append(os.path.basename(
--                os.path.dirname(os.path.dirname(path))) + appendix)
-+                os.path.dirname(os.path.dirname(path))))
- 
-         theme_name_list.extend([
--            'Adwaita', 'Adwaita:dark',
--            'HighContrast', 'HighContrastInverse'
-+            'Adwaita', 'HighContrast', 'HighContrastInverse'
-         ])
-         theme_name_list = list(set(theme_name_list))
-         theme_name_list.sort()
-diff --git a/ui/gtk3/bindingcommon.vala b/ui/gtk3/bindingcommon.vala
-index e825167b..4ecb7159 100644
---- a/ui/gtk3/bindingcommon.vala
-+++ b/ui/gtk3/bindingcommon.vala
-@@ -226,18 +226,10 @@ class BindingCommon {
-         if (use_custom_theme == false)
-             custom_theme = "";
- 
--        if (custom_theme == null || custom_theme == "") {
-+        if (custom_theme == null || custom_theme == "")
-             gtk_settings.reset_property("gtk-theme-name");
--            gtk_settings.reset_property("gtk-application-prefer-dark-theme");
--        } else {
--            string[] custom_theme_splitted = custom_theme.split(":");
--            gtk_settings.gtk_theme_name = custom_theme_splitted[0];
--            if (custom_theme_splitted.length == 2 &&
--            custom_theme_splitted[1] == "dark")
--                gtk_settings.gtk_application_prefer_dark_theme = true;
--            else
--                gtk_settings.gtk_application_prefer_dark_theme = false;
--        }
-+        else
-+            gtk_settings.gtk_theme_name = custom_theme;
-     }
- 
-     public static void
--- 
-2.35.3
-
-From ff99828cb60915318ed0f40998a1a23d5dea42c7 Mon Sep 17 00:00:00 2001
-From: Hollow Man <hollowman@opensuse.org>
-Date: Wed, 26 Jan 2022 11:19:40 +0800
-Subject: [PATCH 3/3] Add tooltip text for use custom icon and theme
-
-BUG=https://github.com/ibus/ibus/pull/2327
-
-Signed-off-by: Hollow Man <hollowman@opensuse.org>
----
- setup/setup.ui | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/setup/setup.ui b/setup/setup.ui
-index 5a9804f9..6ded2061 100644
---- a/setup/setup.ui
-+++ b/setup/setup.ui
-@@ -1339,6 +1339,7 @@
-                             <child>
-                               <object class="GtkCheckButton" id="checkbutton_custom_theme">
-                                 <property name="label" translatable="yes">Use custom theme:</property>
-+                                <property name="tooltip_text" translatable="yes">Choose a theme of the candidate window</property>
-                                 <property name="use_action_appearance">False</property>
-                                 <property name="visible">True</property>
-                                 <property name="can_focus">True</property>
-@@ -1375,6 +1376,7 @@
-                             <child>
-                               <object class="GtkCheckButton" id="checkbutton_custom_icon">
-                                 <property name="label" translatable="yes">Use custom icon:</property>
-+                                <property name="tooltip_text" translatable="yes">Choose a theme of the arrow buttons on the candidate window</property>
-                                 <property name="use_action_appearance">False</property>
-                                 <property name="visible">True</property>
-                                 <property name="can_focus">True</property>
--- 
-2.35.3
-
-From 9ad063746ec3d919217ae18acce2d4768bcfca05 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Mon, 20 Jun 2022 21:01:31 +0900
-Subject: [PATCH] ui/gtk3: Hide XKB engine but enable it in Plasma Wayland
-
-IBus just cannot defer key events to the secondary input methods
-to switch XKB keymaps in Plasma Wayland because IBus has to handle the
-compose keys before defer the key events.
-
-Also update the POT file.
-
-BUG=rhbz#2088656
----
- data/dconf/org.freedesktop.ibus.gschema.xml |   4 +-
- ui/gtk3/panel.vala                          |  50 ++-
- 3 files changed, 248 insertions(+), 180 deletions(-)
-
-diff --git a/data/dconf/org.freedesktop.ibus.gschema.xml b/data/dconf/org.freedesktop.ibus.gschema.xml
-index 051f21a5..0ece2b4f 100644
---- a/data/dconf/org.freedesktop.ibus.gschema.xml
-+++ b/data/dconf/org.freedesktop.ibus.gschema.xml
-@@ -223,12 +223,12 @@
-     <key name="use-custom-icon" type="b">
-       <default>false</default>
-       <summary>Use custom icon</summary>
--      <description>Use custom icon name for language panel</description>
-+      <description>Use custom icon name for arrow buttons on candidate window</description>
-     </key>
-     <key name="custom-icon" type="s">
-       <default>'Adwaita'</default>
-       <summary>Custom icon</summary>
--      <description>Custom icon name for language panel</description>
-+      <description>Custom icon name for arrow buttons on candidate window</description>
-     </key>
-     <key name="use-glyph-from-engine-lang" type="b">
-       <default>true</default>
-diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
-index 101c2b3d..452b14c8 100644
---- a/ui/gtk3/panel.vala
-+++ b/ui/gtk3/panel.vala
-@@ -41,6 +41,7 @@ class Panel : IBus.PanelService {
-     private Gtk.Menu m_ime_menu;
-     private Gtk.Menu m_sys_menu;
-     private IBus.EngineDesc[] m_engines = {};
-+    private IBus.EngineDesc m_en_engine;
-     private GLib.HashTable<string, IBus.EngineDesc> m_engine_contexts =
-             new GLib.HashTable<string, IBus.EngineDesc>(GLib.str_hash,
-                                                         GLib.str_equal);
-@@ -928,13 +929,20 @@ class Panel : IBus.PanelService {
-     }
- 
-     private void switch_engine(int i, bool force = false) {
--        GLib.assert(i >= 0 && i < m_engines.length);
-+        if (m_is_wayland)
-+            GLib.assert(i >= 0 && i <= m_engines.length);
-+        else
-+            GLib.assert(i >= 0 && i < m_engines.length);
- 
-         // Do not need switch
-         if (i == 0 && !force)
-             return;
- 
--        IBus.EngineDesc engine = m_engines[i];
-+        IBus.EngineDesc engine;
-+        if (m_is_wayland && m_engines.length == 0)
-+            engine = m_en_engine;
-+        else
-+            engine = m_engines[i];
- 
-         set_engine(engine);
-     }
-@@ -1024,17 +1032,15 @@ class Panel : IBus.PanelService {
-                                 string[]? order_names) {
-         string[]? engine_names = unowned_engine_names;
- 
--        if (engine_names == null || engine_names.length == 0) {
--            if (m_is_wayland)
--                engine_names = {};
--            else
--                engine_names = {"xkb:us::eng"};
--        }
-+        if (engine_names == null || engine_names.length == 0)
-+            engine_names = {"xkb:us::eng"};
- 
-         string[] names = {};
- 
-         foreach (var name in order_names) {
-             if (m_is_wayland && name.has_prefix("xkb:"))
-+                name = "xkb:us::eng";
-+            if (name in names)
-                 continue;
-             if (name in engine_names)
-                 names += name;
-@@ -1042,7 +1048,7 @@ class Panel : IBus.PanelService {
- 
-         foreach (var name in engine_names) {
-             if (m_is_wayland && name.has_prefix("xkb:"))
--                continue;
-+                name = "xkb:us::eng";
-             if (name in names)
-                 continue;
-             names += name;
-@@ -1083,14 +1089,20 @@ class Panel : IBus.PanelService {
- 	}
- 
-         if (m_engines.length == 0) {
--            if (engines.length > 0) {
--                m_engines = engines;
--                switch_engine(0, true);
--                run_preload_engines(engines, 1);
--            } else {
--                m_candidate_panel.set_language(new Pango.AttrLanguage(
--                        Pango.Language.from_string(null)));
-+            m_engines = engines;
-+            // Do not show engines in panel icon and suggest systemsettings5
-+            // in Plasma Wayland in case all engines are XKB.
-+            if (m_is_wayland && m_engines.length == 1 &&
-+                m_engines[0].get_name() == "xkb:us::eng") {
-+                m_engines = {};
-+                if (m_en_engine == null) {
-+                    m_en_engine =
-+                            m_bus.get_engines_by_names({"xkb:us::eng"})[0];
-+                }
-             }
-+            switch_engine(0, true);
-+            if (m_engines.length > 0)
-+                run_preload_engines(m_engines, 1);
-         } else {
-             var current_engine = m_engines[0];
-             m_engines = engines;
-@@ -1307,6 +1319,10 @@ class Panel : IBus.PanelService {
-             var longname = engine.get_longname();
-             var textdomain = engine.get_textdomain();
-             var transname = GLib.dgettext(textdomain, longname);
-+            if (m_is_wayland && engine.get_name().has_prefix("xkb:")) {
-+                language = _("Other");
-+                transname = _("No input method");
-+            }
-             var item = new Gtk.MenuItem.with_label(
-                 "%s - %s".printf (IBus.get_language_name(language), transname));
-             // Make a copy of engine to workaround a bug in vala.
-@@ -1584,7 +1600,7 @@ class Panel : IBus.PanelService {
- 
-             if (engine != null) {
-                 var name = engine.get_name();
--                if (name.length >= 4 && name[0:4] == "xkb:")
-+                if (!m_is_wayland && name.length >= 4 && name[0:4] == "xkb:")
-                     language = m_switcher.get_xkb_language(engine);
-             }
- 
--- 
-2.35.3
-
-From b94f0c1cea5d0e423fef3bcc13b23f212f04c930 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Thu, 7 Jul 2022 08:13:57 +0900
-Subject: [PATCH] src: Add IBUS_CAP_OSK to IBusCapabilite
-
-Some IMEs' behavior is different between the on-screen keyboard and
-the direct physical keyboard and this flag is useful for the IMEs.
-
-Also fix src/ibusaccelgroup.c for gtkdoc-mkhtml.
-If the API comment of IBusCapabilite is updated, XML & HTML files
-are rebuilt and gtk-doc-1.33.2 no longer accepts HTML tags in
-the comments.
----
- src/ibusaccelgroup.c | 14 +++++++-------
- src/ibustypes.h      |  2 ++
- 2 files changed, 9 insertions(+), 7 deletions(-)
-
-diff --git a/src/ibusaccelgroup.c b/src/ibusaccelgroup.c
-index ef2d3976..aec1c7e4 100644
---- a/src/ibusaccelgroup.c
-+++ b/src/ibusaccelgroup.c
-@@ -267,14 +267,14 @@ is_keycode (const gchar *string)
-  *     modifier mask, %NULL
-  *
-  * Parses a string representing an accelerator. The format looks like
-- * “<Control>a” or “<Shift><Alt>F1” or “<Release>z” (the last one is
-- * for key release).
-+ * “&lt;Control&gt;a” or “&lt;Shift&gt;&lt;Alt&gt;F1” or “&lt;Release%gt;z”
-+ * (the last one is for key release).
-  *
-  * The parser is fairly liberal and allows lower or upper case, and also
-- * abbreviations such as “<Ctl>” and “<Ctrl>”. Key names are parsed using
-- * gdk_keyval_from_name(). For character keys the name is not the symbol,
-- * but the lowercase name, e.g. one would use “<Ctrl>minus” instead of
-- * “<Ctrl>-”.
-+ * abbreviations such as “&lt;Ctl&gt;” and “&lt;Ctrl&gt;”. Key names are
-+ * parsed using gdk_keyval_from_name(). For character keys the name is not the
-+ * symbol, but the lowercase name, e.g. one would use “&lt;Ctrl&gt;minus”
-+ * instead of “&lt;Ctrl&gt;-”.
-  *
-  * If the parse fails, @accelerator_key and @accelerator_mods will
-  * be set to 0 (zero).
-@@ -403,7 +403,7 @@ out:
-  *
-  * Converts an accelerator keyval and modifier mask into a string
-  * parseable by gtk_accelerator_parse(). For example, if you pass in
-- * #IBUS_KEY_q and #IBUS_CONTROL_MASK, this function returns “<Control>q”.
-+ * #IBUS_KEY_q and #IBUS_CONTROL_MASK, this function returns “&lt;Control&gt;q”.
-  *
-  * If you need to display accelerators in the user interface,
-  * see gtk_accelerator_get_label().
-diff --git a/src/ibustypes.h b/src/ibustypes.h
-index 990659ac..60bcb92b 100644
---- a/src/ibustypes.h
-+++ b/src/ibustypes.h
-@@ -108,6 +108,7 @@ typedef enum
-  * @IBUS_CAP_PROPERTY: UI is capable to have property.
-  * @IBUS_CAP_SURROUNDING_TEXT: Client can provide surround text,
-  *  or IME can handle surround text.
-+ * @IBUS_CAP_OSK: UI is owned by on-screen keyboard.
-  *
-  * Capability flags of UI.
-  */
-@@ -118,6 +119,7 @@ typedef enum {
-     IBUS_CAP_FOCUS              = 1 << 3,
-     IBUS_CAP_PROPERTY           = 1 << 4,
-     IBUS_CAP_SURROUNDING_TEXT   = 1 << 5,
-+    IBUS_CAP_OSK                = 1 << 6,
- } IBusCapabilite;
- 
- /**
--- 
-2.35.3
-
-From 4e48e7237d73d20f0426265dbb6b692b14891932 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Thu, 7 Jul 2022 08:21:24 +0900
-Subject: [PATCH] tools: Enable ibus restart in GNOME desktop
-
-If ibus-daemon is called via systemd, IBus restart API cannot restart
-ibus-daemon but just terminates it.
-Now ibus restart command checks the systemd avaiability and restart
-ibus-daemon via systemd.
-ibus start command is also added to launch ibus-daemon with systemd.
-
-BUG=https://github.com/ibus/ibus/issues/2407
----
- tools/Makefile.am |   3 +-
- tools/ibus.1.in   |  30 +++++-
- tools/main.vala   | 261 ++++++++++++++++++++++++++++++++++++++++++++--
- 3 files changed, 330 insertions(+), 44 deletions(-)
-
-diff --git a/tools/Makefile.am b/tools/Makefile.am
-index 5c18d3d6..e380a9aa 100644
---- a/tools/Makefile.am
-+++ b/tools/Makefile.am
-@@ -3,7 +3,7 @@
- # ibus - The Input Bus
- #
- # Copyright (c) 2007-2013 Peng Huang <shawn.p.huang@gmail.com>
--# Copyright (c) 2015-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+# Copyright (c) 2015-2022 Takao Fujiwara <takao.fujiwara1@gmail.com>
- # Copyright (c) 2007-2017 Red Hat, Inc.
- #
- # This library is free software; you can redistribute it and/or
-@@ -57,6 +57,7 @@ AM_LDADD = \
- AM_VALAFLAGS = \
- 	--vapidir=$(top_builddir)/bindings/vala \
- 	--vapidir=$(top_srcdir)/bindings/vala \
-+	--pkg=gio-2.0 \
- 	--pkg=ibus-1.0 \
- 	--pkg=posix \
- 	--pkg=config \
-diff --git a/tools/ibus.1.in b/tools/ibus.1.in
-index 525d972e..fe1b7157 100644
---- a/tools/ibus.1.in
-+++ b/tools/ibus.1.in
-@@ -3,7 +3,7 @@
- .\" Copyright (C) Takao Fujiwara <takao.fujiwara1@gmail.com>, 2013-2017.
- .\" Copyright (c) Peng Huang <shawn.p.huang@gmail.com>, 2013.
- .\"
--.TH "IBUS" 1 "May 2017" "@VERSION@" "User Commands"
-+.TH "IBUS" 1 "Jul 2022" "@VERSION@" "User Commands"
- .SH NAME
- .B ibus
- \- command line utility for ibus
-@@ -45,13 +45,33 @@ Exit ibus-daemon.
- \fBlist-engine\fR
- Show ibus engines list.
- .TP
--\fBrestart\fR
--Restart ibus-daemon.
-+\fBrestart\fR [\fB\-\-type=TYPE|\-\-verbose|\-\-help\fR]
-+Restart ibus-daemon. This command tries to restart ibus-daemon via systemd
-+firstly and directly secondary by default. If
-+.B \-\-type=systemd
-+is given, It tries to restart via systemd only. If
-+.B \-\-type=direct
-+is given, It tries to restart with an IBus API only. GNOME desktop runs
-+ibus-daemon via systemd and other desktops run ibus-daemon directly.
-+.TP
-+\fBstart\fR [\fB\-\-type=TYPE|\-\-verbose|\-\-help\fR]
-+Start ibus-daemon. This command tries to start ibus-daemon via systemd
-+firstly and directly secondary by default. If
-+.B \-\-type=systemd
-+is given, It tries to start as a background process via systemd only. If
-+.B \-\-type=direct
-+is given, It tries to start directly only as a foreground process and other
-+option arguments of ibus command are sent to ibus-daemon. E.g.
-+ibus start
-+.B \-\-type=direct
-+.B \-\-xim
-+&
-+GNOME desktop runs ibus-daemon via systemd and other desktops run ibus-daemon directly.
- .TP
- \fBversion\fR
- Show the ibus version.
- .TP
--\fBread\-cache\fR [\fB\-\-system|\-\-file=FILE\fR]
-+\fBread\-cache\fR [\fB\-\-system|\-\-file=FILE|\-\-help\fR]
- Show the content of the user registry cache if
- .B \-\-system
- is not given.
-@@ -64,7 +84,7 @@ if
- .B \-\-file=FILE
- is given.
- .TP
--\fBwrite\-cache\fR [\fB\-\-system|\-\-file=FILE\fR]
-+\fBwrite\-cache\fR [\fB\-\-system|\-\-file=FILE|\-\-help\fR]
- Save the user registry cache if
- .B \-\-system
- is not given.
-diff --git a/tools/main.vala b/tools/main.vala
-index 26e7fd88..407eaf74 100644
---- a/tools/main.vala
-+++ b/tools/main.vala
-@@ -3,7 +3,7 @@
-  * ibus - The Input Bus
-  *
-  * Copyright(c) 2013 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright(c) 2015-2020 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright(c) 2015-2022 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
-@@ -27,17 +27,23 @@ private const string IBUS_SCHEMAS_GENERAL_HOTKEY =
- private const string IBUS_SCHEMAS_PANEL = "org.freedesktop.ibus.panel";
- private const string IBUS_SCHEMAS_PANEL_EMOJI =
-         "org.freedesktop.ibus.panel.emoji";
-+private const string SYSTEMD_SESSION_GNOME_FILE =
-+        "org.freedesktop.IBus.session.GNOME.service";
- 
- bool name_only = false;
- /* system() exists as a public API. */
- bool is_system = false;
- string cache_file = null;
- string engine_id = null;
-+bool verbose = false;
-+string daemon_type = null;
-+string systemd_service_file = null;
- 
- class EngineList {
-     public IBus.EngineDesc[] data = {};
- }
- 
-+
- IBus.Bus? get_bus() {
-     var bus = new IBus.Bus();
-     if (!bus.is_connected ())
-@@ -45,6 +51,131 @@ IBus.Bus? get_bus() {
-     return bus;
- }
- 
-+
-+GLib.DBusConnection?  get_session_bus(bool verbose) {
-+    try {
-+        return GLib.Bus.get_sync (GLib.BusType.SESSION, null);
-+    } catch (GLib.IOError e) {
-+        if (verbose)
-+            stderr.printf("%s\n", e.message);
-+    }
-+    return null;
-+}
-+
-+string?
-+get_ibus_systemd_object_path(GLib.DBusConnection connection,
-+                             bool                verbose) {
-+    string object_path = null;
-+    assert(systemd_service_file != null);
-+    try {
-+        var variant = connection.call_sync (
-+                "org.freedesktop.systemd1",
-+                "/org/freedesktop/systemd1",
-+                "org.freedesktop.systemd1.Manager",
-+                "GetUnit",
-+                new GLib.Variant("(s)", systemd_service_file),
-+                new GLib.VariantType("(o)"),
-+                GLib.DBusCallFlags.NONE,
-+                -1,
-+                null);
-+        variant.get("(o)", ref object_path);
-+        if (verbose) {
-+            stderr.printf("Succeed to get an object path \"%s\" for IBus " +
-+                          "systemd service file \"%s\".\n",
-+                          object_path, systemd_service_file);
-+        }
-+        return object_path;
-+    } catch (GLib.Error e) {
-+        if (verbose) {
-+            stderr.printf("IBus systemd service file \"%s\" is not installed " +
-+                          "in your system: %s\n",
-+                          systemd_service_file, e.message);
-+        }
-+    }
-+    return null;
-+}
-+
-+
-+bool
-+is_running_daemon_via_systemd(GLib.DBusConnection connection,
-+                              string              object_path,
-+                              bool                verbose) {
-+    string? state = null;
-+    try {
-+        while (true) {
-+            var variant = connection.call_sync (
-+                    "org.freedesktop.systemd1",
-+                    object_path,
-+                    "org.freedesktop.DBus.Properties",
-+                    "Get",
-+                    new GLib.Variant("(ss)",
-+                                     "org.freedesktop.systemd1.Unit",
-+                                     "ActiveState"),
-+                    new GLib.VariantType("(v)"),
-+                    GLib.DBusCallFlags.NONE,
-+                    -1,
-+                    null);
-+            GLib.Variant child = null;
-+            variant.get("(v)", ref child);
-+            state = child.dup_string();
-+            if (verbose) {
-+                stderr.printf("systemd state is \"%s\" for an object " +
-+                              "path \"%s\".\n", state, object_path);
-+            }
-+            if (state != "activating")
-+                break;
-+            Posix.sleep(1);
-+        }
-+    } catch (GLib.Error e) {
-+        if (verbose)
-+            stderr.printf("%s\n", e.message);
-+        return false;
-+    }
-+    if (state == "active")
-+        return true;
-+    return false;
-+}
-+
-+
-+bool
-+start_daemon_via_systemd(GLib.DBusConnection connection,
-+                         bool                restart,
-+                         bool                verbose) {
-+    string object_path = null;
-+    string method = "StartUnit";
-+    assert(systemd_service_file != null);
-+    if (restart)
-+        method = "RestartUnit";
-+    try {
-+        var variant = connection.call_sync (
-+                "org.freedesktop.systemd1",
-+                "/org/freedesktop/systemd1",
-+                "org.freedesktop.systemd1.Manager",
-+                method,
-+                new GLib.Variant("(ss)", systemd_service_file, "fail"),
-+                new GLib.VariantType("(o)"),
-+                GLib.DBusCallFlags.NONE,
-+                -1,
-+                null);
-+        variant.get("(o)", ref object_path);
-+        if (verbose) {
-+            stderr.printf("Succeed to restart IBus daemon via IBus systemd " +
-+                          "service file \"%s\": \"%s\"\n",
-+                          systemd_service_file, object_path);
-+        }
-+        return true;
-+    } catch (GLib.Error e) {
-+        if (verbose) {
-+            stderr.printf("Failed to %s IBus daemon via IBus systemd " +
-+                          "service file \"%s\": %s\n",
-+                          restart ? "restart" : "start",
-+                          systemd_service_file, e.message);
-+        }
-+    }
-+    return false;
-+}
-+
-+
- int list_engine(string[] argv) {
-     const OptionEntry[] options = {
-         { "name-only", 0, 0, OptionArg.NONE, out name_only,
-@@ -99,6 +230,7 @@ int list_engine(string[] argv) {
-     return Posix.EXIT_SUCCESS;
- }
- 
-+
- private int exec_setxkbmap(IBus.EngineDesc engine) {
-     string layout = engine.get_layout();
-     string variant = engine.get_layout_variant();
-@@ -149,6 +281,7 @@ private int exec_setxkbmap(IBus.EngineDesc engine) {
-     return Posix.EXIT_SUCCESS;
- }
- 
-+
- int get_set_engine(string[] argv) {
-     var bus = get_bus();
-     string engine = null;
-@@ -182,20 +315,121 @@ int get_set_engine(string[] argv) {
-     return Posix.EXIT_SUCCESS;
- }
- 
-+
- int message_watch(string[] argv) {
-     return Posix.EXIT_SUCCESS;
- }
- 
--int restart_daemon(string[] argv) {
--    var bus = get_bus();
--    if (bus == null) {
--        stderr.printf(_("Can't connect to IBus.\n"));
-+
-+int start_daemon_real(string[] argv,
-+                      bool     restart) {
-+    const OptionEntry[] options = {
-+        { "type", 0, 0, OptionArg.STRING, out daemon_type,
-+          N_("Start or restart daemon with \"direct\" or \"systemd\" TYPE."),
-+          "TYPE" },
-+        { "service-file", 0, 0, OptionArg.STRING, out systemd_service_file,
-+          N_("Start or restart daemon with SYSTEMD_SERVICE file."),
-+          "SYSTEMD_SERVICE" },
-+        { "verbose", 0, 0, OptionArg.NONE, out verbose,
-+          N_("Show debug messages."), null },
-+        { null }
-+    };
-+
-+    var option = new OptionContext();
-+    option.add_main_entries(options, Config.GETTEXT_PACKAGE);
-+    option.set_ignore_unknown_options(true);
-+
-+    try {
-+        option.parse(ref argv);
-+    } catch (OptionError e) {
-+        stderr.printf("%s\n", e.message);
-+        return Posix.EXIT_FAILURE;
-+    }
-+    if (daemon_type != null && daemon_type != "direct" &&
-+        daemon_type != "systemd") {
-+        stderr.printf("type argument must be \"direct\" or \"systemd\"\n");
-+        return Posix.EXIT_FAILURE;
-+    }
-+    if (systemd_service_file == null)
-+        systemd_service_file = SYSTEMD_SESSION_GNOME_FILE;
-+
-+    do {
-+        if (daemon_type == "direct")
-+            break;
-+        GLib.DBusConnection? connection = get_session_bus(verbose);
-+        if (connection == null)
-+            break;
-+        string? object_path = null;
-+        if (restart) {
-+            object_path = get_ibus_systemd_object_path(connection, verbose);
-+            if (object_path == null)
-+                break;
-+            if (!is_running_daemon_via_systemd(connection,
-+                                               object_path,
-+                                               verbose)) {
-+                break;
-+            }
-+        }
-+        if (!start_daemon_via_systemd(connection, restart, verbose))
-+            break;
-+        // Do not check the systemd state in case of restart because
-+        // the systemd file validation is already done and also stopping
-+        // daemon and starting daemon take time and the state could be
-+        // "inactive" with the time lag.
-+        if (restart)
-+            return Posix.EXIT_SUCCESS;
-+        object_path = get_ibus_systemd_object_path(connection, verbose);
-+        if (object_path == null)
-+            break;
-+        if (!is_running_daemon_via_systemd(connection, object_path, verbose))
-+            break;
-+        return Posix.EXIT_SUCCESS;
-+    } while (false);
-+
-+    if (daemon_type == "systemd")
-         return Posix.EXIT_FAILURE;
-+    if (restart) {
-+        var bus = get_bus();
-+        if (bus == null) {
-+            stderr.printf(_("Can't connect to IBus.\n"));
-+            return Posix.EXIT_FAILURE;
-+        }
-+        bus.exit(true);
-+        if (verbose) {
-+            stderr.printf("Succeed to restart ibus-daemon with an IBus API " +
-+                          "directly.\n");
-+        }
-+    } else {
-+        string startarg = "ibus-daemon";
-+        argv[0] = startarg;
-+        var paths = GLib.Environment.get_variable("PATH").split(":");
-+        foreach (unowned string path in paths) {
-+            var full_path = "%s/%s".printf(path, startarg);
-+            if (GLib.FileUtils.test(full_path, GLib.FileTest.IS_EXECUTABLE)) {
-+                startarg = full_path;
-+                break;
-+            }
-+        }
-+        // When ibus-daemon is launched by GLib.Process.spawn_async(),
-+        // the parent process will be systemd
-+        if (verbose) {
-+            stderr.printf("Running \"%s\" directly as a foreground " +
-+                          "process.\n", startarg);
-+        }
-+        Posix.execv(startarg, argv);
-     }
--    bus.exit(true);
-     return Posix.EXIT_SUCCESS;
- }
- 
-+
-+int restart_daemon(string[] argv) {
-+    return start_daemon_real(argv, true);
-+}
-+
-+int start_daemon(string[] argv) {
-+    return start_daemon_real(argv, false);
-+}
-+
- int exit_daemon(string[] argv) {
-     var bus = get_bus();
-     if (bus == null) {
-@@ -206,11 +440,13 @@ int exit_daemon(string[] argv) {
-     return Posix.EXIT_SUCCESS;
- }
- 
-+
- int print_version(string[] argv) {
-     print("IBus %s\n", Config.PACKAGE_VERSION);
-     return Posix.EXIT_SUCCESS;
- }
- 
-+
- int read_cache (string[] argv) {
-     const OptionEntry[] options = {
-         { "system", 0, 0, OptionArg.NONE, out is_system,
-@@ -251,6 +487,7 @@ int read_cache (string[] argv) {
-     return Posix.EXIT_SUCCESS;
- }
- 
-+
- int write_cache (string[] argv) {
-     const OptionEntry[] options = {
-         { "system", 0, 0, OptionArg.NONE, out is_system,
-@@ -283,12 +520,14 @@ int write_cache (string[] argv) {
-             Posix.EXIT_SUCCESS : Posix.EXIT_FAILURE;
- }
- 
-+
- int print_address(string[] argv) {
-     string address = IBus.get_address();
-     print("%s\n", address != null ? address : "(null)");
-     return Posix.EXIT_SUCCESS;
- }
- 
-+
- private int read_config_options(string[] argv) {
-     const OptionEntry[] options = {
-         { "engine-id", 0, 0, OptionArg.STRING, out engine_id,
-@@ -309,6 +548,7 @@ private int read_config_options(string[] argv) {
-     return Posix.EXIT_SUCCESS;
- }
- 
-+
- private GLib.SList<string> get_ibus_schemas() {
-     string[] ids = {};
-     if (engine_id != null) {
-@@ -342,6 +582,7 @@ private GLib.SList<string> get_ibus_schemas() {
-     return ibus_schemas;
- }
- 
-+
- int read_config(string[] argv) {
-     if (read_config_options(argv) == Posix.EXIT_FAILURE)
-         return Posix.EXIT_FAILURE;
-@@ -370,6 +611,7 @@ int read_config(string[] argv) {
-     return Posix.EXIT_SUCCESS;
- }
- 
-+
- int reset_config(string[] argv) {
-     if (read_config_options(argv) == Posix.EXIT_FAILURE)
-         return Posix.EXIT_FAILURE;
-@@ -401,6 +643,7 @@ int reset_config(string[] argv) {
-     return Posix.EXIT_SUCCESS;
- }
- 
-+
- #if EMOJI_DICT
- int emoji_dialog(string[] argv) {
-     string cmd = Config.LIBEXECDIR + "/ibus-ui-emojier";
-@@ -427,11 +670,13 @@ int emoji_dialog(string[] argv) {
- }
- #endif
- 
-+
- int print_help(string[] argv) {
-     print_usage(stdout);
-     return Posix.EXIT_SUCCESS;
- }
- 
-+
- delegate int EntryFunc(string[] argv);
- 
- struct CommandEntry {
-@@ -440,12 +685,14 @@ struct CommandEntry {
-     unowned EntryFunc entry;
- }
- 
-+
- const CommandEntry commands[]  = {
-     { "engine", N_("Set or get engine"), get_set_engine },
-     { "exit", N_("Exit ibus-daemon"), exit_daemon },
-     { "list-engine", N_("Show available engines"), list_engine },
-     { "watch", N_("(Not implemented)"), message_watch },
-     { "restart", N_("Restart ibus-daemon"), restart_daemon },
-+    { "start", N_("Start ibus-daemon"), start_daemon },
-     { "version", N_("Show version"), print_version },
-     { "read-cache", N_("Show the content of registry cache"), read_cache },
-     { "write-cache", N_("Create registry cache"), write_cache },
-@@ -460,6 +707,7 @@ const CommandEntry commands[]  = {
- 
- static string program_name;
- 
-+
- void print_usage(FileStream stream) {
-     stream.printf(_("Usage: %s COMMAND [OPTION...]\n\n"), program_name);
-     stream.printf(_("Commands:\n"));
-@@ -470,6 +718,7 @@ void print_usage(FileStream stream) {
-     }
- }
- 
-+
- public int main(string[] argv) {
-     GLib.Intl.setlocale(GLib.LocaleCategory.ALL, "");
-     GLib.Intl.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
--- 
-2.35.3
-
-From 5b441fabc9d766e694b992e0e2f28924d00a7402 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Thu, 7 Jul 2022 08:22:26 +0900
-Subject: [PATCH] tools: Add ibus im-module command
-
-ibus im-module command can retrive gtk-im-module value from an
-instance of GtkIMMultiContext.
-The GTK version can be specified by --type option and the default
-is --type=gtk3 and GTK3 im-ibus.so is dlopened.
----
- client/gtk2/ibusim.c            |  20 ++++++
- client/gtk4/ibusim.c            |  20 ++++++
- tools/IBusIMModule-1.0.metadata |   1 +
- tools/Makefile.am               | 116 ++++++++++++++++++++++++++------
- tools/ibus.1.in                 |  10 +++
- tools/ibusimmodule.c            |  87 ++++++++++++++++++++++++
- tools/ibusimmodule.h            |  36 ++++++++++
- tools/main.vala                 |  11 +++
- 8 files changed, 308 insertions(+), 40 deletions(-)
- create mode 100644 tools/IBusIMModule-1.0.metadata
- create mode 100644 tools/ibusimmodule.c
- create mode 100644 tools/ibusimmodule.h
-
-diff --git a/client/gtk2/ibusim.c b/client/gtk2/ibusim.c
-index 55609ce7..e196d536 100644
---- a/client/gtk2/ibusim.c
-+++ b/client/gtk2/ibusim.c
-@@ -77,3 +77,23 @@ im_module_list (const GtkIMContextInfo ***contexts,
-     *n_contexts = G_N_ELEMENTS (info_list);
- }
- 
-+G_MODULE_EXPORT const char *
-+im_get_context_id (int    *argc,
-+                   char ***argv)
-+{
-+    GtkIMContext *context;
-+    char *preedit_string = NULL;
-+    PangoAttrList *preedit_attrs = NULL;
-+    const char *context_id;
-+
-+    gtk_init (argc, argv);
-+    context = gtk_im_multicontext_new ();
-+    gtk_im_context_get_preedit_string (context,
-+                                       &preedit_string,
-+                                       &preedit_attrs,
-+                                       0);
-+    context_id = gtk_im_multicontext_get_context_id (
-+            GTK_IM_MULTICONTEXT (context));
-+    return context_id;
-+}
-+
-diff --git a/client/gtk4/ibusim.c b/client/gtk4/ibusim.c
-index 5ecf9778..562bdf2d 100644
---- a/client/gtk4/ibusim.c
-+++ b/client/gtk4/ibusim.c
-@@ -50,3 +50,23 @@ g_io_im_ibus_unload (GTypeModule *type_module)
-     g_type_module_unuse (type_module);
- }
- 
-+G_MODULE_EXPORT const char *
-+im_get_context_id (int    *argc,
-+                   char ***argv)
-+{
-+    GtkIMContext *context;
-+    char *preedit_string = NULL;
-+    PangoAttrList *preedit_attrs = NULL;
-+    const char *context_id;
-+
-+    gtk_init ();
-+    context = gtk_im_multicontext_new ();
-+    gtk_im_context_get_preedit_string (context,
-+                                       &preedit_string,
-+                                       &preedit_attrs,
-+                                       0);
-+    context_id = gtk_im_multicontext_get_context_id (
-+            GTK_IM_MULTICONTEXT (context));
-+    return context_id;
-+}
-+
-diff --git a/tools/IBusIMModule-1.0.metadata b/tools/IBusIMModule-1.0.metadata
-new file mode 100644
-index 00000000..14adc9ee
---- /dev/null
-+++ b/tools/IBusIMModule-1.0.metadata
-@@ -0,0 +1 @@
-+IBusIMModule cheader_filename="ibusimmodule.h" name="IBusIMModule"
-diff --git a/tools/Makefile.am b/tools/Makefile.am
-index e380a9aa..a9262ee0 100644
---- a/tools/Makefile.am
-+++ b/tools/Makefile.am
-@@ -24,9 +24,19 @@
- NULL =
- 
- libibus = $(top_builddir)/src/libibus-@IBUS_API_VERSION@.la
-+libibusimmodule = libibusimmodule.la
-+ibusimmodule_gir = IBusIMModule-1.0.gir
-+ibus_immodule_vapi = ibus-immodule-1.0.vapi
- libibus_emoji_dialog = \
-     $(top_builddir)/ui/gtk3/libibus-emoji-dialog-@IBUS_API_VERSION@.la
- 
-+noinst_LTLIBRARIES = $(libibusimmodule)
-+noinst_DATA =
-+INTROSPECTION_GIRS =
-+MAINTAINERCLEANFILES =
-+DISTCLEANFILES =
-+VAPIGEN_VAPIS =
-+
- # force include config.h before gi18n.h.
- AM_CPPFLAGS = \
- 	-I$(top_srcdir)/src \
-@@ -47,22 +57,26 @@ AM_CFLAGS = \
- 	$(NULL)
- 
- AM_LDADD = \
--	@GOBJECT2_LIBS@ \
--	@GLIB2_LIBS@ \
--	@GIO2_LIBS@ \
--	@GTHREAD2_LIBS@ \
--	$(libibus) \
--	$(NULL)
-+    @GOBJECT2_LIBS@ \
-+    @GLIB2_LIBS@ \
-+    @GIO2_LIBS@ \
-+    @GTHREAD2_LIBS@ \
-+    $(libibus) \
-+    $(libibusimmodule) \
-+    $(NULL)
- 
- AM_VALAFLAGS = \
--	--vapidir=$(top_builddir)/bindings/vala \
--	--vapidir=$(top_srcdir)/bindings/vala \
--	--pkg=gio-2.0 \
--	--pkg=ibus-1.0 \
--	--pkg=posix \
--	--pkg=config \
--	--target-glib="$(VALA_TARGET_GLIB_VERSION)" \
--	$(NULL)
-+    --vapidir=$(top_builddir)/bindings/vala \
-+    --vapidir=$(top_srcdir)/bindings/vala \
-+    --vapidir=$(builddir) \
-+    --vapidir=$(srcdir) \
-+    --pkg=gio-2.0 \
-+    --pkg=ibus-1.0 \
-+    --pkg=ibus-immodule-1.0 \
-+    --pkg=posix \
-+    --pkg=config \
-+    --target-glib="$(VALA_TARGET_GLIB_VERSION)" \
-+    $(NULL)
- 
- bin_PROGRAMS = ibus
- 
-@@ -79,9 +93,27 @@ bash_completion_DATA= \
- 	$(NULL)
- bash_completiondir=@datadir@/bash-completion/completions
- 
-+libibusimmodule_la_SOURCES = \
-+    ibusimmodule.c                                      \
-+    ibusimmodule.h                                      \
-+    $(NULL)
-+libibusimmodule_la_CFLAGS = \
-+    @GLIB2_CFLAGS@                                      \
-+    -DGTK2_IM_MODULEDIR=\"$(GTK2_IM_MODULEDIR)\"        \
-+    -DGTK3_IM_MODULEDIR=\"$(GTK3_IM_MODULEDIR)\"        \
-+    -DGTK4_IM_MODULEDIR=\"$(GTK4_IM_MODULEDIR)\"        \
-+    $(NULL)
-+libibusimmodule_la_LIBADD = \
-+    @GLIB2_LIBS@                                        \
-+    $(NULL)
-+libibusimmodule_la_LDFLAGS = \
-+    -no-undefined                                       \
-+    -export-symbols-regex "ibus_.*"                     \
-+    $(NULL)
-+
- man_one_in_files = ibus.1.in
- man_one_files = $(man_one_in_files:.1.in=.1)
--man_one_DATA =$(man_one_files:.1=.1.gz) 
-+man_one_DATA =$(man_one_files:.1=.1.gz)
- man_onedir = $(mandir)/man1
- %.1: %.1.in
- 	$(AM_V_GEN) sed \
-@@ -91,14 +123,17 @@ man_onedir = $(mandir)/man1
- 	$(AM_V_GEN) gzip -c $< > $@.tmp && mv $@.tmp $@
- 
- EXTRA_DIST = \
--	$(man_one_in_files) \
--	ibus.bash \
--	$(NULL)
-+    $(ibus_immodule_vapi) \
-+    $(ibusimmodule_gir) \
-+    $(man_one_in_files) \
-+    ibus.bash \
-+    IBusIMModule-1.0.metadata \
-+    $(NULL)
- 
- CLEANFILES = \
--	$(man_one_DATA) \
--	$(man_one_files) \
--	$(NULL)
-+    $(man_one_DATA) \
-+    $(man_one_files) \
-+    $(NULL)
- 
- if ENABLE_EMOJI_DICT
- if ENABLE_UI
-@@ -108,4 +143,43 @@ AM_VALAFLAGS += \
- endif
- endif
- 
-+if HAVE_INTROSPECTION
-+BUILT_SOURCES = $(INTROSPECTION_GIRS) $(VAPIGEN_VAPIS)
-+
-+-include $(INTROSPECTION_MAKEFILE)
-+INTROSPECTION_SCANNER_ARGS =
-+INTROSPECTION_COMPILER_ARGS = \
-+    --includedir=$(srcdir)                              \
-+    --includedir=.                                      \
-+    $(NULL)
-+
-+IBusIMModule-1.0.gir: $(libibusimmodule) Makefile
-+IBusIMModule_1_0_gir_SCANNERFLAGS = \
-+    --pkg=glib-2.0                                      \
-+    $(IBUS_GIR_SCANNERFLAGS)                            \
-+    $(NULL)
-+IBusIMModule_1_0_gir_INCLUDES = GLib-2.0
-+IBusIMModule_1_0_gir_LIBS = $(libibusimmodule)
-+IBusIMModule_1_0_gir_FILES = ibusimmodule.h
-+IBusIMModule_1_0_gir_CFLAGS = \
-+    -I$(srcdir)                                         \
-+    -I$(builddir)                                       \
-+    $(NULL)
-+
-+INTROSPECTION_GIRS += $(ibusimmodule_gir)
-+noinst_DATA += $(ibusimmodule_gir)
-+MAINTAINERCLEANFILES += $(ibusimmodule_gir)
-+DISTCLEANFILES += $(ibusimmodule_gir)
-+
-+-include $(VAPIGEN_MAKEFILE)
-+ibus-immodule-1.0.vapi: $(ibusimmodule_gir) IBusIMModule-1.0.metadata
-+ibus_immodule_1_0_vapi_DEPS = glib-2.0
-+ibus_immodule_1_0_vapi_METADATADIRS = $(srcdir)
-+ibus_immodule_1_0_vapi_FILES = IBusIMModule-1.0.gir
-+VAPIGEN_VAPIS += $(ibus_immodule_vapi)
-+noinst_DATA += $(ibus_immodule_vapi)
-+MAINTAINERCLEANFILES += $(ibus_immodule_vapi)
-+DISTCLEANFILES += $(ibus_immodule_vapi)
-+endif
-+
- -include $(top_srcdir)/git.mk
-diff --git a/tools/ibus.1.in b/tools/ibus.1.in
-index fe1b7157..84ef5fff 100644
---- a/tools/ibus.1.in
-+++ b/tools/ibus.1.in
-@@ -128,6 +128,16 @@ option enables to match annotations with a partial string. These settings
- are available with
- .B ibus\-setup (1)
- utility.
-+.TP
-+\fBim-module\fR [\fB\-\-type=TYPE|\-\-help\fR]
-+Show an internal im-module value in a virtual GTK application. If IBus is
-+installed and configured properly, the output is "ibus". This sub-command
-+is useful for some users who build IBus from the source codes and check
-+the configurations. Currently the sub-command supports GTK applications only
-+and the default is GTK3. If you wish to check a GTK4 application, you can
-+specify
-+.B \-\-type=gtk4
-+option and you can choose one of "gtk2", "gtk3" and "gtk4".
- 
- .SH BUGS
- If you find a bug, please report it at https://github.com/ibus/ibus/issues
-diff --git a/tools/ibusimmodule.c b/tools/ibusimmodule.c
-new file mode 100644
-index 00000000..20ccc748
---- /dev/null
-+++ b/tools/ibusimmodule.c
-@@ -0,0 +1,87 @@
-+#include <glib.h>
-+#include <glib/gi18n-lib.h>
-+#include <dlfcn.h>
-+
-+#ifndef DEFAULT_IM_MODULE_TYPE
-+#define DEFAULT_IM_MODULE_TYPE "gtk3"
-+#endif
-+
-+#define OPTION_TYPE_MESSAGE \
-+  N_("Type im-module TYPE = \"gtk2\",  \"gtk3\", \"gtk4\". Default is " \
-+     "\"gtk3\".")
-+
-+typedef const char * (* IBusIMGetContextIdFunc) (int *argc, char ***argv);
-+
-+static char *im_module_type;
-+
-+
-+char *
-+ibus_im_module_get_id (int argc, char *argv[])
-+{
-+    static const GOptionEntry options[3] = {
-+        { "type", (char)0, (int)0, G_OPTION_ARG_STRING, &im_module_type,
-+          OPTION_TYPE_MESSAGE,
-+         "TYPE"},
-+        { NULL }
-+    };
-+    GOptionContext *option;
-+    GError *error = NULL;
-+    void *module;
-+    char *im_context_id;
-+    IBusIMGetContextIdFunc im_get_context_id;
-+
-+    if (!(option = g_option_context_new (NULL))) {
-+        g_critical ("malloc GOptionContext is failed.");
-+        return NULL;
-+    }
-+    g_option_context_add_main_entries (option, options, GETTEXT_PACKAGE);
-+    g_option_context_parse (option, &argc, &argv, &error);
-+    if (error) {
-+        g_critical ("%s", error->message);
-+        g_clear_error (&error);
-+        return NULL;
-+    }
-+    g_option_context_free (option);
-+    if (!im_module_type)
-+        im_module_type = g_strdup (DEFAULT_IM_MODULE_TYPE);
-+
-+    if (G_LIKELY (!g_strcmp0 (im_module_type, "gtk3"))) {
-+        module = dlopen (GTK3_IM_MODULEDIR "/im-ibus.so",
-+                         RTLD_LAZY);
-+    } else if (!g_strcmp0 (im_module_type, "gtk4")) {
-+        const char *module_path_env = g_getenv ("GTK_PATH");
-+        char *module_path;
-+        if (module_path_env) {
-+            module_path = g_build_filename (module_path_env,
-+                                            GTK4_IM_MODULEDIR "/libim-ibus.so",
-+                                            NULL);
-+        } else {
-+            module_path = g_strdup (GTK4_IM_MODULEDIR "/libim-ibus.so");
-+        }
-+        module = dlopen (module_path, RTLD_LAZY);
-+        g_free (module_path);
-+    } else if (!g_strcmp0 (im_module_type, "gtk2")) {
-+        module = dlopen (GTK2_IM_MODULEDIR "/im-ibus.so",
-+                         RTLD_LAZY);
-+    } else {
-+        module = dlopen (im_module_type, RTLD_LAZY);
-+    }
-+    if (!module) {
-+        g_warning ("Not found module: %s", dlerror ());
-+        return NULL;
-+    }
-+
-+    im_get_context_id = dlsym (module, "im_get_context_id");
-+    if (!im_get_context_id) {
-+        g_warning ("Not found im_get_context_id: %s", dlerror ());
-+        dlclose (module);
-+        return NULL;
-+    }
-+
-+    im_context_id = strdup (im_get_context_id (&argc, &argv));
-+    dlclose (module);
-+    return im_context_id;
-+}
-+
-+#undef DEFAULT_IM_MODULE_TYPE
-+
-diff --git a/tools/ibusimmodule.h b/tools/ibusimmodule.h
-new file mode 100644
-index 00000000..e762a747
---- /dev/null
-+++ b/tools/ibusimmodule.h
-@@ -0,0 +1,36 @@
-+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
-+/* vim:set et sts=4: */
-+/* ibus - The Input Bus
-+ * Copyright (C) 2022 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, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-+ * USA
-+ */
-+
-+#ifndef __IBUS_IM_MODULE_CONTEXT_H_
-+#define __IBUS_IM_MODULE_CONTEXT_H_
-+
-+/**
-+ * ibus_im_module_get_id:
-+ * @argc: The length of argv
-+ * @argv: (array length=argc) (element-type utf8): argv from main()
-+ *
-+ * Retrieve im-module value from GTK instance.
-+ *
-+ * Returns: (nullable): im-module value.
-+ */
-+char * ibus_im_module_get_id (int argc, char *argv[]);
-+
-+#endif
-diff --git a/tools/main.vala b/tools/main.vala
-index 407eaf74..1fed2440 100644
---- a/tools/main.vala
-+++ b/tools/main.vala
-@@ -671,6 +671,15 @@ int emoji_dialog(string[] argv) {
- #endif
- 
- 
-+int read_im_module(string[] argv) {
-+    string? im_module = IBusIMModule.im_module_get_id(argv);
-+    if (im_module == null)
-+        return Posix.EXIT_FAILURE;
-+    print("%s\n".printf(im_module));
-+    return Posix.EXIT_SUCCESS;
-+}
-+
-+
- int print_help(string[] argv) {
-     print_usage(stdout);
-     return Posix.EXIT_SUCCESS;
-@@ -702,6 +711,8 @@ const CommandEntry commands[]  = {
- #if EMOJI_DICT
-     { "emoji", N_("Save emoji on dialog to clipboard"), emoji_dialog },
- #endif
-+    { "im-module", N_("Retrieve im-module value from GTK instance"),
-+      read_im_module },
-     { "help", N_("Show this information"), print_help }
- };
- 
--- 
-2.35.3
-
-From 7e42b437c901bb56ca2f776aad5fe65d0d8c246a Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Thu, 7 Jul 2022 08:22:42 +0900
-Subject: [PATCH] client/gtk2: Implement new process_key_event for GTK4
-
----
- client/gtk2/ibusimcontext.c | 147 ++++++++++++++++++++++++++++++------
- src/ibustypes.h             |   4 +
- 2 files changed, 127 insertions(+), 24 deletions(-)
-
-diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c
-index c7f23293..bc14df00 100644
---- a/client/gtk2/ibusimcontext.c
-+++ b/client/gtk2/ibusimcontext.c
-@@ -111,13 +111,13 @@ static guint    _signal_delete_surrounding_id = 0;
- static guint    _signal_retrieve_surrounding_id = 0;
- 
- #if GTK_CHECK_VERSION (3, 98, 4)
--static gboolean _use_sync_mode = TRUE;
-+static char _use_sync_mode = 2;
- #else
- static const gchar *_no_snooper_apps = NO_SNOOPER_APPS;
- static gboolean _use_key_snooper = ENABLE_SNOOPER;
- static guint    _key_snooper_id = 0;
- 
--static gboolean _use_sync_mode = FALSE;
-+static char _use_sync_mode = 0;
- #endif
- 
- static const gchar *_discard_password_apps  = "";
-@@ -375,12 +375,15 @@ ibus_im_context_commit_event (IBusIMContext *ibusimcontext,
-    return FALSE;
- }
- 
--struct _ProcessKeyEventData {
-+typedef struct {
-     GdkEvent *event;
-     IBusIMContext *ibusimcontext;
--};
-+} ProcessKeyEventData;
- 
--typedef struct _ProcessKeyEventData ProcessKeyEventData;
-+typedef struct {
-+    GMainLoop *loop;
-+    gboolean    retval;
-+} ProcessKeyEventReplyData;
- 
- static void
- _process_key_event_done (GObject      *object,
-@@ -395,12 +398,12 @@ _process_key_event_done (GObject      *object,
-     IBusIMContext *ibusimcontext = data->ibusimcontext;
- #endif
-     GError *error = NULL;
-+    gboolean retval;
- 
-     g_slice_free (ProcessKeyEventData, data);
--    gboolean retval = ibus_input_context_process_key_event_async_finish (
--            context,
--            res,
--            &error);
-+    retval = ibus_input_context_process_key_event_async_finish (context,
-+                                                                res,
-+                                                                &error);
- 
-     if (error != NULL) {
-         g_warning ("Process Key Event failed: %s.", error->message);
-@@ -431,6 +434,27 @@ _process_key_event_done (GObject      *object,
- #endif
- }
- 
-+static void
-+_process_key_event_reply_done (GObject      *object,
-+                               GAsyncResult *res,
-+                               gpointer      user_data)
-+{
-+    IBusInputContext *context = (IBusInputContext *)object;
-+    ProcessKeyEventReplyData *data = (ProcessKeyEventReplyData *)user_data;
-+    GError *error = NULL;
-+    gboolean retval = ibus_input_context_process_key_event_async_finish (
-+            context,
-+            res,
-+            &error);
-+    if (error != NULL) {
-+        g_warning ("Process Key Event failed: %s.", error->message);
-+        g_error_free (error);
-+    }
-+    g_return_if_fail (data);
-+    data->retval = retval;
-+    g_main_loop_quit (data->loop);
-+}
-+
- static gboolean
- _process_key_event (IBusInputContext *context,
- #if GTK_CHECK_VERSION (3, 98, 4)
-@@ -462,13 +486,45 @@ _process_key_event (IBusInputContext *context,
- #endif
-     keycode = hardware_keycode;
- 
--    if (_use_sync_mode) {
-+    switch (_use_sync_mode) {
-+    case 1: {
-         retval = ibus_input_context_process_key_event (context,
-+                                                       keyval,
-+                                                       keycode - 8,
-+                                                       state);
-+        break;
-+    }
-+    case 2: {
-+        GMainLoop *loop = g_main_loop_new (NULL, TRUE);
-+        ProcessKeyEventReplyData *data = NULL;
-+
-+        if (loop)
-+            data = g_slice_new0 (ProcessKeyEventReplyData);
-+        if (!data) {
-+            g_warning ("Cannot wait for the reply of the process key event.");
-+            retval = ibus_input_context_process_key_event (context,
-+                                                           keyval,
-+                                                           keycode - 8,
-+                                                           state);
-+            if (loop)
-+                g_main_loop_quit (loop);
-+            break;
-+        }
-+        data->loop = loop;
-+        ibus_input_context_process_key_event_async (context,
-             keyval,
-             keycode - 8,
--            state);
-+            state,
-+            -1,
-+            NULL,
-+            _process_key_event_reply_done,
-+            data);
-+        g_main_loop_run (loop);
-+        retval = data->retval;
-+        g_slice_free (ProcessKeyEventReplyData, data);
-+        break;
-     }
--    else {
-+    default: {
-         ProcessKeyEventData *data = g_slice_new0 (ProcessKeyEventData);
- #if GTK_CHECK_VERSION (3, 98, 4)
-         data->event = gdk_event_ref (event);
-@@ -487,6 +543,7 @@ _process_key_event (IBusInputContext *context,
- 
-         retval = TRUE;
-     }
-+    }
- 
-     /* GTK4 does not provide gtk_key_snooper_install() and also
-      * GtkIMContextClass->filter_keypress() cannot send the updated
-@@ -676,24 +733,47 @@ _key_snooper_cb (GtkWidget   *widget,
- #endif
- 
- static gboolean
--_get_boolean_env(const gchar *name,
--                 gboolean     defval)
-+_get_boolean_env (const gchar *name,
-+                  gboolean     defval)
- {
-     const gchar *value = g_getenv (name);
- 
-     if (value == NULL)
--      return defval;
-+        return defval;
- 
-     if (g_strcmp0 (value, "") == 0 ||
-         g_strcmp0 (value, "0") == 0 ||
-         g_strcmp0 (value, "false") == 0 ||
-         g_strcmp0 (value, "False") == 0 ||
--        g_strcmp0 (value, "FALSE") == 0)
--      return FALSE;
-+        g_strcmp0 (value, "FALSE") == 0) {
-+        return FALSE;
-+    }
- 
-     return TRUE;
- }
- 
-+static char
-+_get_char_env (const gchar *name,
-+               char         defval)
-+{
-+    const gchar *value = g_getenv (name);
-+
-+    if (value == NULL)
-+        return defval;
-+
-+    if (g_strcmp0 (value, "") == 0 ||
-+        g_strcmp0 (value, "0") == 0 ||
-+        g_strcmp0 (value, "false") == 0 ||
-+        g_strcmp0 (value, "False") == 0 ||
-+        g_strcmp0 (value, "FALSE") == 0) {
-+        return 0;
-+    } else if (!g_strcmp0 (value, "2")) {
-+        return 2;
-+    }
-+
-+    return 1;
-+}
-+
- static void
- daemon_name_appeared (GDBusConnection *connection,
-                       const gchar     *name,
-@@ -777,11 +857,11 @@ ibus_im_context_class_init (IBusIMContextClass *class)
-     g_assert (_signal_retrieve_surrounding_id != 0);
- 
- #if GTK_CHECK_VERSION (3, 98, 4)
--    _use_sync_mode = _get_boolean_env ("IBUS_ENABLE_SYNC_MODE", TRUE);
-+    _use_sync_mode = _get_char_env ("IBUS_ENABLE_SYNC_MODE", 2);
- #else
-     _use_key_snooper = !_get_boolean_env ("IBUS_DISABLE_SNOOPER",
-                                           !(ENABLE_SNOOPER));
--    _use_sync_mode = _get_boolean_env ("IBUS_ENABLE_SYNC_MODE", FALSE);
-+    _use_sync_mode = (char)_get_char_env ("IBUS_ENABLE_SYNC_MODE", 0);
- #endif
-     _use_discard_password = _get_boolean_env ("IBUS_DISCARD_PASSWORD", FALSE);
- 
-@@ -904,6 +984,8 @@ ibus_im_context_init (GObject *obj)
- #else
-     ibusimcontext->caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS;
- #endif
-+    if (_use_sync_mode != 1)
-+        ibusimcontext->caps |= IBUS_CAP_SYNC_PROCESS_KEY;
- 
-     ibusimcontext->events_queue = g_queue_new ();
- 
-@@ -1246,7 +1328,7 @@ ibus_im_context_reset (GtkIMContext *context)
-          * IBus uses button-press-event instead until GTK is fixed.
-          * https://gitlab.gnome.org/GNOME/gtk/issues/1534
-          */
--        if (_use_sync_mode)
-+        if (_use_sync_mode == 1)
-             ibus_im_context_clear_preedit_text (ibusimcontext);
-         ibus_input_context_reset (ibusimcontext->ibuscontext);
-     }
-@@ -1361,7 +1443,7 @@ ibus_im_context_set_client_window (GtkIMContext *context,
- 
-     if (ibusimcontext->client_window) {
- #if !GTK_CHECK_VERSION (3, 98, 4)
--        if (ibusimcontext->use_button_press_event && !_use_sync_mode)
-+        if (ibusimcontext->use_button_press_event && _use_sync_mode != 1)
-             _connect_button_press_event (ibusimcontext, FALSE);
- #endif
-         g_object_unref (ibusimcontext->client_window);
-@@ -1371,7 +1453,7 @@ ibus_im_context_set_client_window (GtkIMContext *context,
-     if (client != NULL) {
-         ibusimcontext->client_window = g_object_ref (client);
- #if !GTK_CHECK_VERSION (3, 98, 4)
--        if (!ibusimcontext->use_button_press_event && !_use_sync_mode)
-+        if (!ibusimcontext->use_button_press_event && _use_sync_mode != 1)
-             _connect_button_press_event (ibusimcontext, TRUE);
- #endif
-     }
-@@ -1993,7 +2075,7 @@ _ibus_context_update_preedit_text_cb (IBusInputContext  *ibuscontext,
- #if !GTK_CHECK_VERSION (3, 98, 4)
-     if (!ibusimcontext->use_button_press_event &&
-         mode == IBUS_ENGINE_PREEDIT_COMMIT &&
--        !_use_sync_mode) {
-+        _use_sync_mode != 1) {
-         if (ibusimcontext->client_window) {
-             _connect_button_press_event (ibusimcontext, TRUE);
-         }
-@@ -2200,6 +2282,8 @@ _create_input_context_done (IBusBus       *bus,
- static void
- _create_input_context (IBusIMContext *ibusimcontext)
- {
-+    gchar *prgname = g_strdup (g_get_prgname());
-+    gchar *client_name;
-     IDEBUG ("%s", __FUNCTION__);
- 
-     g_assert (ibusimcontext->ibuscontext == NULL);
-@@ -2208,11 +2292,24 @@ _create_input_context (IBusIMContext *ibusimcontext)
- 
-     ibusimcontext->cancellable = g_cancellable_new ();
- 
-+    if (!prgname)
-+        prgname = g_strdup_printf ("(%d)", getpid ());
-+    client_name = g_strdup_printf ("%s:%s",
-+#if GTK_CHECK_VERSION (3, 98, 4)
-+                                   "gtk4-im",
-+#elif GTK_CHECK_VERSION (2, 91, 0)
-+                                   "gtk3-im",
-+#else
-+                                   "gtk-im",
-+#endif
-+                                   prgname);
-+    g_free (prgname);
-     ibus_bus_create_input_context_async (_bus,
--            "gtk-im", -1,
-+            client_name, -1,
-             ibusimcontext->cancellable,
-             (GAsyncReadyCallback)_create_input_context_done,
-             g_object_ref (ibusimcontext));
-+    g_free (client_name);
- }
- 
- /* Callback functions for slave context */
-@@ -2329,6 +2426,8 @@ _create_fake_input_context_done (IBusBus       *bus,
-                       NULL);
- 
-     guint32 caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS | IBUS_CAP_SURROUNDING_TEXT;
-+    if (_use_sync_mode != 1)
-+        caps |= IBUS_CAP_SYNC_PROCESS_KEY;
-     ibus_input_context_set_capabilities (_fake_context, caps);
- 
-     /* focus in/out the fake context */
-diff --git a/src/ibustypes.h b/src/ibustypes.h
-index 60bcb92b..a8eee319 100644
---- a/src/ibustypes.h
-+++ b/src/ibustypes.h
-@@ -109,6 +109,9 @@ typedef enum
-  * @IBUS_CAP_SURROUNDING_TEXT: Client can provide surround text,
-  *  or IME can handle surround text.
-  * @IBUS_CAP_OSK: UI is owned by on-screen keyboard.
-+ * @IBUS_CAP_SYNC_PROCESS_KEY: Asynchronous process key events are not
-+ *  supported and the ibus_engine_forward_key_event() should not be
-+ *  used for the return value of #IBusEngine::process_key_event().
-  *
-  * Capability flags of UI.
-  */
-@@ -120,6 +123,7 @@ typedef enum {
-     IBUS_CAP_PROPERTY           = 1 << 4,
-     IBUS_CAP_SURROUNDING_TEXT   = 1 << 5,
-     IBUS_CAP_OSK                = 1 << 6,
-+    IBUS_CAP_SYNC_PROCESS_KEY   = 1 << 7,
- } IBusCapabilite;
- 
- /**
--- 
-2.35.3
-
-From b14cab3753c6510a0a48eec673aa6eac89c793a1 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Thu, 7 Jul 2022 08:22:45 +0900
-Subject: [PATCH] src/ibusengine: Add focus_in_id()/focus_out_id() class
- methods
-
-IBusEngine constructor now has a 'has-focus-id' property and if it's %TRUE,
-IBusEngine::focus_in_id()/focus_out_id() are called instaed of
-IBusEngine::focus_in()/focus_out() and the class method has an object_path
-argument for the unique input context ID and a client argument for
-the client application type likes ibus-gtk, ibus-gtk4, xim.
----
- bus/engineproxy.c       | 304 +++++++++++++++++++++++++++++-----------
- bus/engineproxy.h       |  12 +-
- bus/ibusimpl.c          |  13 ++
- bus/ibusimpl.h          |  13 +-
- bus/inputcontext.c      |  50 +++++--
- src/ibusengine.c        | 217 ++++++++++++++++++++++++++--
- src/ibusengine.h        |  10 +-
- src/ibusmarshalers.list |   1 +
- 8 files changed, 505 insertions(+), 115 deletions(-)
-
-diff --git a/bus/engineproxy.c b/bus/engineproxy.c
-index 2d98995c..fd1f34fb 100644
---- a/bus/engineproxy.c
-+++ b/bus/engineproxy.c
-@@ -2,7 +2,7 @@
- /* vim:set et sts=4: */
- /* ibus - The Input Bus
-  * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2015-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2015-2022 Takao Fujiwara <takao.fujiwara1@gmail.com>
-  * Copyright (C) 2008-2016 Red Hat, Inc.
-  *
-  * This library is free software; you can redistribute it and/or
-@@ -59,6 +59,7 @@ struct _BusEngineProxy {
- 
-     /* cached properties */
-     IBusPropList *prop_list;
-+    gboolean has_focus_id;
- };
- 
- struct _BusEngineProxyClass {
-@@ -105,30 +106,35 @@ static IBusText *text_empty = NULL;
- static IBusPropList *prop_list_empty = NULL;
- 
- /* functions prototype */
--static void     bus_engine_proxy_set_property   (BusEngineProxy      *engine,
--                                                 guint                prop_id,
--                                                 const GValue        *value,
--                                                 GParamSpec          *pspec);
--static void     bus_engine_proxy_get_property   (BusEngineProxy      *engine,
--                                                 guint                prop_id,
--                                                 GValue              *value,
--                                                 GParamSpec          *pspec);
-+static void     bus_engine_proxy_set_property   (BusEngineProxy    *engine,
-+                                                 guint              prop_id,
-+                                                 const GValue      *value,
-+                                                 GParamSpec        *pspec);
-+static void     bus_engine_proxy_get_property   (BusEngineProxy    *engine,
-+                                                 guint              prop_id,
-+                                                 GValue            *value,
-+                                                 GParamSpec        *pspec);
- static void     bus_engine_proxy_real_register_properties
--                                                (BusEngineProxy      *engine,
--                                                 IBusPropList        *prop_list);
-+                                                (BusEngineProxy    *engine,
-+                                                 IBusPropList      *prop_list);
- static void     bus_engine_proxy_real_update_property
--                                                (BusEngineProxy      *engine,
--                                                 IBusProperty        *prop);
--static void     bus_engine_proxy_real_destroy   (IBusProxy           *proxy);
--static void     bus_engine_proxy_g_signal       (GDBusProxy          *proxy,
--                                                 const gchar         *sender_name,
--                                                 const gchar         *signal_name,
--                                                 GVariant            *parameters);
-+                                                (BusEngineProxy    *engine,
-+                                                 IBusProperty      *prop);
-+static void     bus_engine_proxy_real_destroy   (IBusProxy         *proxy);
-+static void     bus_engine_proxy_g_signal       (GDBusProxy        *proxy,
-+                                                 const gchar       *sender_name,
-+                                                 const gchar       *signal_name,
-+                                                 GVariant          *parameters);
- static void     bus_engine_proxy_initable_iface_init
--                                                (GInitableIface      *initable_iface);
-+                                                (GInitableIface
-+                                                               *initable_iface);
-+static void     bus_engine_proxy_get_has_focus_id
-+                                                (BusEngineProxy    *engine);
- 
- G_DEFINE_TYPE_WITH_CODE (BusEngineProxy, bus_engine_proxy, IBUS_TYPE_PROXY,
--                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, bus_engine_proxy_initable_iface_init)
-+                         G_IMPLEMENT_INTERFACE (
-+                                 G_TYPE_INITABLE,
-+                                 bus_engine_proxy_initable_iface_init)
-                         );
- 
- static GInitableIface *parent_initable_iface = NULL;
-@@ -138,8 +144,10 @@ bus_engine_proxy_class_init (BusEngineProxyClass *class)
- {
-     GObjectClass *gobject_class = G_OBJECT_CLASS (class);
- 
--    gobject_class->set_property = (GObjectSetPropertyFunc)bus_engine_proxy_set_property;
--    gobject_class->get_property = (GObjectGetPropertyFunc)bus_engine_proxy_get_property;
-+    gobject_class->set_property =
-+            (GObjectSetPropertyFunc)bus_engine_proxy_set_property;
-+    gobject_class->get_property =
-+            (GObjectGetPropertyFunc)bus_engine_proxy_get_property;
- 
-     class->register_properties = bus_engine_proxy_real_register_properties;
-     class->update_property = bus_engine_proxy_real_update_property;
-@@ -147,8 +155,9 @@ bus_engine_proxy_class_init (BusEngineProxyClass *class)
-     IBUS_PROXY_CLASS (class)->destroy = bus_engine_proxy_real_destroy;
-     G_DBUS_PROXY_CLASS (class)->g_signal = bus_engine_proxy_g_signal;
- 
--    parent_initable_iface =
--            (GInitableIface *)g_type_interface_peek (bus_engine_proxy_parent_class, G_TYPE_INITABLE);
-+    parent_initable_iface = (GInitableIface *)g_type_interface_peek (
-+            bus_engine_proxy_parent_class,
-+            G_TYPE_INITABLE);
- 
-     /* install properties */
-     g_object_class_install_property (gobject_class,
-@@ -164,7 +173,9 @@ bus_engine_proxy_class_init (BusEngineProxyClass *class)
-                         G_PARAM_STATIC_NICK
-                         ));
- 
--    /* install glib signals that will be sent when corresponding D-Bus signals are sent from an engine process. */
-+    /* install glib signals that will be sent when corresponding D-Bus signals
-+     * are sent from an engine process.
-+     */
-     engine_signals[COMMIT_TEXT] =
-         g_signal_new (I_("commit-text"),
-             G_TYPE_FROM_CLASS (class),
-@@ -473,7 +484,8 @@ bus_engine_proxy_real_destroy (IBusProxy *proxy)
-         engine->prop_list = NULL;
-     }
- 
--    IBUS_PROXY_CLASS (bus_engine_proxy_parent_class)->destroy ((IBusProxy *)engine);
-+    IBUS_PROXY_CLASS (bus_engine_proxy_parent_class)->destroy (
-+            (IBusProxy *)engine);
- }
- 
- static void
-@@ -486,7 +498,8 @@ _g_object_unref_if_floating (gpointer instance)
- /**
-  * bus_engine_proxy_g_signal:
-  *
-- * Handle all D-Bus signals from the engine process. This function emits corresponding glib signal for the D-Bus signal.
-+ * Handle all D-Bus signals from the engine process. This function emits
-+ * corresponding glib signal for the D-Bus signal.
-  */
- static void
- bus_engine_proxy_g_signal (GDBusProxy  *proxy,
-@@ -522,7 +535,9 @@ bus_engine_proxy_g_signal (GDBusProxy  *proxy,
-         }
-     }
- 
--    /* Handle D-Bus signals with parameters. Deserialize them and emit a glib signal. */
-+    /* Handle D-Bus signals with parameters. Deserialize them and emit a glib
-+     * signal.
-+     */
-     if (g_strcmp0 (signal_name, "CommitText") == 0) {
-         GVariant *arg0 = NULL;
-         g_variant_get (parameters, "(v)", &arg0);
-@@ -568,7 +583,8 @@ bus_engine_proxy_g_signal (GDBusProxy  *proxy,
-         gboolean visible = FALSE;
-         guint mode = 0;
- 
--        g_variant_get (parameters, "(vubu)", &arg0, &cursor_pos, &visible, &mode);
-+        g_variant_get (parameters, "(vubu)",
-+                       &arg0, &cursor_pos, &visible, &mode);
-         g_return_if_fail (arg0 != NULL);
- 
-         IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (arg0));
-@@ -594,7 +610,11 @@ bus_engine_proxy_g_signal (GDBusProxy  *proxy,
-         g_variant_unref (arg0);
-         g_return_if_fail (text != NULL);
- 
--        g_signal_emit (engine, engine_signals[UPDATE_AUXILIARY_TEXT], 0, text, visible);
-+        g_signal_emit (engine,
-+                       engine_signals[UPDATE_AUXILIARY_TEXT],
-+                       0,
-+                       text,
-+                       visible);
-         _g_object_unref_if_floating (text);
-         return;
-     }
-@@ -606,11 +626,16 @@ bus_engine_proxy_g_signal (GDBusProxy  *proxy,
-         g_variant_get (parameters, "(vb)", &arg0, &visible);
-         g_return_if_fail (arg0 != NULL);
- 
--        IBusLookupTable *table = IBUS_LOOKUP_TABLE (ibus_serializable_deserialize (arg0));
-+        IBusLookupTable *table =
-+                IBUS_LOOKUP_TABLE (ibus_serializable_deserialize (arg0));
-         g_variant_unref (arg0);
-         g_return_if_fail (table != NULL);
- 
--        g_signal_emit (engine, engine_signals[UPDATE_LOOKUP_TABLE], 0, table, visible);
-+        g_signal_emit (engine,
-+                       engine_signals[UPDATE_LOOKUP_TABLE],
-+                       0,
-+                       table,
-+                       visible);
-         _g_object_unref_if_floating (table);
-         return;
-     }
-@@ -620,11 +645,15 @@ bus_engine_proxy_g_signal (GDBusProxy  *proxy,
-         g_variant_get (parameters, "(v)", &arg0);
-         g_return_if_fail (arg0 != NULL);
- 
--        IBusPropList *prop_list = IBUS_PROP_LIST (ibus_serializable_deserialize (arg0));
-+        IBusPropList *prop_list =
-+                IBUS_PROP_LIST (ibus_serializable_deserialize (arg0));
-         g_variant_unref (arg0);
-         g_return_if_fail (prop_list != NULL);
- 
--        g_signal_emit (engine, engine_signals[REGISTER_PROPERTIES], 0, prop_list);
-+        g_signal_emit (engine,
-+                       engine_signals[REGISTER_PROPERTIES],
-+                       0,
-+                       prop_list);
-         _g_object_unref_if_floating (prop_list);
-         return;
-     }
-@@ -634,7 +663,8 @@ bus_engine_proxy_g_signal (GDBusProxy  *proxy,
-         g_variant_get (parameters, "(v)", &arg0);
-         g_return_if_fail (arg0 != NULL);
- 
--        IBusProperty *prop = IBUS_PROPERTY (ibus_serializable_deserialize (arg0));
-+        IBusProperty *prop =
-+                IBUS_PROPERTY (ibus_serializable_deserialize (arg0));
-         g_variant_unref (arg0);
-         g_return_if_fail (prop != NULL);
- 
-@@ -665,26 +695,45 @@ bus_engine_proxy_new_internal (const gchar     *path,
-                                IBusEngineDesc  *desc,
-                                GDBusConnection *connection)
- {
-+    GDBusProxyFlags flags;
-+    BusEngineProxy *engine;
-+    BusIBusImpl *ibus = BUS_DEFAULT_IBUS;
-+    GHashTable *hash_table = NULL;
-+    EngineFocusCategory category = ENGINE_FOCUS_CATEGORY_NONE;
-+
-     g_assert (path);
-     g_assert (IBUS_IS_ENGINE_DESC (desc));
-     g_assert (G_IS_DBUS_CONNECTION (connection));
- 
--    GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START;
--    BusEngineProxy *engine =
--        (BusEngineProxy *) g_initable_new (BUS_TYPE_ENGINE_PROXY,
--                                           NULL,
--                                           NULL,
--                                           "desc",              desc,
--                                           "g-connection",      connection,
--                                           "g-interface-name",  IBUS_INTERFACE_ENGINE,
--                                           "g-object-path",     path,
--                                           "g-default-timeout", g_gdbus_timeout,
--                                           "g-flags",           flags,
--                                           NULL);
-+    flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START;
-+    engine = (BusEngineProxy *) g_initable_new (
-+            BUS_TYPE_ENGINE_PROXY,
-+            NULL,
-+            NULL,
-+            "desc",              desc,
-+            "g-connection",      connection,
-+            "g-interface-name",  IBUS_INTERFACE_ENGINE,
-+            "g-object-path",     path,
-+            "g-default-timeout", g_gdbus_timeout,
-+            "g-flags",           flags,
-+            NULL);
-     const gchar *layout = ibus_engine_desc_get_layout (desc);
-     if (layout != NULL && layout[0] != '\0') {
-         engine->keymap = ibus_keymap_get (layout);
-     }
-+    if (ibus)
-+        hash_table = bus_ibus_impl_get_engine_focus_id_table (ibus);
-+    if (hash_table) {
-+        category = (EngineFocusCategory)GPOINTER_TO_INT (
-+                g_hash_table_lookup (hash_table,
-+                                     ibus_engine_desc_get_name (desc)));
-+        if (category == ENGINE_FOCUS_CATEGORY_HAS_ID)
-+            engine->has_focus_id = TRUE;
-+        else if (category == ENGINE_FOCUS_CATEGORY_NO_ID)
-+            engine->has_focus_id = FALSE;
-+        else
-+            bus_engine_proxy_get_has_focus_id (engine);
-+    }
-     return engine;
- }
- 
-@@ -740,7 +789,8 @@ engine_proxy_new_data_free (EngineProxyNewData *data)
- /**
-  * create_engine_ready_cb:
-  *
-- * A callback function to be called when bus_factory_proxy_create_engine finishes.
-+ * A callback function to be called when bus_factory_proxy_create_engine
-+ * finishes.
-  * Create an BusEngineProxy object and call the GAsyncReadyCallback.
-  */
- static void
-@@ -775,8 +825,10 @@ create_engine_ready_cb (BusFactoryProxy    *factory,
- /**
-  * notify_factory_cb:
-  *
-- * A callback function to be called when bus_component_start() emits "notify::factory" signal within 5 seconds.
-- * Call bus_factory_proxy_create_engine to create the engine proxy asynchronously.
-+ * A callback function to be called when bus_component_start() emits
-+ * "notify::factory" signal within 5 seconds.
-+ * Call bus_factory_proxy_create_engine to create the engine proxy
-+ * asynchronously.
-  */
- static void
- notify_factory_cb (BusComponent       *component,
-@@ -798,22 +850,25 @@ notify_factory_cb (BusComponent       *component,
-             data->handler_id = 0;
-         }
- 
--        /* We *have to* disconnect the cancelled_cb here, since g_dbus_proxy_call
--         * calls create_engine_ready_cb even if the proxy call is cancelled, and
--         * in this case, create_engine_ready_cb itself will return error using
--         * g_task_return_error(). */
-+        /* We *have to* disconnect the cancelled_cb here, since
-+         * g_dbus_proxy_call calls create_engine_ready_cb even if the proxy
-+         * call is cancelled, and in this case, create_engine_ready_cb itself
-+         * will return error using g_task_return_error().
-+         */
-         if (data->cancellable && data->cancelled_handler_id != 0) {
--            g_cancellable_disconnect (data->cancellable, data->cancelled_handler_id);
-+            g_cancellable_disconnect (data->cancellable, 
-+                                      data->cancelled_handler_id);
-             data->cancelled_handler_id = 0;
-         }
- 
-         /* Create engine from factory. */
--        bus_factory_proxy_create_engine (data->factory,
--                                         data->desc,
--                                         data->timeout,
--                                         data->cancellable,
--                                         (GAsyncReadyCallback) create_engine_ready_cb,
--                                         data);
-+        bus_factory_proxy_create_engine (
-+                data->factory,
-+                data->desc,
-+                data->timeout,
-+                data->cancellable,
-+                (GAsyncReadyCallback) create_engine_ready_cb,
-+                data);
-     }
-     /* If factory is NULL, we will continue wait for
-      * factory notify signal or timeout */
-@@ -822,7 +877,8 @@ notify_factory_cb (BusComponent       *component,
- /**
-  * timeout_cb:
-  *
-- * A callback function to be called when bus_component_start() does not emit "notify::factory" signal within 5 seconds.
-+ * A callback function to be called when bus_component_start() does not emit
-+ * "notify::factory" signal within 5 seconds.
-  * Call the GAsyncReadyCallback and stop the 5 sec timer.
-  */
- static gboolean
-@@ -927,16 +983,18 @@ bus_engine_proxy_new (IBusEngineDesc      *desc,
-         /* The factory is ready. We'll create the engine proxy directly. */
-         g_object_ref (data->factory);
- 
--        /* We don't have to connect to cancelled_cb here, since g_dbus_proxy_call
--         * calls create_engine_ready_cb even if the proxy call is cancelled, and
--         * in this case, create_engine_ready_cb itself can return error using
--         * g_task_return_error(). */
--        bus_factory_proxy_create_engine (data->factory,
--                                         data->desc,
--                                         timeout,
--                                         cancellable,
--                                         (GAsyncReadyCallback) create_engine_ready_cb,
--                                         data);
-+        /* We don't have to connect to cancelled_cb here, since
-+         * g_dbus_proxy_call calls create_engine_ready_cb even if the proxy
-+         * call is cancelled, and in this case, create_engine_ready_cb itself
-+         * can return error using g_task_return_error().
-+         */
-+        bus_factory_proxy_create_engine (
-+                data->factory,
-+                data->desc,
-+                timeout,
-+                cancellable,
-+                (GAsyncReadyCallback) create_engine_ready_cb,
-+                data);
-     }
- }
- 
-@@ -978,8 +1036,11 @@ bus_engine_proxy_process_key_event (BusEngineProxy      *engine,
- {
-     g_assert (BUS_IS_ENGINE_PROXY (engine));
- 
--    if (keycode != 0 && bus_ibus_impl_is_use_sys_layout (BUS_DEFAULT_IBUS) == FALSE) {
--        /* Since use_sys_layout is false, we don't rely on XKB. Try to convert keyval from keycode by using our own mapping. */
-+    if (keycode != 0 &&
-+        bus_ibus_impl_is_use_sys_layout (BUS_DEFAULT_IBUS) == FALSE) {
-+        /* Since use_sys_layout is false, we don't rely on XKB. Try to convert
-+         * keyval from keycode by using our own mapping.
-+         */
-         IBusKeymap *keymap = engine->keymap;
-         if (keymap == NULL)
-             keymap = BUS_DEFAULT_KEYMAP;
-@@ -1142,7 +1203,8 @@ void bus_engine_proxy_set_surrounding_text (BusEngineProxy *engine,
-         g_strcmp0 (text->text, engine->surrounding_text->text) != 0 ||
-         cursor_pos != engine->surrounding_cursor_pos ||
-         anchor_pos != engine->selection_anchor_pos) {
--        GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)text);
-+        GVariant *variant =
-+                ibus_serializable_serialize ((IBusSerializable *)text);
-         if (engine->surrounding_text)
-             g_object_unref (engine->surrounding_text);
-         engine->surrounding_text = (IBusText *) g_object_ref_sink (text);
-@@ -1201,6 +1263,61 @@ bus_engine_proxy_set_content_type (BusEngineProxy *engine,
-     g_variant_unref (content_type);
- }
- 
-+static void
-+_get_has_focus_id_cb (GObject        *object,
-+                      GAsyncResult   *res,
-+                      gpointer        user_data)
-+{
-+    GHashTable *hash_table = (GHashTable*)user_data;
-+    BusEngineProxy *engine;
-+    GError *error = NULL;
-+    GVariant *result;
-+
-+    g_return_if_fail (BUS_IS_ENGINE_PROXY (object));
-+    engine = BUS_ENGINE_PROXY (object);
-+    result = g_dbus_proxy_call_finish (G_DBUS_PROXY (object), res, &error);
-+
-+    if (result != NULL) {
-+        GVariant *variant = NULL;
-+        gpointer value;
-+        g_variant_get (result, "(v)", &variant);
-+        engine->has_focus_id = g_variant_get_boolean (variant);
-+        g_variant_unref (variant);
-+        g_variant_unref (result);
-+        value =  GINT_TO_POINTER (engine->has_focus_id
-+                                  ? ENGINE_FOCUS_CATEGORY_HAS_ID
-+                                  : ENGINE_FOCUS_CATEGORY_NO_ID);
-+        g_hash_table_replace (
-+            hash_table,
-+            (gpointer)ibus_engine_desc_get_name (engine->desc),
-+            value);
-+    }
-+    g_hash_table_unref (hash_table);
-+}
-+
-+static void
-+bus_engine_proxy_get_has_focus_id (BusEngineProxy *engine)
-+{
-+    BusIBusImpl *ibus = BUS_DEFAULT_IBUS;
-+    GHashTable *hash_table;
-+
-+    g_assert (BUS_IS_ENGINE_PROXY (engine));
-+    g_assert (ibus);
-+
-+    hash_table = bus_ibus_impl_get_engine_focus_id_table (ibus);
-+    g_assert (hash_table);
-+    g_dbus_proxy_call ((GDBusProxy *) engine,
-+                       "org.freedesktop.DBus.Properties.Get",
-+                       g_variant_new ("(ss)",
-+                                      IBUS_INTERFACE_ENGINE,
-+                                      "FocusId"),
-+                       G_DBUS_CALL_FLAGS_NONE,
-+                       -1,
-+                       NULL,
-+                       _get_has_focus_id_cb,
-+                       g_hash_table_ref (hash_table));
-+}
-+
- /* a macro to generate a function to call a nullary D-Bus method. */
- #define DEFINE_FUNCTION(Name, name)                         \
-     void                                                    \
-@@ -1223,11 +1340,24 @@ DEFINE_FUNCTION (CursorDown, cursor_down)
- #undef DEFINE_FUNCTION
- 
- void
--bus_engine_proxy_focus_in (BusEngineProxy *engine)
-+bus_engine_proxy_focus_in (BusEngineProxy *engine,
-+                           const gchar    *object_path,
-+                           const gchar    *client)
- {
-     g_assert (BUS_IS_ENGINE_PROXY (engine));
--    if (!engine->has_focus) {
--        engine->has_focus = TRUE;
-+    if (engine->has_focus)
-+        return;
-+    engine->has_focus = TRUE;
-+    if (engine->has_focus_id) {
-+        g_dbus_proxy_call ((GDBusProxy *)engine,
-+                           "FocusInId",
-+                           g_variant_new ("(ss)", object_path, client),
-+                           G_DBUS_CALL_FLAGS_NONE,
-+                           -1,
-+                           NULL,
-+                           NULL,
-+                           NULL);
-+    } else {
-         g_dbus_proxy_call ((GDBusProxy *)engine,
-                            "FocusIn",
-                            NULL,
-@@ -1240,11 +1370,23 @@ bus_engine_proxy_focus_in (BusEngineProxy *engine)
- }
- 
- void
--bus_engine_proxy_focus_out (BusEngineProxy *engine)
-+bus_engine_proxy_focus_out (BusEngineProxy *engine,
-+                            const gchar    *object_path)
- {
-     g_assert (BUS_IS_ENGINE_PROXY (engine));
--    if (engine->has_focus) {
--        engine->has_focus = FALSE;
-+    if (!engine->has_focus)
-+        return;
-+    engine->has_focus = FALSE;
-+    if (engine->has_focus_id) {
-+        g_dbus_proxy_call ((GDBusProxy *)engine,
-+                           "FocusOutId",
-+                           g_variant_new ("(s)", object_path),
-+                           G_DBUS_CALL_FLAGS_NONE,
-+                           -1,
-+                           NULL,
-+                           NULL,
-+                           NULL);
-+    } else {
-         g_dbus_proxy_call ((GDBusProxy *)engine,
-                            "FocusOut",
-                            NULL,
-diff --git a/bus/engineproxy.h b/bus/engineproxy.h
-index a3006b47..957b7851 100644
---- a/bus/engineproxy.h
-+++ b/bus/engineproxy.h
-@@ -2,7 +2,7 @@
- /* vim:set et sts=4: */
- /* ibus - The Input Bus
-  * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2018 Takao Fujiwara <takao.fujiwara@gmail.com>
-+ * Copyright (C) 2018-2022 Takao Fujiwara <takao.fujiwara@gmail.com>
-  * Copyright (C) 2008-2018 Red Hat, Inc.
-  *
-  * This library is free software; you can redistribute it and/or
-@@ -126,20 +126,26 @@ void            bus_engine_proxy_set_cursor_location
- /**
-  * bus_engine_proxy_focus_in:
-  * @engine: A #BusEngineProxy.
-+ * @object_path: An object path.
-+ * @client: A client name.
-  *
-  * Call "FocusIn" method of an engine asynchronously. Do nothing if
-  * the engine already has a focus.
-  */
--void            bus_engine_proxy_focus_in    (BusEngineProxy     *engine);
-+void            bus_engine_proxy_focus_in    (BusEngineProxy     *engine,
-+                                              const gchar        *object_path,
-+                                              const gchar        *client);
- 
- /**
-  * bus_engine_proxy_focus_out:
-  * @engine: A #BusEngineProxy.
-+ * @object_path: An object path.
-  *
-  * Call "FocusOut" method of an engine asynchronously. Do nothing if
-  * the engine does not have a focus.
-  */
--void            bus_engine_proxy_focus_out   (BusEngineProxy     *engine);
-+void            bus_engine_proxy_focus_out   (BusEngineProxy     *engine,
-+                                              const gchar        *object_path);
- 
- /**
-  * bus_engine_proxy_reset:
-diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c
-index 49a138fe..8a443545 100644
---- a/bus/ibusimpl.c
-+++ b/bus/ibusimpl.c
-@@ -72,6 +72,8 @@ struct _BusIBusImpl {
-      * IBusEngineDesc object. */
-     GHashTable *engine_table;
- 
-+    GHashTable *engine_focus_id_table;
-+
-     BusInputContext *focused_context;
-     BusPanelProxy   *panel;
-     BusPanelProxy   *emoji_extension;
-@@ -596,6 +598,7 @@ bus_ibus_impl_init (BusIBusImpl *ibus)
-     ibus->use_global_engine = TRUE;
-     ibus->global_engine_name = NULL;
-     ibus->global_previous_engine_name = NULL;
-+    ibus->engine_focus_id_table = g_hash_table_new (g_str_hash, g_str_equal);
- 
-     /* focus the fake_context, if use_global_engine is enabled. */
-     if (ibus->use_global_engine)
-@@ -2384,3 +2387,13 @@ bus_ibus_impl_get_focused_input_context (BusIBusImpl *ibus)
- 
-     return ibus->focused_context;
- }
-+
-+GHashTable *
-+bus_ibus_impl_get_engine_focus_id_table (BusIBusImpl *ibus)
-+{
-+
-+    g_assert (BUS_IS_IBUS_IMPL (ibus));
-+
-+    return ibus->engine_focus_id_table;
-+}
-+
-diff --git a/bus/ibusimpl.h b/bus/ibusimpl.h
-index 0bb18daf..cbe6856d 100644
---- a/bus/ibusimpl.h
-+++ b/bus/ibusimpl.h
-@@ -2,7 +2,8 @@
- /* vim:set et sts=4: */
- /* bus - The Input Bus
-  * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2008-2013 Red Hat, Inc.
-+ * Copyright (C) 2022 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2008-2022 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
-@@ -58,6 +59,13 @@ G_BEGIN_DECLS
- typedef struct _BusIBusImpl BusIBusImpl;
- typedef struct _BusIBusImplClass BusIBusImplClass;
- 
-+typedef enum
-+{
-+    ENGINE_FOCUS_CATEGORY_NONE = 0,
-+    ENGINE_FOCUS_CATEGORY_NO_ID,
-+    ENGINE_FOCUS_CATEGORY_HAS_ID
-+} EngineFocusCategory;
-+
- GType            bus_ibus_impl_get_type             (void);
- 
- /**
-@@ -81,6 +89,7 @@ gboolean         bus_ibus_impl_is_embed_preedit_text
-                                                     (BusIBusImpl        *ibus);
- BusInputContext *bus_ibus_impl_get_focused_input_context
-                                                     (BusIBusImpl        *ibus);
--
-+GHashTable      *bus_ibus_impl_get_engine_focus_id_table
-+                                                    (BusIBusImpl        *ibus);
- G_END_DECLS
- #endif
-diff --git a/bus/inputcontext.c b/bus/inputcontext.c
-index 8d84fd05..72041ecb 100644
---- a/bus/inputcontext.c
-+++ b/bus/inputcontext.c
-@@ -846,7 +846,8 @@ _ic_process_key_event_reply_cb (GObject               *source,
- /**
-  * _ic_process_key_event:
-  *
-- * Implement the "ProcessKeyEvent" method call of the org.freedesktop.IBus.InputContext interface.
-+ * Implement the "ProcessKeyEvent" method call of the
-+ * org.freedesktop.IBus.InputContext interface.
-  */
- static void
- _ic_process_key_event  (BusInputContext       *context,
-@@ -860,11 +861,13 @@ _ic_process_key_event  (BusInputContext       *context,
-     g_variant_get (parameters, "(uuu)", &keyval, &keycode, &modifiers);
-     if (G_UNLIKELY (!context->has_focus)) {
-         /* workaround: set focus if context does not have focus */
--        BusInputContext *focused_context = bus_ibus_impl_get_focused_input_context (BUS_DEFAULT_IBUS);
-+        BusInputContext *focused_context =
-+                bus_ibus_impl_get_focused_input_context (BUS_DEFAULT_IBUS);
-         if (focused_context == NULL ||
-             focused_context->fake == TRUE ||
-             context->fake == FALSE) {
--            /* grab focus, if context is a real IC or current focused IC is fake */
-+            /* grab focus, if context is a real IC or current focused IC is
-+             * fake */
-             bus_input_context_focus_in (context);
-         }
-     }
-@@ -914,7 +917,8 @@ _ic_process_key_event  (BusInputContext       *context,
-                                             data);
-     }
-     else {
--        g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", FALSE));
-+        g_dbus_method_invocation_return_value (invocation,
-+                                               g_variant_new ("(b)", FALSE));
-     }
- }
- 
-@@ -1438,7 +1442,9 @@ bus_input_context_focus_in (BusInputContext *context)
-     context->prev_modifiers = 0;
- 
-     if (context->engine) {
--        bus_engine_proxy_focus_in (context->engine);
-+        const gchar *path =
-+                ibus_service_get_object_path ((IBusService *)context);
-+        bus_engine_proxy_focus_in (context->engine, path, context->client);
-         bus_engine_proxy_enable (context->engine);
-         bus_engine_proxy_set_capabilities (context->engine, context->capabilities);
-         bus_engine_proxy_set_cursor_location (context->engine, context->x, context->y, context->w, context->h);
-@@ -1538,7 +1544,9 @@ bus_input_context_focus_out (BusInputContext *context)
-     bus_input_context_register_properties (context, props_empty);
- 
-     if (context->engine) {
--        bus_engine_proxy_focus_out (context->engine);
-+        const gchar *path =
-+            ibus_service_get_object_path ((IBusService *)context);
-+        bus_engine_proxy_focus_out (context->engine, path);
-     }
- 
-     context->has_focus = FALSE;
-@@ -2376,11 +2384,19 @@ bus_input_context_enable (BusInputContext *context)
-     if (context->engine == NULL)
-         return;
- 
--    bus_engine_proxy_focus_in (context->engine);
--    bus_engine_proxy_enable (context->engine);
--    bus_engine_proxy_set_capabilities (context->engine, context->capabilities);
--    bus_engine_proxy_set_cursor_location (context->engine, context->x, context->y, context->w, context->h);
--    bus_engine_proxy_set_content_type (context->engine, context->purpose, context->hints);
-+    {
-+        const gchar *path =
-+                ibus_service_get_object_path ((IBusService *)context);
-+        bus_engine_proxy_focus_in (context->engine, path, context->client);
-+        bus_engine_proxy_enable (context->engine);
-+        bus_engine_proxy_set_capabilities (context->engine,
-+                                           context->capabilities);
-+        bus_engine_proxy_set_cursor_location (context->engine,
-+                                              context->x, context->y,
-+                                              context->w, context->h);
-+        bus_engine_proxy_set_content_type (context->engine,
-+                                           context->purpose, context->hints);
-+    }
- }
- 
- void
-@@ -2397,7 +2413,9 @@ bus_input_context_disable (BusInputContext *context)
-     bus_input_context_register_properties (context, props_empty);
- 
-     if (context->engine) {
--        bus_engine_proxy_focus_out (context->engine);
-+        const gchar *path =
-+            ibus_service_get_object_path ((IBusService *)context);
-+        bus_engine_proxy_focus_out (context->engine, path);
-         bus_engine_proxy_disable (context->engine);
-     }
- }
-@@ -2445,6 +2463,8 @@ bus_input_context_unset_engine (BusInputContext *context)
- 
-     if (context->engine) {
-         gint i;
-+        const gchar *path =
-+            ibus_service_get_object_path ((IBusService *)context);
-         /* uninstall signal handlers for the engine. */
-         for (i = 0; i < G_N_ELEMENTS(engine_signals); i++) {
-             g_signal_handlers_disconnect_by_func (context->engine,
-@@ -2453,7 +2473,7 @@ bus_input_context_unset_engine (BusInputContext *context)
-         /* focus out engine so that the next call of
-            bus_engine_proxy_focus_in() will take effect and trigger
-            RegisterProperties. */
--        bus_engine_proxy_focus_out (context->engine);
-+        bus_engine_proxy_focus_out (context->engine, path);
-         g_object_unref (context->engine);
-         context->engine = NULL;
-     }
-@@ -2488,7 +2508,9 @@ bus_input_context_set_engine (BusInputContext *context,
-                               context);
-         }
-         if (context->has_focus) {
--            bus_engine_proxy_focus_in (context->engine);
-+            const gchar *path =
-+                    ibus_service_get_object_path ((IBusService *)context);
-+            bus_engine_proxy_focus_in (context->engine, path, context->client);
-             bus_engine_proxy_enable (context->engine);
-             bus_engine_proxy_set_capabilities (context->engine, context->capabilities);
-             bus_engine_proxy_set_cursor_location (context->engine, context->x, context->y, context->w, context->h);
-diff --git a/src/ibusengine.c b/src/ibusengine.c
-index 7e844838..7c797103 100644
---- a/src/ibusengine.c
-+++ b/src/ibusengine.c
-@@ -2,7 +2,7 @@
- /* vim:set et sts=4: */
- /* ibus - The Input Bus
-  * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2018-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2018-2022 Takao Fujiwara <takao.fujiwara1@gmail.com>
-  * Copyright (C) 2008-2021 Red Hat, Inc.
-  *
-  * This library is free software; you can redistribute it and/or
-@@ -37,7 +37,9 @@
- enum {
-     PROCESS_KEY_EVENT,
-     FOCUS_IN,
-+    FOCUS_IN_ID,
-     FOCUS_OUT,
-+    FOCUS_OUT_ID,
-     RESET,
-     ENABLE,
-     DISABLE,
-@@ -61,6 +63,7 @@ enum {
- enum {
-     PROP_0,
-     PROP_ENGINE_NAME,
-+    PROP_HAS_FOCUS_ID,
- };
- 
- 
-@@ -82,6 +85,7 @@ struct _IBusEnginePrivate {
-     GHashTable            *extension_keybindings;
-     gboolean               enable_extension;
-     gchar                 *current_extension_name;
-+    gboolean               has_focus_id;
- };
- 
- 
-@@ -104,7 +108,8 @@ static void      ibus_engine_service_method_call
-                                                GDBusConnection    *connection,
-                                                const gchar        *sender,
-                                                const gchar        *object_path,
--                                               const gchar        *interface_name,
-+                                               const gchar
-+                                                                *interface_name,
-                                                const gchar        *method_name,
-                                                GVariant           *parameters,
-                                                GDBusMethodInvocation
-@@ -132,7 +137,12 @@ static gboolean  ibus_engine_process_key_event
-                                               guint               keycode,
-                                               guint               state);
- static void      ibus_engine_focus_in        (IBusEngine         *engine);
-+static void      ibus_engine_focus_in_id     (IBusEngine         *engine,
-+                                              const gchar        *object_path,
-+                                              const gchar        *client);
- static void      ibus_engine_focus_out       (IBusEngine         *engine);
-+static void      ibus_engine_focus_out_id    (IBusEngine         *engine,
-+                                              const gchar        *object_path);
- static void      ibus_engine_reset           (IBusEngine         *engine);
- static void      ibus_engine_enable          (IBusEngine         *engine);
- static void      ibus_engine_disable         (IBusEngine         *engine);
-@@ -170,7 +180,8 @@ static void      ibus_engine_set_surrounding_text
- static void      ibus_engine_process_hand_writing_event
-                                              (IBusEngine         *engine,
-                                               const gdouble      *coordinates,
--                                              guint               coordinates_len);
-+                                              guint
-+                                                               coordinates_len);
- static void      ibus_engine_cancel_hand_writing
-                                              (IBusEngine         *engine,
-                                               guint               n_strokes);
-@@ -230,7 +241,15 @@ static const gchar introspection_xml[] =
-     "      <arg direction='in'  type='u' name='state' />"
-     "    </method>"
-     "    <method name='FocusIn' />"
-+    "    <method name='FocusInId'>"
-+    "      <arg direction='in'  type='s' name='object_path' />"
-+    "      <arg direction='in'  type='s' name='client' />"
-+    "    </method>"
-+    "    <method name='FocusIn' />"
-     "    <method name='FocusOut' />"
-+    "    <method name='FocusOutId'>"
-+    "      <arg direction='in'  type='s' name='object_path' />"
-+    "    </method>"
-     "    <method name='Reset' />"
-     "    <method name='Enable' />"
-     "    <method name='Disable' />"
-@@ -283,6 +302,7 @@ static const gchar introspection_xml[] =
-     "    </signal>"
-     /* FIXME properties */
-     "    <property name='ContentType' type='(uu)' access='write' />"
-+    "    <property name='FocusId' type='(b)' access='read' />"
-     "  </interface>"
-     "</node>";
- 
-@@ -324,7 +344,9 @@ ibus_engine_class_init (IBusEngineClass *class)
- 
-     class->process_key_event = ibus_engine_process_key_event;
-     class->focus_in     = ibus_engine_focus_in;
-+    class->focus_in_id  = ibus_engine_focus_in_id;
-     class->focus_out    = ibus_engine_focus_out;
-+    class->focus_out_id = ibus_engine_focus_out_id;
-     class->reset        = ibus_engine_reset;
-     class->enable       = ibus_engine_enable;
-     class->disable      = ibus_engine_disable;
-@@ -360,6 +382,15 @@ ibus_engine_class_init (IBusEngineClass *class)
-                         G_PARAM_CONSTRUCT_ONLY |
-                         G_PARAM_STATIC_STRINGS));
- 
-+    g_object_class_install_property (gobject_class,
-+                    PROP_HAS_FOCUS_ID,
-+                    g_param_spec_boolean ("has-focus-id",
-+                        "has focus id",
-+                        "Has focus ID",
-+                        FALSE,
-+                        G_PARAM_READWRITE |
-+                        G_PARAM_CONSTRUCT_ONLY));
-+
-     /* install signals */
-     /**
-      * IBusEngine::process-key-event:
-@@ -378,7 +409,8 @@ ibus_engine_class_init (IBusEngineClass *class)
-      * Returns: %TRUE for successfully process the key; %FALSE otherwise.
-      * See also:  ibus_input_context_process_key_event().
-      *
--     * <note><para>Argument @user_data is ignored in this function.</para></note>
-+     * <note><para>Argument @user_data is ignored in this function.</para>
-+     * </note>
-      */
-     engine_signals[PROCESS_KEY_EVENT] =
-         g_signal_new (I_("process-key-event"),
-@@ -402,7 +434,8 @@ ibus_engine_class_init (IBusEngineClass *class)
-      * in extended class to receive this signal.
-      *
-      * See also: ibus_input_context_focus_in()
--     * <note><para>Argument @user_data is ignored in this function.</para></note>
-+     * <note><para>Argument @user_data is ignored in this function.</para>
-+     * </note>
-      */
-     engine_signals[FOCUS_IN] =
-         g_signal_new (I_("focus-in"),
-@@ -414,6 +447,58 @@ ibus_engine_class_init (IBusEngineClass *class)
-             G_TYPE_NONE,
-             0);
- 
-+    /**
-+     * IBusEngine::focus-in-id:
-+     * @engine: An IBusEngine.
-+     * @object_path: An object path.
-+     * @client: An client name.
-+     *
-+     * Emitted when the client application get the focus.
-+     * Implement the member function IBusEngineClass::focus_in
-+     * in extended class to receive this signal.
-+     * @object_path is a unique id by input context.
-+     * @client indicates a client type:
-+     * 'fake':    focus is on desktop background or other programs where no
-+     *            input is possible
-+     * 'xim':     old X11 programs like xterm, emacs, ...
-+     *            GTK3 programs in a Gnome Xorg session when GTK_IM_MODULE
-+     *            is unset also use xim
-+     * 'gtk-im:&lt;client-name&gt;':  Gtk2 input module is used
-+     * 'gtk3-im:&lt;client-name&gt;': Gtk3 input module is used
-+     * 'gtk4-im:&lt;client-name&gt;': Gtk4 input module is used
-+     *            In case of the Gtk input modules, the name of the
-+     *            client is also shown after the “:”, for example
-+     *            like 'gtk3-im:firefox', 'gtk4-im:gnome-text-editor', …
-+     * 'gnome-shell': Entries handled by gnome-shell
-+     *                (like the command line dialog opened with Alt+F2
-+     *                or the search field when pressing the Super key.)
-+     *                When GTK_IM_MODULE is unset in a Gnome Wayland session
-+     *                all programs which would show 'gtk3-im' or 'gtk4-im'
-+     *                with GTK_IM_MODULE=ibus then show 'gnome-shell'
-+     *                instead.
-+     * 'Qt':      Qt4 programs like keepassx-2.0.3 …
-+     * 'QIBusInputContext': Qt5 programs like keepassxc-2.7.1, anki-2.1.15
-+     *                      telegram-desktop-3.7.3, 
-+     *
-+     * You need to set #IBusEngine::has-focus-id property to %TRUE when you
-+     * construct an #IBusEngine to use this class method.
-+     *
-+     * See also: ibus_input_context_focus_in()
-+     * <note><para>Argument @user_data is ignored in this function.</para>
-+     * </note>
-+     */
-+    engine_signals[FOCUS_IN_ID] =
-+        g_signal_new (I_("focus-in-id"),
-+            G_TYPE_FROM_CLASS (gobject_class),
-+            G_SIGNAL_RUN_LAST,
-+            G_STRUCT_OFFSET (IBusEngineClass, focus_in_id),
-+            NULL, NULL,
-+            _ibus_marshal_VOID__STRING_STRING,
-+            G_TYPE_NONE,
-+            2,
-+            G_TYPE_STRING,
-+            G_TYPE_STRING);
-+
-     /**
-      * IBusEngine::focus-out:
-      * @engine: An IBusEngine.
-@@ -423,7 +508,8 @@ ibus_engine_class_init (IBusEngineClass *class)
-      * in extended class to receive this signal.
-      *
-      * See also: ibus_input_context_focus_out()
--     * <note><para>Argument @user_data is ignored in this function.</para></note>
-+     * <note><para>Argument @user_data is ignored in this function.</para>
-+     * </note>
-      */
-     engine_signals[FOCUS_OUT] =
-         g_signal_new (I_("focus-out"),
-@@ -435,6 +521,33 @@ ibus_engine_class_init (IBusEngineClass *class)
-             G_TYPE_NONE,
-             0);
- 
-+    /**
-+     * IBusEngine::focus-out-id:
-+     * @engine: An IBusEngine.
-+     * @object_path: An object path.
-+     *
-+     * Emitted when the client application  lost the focus.
-+     * Implement the member function IBusEngineClass::focus_out
-+     * in extended class to receive this signal.
-+     * @object_path is a unique id by input context.
-+     * You need to set #IBusEngine::has-focus-id property to %TRUE when you
-+     * construct an #IBusEngine to use this class method.
-+     *
-+     * See also: ibus_input_context_focus_out()
-+     * <note><para>Argument @user_data is ignored in this function.</para>
-+     * </note>
-+     */
-+    engine_signals[FOCUS_OUT_ID] =
-+        g_signal_new (I_("focus-out-id"),
-+            G_TYPE_FROM_CLASS (gobject_class),
-+            G_SIGNAL_RUN_LAST,
-+            G_STRUCT_OFFSET (IBusEngineClass, focus_out_id),
-+            NULL, NULL,
-+            _ibus_marshal_VOID__STRING,
-+            G_TYPE_NONE,
-+            1,
-+            G_TYPE_STRING);
-+
-     /**
-      * IBusEngine::reset:
-      * @engine: An IBusEngine.
-@@ -872,6 +985,9 @@ ibus_engine_set_property (IBusEngine   *engine,
-     case PROP_ENGINE_NAME:
-         engine->priv->engine_name = g_value_dup_string (value);
-         break;
-+    case PROP_HAS_FOCUS_ID:
-+        engine->priv->has_focus_id = g_value_get_boolean (value);
-+        break;
-     default:
-         G_OBJECT_WARN_INVALID_PROPERTY_ID (engine, prop_id, pspec);
-     }
-@@ -887,7 +1003,9 @@ ibus_engine_get_property (IBusEngine *engine,
-     case PROP_ENGINE_NAME:
-         g_value_set_string (value, engine->priv->engine_name);
-         break;
--
-+    case PROP_HAS_FOCUS_ID:
-+        g_value_set_boolean (value, engine->priv->has_focus_id);
-+        break;
-     default:
-         G_OBJECT_WARN_INVALID_PROPERTY_ID (engine, prop_id, pspec);
-     }
-@@ -1176,6 +1294,30 @@ ibus_engine_service_method_call (IBusService           *service,
-         }
-     }
- 
-+    if (g_strcmp0 (method_name, "FocusInId") == 0) {
-+        gchar *object_path = NULL;
-+        gchar *client = NULL;
-+        g_variant_get (parameters, "(&s&s)", &object_path, &client);
-+        g_signal_emit (engine,
-+                       engine_signals[FOCUS_IN_ID],
-+                       0,
-+                       object_path,
-+                       client);
-+        g_dbus_method_invocation_return_value (invocation, NULL);
-+        return;
-+    }
-+
-+    if (g_strcmp0 (method_name, "FocusOutId") == 0) {
-+        gchar *object_path = NULL;
-+        g_variant_get (parameters, "(&s)", &object_path);
-+        g_signal_emit (engine,
-+                       engine_signals[FOCUS_OUT_ID],
-+                       0,
-+                       object_path);
-+        g_dbus_method_invocation_return_value (invocation, NULL);
-+        return;
-+    }
-+
-     if (g_strcmp0 (method_name, "CandidateClicked") == 0) {
-         guint index, button, state;
-         g_variant_get (parameters, "(uuu)", &index, &button, &state);
-@@ -1303,6 +1445,23 @@ ibus_engine_service_method_call (IBusService           *service,
-     g_return_if_reached ();
- }
- 
-+/**
-+ * _ibus_engine_has_focus_id:
-+ *
-+ * Implement the "FocusId" method call of the org.freedesktop.IBus interface.
-+ */
-+static GVariant *
-+_ibus_engine_has_focus_id (IBusEngine      *engine,
-+                           GDBusConnection *connection,
-+                           GError         **error)
-+{
-+    if (error) {
-+        *error = NULL;
-+    }
-+
-+    return g_variant_new_boolean (engine->priv->has_focus_id);
-+}
-+
- static GVariant *
- ibus_engine_service_get_property (IBusService        *service,
-                                   GDBusConnection    *connection,
-@@ -1312,7 +1471,18 @@ ibus_engine_service_get_property (IBusService        *service,
-                                   const gchar        *property_name,
-                                   GError            **error)
- {
--    return IBUS_SERVICE_CLASS (ibus_engine_parent_class)->
-+    int i;
-+    static const struct {
-+        const gchar *method_name;
-+        GVariant * (* method_callback) (IBusEngine *,
-+                                        GDBusConnection *,
-+                                        GError **);
-+    } methods [] =  {
-+        { "FocusId",                    _ibus_engine_has_focus_id },
-+    };
-+
-+    if (g_strcmp0 (interface_name, IBUS_INTERFACE_ENGINE) != 0) {
-+        return IBUS_SERVICE_CLASS (ibus_engine_parent_class)->
-                 service_get_property (service,
-                                       connection,
-                                       sender,
-@@ -1320,6 +1490,19 @@ ibus_engine_service_get_property (IBusService        *service,
-                                       interface_name,
-                                       property_name,
-                                       error);
-+    }
-+
-+    for (i = 0; i < G_N_ELEMENTS (methods); i++) {
-+        if (g_strcmp0 (methods[i].method_name, property_name) == 0) {
-+            return methods[i].method_callback ((IBusEngine *) service,
-+                                               connection,
-+                                               error);
-+        }
-+    }
-+
-+    g_warning ("service_get_property received an unknown property: %s",
-+               property_name ? property_name : "(null)");
-+    return NULL;
- }
- 
- static gboolean
-@@ -1386,31 +1569,39 @@ ibus_engine_process_key_event (IBusEngine *engine,
- static void
- ibus_engine_focus_in (IBusEngine *engine)
- {
--    // g_debug ("focus-in");
-+}
-+
-+static void
-+ibus_engine_focus_in_id (IBusEngine  *engine,
-+                         const gchar *object_path,
-+                         const gchar *client)
-+{
- }
- 
- static void
- ibus_engine_focus_out (IBusEngine *engine)
- {
--    // g_debug ("focus-out");
-+}
-+
-+static void
-+ibus_engine_focus_out_id (IBusEngine  *engine,
-+                          const gchar *object_path)
-+{
- }
- 
- static void
- ibus_engine_reset (IBusEngine *engine)
- {
--    // g_debug ("reset");
- }
- 
- static void
- ibus_engine_enable (IBusEngine *engine)
- {
--    // g_debug ("enable");
- }
- 
- static void
- ibus_engine_disable (IBusEngine *engine)
- {
--    // g_debug ("disable");
- }
- 
- static void
-diff --git a/src/ibusengine.h b/src/ibusengine.h
-index 43eaa554..6af0e856 100644
---- a/src/ibusengine.h
-+++ b/src/ibusengine.h
-@@ -2,7 +2,8 @@
- /* vim:set et sts=4: */
- /* ibus - The Input Bus
-  * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2008-2013 Red Hat, Inc.
-+ * Copyright (C) 2012-2022 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2008-2022 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
-@@ -153,10 +154,15 @@ struct _IBusEngineClass {
-                                     (IBusEngine     *engine,
-                                      guint           purpose,
-                                      guint           hints);
-+    void        (* focus_in_id)     (IBusEngine     *engine,
-+                                     const gchar    *object_path,
-+                                     const gchar    *client);
-+    void        (* focus_out_id)    (IBusEngine     *engine,
-+                                     const gchar    *object_path);
- 
-     /*< private >*/
-     /* padding */
--    gpointer pdummy[4];
-+    gpointer pdummy[2];
- };
- 
- GType        ibus_engine_get_type       (void);
-diff --git a/src/ibusmarshalers.list b/src/ibusmarshalers.list
-index aa9ea82a..7489f842 100644
---- a/src/ibusmarshalers.list
-+++ b/src/ibusmarshalers.list
-@@ -19,6 +19,7 @@ VOID:OBJECT,UINT,UINT
- VOID:OBJECT,BOOLEAN
- VOID:BOXED,BOOLEAN
- VOID:BOXED
-+VOID:STRING,STRING
- VOID:STRING,STRING,VARIANT
- VOID:STRING,STRING,STRING
- VOID:UINT
--- 
-2.35.3
-
-From 59c13597918db98ec8120ccdac09f1e2dc576e1b Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Thu, 7 Jul 2022 08:22:48 +0900
-Subject: [PATCH] src/tests: Unset G_MESSAGES_DEBUG for gsettings in
- xkb-latin-layouts
-
-gsettings cannot get the key value when G_MESSAGES_DEBUG is enabled.
-Add denylist.txt to engine/Makefile.am
----
- engine/Makefile.am          | 3 ++-
- src/tests/xkb-latin-layouts | 7 +++++++
- 2 files changed, 9 insertions(+), 1 deletion(-)
-
-diff --git a/engine/Makefile.am b/engine/Makefile.am
-index 03867f52..7256fbc8 100644
---- a/engine/Makefile.am
-+++ b/engine/Makefile.am
-@@ -4,7 +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>
-+# Copyright (c) 2013-2021 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
-@@ -88,6 +88,7 @@ CLEANFILES = \
- 	$(NULL)
- 
- EXTRA_DIST = \
-+	denylist.txt \
- 	gensimple.py \
- 	iso639converter.py \
- 	simple.xml.in \
-diff --git a/src/tests/xkb-latin-layouts b/src/tests/xkb-latin-layouts
-index f8dced6b..92464234 100755
---- a/src/tests/xkb-latin-layouts
-+++ b/src/tests/xkb-latin-layouts
-@@ -82,9 +82,16 @@ finit()
- 
- test_xkb_keymaps()
- {
-+    # G_MESSAGES_DEBUG=all or G_MESSAGES_DEBUG=GLib-GIO-DEBUG would append
-+    # debug messages to gsettings output and could not get the result correctly.
-+    backup_G_MESSAGES_DEBUG="$G_MESSAGES_DEBUG"
-+    unset G_MESSAGES_DEBUG
-     # Loop over top level schemas since "gsettings list-recursively" only
-     # looks for direct children.
-     xkb_latin_layouts=`gsettings get org.freedesktop.ibus.general xkb-latin-layouts`
-+    if [ x"$backup_G_MESSAGES_DEBUG" != x ] ; then
-+        export G_MESSAGES_DEBUG=$backup_G_MESSAGES_DEBUG
-+    fi
-     while read keymap ; do
-         eval keymap="$keymap"
-         HAS_VARIANT=$($ECHO "$keymap" | grep '(' 2> /dev/null) ||:
--- 
-2.35.3
-
-From d47dbfada41aa4fb5df9f7cffe873786fc4849cc Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Mon, 25 Jul 2022 17:22:21 +0900
-Subject: [PATCH] client/x11: Enhance Xutf8TextListToTextProperty
-
-XCompoundTextStyle depends on the current locale and some locales fail
-to to get the compound text style.
-If Xutf8TextListToTextProperty() fails, now ibus-x11 tries to get
-the compound text style with UTF-8 encoding.
-
-BUG=https://github.com/ibus/ibus/issues/2422
----
- client/x11/main.c | 41 ++++++++++++++++++++++++++++++++++-------
- 1 file changed, 34 insertions(+), 7 deletions(-)
-
-diff --git a/client/x11/main.c b/client/x11/main.c
-index fe30c1d6..6057cc03 100644
---- a/client/x11/main.c
-+++ b/client/x11/main.c
-@@ -2,7 +2,7 @@
- /* vim:set et sts=4: */
- /* ibus
-  * Copyright (C) 2007-2015 Peng Huang <shawn.p.huang@gmail.com>
-- * Copyright (C) 2015-2021 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2015-2022 Takao Fujiwara <takao.fujiwara1@gmail.com>
-  * Copyright (C) 2007-2015 Red Hat, Inc.
-  *
-  * main.c:
-@@ -48,6 +48,8 @@
- 
- #include <getopt.h>
- 
-+#define ESC_SEQUENCE_ISO10646_1 "\033%G"
-+
- #define LOG(level, fmt_args...) \
-     if (g_debug_level >= (level)) { \
-         g_debug (fmt_args); \
-@@ -254,9 +256,17 @@ _xim_preedit_callback_draw (XIMS xims, X11IC *x11ic, const gchar *preedit_string
-     text.feedback = feedback;
- 
-     if (len > 0) {
--        Xutf8TextListToTextProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
--                                     (char **)&preedit_string,
--                                     1, XCompoundTextStyle, &tp);
-+        int ret = Xutf8TextListToTextProperty (
-+                GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
-+                (char **)&preedit_string,
-+                1, XCompoundTextStyle, &tp);
-+        if (ret == EXIT_FAILURE) {
-+            XFree (tp.value);
-+            tp.value = (unsigned char *)g_strdup_printf (
-+                    "%s%s",
-+                    ESC_SEQUENCE_ISO10646_1,
-+                    preedit_string);
-+        }
-         text.encoding_is_wchar = 0;
-         text.length = strlen ((char*)tp.value);
-         text.string.multi_byte = (char*)tp.value;
-@@ -883,9 +893,26 @@ _context_commit_text_cb (IBusInputContext *context,
- 
-     XTextProperty tp;
-     IMCommitStruct cms = {0};
--
--    Xutf8TextListToTextProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
--        (gchar **)&(text->text), 1, XCompoundTextStyle, &tp);
-+    int ret;
-+
-+    ret = Xutf8TextListToTextProperty (
-+            GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
-+            (gchar **)&(text->text), 1, XCompoundTextStyle, &tp);
-+    /* XCompoundTextStyle uses the encoding escaped sequence + encoded chars
-+     * matched to the specified multibyte characters: text->text, and
-+     * libX11.so sorts the encoding sets by locale.
-+     * If an encoded string fails to be matched, ibus-x11 specifies the
-+     * ISO10641-1 encoding and that escaped sequence is "\033%G":
-+     * https://gitlab.freedesktop.org/xorg/lib/libx11/-/blob/master/src/xlibi18n/lcCT.c
-+     * , and the encoding is UTF-8 with utf8_wctomb():
-+     * https://gitlab.freedesktop.org/xorg/lib/libx11/-/blob/master/src/xlibi18n/lcUniConv/utf8.h
-+     */
-+    if (ret == EXIT_FAILURE) {
-+        XFree (tp.value);
-+        tp.value = (unsigned char *)g_strdup_printf ("%s%s",
-+                                                     ESC_SEQUENCE_ISO10646_1,
-+                                                     text->text);
-+    }
- 
-     cms.major_code = XIM_COMMIT;
-     cms.icid = x11ic->icid;
--- 
-2.35.3
-
-From 53d8a826a62f2b43d7361f719fb72e26da8732f8 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 12 Aug 2022 11:41:16 +0900
-Subject: [PATCH] data/dconf: Revert Emoji shoftcut key to Super-space
-
-IBus provides the D-Bus method to override IBus emoji UI and i think
-Super-period is better than Ctrl-period for the emoji shortcut key to
-compare MS-Window, Macintosh. IBus emoji UI connects to the input method
-and provides the language emoji annotations.
-
-Seems moving GTK Cotrol-period to gnome-shell Suer-period is difficult
-at present.
-
-BUG=https://github.com/ibus/ibus/issues/2390
-BUG=https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5728
----
- data/dconf/org.freedesktop.ibus.gschema.xml | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/data/dconf/org.freedesktop.ibus.gschema.xml b/data/dconf/org.freedesktop.ibus.gschema.xml
-index 0ece2b4f..4d3b7ae2 100644
---- a/data/dconf/org.freedesktop.ibus.gschema.xml
-+++ b/data/dconf/org.freedesktop.ibus.gschema.xml
-@@ -248,7 +248,7 @@
-       <description>The shortcut keys for turning Unicode typing on or off</description>
-     </key>
-     <key name="hotkey" type="as">
--      <default>[ '&lt;Control&gt;period', '&lt;Control&gt;semicolon' ]</default>
-+      <default>[ '&lt;Super&gt;period' ]</default>
-       <summary>Emoji shortcut keys for gtk_accelerator_parse</summary>
-       <description>The shortcut keys for turning emoji typing on or off</description>
-     </key>
--- 
-2.37.1
-

             reply	other threads:[~2026-05-31  2:07 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-31  2:07 Takao Fujiwara [this message]
  -- strict thread matches above, loose matches on Subject: below --
2026-05-31  2:09 [rpms/ibus] autotool: Delete upstreamed patches Takao Fujiwara
2026-05-31  2:09 Takao Fujiwara
2026-05-31  2:09 Takao Fujiwara
2026-05-31  2:08 Takao Fujiwara
2026-05-31  2:08 Takao Fujiwara
2026-05-31  2:08 Takao Fujiwara
2026-05-31  2:08 Takao Fujiwara
2026-05-31  2:08 Takao Fujiwara
2026-05-31  2:08 Takao Fujiwara
2026-05-31  2:08 [rpms/ibus] autotool: Delete Upstreamed patches Takao Fujiwara
2026-05-31  2:08 [rpms/ibus] autotool: Delete upstreamed patches Takao Fujiwara
2026-05-31  2:08 Takao Fujiwara
2026-05-31  2:07 Takao Fujiwara
2026-05-31  2:07 Takao Fujiwara
2026-05-31  2:07 Takao Fujiwara

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178019327714.1.14866051828136667805.rpms-ibus-e9877b0a75da@fedoraproject.org \
    --to=tfujiwar@redhat.com \
    --cc=git-commits@fedoraproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox