public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/ibus] f44: Backport upstream patches
@ 2026-06-03 3:16 Takao Fujiwara
0 siblings, 0 replies; only message in thread
From: Takao Fujiwara @ 2026-06-03 3:16 UTC (permalink / raw)
To: git-commits
A new commit has been pushed.
Repo : rpms/ibus
Branch : f44
Commit : 2f7e8dde9a6cf91645d060ed161e11aa06ebcc82
Author : Takao Fujiwara <tfujiwar@redhat.com>
Date : 2026-06-03T12:11:38+09:00
Stats : +1663/-27 in 3 file(s)
URL : https://src.fedoraproject.org/rpms/ibus/c/2f7e8dde9a6cf91645d060ed161e11aa06ebcc82?branch=f44
Log:
Backport upstream patches
- Make an IBusText own an updated IBusAttrList reference
- Resolves: #2444787 SEGV with wrong anchor in surrounding-text in Wayland
- Updates: #2480408 IBus callbacks in Wayland to clarify SEGVs
---
diff --git a/ibus-1385349-segv-bus-proxy.patch b/ibus-1385349-segv-bus-proxy.patch
index 9084ee0..e7c7b30 100644
--- a/ibus-1385349-segv-bus-proxy.patch
+++ b/ibus-1385349-segv-bus-proxy.patch
@@ -1,6 +1,6 @@
From 656390df46ba963afe51420ecb9399b6dde9a2bd Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Fri, 12 Jul 2024 23:30:25 +0900
+Date: Thu, 30 Apr 2026 09:00:00 +0900
Subject: [PATCH] Fix SEGV in bus_panel_proxy_focus_in()
rhbz#1350291 SEGV in BUS_IS_CONNECTION(skip_connection) in
@@ -39,27 +39,34 @@ rhbz#2239633 SEGV with g_object_unref() in
ibus_portal_context_handle_destroy()
Connect "handle-destroy" signal after g_list_prepend().
-BUG=rhbz#1350291
-BUG=rhbz#1601577
-BUG=rhbz#1663528
-BUG=rhbz#1795499
-BUG=rhbz#1771238
-BUG=rhbz#1767976
-BUG=rhbz#2151344
-BUG=rhbz#2195895
-BUG=rhbz#2239633
+rhbz#2480408 SEGV with zwp_input_method_context_v1_preedit_string() in
+_context_hide_preedit_text_cb()
+If the `zwp_input_method_context_v1` is deactivate, the `IBusIMContext`
+is should be cleared and the "hide-preedit-text" signal is also
+disconnected.
+
+Closes: rhbz#1350291
+Closes: rhbz#1601577
+Closes: rhbz#1663528
+Closes: rhbz#1795499
+Closes: rhbz#1771238
+Closes: rhbz#1767976
+Closes: rhbz#2151344
+Closes: rhbz#2195895
+Closes: rhbz#2239633
+Closes: rhbz#2480408
---
- bus/dbusimpl.c | 47 ++++++++++++++++++++++++++++++++++++----
- bus/engineproxy.c | 44 ++++++++++++++++++++++++++++---------
- bus/panelproxy.c | 9 +++++++-
- client/x11/main.c | 49 +++++++++++++++++++++++++++++++++++++-----
- portal/portal.c | 25 ++++++++++++++++-----
- src/ibusbus.c | 6 ++++++
- ui/gtk3/switcher.vala | 48 +++++++++++++++++++++++++----------------
- 7 files changed, 188 insertions(+), 44 deletions(-)
+ bus/engineproxy.c | 44 +++++++++++++++++++++++-------
+ bus/panelproxy.c | 9 ++++++-
+ client/wayland/ibuswaylandim.c | 20 +++++++++++++-
+ client/x11/main.c | 49 ++++++++++++++++++++++++++++++----
+ portal/portal.c | 25 +++++++++++++----
+ src/ibusbus.c | 6 +++++
+ ui/gtk3/switcher.vala | 48 ++++++++++++++++++++-------------
+ 8 files changed, 203 insertions(+), 45 deletions(-)
diff --git a/bus/dbusimpl.c b/bus/dbusimpl.c
-index 70792be8..9c535bf2 100644
+index 70792be..9c535bf 100644
--- a/bus/dbusimpl.c
+++ b/bus/dbusimpl.c
@@ -634,6 +634,7 @@ static void
@@ -147,7 +154,7 @@ index 70792be8..9c535bf2 100644
if (incoming) {
/* is incoming message */
diff --git a/bus/engineproxy.c b/bus/engineproxy.c
-index 37736b69..7f34604c 100644
+index 37736b6..7f34604 100644
--- a/bus/engineproxy.c
+++ b/bus/engineproxy.c
@@ -775,10 +775,12 @@ bus_engine_proxy_g_signal (GDBusProxy *proxy,
@@ -247,7 +254,7 @@ index 37736b69..7f34604c 100644
/* FIXME: set destroy callback ? */
g_task_return_pointer (data->task, engine, NULL);
diff --git a/bus/panelproxy.c b/bus/panelproxy.c
-index 4c2c8885..a7bec193 100644
+index 4c2c888..a7bec19 100644
--- a/bus/panelproxy.c
+++ b/bus/panelproxy.c
@@ -124,6 +124,8 @@ bus_panel_proxy_new (BusConnection *connection,
@@ -280,8 +287,81 @@ index 4c2c8885..a7bec193 100644
panel = BUS_PANEL_PROXY (obj);
panel->panel_type = panel_type;
return panel;
+diff --git a/client/wayland/ibuswaylandim.c b/client/wayland/ibuswaylandim.c
+index 5762f10..f1e3b9e 100644
+--- a/client/wayland/ibuswaylandim.c
++++ b/client/wayland/ibuswaylandim.c
+@@ -387,7 +387,7 @@ ibus_wayland_im_commit_text (IBusWaylandIM *wlim,
+ const char *str)
+ {
+ IBusWaylandIMPrivate *priv;
+- g_return_if_fail (IBUS_IS_WAYLAND_IM (wlim));
++ g_assert (IBUS_IS_WAYLAND_IM (wlim));
+ priv = ibus_wayland_im_get_instance_private (wlim);
+ switch (priv->version) {
+ case INPUT_METHOD_V1:
+@@ -822,6 +822,14 @@ _context_commit_text_cb (IBusInputContext *context,
+ IBusText *text,
+ IBusWaylandIM *wlim)
+ {
++ IBusWaylandIMPrivate *priv;
++
++ g_return_if_fail (IBUS_IS_WAYLAND_IM (wlim));
++ priv = ibus_wayland_im_get_instance_private (wlim);
++ /* FIXME: rhbz#2480408 If priv->ibuscontext exists,
++ * priv->context also should exists.
++ */
++ g_assert (priv->ibuscontext);
+ ibus_wayland_im_commit_text (wlim, text->text);
+ }
+
+@@ -838,6 +846,8 @@ _context_forward_key_event_cb (IBusInputContext *context,
+
+ g_return_if_fail (IBUS_IS_WAYLAND_IM (wlim));
+ priv = ibus_wayland_im_get_instance_private (wlim);
++ /* FIXME: rhbz#2480408 */
++ g_assert (priv->ibuscontext);
+ if (modifiers & IBUS_RELEASE_MASK)
+ state = WL_KEYBOARD_KEY_STATE_RELEASED;
+ else
+@@ -1055,6 +1065,8 @@ _context_show_preedit_text_cb (IBusInputContext *context,
+ const char *commit = "";
+ g_return_if_fail (IBUS_IS_WAYLAND_IM (wlim));
+ priv = ibus_wayland_im_get_instance_private (wlim);
++ /* FIXME: rhbz#2480408 */
++ g_assert (priv->ibuscontext);
+ /* CURSOR is byte offset. */
+ cursor =
+ g_utf8_offset_to_pointer (priv->preedit_text->text,
+@@ -1098,6 +1110,8 @@ _context_hide_preedit_text_cb (IBusInputContext *context,
+ IBusWaylandIMPrivate *priv;
+ g_return_if_fail (IBUS_IS_WAYLAND_IM (wlim));
+ priv = ibus_wayland_im_get_instance_private (wlim);
++ /* FIXME: rhbz#2480408 */
++ g_assert (priv->ibuscontext);
+ switch (priv->version) {
+ case INPUT_METHOD_V1:
+ zwp_input_method_context_v1_preedit_string (priv->context,
+@@ -1137,6 +1151,8 @@ _context_update_preedit_text_cb (IBusInputContext *context,
+ priv->preedit_cursor_pos = cursor_pos;
+ priv->preedit_mode = mode;
+
++ /* FIXME: rhbz#2480408 */
++ g_assert (priv->ibuscontext);
+ if (visible)
+ _context_show_preedit_text_cb (context, wlim);
+ else
+@@ -1161,6 +1177,8 @@ _context_delete_surrounding_text_cb (IBusInputContext *context,
+ g_return_if_fail (IBUS_IS_WAYLAND_IM (wlim));
+ priv = ibus_wayland_im_get_instance_private (wlim);
+
++ /* FIXME: rhbz#2480408 */
++ g_assert (priv->ibuscontext);
+ if (!priv->surrounding_text)
+ return;
+
diff --git a/client/x11/main.c b/client/x11/main.c
-index 5fadd43d..26d4a7f1 100644
+index accebde..cac4cd6 100644
--- a/client/x11/main.c
+++ b/client/x11/main.c
@@ -45,6 +45,7 @@
@@ -428,7 +508,7 @@ index 5fadd43d..26d4a7f1 100644
ibus_input_context_reset (x11ic->context);
diff --git a/portal/portal.c b/portal/portal.c
-index 5cd38779..5110baad 100644
+index 5cd3877..5110baa 100644
--- a/portal/portal.c
+++ b/portal/portal.c
@@ -92,6 +92,11 @@ static void portal_context_g_signal (GDBusProxy *proxy,
@@ -487,7 +567,7 @@ index 5cd38779..5110baad 100644
g_object_unref (portal_context);
}
diff --git a/src/ibusbus.c b/src/ibusbus.c
-index 540d1da3..defdb73b 100644
+index 540d1da..defdb73 100644
--- a/src/ibusbus.c
+++ b/src/ibusbus.c
@@ -750,6 +750,12 @@ ibus_bus_destroy (IBusObject *object)
@@ -504,7 +584,7 @@ index 540d1da3..defdb73b 100644
bus->priv->monitor = NULL;
}
diff --git a/ui/gtk3/switcher.vala b/ui/gtk3/switcher.vala
-index d4a5fa11..788eea06 100644
+index d4a5fa1..788eea0 100644
--- a/ui/gtk3/switcher.vala
+++ b/ui/gtk3/switcher.vala
@@ -251,27 +251,37 @@ class Switcher : Gtk.Window {
@@ -565,5 +645,5 @@ index d4a5fa11..788eea06 100644
seat.ungrab();
--
-2.51.0
+2.53.0
diff --git a/ibus-HEAD.patch b/ibus-HEAD.patch
index e69de29..05d93de 100644
--- a/ibus-HEAD.patch
+++ b/ibus-HEAD.patch
@@ -0,0 +1,1549 @@
+From 2e901bb74d8d7b775a15eddde9f794ffb2c253cb Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Tue, 19 May 2026 19:31:38 +0900
+Subject: [PATCH 01/15] Update test builds which is part of Meson builds
+
+bindings/pygobject/test-override-ibus: Add gi.require_versions().
+bus/test-matchrule: Support the TAP test.
+bus/test-stress: Support the TAP test.
+src/ibuscomposetable: Replace g_print() with g_debug() for TAP comments.
+src/tests/ibus-keypress: Prepend "# " for TAP comments.
+src/tests/ibus-registry: Support the TAP test.
+src/tests/ibus-util: Support the TAP test.
+src/tests/runtest:
+ - Expect the relative paths for Autotool and absolute paths for Meson.
+ - Support Python tests.
+ - Cease warnings with `glib-compile-schemas` command.
+ - Enable subtests with TAP for Meson and set G_TEST_ROOT_PROCESS
+ to consist test cases in Plan and ones in test results.
+src/tests/xkb-latin-layouts: Support the TAP test.
+---
+ bindings/pygobject/test-override-ibus.py | 2 +
+ bus/test-matchrule.c | 26 ++++--
+ bus/test-stress.c | 17 ++--
+ src/ibuscomposetable.c | 38 +++++---
+ src/tests/ibus-keypress.c | 6 +-
+ src/tests/ibus-registry.c | 15 +++-
+ src/tests/ibus-util.c | 14 ++-
+ src/tests/runtest | 109 ++++++++++++++++++-----
+ src/tests/xkb-latin-layouts | 21 +++--
+ 9 files changed, 284 insertions(+), 96 deletions(-)
+
+diff --git a/bindings/pygobject/test-override-ibus.py b/bindings/pygobject/test-override-ibus.py
+index 087a6558..8853ff64 100644
+--- a/bindings/pygobject/test-override-ibus.py
++++ b/bindings/pygobject/test-override-ibus.py
+@@ -31,6 +31,8 @@ tests_builddir = os.path.abspath(os.path.dirname(__file__))
+ sys.path = [path for path in sys.path if path != tests_builddir]
+ sys.path.append(tests_builddir)
+
++import gi
++gi.require_versions({'GLib': '2.0', 'IBus': '1.0'})
+ from gi.repository import GLib, IBus
+
+ class TestOverride(unittest.TestCase):
+diff --git a/bus/test-matchrule.c b/bus/test-matchrule.c
+index d85fc90c..15a4ed45 100644
+--- a/bus/test-matchrule.c
++++ b/bus/test-matchrule.c
+@@ -16,15 +16,13 @@ struct _BusMatchRule {
+ GList *recipients;
+ };
+
+-int
+-main(gint argc, gchar **argv)
++static void
++test (void)
+ {
+ BusMatchRule *rule, *rule1;
+-#if !GLIB_CHECK_VERSION(2,35,0)
+- g_type_init ();
+-#endif
+
+- rule = bus_match_rule_new (" type='signal' , interface = 'org.freedesktop.IBus' ");
++ rule = bus_match_rule_new (" type='signal' ,"
++ " interface = 'org.freedesktop.IBus' ");
+ g_assert (rule->message_type == G_DBUS_MESSAGE_TYPE_SIGNAL);
+ g_assert (g_strcmp0 (rule->interface, "org.freedesktop.IBus") == 0 );
+ g_object_unref (rule);
+@@ -55,12 +53,22 @@ main(gint argc, gchar **argv)
+ g_object_unref (rule);
+ g_object_unref (rule1);
+
+- rule = bus_match_rule_new ("type='method_call',interface='org.freedesktop.IBus ");
++ rule = bus_match_rule_new ("type='method_call',"
++ "interface='org.freedesktop.IBus ");
+ g_assert (rule == NULL);
+
+ rule = bus_match_rule_new ("eavesdrop=true");
+ g_assert (rule != NULL);
+ g_object_unref (rule);
+-
+- return 0;
++}
++
++int
++main (int argc, char *argv[])
++{
++ g_test_init (&argc, &argv, NULL);
++#if !GLIB_CHECK_VERSION(2,35,0)
++ g_type_init ();
++#endif
++ g_test_add_func ("/test-matchrule", test);
++ return g_test_run ();
+ }
+diff --git a/bus/test-stress.c b/bus/test-stress.c
+index 1c277e74..3908e60e 100644
+--- a/bus/test-stress.c
++++ b/bus/test-stress.c
+@@ -48,8 +48,8 @@ _sleep (guint millisecond)
+ Key kind are a-z and space.
+ Check ibus-daemon and ibus engine crash.
+ */
+-gint
+-main (gint argc, gchar **argv)
++static void
++test (void)
+ {
+ GTimer *timer;
+ GRand *rnd;
+@@ -59,9 +59,6 @@ main (gint argc, gchar **argv)
+ int count = 0;
+ int send_key_num = 0;
+
+- setlocale (LC_ALL, "");
+- ibus_init ();
+-
+ /* need to set active engine */
+ client = bus_test_client_new ();
+ if (client == NULL) {
+@@ -112,6 +109,14 @@ main (gint argc, gchar **argv)
+ g_print ("%f sec\n", g_timer_elapsed (timer, NULL));
+ g_timer_destroy (timer);
+ g_rand_free (rnd);
++}
+
+- return 0;
++int
++main (int argc, char *argv[])
++{
++ g_test_init (&argc, &argv, NULL);
++ setlocale (LC_ALL, "");
++ ibus_init ();
++ g_test_add_func ("/test-stress", test);
++ return g_test_run ();
+ }
+diff --git a/src/ibuscomposetable.c b/src/ibuscomposetable.c
+index 116d0131..93262f3a 100644
+--- a/src/ibuscomposetable.c
++++ b/src/ibuscomposetable.c
+@@ -1,7 +1,7 @@
+ /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+ /* ibus - The Input Bus
+ * Copyright (C) 2013-2014 Peng Huang <shawn.p.huang@gmail.com>
+- * Copyright (C) 2013-2025 Takao Fujiwara <takao.fujiwara1@gmail.com>
++ * Copyright (C) 2013-2026 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
+@@ -711,6 +711,7 @@ ibus_compose_list_check_duplicated_with_own (GList *compose_list,
+ IBusComposeData *compose_data_a, *compose_data_b;
+ int i;
+ GList *removed_list = NULL;
++ GString *string;
+
+ if (!compose_list)
+ return NULL;
+@@ -729,18 +730,33 @@ ibus_compose_list_check_duplicated_with_own (GList *compose_list,
+ break;
+ }
+ }
++ string = g_string_new (NULL);
++ if (is_different_value) {
++ g_string_append (
++ string,
++ "Deleting different outputs for same sequence.");
++ } else {
++ g_string_append (
++ string,
++ "Deleting same compose output for same sequence.");
++ }
++ g_string_append (string, "\n{");
++ for (i = 0; compose_data_a->values[i]; i++) {
++ g_string_append_printf (string,
++ "U+%X, ", compose_data_a->values[i]);
++ }
++ g_string_append (string, "}");
++ g_string_append (string, " {");
++ for (i = 0; compose_data_b->values[i]; i++) {
++ g_string_append_printf (string,
++ "U+%X, ", compose_data_b->values[i]);
++ }
++ g_string_append (string, "}\n");
+ if (is_different_value)
+- g_warning ("Deleting different outputs for same sequence.");
++ g_warning ("%s", string->str);
+ else
+- g_debug ("Deleting same compose output for same sequence.");
+- g_print ("{");
+- for (i = 0; compose_data_a->values[i]; i++)
+- g_print ("U+%X, ", compose_data_a->values[i]);
+- g_print ("}");
+- g_print (" {");
+- for (i = 0; compose_data_b->values[i]; i++)
+- g_print ("U+%X, ", compose_data_b->values[i]);
+- g_print ("}\n");
++ g_debug ("%s", string->str);
++ g_string_free (string, TRUE);
+ removed_list = g_list_append (removed_list, compose_data_a);
+ }
+ }
+diff --git a/src/tests/ibus-keypress.c b/src/tests/ibus-keypress.c
+index b9068d32..78296381 100644
+--- a/src/tests/ibus-keypress.c
++++ b/src/tests/ibus-keypress.c
+@@ -1,7 +1,7 @@
+ /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+ /* vim:set et sts=4: */
+ /* ibus - The Input Bus
+- * Copyright (C) 2025 Takao Fujiwara <takao.fujiwara1@gmail.com>
++ * Copyright (C) 2025-2026 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (c) 2025 Peter Hutterer <peter.hutterer@who-t.net>
+ * Copyright (C) 2025 Red Hat, Inc.
+ *
+@@ -628,7 +628,7 @@ window_inserted_text_cb (GtkEntryBuffer *buffer,
+ if (!(code = g_utf8_get_char (chars)))
+ return;
+ if (code != test_results[i][j++]) {
+- test = RED "FAIL" NC;
++ test = "# " RED "FAIL" NC;
+ g_test_fail_printf ("%05d:%05d %s expected: %04X typed: %04X",
+ i, j - 1,
+ test,
+@@ -637,7 +637,7 @@ window_inserted_text_cb (GtkEntryBuffer *buffer,
+ } else if (test_results[i][j]) {
+ return;
+ } else {
+- g_print (GREEN "PASS" NC " ");
++ g_print ("# " GREEN "PASS" NC " ");
+ for (k = 0; k < j; k++)
+ g_print ("%lc(%X) ", test_results[i][k], test_results[i][k]);
+ g_print ("\n");
+diff --git a/src/tests/ibus-registry.c b/src/tests/ibus-registry.c
+index 4c612926..1a109e7f 100644
+--- a/src/tests/ibus-registry.c
++++ b/src/tests/ibus-registry.c
+@@ -1,10 +1,17 @@
+ #include <ibus.h>
+
+-int main()
++static void
++test (void)
+ {
+- ibus_init ();
+-
+ IBusRegistry *registry = ibus_registry_new ();
+ g_object_unref (registry);
+- return 0;
++}
++
++int
++main(int argc, char *argv[])
++{
++ g_test_init (&argc, &argv, NULL);
++ ibus_init ();
++ g_test_add_func ("/ibus-registry", test);
++ return g_test_run ();
+ }
+diff --git a/src/tests/ibus-util.c b/src/tests/ibus-util.c
+index 4110e529..9f2ab2b6 100644
+--- a/src/tests/ibus-util.c
++++ b/src/tests/ibus-util.c
+@@ -4,13 +4,19 @@
+
+ #include "ibus.h"
+
+-int main (int argc, char **argv)
++static void
++test (void)
+ {
+ gchar *name;
+- setlocale(LC_ALL, "C");
+-
+ g_assert_cmpstr (name = ibus_get_language_name ("eng"), ==, "English");
+ g_free (name);
++}
+
+- return 0;
++int
++main (int argc, char *argv[])
++{
++ g_test_init (&argc, &argv, NULL);
++ setlocale(LC_ALL, "C");
++ g_test_add_func ("/ibus-util", test);
++ return g_test_run ();
+ }
+diff --git a/src/tests/runtest b/src/tests/runtest
+index 71559fc1..7bd98575 100755
+--- a/src/tests/runtest
++++ b/src/tests/runtest
+@@ -17,10 +17,10 @@
+ #
+ # $ top_builddir=<...> top_srcdir=<...> builddir=<...> ./runtest ibus-foo
+
+-: ${top_builddir:=../..}
+-: ${top_srcdir:=../..}
+-: ${builddir:=.}
+-: ${srcdir:=.}
++: ${top_builddir:='../..'}
++: ${top_srcdir:='../..'}
++: ${builddir:='.'}
++: ${srcdir:='.'}
+ : ${DISABLE_GUI_TESTS:=''}
+ : ${DISABLE_DAEMONIZE_IN_TESTS:=''}
+ : ${TEST_GTK_VERSION:=0}
+@@ -37,7 +37,7 @@ ibus-engine-switch
+ ibus-compose
+ ibus-keypress
+ test-stress
+-xkb-latin-layouts
++test-override-ibus.py
+ "
+ IBUS_SCHEMA_FILE='org.freedesktop.ibus.gschema.xml'
+ GTK_QUERY_MODULE=gtk-query-immodules-3.0-32
+@@ -50,6 +50,22 @@ if ! command -v $GTK_QUERY_MODULE > /dev/null 2>&1 ; then
+ GTK_QUERY_MODULE=gtk-query-immodules-3.0
+ fi
+
++if echo "$top_builddir" | grep -q '^/' ; then
++ # absolute path for meson
++ test_top_builddir="$top_builddir"
++else
++ # relative path for autotool and default value
++ test_top_builddir="../$top_builddir"
++fi
++
++if echo "$top_srcdir" | grep -q '^/' ; then
++ # absolute path for meson
++ test_top_srcdir="$top_srcdir"
++else
++ # relative path for autotool and default value
++ test_top_srcdir="../$top_srcdir"
++fi
++
+ retval=0
+
+ # Portable replacement of basename.
+@@ -120,21 +136,26 @@ run_test_case()
+ backup_dir=$PWD
+ cd $tstdir
+
++ if echo "$tst" | grep -q 'python' ; then
++ name=`func_basename "$1"`
++ else
++ name=`func_basename "$tst"`
++ fi
+ need_bus=no
+ for t in $BUS_REQUIRED_TESTS; do
+- if test $t = `func_basename $tst`; then
++ if test "$t" = "$name"; then
+ need_bus=yes
+ fi
+ done
+
+ if test $need_bus = yes; then
+- if test ! -f "../$top_builddir/conf/memconf/ibus-memconf" ; then
++ if test ! -f "$test_top_builddir/conf/memconf/ibus-memconf" ; then
+ echo "NOT FOUNND ibus-memconf. Need configure --enable-memconf"
+ exit 1
+ fi
+ # func_copy_component replaces s/$top_srcdir/%top_builddir/
+- func_copy_component "../$top_srcdir/engine/simple.xml"
+- func_copy_component "../$top_srcdir/conf/memconf/memconf.xml"
++ func_copy_component "$test_top_srcdir/engine/simple.xml"
++ func_copy_component "$test_top_srcdir/conf/memconf/memconf.xml"
+
+ IBUS_COMPONENT_PATH=$PWD/components
+ export IBUS_COMPONENT_PATH
+@@ -144,10 +165,10 @@ run_test_case()
+
+ test $TEST_GTK -eq 1 && case $TEST_GTK_VERSION in
+ 4)
+- if test -f "../$top_builddir/client/gtk4/.libs/libim-ibus.so" ; then
+- IM_IBUS_SO="../$top_builddir/client/gtk4/.libs/libim-ibus.so"
+- elif test -f "../$top_builddir/client/gtk4/libim-ibus.so" ; then
+- IM_IBUS_SO="../$top_builddir/client/gtk4/libim-ibus.so"
++ if test -f "$test_top_builddir/client/gtk4/.libs/libim-ibus.so" ; then
++ IM_IBUS_SO="$test_top_builddir/client/gtk4/.libs/libim-ibus.so"
++ elif test -f "$test_top_builddir/client/gtk4/libim-ibus.so" ; then
++ IM_IBUS_SO="$test_top_builddir/client/gtk4/libim-ibus.so"
+ else
+ echo "NOT FOUND $top_builddir/client/gtk4/libim-ibus.so"
+ exit 1
+@@ -157,10 +178,10 @@ run_test_case()
+ export GTK_EXE_PREFIX="$PWD"
+ ;;
+ 3)
+- if test -f "../$top_builddir/client/gtk3/.libs/im-ibus.so" ; then
+- IM_IBUS_SO="../$top_builddir/client/gtk3/.libs/im-ibus.so"
+- elif test -f "../$top_builddir/client/gtk3/im-ibus.so" ; then
+- IM_IBUS_SO="../$top_builddir/client/gtk3/im-ibus.so"
++ if test -f "$test_top_builddir/client/gtk3/.libs/im-ibus.so" ; then
++ IM_IBUS_SO="$test_top_builddir/client/gtk3/.libs/im-ibus.so"
++ elif test -f "$test_top_builddir/client/gtk3/im-ibus.so" ; then
++ IM_IBUS_SO="$test_top_builddir/client/gtk3/im-ibus.so"
+ else
+ echo "NOT FOUND $top_builddir/client/gtk3/im-ibus.so"
+ exit 1
+@@ -175,8 +196,8 @@ run_test_case()
+ ;;
+ esac || :
+
+- cp "../$top_srcdir/data/dconf/$IBUS_SCHEMA_FILE" $PWD
+- glib-compile-schemas $PWD
++ cp "$test_top_srcdir/data/dconf/$IBUS_SCHEMA_FILE" $PWD
++ glib-compile-schemas $PWD 2>/dev/null
+ if test $? -ne 0 ; then
+ echo "FAILED glib-compile-schemas"
+ retval=1
+@@ -198,10 +219,10 @@ run_test_case()
+ --verbose
+ '
+ if test x"$DISABLE_DAEMONIZE_IN_TESTS" = x ; then
+- ../$top_builddir/bus/ibus-daemon \
++ $test_top_builddir/bus/ibus-daemon \
+ $DAEMON_ARGS --daemonize;
+ else
+- ../$top_builddir/bus/ibus-daemon \
++ $test_top_builddir/bus/ibus-daemon \
+ $DAEMON_ARGS &
+ fi
+
+@@ -219,7 +240,26 @@ run_test_case()
+
+ export IBUS_COMPOSE_CACHE_DIR=$PWD
+
+- "../$tst" ../$top_srcdir/src/tests ${1+"$@"}
++ if echo "$tst" | grep -q '^/' ; then
++ if echo "$tst" | grep -q 'python' ; then
++ interpreter=$tst
++ tst=$1
++ shift
++ if echo "$tst" | grep -q '^/' ; then
++ # absolute path for Meson
++ "$interpreter" "$tst" ${1+"$@"}
++ else
++ # relative path for autotools
++ "$interpreter" "../$tst" ${1+"$@"}
++ fi
++ else
++ # absolute path for Meson
++ "$tst" $test_top_srcdir/src/tests ${1+"$@"}
++ fi
++ else
++ # relative path for each execution
++ "../$tst" $test_top_srcdir/src/tests ${1+"$@"}
++ fi
+
+ retval=`expr $retval \| $?`
+
+@@ -237,6 +277,16 @@ if test x"$ENVS" = x ; then
+ else
+ LANG_backup=$LANG
+ i=1
++ # mesonbuild/mtest.py:TAPParser.parse_line() says:
++ # 'version number must be on the first line'
++ echo "TAP version 14"
++ NUM_CASES=`wc -l $envfile | sed -e 's/^\([0-9]*\) .*/\1/'`
++ # Meson checks #Plan with the number of test cases
++ # like "1..Number"
++ # https://testanything.org/tap-version-14-specification.html
++ echo "1..$NUM_CASES"
++ # Set subtest for GTestLog to hide the "TAP version" output
++ export G_TEST_ROOT_PROCESS=1
+ # "for e in $ENVS" separates the variable by space but not line feed.
+ # "echo $ENVS | while read e" does not forward `retval`
+ # to the parent process.
+@@ -248,14 +298,25 @@ else
+ unset NO_LOAD_COMPOSE_FILE
+ unset COMPOSE_FILE
+ export $e
+- echo "Run `func_basename $tst` on $e"
+- echo "======================="
++ # TAP info should start with "# ".
++ echo "# Run `func_basename $tst` on $e"
++ echo "# ======================="
+ run_test_case $@
++ name="/"`basename "$1"`":$LANG:$COMPOSE_FILE:$NO_LOAD_COMPOSE_FILE"
++ # Meson compares the numer of tests in #Plan and the number of
++ # #TestPoint like "ok Number Description"
++ # https://testanything.org/tap-version-14-specification.html
++ if test $retval -eq 0; then
++ echo "ok $i $name"
++ else
++ echo "not ok $i $name"
++ fi
+ echo ""
+ i=`expr $i + 1`
+ done << EOF_ENVS
+ `echo "$ENVS"`
+ EOF_ENVS
++ unset G_TEST_ROOT_PROCESS
+ export LANG=$LANG_backup
+ fi
+
+diff --git a/src/tests/xkb-latin-layouts b/src/tests/xkb-latin-layouts
+index 45c99358..dd49ff97 100755
+--- a/src/tests/xkb-latin-layouts
++++ b/src/tests/xkb-latin-layouts
+@@ -1,7 +1,7 @@
+ #!/bin/bash
+
+ PROGNAME=`basename $0`
+-VERSION=0.1
++VERSION=0.2
+ # POSIX sh has no 'echo -e'
+ : ${ECHO:='/usr/bin/echo'}
+ TMPDIR=
+@@ -25,15 +25,14 @@ usage()
+ parse_args()
+ {
+ # This is GNU getopt. "sudo port getopt" in BSD?
+- ARGS=`getopt -o hD:Tv --long \
+- help,schemasdir:,tap,version\
++ ARGS=`getopt -o hD:v --long \
++ help,schemasdir:,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;;
+@@ -98,11 +97,11 @@ test_xkb_keymaps()
+ 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
++ $ECHO "# setxkbmap -layout $layout -variant $variant"
+ setxkbmap -layout $layout -variant $variant
+ else
+ layout="$keymap"
+- $ECHO setxkbmap -layout $layout
++ $ECHO "# setxkbmap -layout $layout"
+ setxkbmap -layout $layout
+ fi
+ if [ $? -ne 0 ] ; then
+@@ -121,22 +120,28 @@ EOF_READ_XKB
+ main()
+ {
+ if [ x"$DISPLAY" = x ] ; then
+- echo "skip: No display. Maybe headless mode."
++ echo "# skip No display. Maybe headless mode."
+ exit 77
+ fi
+ if ! which setxkbmap > /dev/null ; then
+- echo "skip: No setxkbmap"
++ echo "# skip No setxkbmap"
+ exit 77
+ fi
+
+ parse_args "$@"
+
++ # Meson checks TAP #Version, #Plan, #TestPoint
++ echo "TAP version 14"
++ echo "1..1"
++
+ if [ x"$INSTALLED_SCHEMAS_DIR" != x ] ; then
+ init
+ fi
+
+ test_xkb_keymaps
+
++ echo "ok 1 /$PROGNAME"
++
+ if [ x"$INSTALLED_SCHEMAS_DIR" != x ] ; then
+ finit
+ fi
+--
+2.54.0
+
+From 6d3a98b94f5f19774595af69c54282565fd31873 Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Tue, 19 May 2026 20:03:38 +0900
+Subject: [PATCH 02/15] bus: Unset G_DISABLE_ASSERT for test builds
+
+Now GTest is implemented in test-matchrule and test-stress for TAP
+and G_DISABLE_ASSERT cannot be applied to the test builds.
+
+Also delete the unnecessary GTK2_CFLAGS.
+
+Closes: #2358
+---
+ bus/Makefile.am | 10 +++++-----
+ configure.ac | 3 +++
+ 2 files changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/bus/Makefile.am b/bus/Makefile.am
+index bd3481b9..7fbc9a29 100644
+--- a/bus/Makefile.am
++++ b/bus/Makefile.am
+@@ -3,7 +3,7 @@
+ # ibus - The Input Bus
+ #
+ # Copyright (c) 2007-2013 Peng Huang <shawn.p.huang@gmail.com>
+-# Copyright (c) 2013-2022 Takao Fujiwara <takao.fujiwara1@gmail.com>
++# Copyright (c) 2013-2026 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ # Copyright (c) 2007-2022 Red Hat, Inc.
+ #
+ # This library is free software; you can redistribute it and/or
+@@ -22,6 +22,7 @@
+ # USA
+
+ NULL =
++CFLAGS = $(TEST_CFLAGS)
+ SUBDIRS = . services
+
+ libibus = $(top_builddir)/src/libibus-@IBUS_API_VERSION@.la
+@@ -87,6 +88,7 @@ ibus_daemon_SOURCES = \
+ $(NULL)
+ ibus_daemon_CFLAGS = \
+ $(AM_CFLAGS) \
++ $(PRODUCT_CFLAGS) \
+ $(NULL)
+ ibus_daemon_LDADD = \
+ $(AM_LDADD) \
+@@ -153,13 +155,11 @@ test_stress_SOURCES = \
+ $(NULL)
+ test_stress_CFLAGS = \
+ $(AM_CFLAGS) \
+- @GTK2_CFLAGS@ \
+- @X11_CFLAGS@ \
++ $(X11_CFLAGS) \
+ $(NULL)
+ test_stress_LDADD = \
+ $(AM_LDADD) \
+- @GTK2_LIBS@ \
+- @X11_LIBS@ \
++ $(X11_LIBS) \
+ $(NULL)
+
+ EXTRA_DIST = \
+diff --git a/configure.ac b/configure.ac
+index 49020039..303798fb 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -160,18 +160,21 @@ if test x"$enable_product_build" = xauto; then
+ fi
+ fi
+ TEST_CFLAGS="$CFLAGS"
++PRODUCT_CFLAGS="$CFLAGS"
+ PRODUCT_LIB_CFLAGS=''
+ if test x"$enable_product_build" = xyes; then
+ if test $ac_compiler_gnu = yes; then
+ _CFLAGS="-DG_DISABLE_CAST_CHECKS -Wl,-z,relro -Wl,-z,now $CFLAGS"
+ TEST_CFLAGS="$_CFLAGS"
+ CFLAGS="-DG_DISABLE_ASSERT $_CFLAGS"
++ PRODUCT_CFLAGS="$CFLAGS"
+ PRODUCT_LIB_CFLAGS="-Wl,-Bsymbolic -fno-plt"
+ fi
+ AC_DEFINE(HAVE_PRODUCT_BUILD, 1, [Enable product build])
+ fi
+ AC_SUBST(PRODUCT_LIB_CFLAGS)
+ AC_SUBST(TEST_CFLAGS)
++AC_SUBST(PRODUCT_CFLAGS)
+ AC_MSG_RESULT([$enable_product_build])
+
+ # Check header filess.
+--
+2.54.0
+
+From aeca3e885b1aec02d9f14a5ab6c83f928eca6c9b Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Thu, 7 May 2026 09:35:47 +0900
+Subject: [PATCH 03/15] client/x11: Call setlocale()
+
+To enhance #2547, ibus-x11 replaces gtk_init() with gdk_init().
+Seems gdk_init() does not call setlocale() internally and ibus-x11
+causes some encoding errors when the multi-byte chars are converted
+to the text property of compound text.
+
+BUG=https://github.com/ibus/ibus/issues/2896
+Fixes: https://github.com/ibus/ibus/commit/b185b21
+---
+ client/x11/main.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/client/x11/main.c b/client/x11/main.c
+index 5fadd43d..accebde5 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-2025 Takao Fujiwara <takao.fujiwara1@gmail.com>
++ * Copyright (C) 2015-2026 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2007-2015 Red Hat, Inc.
+ *
+ * main.c:
+@@ -1368,6 +1368,11 @@ main (int argc, char **argv)
+ gdk_set_allowed_backends ("x11");
+ #endif
+
++ /* gdk_init() does not call setlocale() */
++ if (!setlocale (LC_ALL, "")) {
++ g_warning ("Failed to set locale with your environment variables. "
++ "Some multi-byte characters won't be committed correctly.");
++ }
+ gdk_init (&argc, &argv);
+ XSetErrorHandler (_xerror_handler);
+ XSetIOErrorHandler (_xerror_io_handler);
+--
+2.54.0
+
+From 3768387b5c1f72c2c3840ebc4c6a46c3c711c71e Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Fri, 17 Apr 2026 19:54:22 +0900
+Subject: [PATCH 04/15] Disable Unicode input with Ctrl-Shift-u twice
+
+Once the Unicode module receives Ctrl-Shift-u key twice, the pre-edit
+should be disabled as the current IBus engines expect the nest format
+<emoji_preedit <engine_predit /> /> but not the reverse format.
+
+Closes: #2903
+---
+ bus/inputcontext.c | 17 ++++++++++++-----
+ ui/gtk3/panelbinding.vala | 3 +++
+ 2 files changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/bus/inputcontext.c b/bus/inputcontext.c
+index 5adcdf6e..7de594ad 100644
+--- a/bus/inputcontext.c
++++ b/bus/inputcontext.c
+@@ -2,7 +2,7 @@
+ /* vim:set et sts=4: */
+ /* ibus - The Input Bus
+ * Copyright (C) 2008-2014 Peng Huang <shawn.p.huang@gmail.com>
+- * Copyright (C) 2015-2025 Takao Fujiwara <takao.fujiwara1@gmail.com>
++ * Copyright (C) 2015-2026 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ * Copyright (C) 2008-2025 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+@@ -3473,10 +3473,17 @@ bus_input_context_update_preedit_text (BusInputContext *context,
+ }
+
+ context->preedit_cursor_pos = cursor_pos;
+- if (use_extension) {
+- context->preedit_visible = visible;
+- context->preedit_mode = mode;
+- }
++ /* The `visible` flag is set whether use_extension is enabled or not.
++ * I.e. If both an emoji preedit text and an engine preedit exist,
++ * the engine preedit is expected to exist in the emoji preedit like
++ * <emoji_preedit <engine_preedit /> />, so if the emoji preedit is
++ * hidden, the engine preedit is also hidden in the nested state.
++ * If some engines would need the reverse case like
++ * <engine_preedit <emoji_preedit /> />, probably another API is needed
++ * like ibus_engine_show_emoji_candidate_in_preedit().
++ */
++ context->preedit_visible = visible;
++ context->preedit_mode = mode;
+ context->ignore_focus_out = FALSE;
+ extension_visible = context->preedit_visible ||
+ (context->emoji_extension != NULL);
+diff --git a/ui/gtk3/panelbinding.vala b/ui/gtk3/panelbinding.vala
+index 56d7f09c..0f20d973 100644
+--- a/ui/gtk3/panelbinding.vala
++++ b/ui/gtk3/panelbinding.vala
+@@ -885,6 +885,9 @@ class PanelBinding : IBus.PanelService {
+ m_enable_extension = event.is_enabled;
+ if (!m_enable_extension) {
+ hide_emoji_lookup_table();
++ update_preedit_text_received(new IBus.Text.from_string(""),
++ 0,
++ false);
+ return;
+ }
+ if (!m_loaded_emoji)
+--
+2.54.0
+
+From a8ff755971509f09e1d0ea52a10be1bfc13af39b Mon Sep 17 00:00:00 2001
+From: Danny Milosavljevic <dannym@friendly-machines.com>
+Date: Wed, 27 May 2026 13:38:47 +0900
+Subject: [PATCH 05/15] client/wayland: Fix serial handling
+
+Closes: #2870
+---
+ client/wayland/ibuswaylandim.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/client/wayland/ibuswaylandim.c b/client/wayland/ibuswaylandim.c
+index e1bad27d..cf090e2e 100644
+--- a/client/wayland/ibuswaylandim.c
++++ b/client/wayland/ibuswaylandim.c
+@@ -2431,13 +2431,14 @@ registry_handle_global (void *data,
+ interface, name, version);
+ fflush (priv->log);
+ }
+- priv->im_serial = 0;
+ if (!g_strcmp0 (interface, zwp_input_method_manager_v2_interface.name)) {
++ priv->im_serial = 0;
+ priv->version = INPUT_METHOD_V2;
+ priv->input_method_manager_v2 =
+ wl_registry_bind (registry, name,
+ &zwp_input_method_manager_v2_interface, 1);
+ } else if (!g_strcmp0 (interface, zwp_input_method_v1_interface.name)) {
++ priv->im_serial = 0;
+ if (version >= 4)
+ version = 4;
+ priv->version = INPUT_METHOD_V1;
+--
+2.54.0
+
+From 18d8e37e112a155f3f80d36e4d6a845cc2e23bd8 Mon Sep 17 00:00:00 2001
+From: Danny Milosavljevic <dannym@friendly-machines.com>
+Date: Thu, 28 May 2026 09:51:11 +0900
+Subject: [PATCH 06/15] client/wayland: Guard against NULL seat in IMv2 code paths
+
+registry_handle_global_remove() sets priv->seat to NULL when the last
+seat is removed. IBus engine callbacks (commit_text, forward_key_event,
+show/hide_preedit_text, delete_surrounding_text) and the modifier
+handler can fire asynchronously via D-Bus after seat removal, causing
+a NULL pointer dereference.
+
+Add NULL checks for priv->seat in all IMv2 branches that dereference it
+from these callback paths.
+
+Closes: #2877
+---
+ client/wayland/ibuswaylandim.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/client/wayland/ibuswaylandim.c b/client/wayland/ibuswaylandim.c
+index cf090e2e..57b0ad21 100644
+--- a/client/wayland/ibuswaylandim.c
++++ b/client/wayland/ibuswaylandim.c
+@@ -334,6 +334,8 @@ ibus_wayland_im_commit_text (IBusWaylandIM *wlim,
+ str);
+ break;
+ case INPUT_METHOD_V2:
++ if (!priv->seat)
++ break;
+ zwp_input_method_v2_commit_string (priv->seat->input_method_v2, str);
+ zwp_input_method_v2_commit (priv->seat->input_method_v2,
+ priv->im_serial);
+@@ -367,6 +369,8 @@ ibus_wayland_im_key (IBusWaylandIM *wlim,
+ * returns "Cannot send a keypress before defining a keymap"
+ * if `has_keymap` is %FALSE.
+ */
++ if (!priv->seat)
++ break;
+ if (priv->seat->has_keymap) {
+ zwp_virtual_keyboard_v1_key (priv->seat->virtual_keyboard,
+ time, key, state);
+@@ -663,6 +667,8 @@ _context_show_preedit_text_cb (IBusInputContext *context,
+ commit);
+ break;
+ case INPUT_METHOD_V2:
++ if (!priv->seat)
++ break;
+ zwp_input_method_v2_set_preedit_string (
+ priv->seat->input_method_v2,
+ priv->preedit_text->text,
+@@ -693,6 +699,8 @@ _context_hide_preedit_text_cb (IBusInputContext *context,
+ "");
+ break;
+ case INPUT_METHOD_V2:
++ if (!priv->seat)
++ break;
+ zwp_input_method_v2_set_preedit_string (priv->seat->input_method_v2,
+ "", 0, 0);
+ zwp_input_method_v2_commit (priv->seat->input_method_v2,
+@@ -771,6 +779,8 @@ _context_delete_surrounding_text_cb (IBusInputContext *context,
+ before_length + after_length);
+ break;
+ case INPUT_METHOD_V2:
++ if (!priv->seat)
++ break;
+ zwp_input_method_v2_delete_surrounding_text (
+ priv->seat->input_method_v2,
+ before_length,
+@@ -1201,7 +1211,7 @@ ibus_wayland_im_post_key (IBusWaylandIM *wlim,
+ return FALSE;
+ break;
+ case INPUT_METHOD_V2:
+- if (!priv->seat->active)
++ if (!priv->seat || !priv->seat->active)
+ return FALSE;
+ break;
+ default:
+@@ -1760,6 +1770,8 @@ input_method_keyboard_modifiers (void *data,
+ * returns "Cannot send a modifier state before defining a keymap"
+ * if `has_keymap` is %FALSE.
+ */
++ if (!priv->seat)
++ break;
+ if (priv->seat->has_keymap) {
+ zwp_virtual_keyboard_v1_modifiers (priv->seat->virtual_keyboard,
+ mods_depressed, mods_latched,
+--
+2.54.0
+
+From 06b073dfef47b83ee4cf4969f7269b75dff387f7 Mon Sep 17 00:00:00 2001
+From: Danny Milosavljevic <dannym@friendly-machines.com>
+Date: Thu, 28 May 2026 10:24:42 +0900
+Subject: [PATCH 07/15] client/wayland: Fix preedit cursor_end in set_preedit_string
+
+cursor_end was set to strlen(text), making the cursor span from the
+cursor position to the end of the preedit string. Per the
+zwp_input_method_v2 protocol, cursor_begin == cursor_end means a point
+cursor. Pass cursor for both begin and end.
+
+Closes: #2880
+---
+ client/wayland/ibuswaylandim.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/client/wayland/ibuswaylandim.c b/client/wayland/ibuswaylandim.c
+index 57b0ad21..69d10fe8 100644
+--- a/client/wayland/ibuswaylandim.c
++++ b/client/wayland/ibuswaylandim.c
+@@ -673,7 +673,7 @@ _context_show_preedit_text_cb (IBusInputContext *context,
+ priv->seat->input_method_v2,
+ priv->preedit_text->text,
+ cursor,
+- strlen (priv->preedit_text->text));
++ cursor);
+ zwp_input_method_v2_commit (priv->seat->input_method_v2,
+ priv->im_serial);
+ priv->hiding_preedit_text = FALSE;
+--
+2.54.0
+
+From 72b09de3b4c4c3695eb877a70cbe88c4f5c398cd Mon Sep 17 00:00:00 2001
+From: Danny Milosavljevic <dannym@friendly-machines.com>
+Date: Thu, 28 May 2026 10:33:09 +0900
+Subject: [PATCH 08/15] client/wayland: Fix typo "waylayd" -> "wayland" in Makefile.am
+
+The misspelled variable name caused the METADATADIRS and VAPIDIRS
+settings to be silently ignored by automake.
+
+Closes: #2881
+---
+ client/wayland/Makefile.am | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/client/wayland/Makefile.am b/client/wayland/Makefile.am
+index 25269557..3275d1c5 100644
+--- a/client/wayland/Makefile.am
++++ b/client/wayland/Makefile.am
+@@ -184,8 +184,8 @@ MAINTAINERCLEANFILES += $(VAPIGEN_VAPIS)
+ DISTCLEANFILES += $(VAPIGEN_VAPIS)
+ $(VAPIGEN_VAPIS): $(INTROSPECTION_GIRS)
+ ibus_wayland_im_1_0_vapi_DEPS = glib-2.0 gobject-2.0 gio-2.0 ibus-1.0
+-ibus_waylayd_im_1_0_vapi_METADATADIRS = $(srcdir) $(top_srcdir)/bindings/vala
+-#ibus_waylayd_im_1_0_vapi_VAPIDIRS = $(top_srcdir)/bindings/vala
++ibus_wayland_im_1_0_vapi_METADATADIRS = $(srcdir) $(top_srcdir)/bindings/vala
++#ibus_wayland_im_1_0_vapi_VAPIDIRS = $(top_srcdir)/bindings/vala
+ ibus_wayland_im_1_0_vapi_FILES = \
+ $(INTROSPECTION_GIRS) \
+ $(srcdir)/ibus-wayland-im-custom.vala \
+--
+2.54.0
+
+From 614eb098016afe280e860732c60a50aefdb1ed65 Mon Sep 17 00:00:00 2001
+From: Danny Milosavljevic <dannym@friendly-machines.com>
+Date: Thu, 28 May 2026 10:47:34 +0900
+Subject: [PATCH 09/15] ui/gtk3: Fix display wait timeout from ~5 years to 3 minutes
+
+MAX_DISPLAY_IDLE_TIME included G_USEC_PER_SEC in the multiplication,
+making the iteration count 18 billion instead of the intended 18000.
+Each iteration sleeps 10ms, so the effective timeout was 5.7 years
+instead of the intended 3 minutes.
+
+The sleep duration already uses G_USEC_PER_SEC / SLEEP_DIV_PER_SEC,
+so the iteration count should just be SLEEP_DIV_PER_SEC * 60 * 3.
+
+Closes: #2882
+---
+ ui/gtk3/application.vala | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ui/gtk3/application.vala b/ui/gtk3/application.vala
+index dcabc892..aa331543 100644
+--- a/ui/gtk3/application.vala
++++ b/ui/gtk3/application.vala
+@@ -25,7 +25,7 @@ const string IBUS_WAYLAND_VERSION="1.1";
+ const ulong G_USEC_PER_SEC=1000000L;
+ const ulong SLEEP_DIV_PER_SEC = 100L;
+ const ulong MAX_DISPLAY_IDLE_TIME =
+- G_USEC_PER_SEC * SLEEP_DIV_PER_SEC * 60 * 3;
++ SLEEP_DIV_PER_SEC * 60 * 3;
+
+ static string prgname;
+ static IBus.Bus bus;
+--
+2.54.0
+
+From 41f36c09b47daf34accecb5c0b870af63b3ba730 Mon Sep 17 00:00:00 2001
+From: Danny Milosavljevic <dannym@friendly-machines.com>
+Date: Thu, 28 May 2026 10:59:14 +0900
+Subject: [PATCH 10/15] ui/gtk3: Fix log timestamp losing microsecond precision
+
+get_microsecond() was divided by 1000 (giving milliseconds) then
+formatted with %06d, producing misleading output like "000846".
+Use get_microsecond() directly with %06d, matching the C counterpart
+in ibuswaylandim.c. Also use '.' separator instead of ':' to
+distinguish sub-second part from the time fields.
+
+Closes: #2884
+---
+ ui/gtk3/application.vala | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/ui/gtk3/application.vala b/ui/gtk3/application.vala
+index aa331543..a9962685 100644
+--- a/ui/gtk3/application.vala
++++ b/ui/gtk3/application.vala
+@@ -216,9 +216,9 @@ class Application {
+ if (m_user == null)
+ m_user = "UNKNOW";
+ GLib.DateTime now = new GLib.DateTime.now_local();
+- var msec = now.get_microsecond() / 1000;
+- m_log.printf("Start %02d:%02d:%02d:%06d\n",
+- now.get_hour(), now.get_minute(), now.get_second(), msec);
++ m_log.printf("Start %02d:%02d:%02d.%06d\n",
++ now.get_hour(), now.get_minute(), now.get_second(),
++ now.get_microsecond());
+ m_log.flush();
+ return true;
+ }
+--
+2.54.0
+
+From e8d36baadfb138742403b484dbaaa53d1bdda3bc Mon Sep 17 00:00:00 2001
+From: Danny Milosavljevic <dannym@friendly-machines.com>
+Date: Thu, 28 May 2026 11:07:10 +0900
+Subject: [PATCH 11/15] client/wayland: Copy keysym into async key event
+
+_process_key_event_async() did not copy event->sym into the async
+event struct. The callback _process_key_event_done() then called
+ibus_wayland_im_post_key() with sym=0, so ISO_Level*_Latch keysyms
+were not filtered in async mode.
+
+Closes: #2886
+---
+ client/wayland/ibuswaylandim.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/client/wayland/ibuswaylandim.c b/client/wayland/ibuswaylandim.c
+index 69d10fe8..37fe4bad 100644
+--- a/client/wayland/ibuswaylandim.c
++++ b/client/wayland/ibuswaylandim.c
+@@ -1419,6 +1419,7 @@ _process_key_event_async (IBusWaylandIM *wlim,
+ async_event->key_serial = event->key_serial;
+ async_event->time = event->time;
+ async_event->key = event->key;
++ async_event->sym = event->sym;
+ async_event->modifiers = event->modifiers & ~IBUS_RELEASE_MASK;
+ async_event->state = event->state;
+ async_event->wlim = wlim;
+--
+2.54.0
+
+From 526e509b968cb1334727dbdc9f91f44e8dc038b5 Mon Sep 17 00:00:00 2001
+From: matiwari <matiwari@redhat.com>
+Date: Thu, 28 May 2026 11:21:25 +0900
+Subject: [PATCH 12/15] ui/gtk3: remove unused m_candidates array
+
+The 'm_candidates' array was never read and retained references to obsolete
+Gtk.Label objects during panel rebuilds, contributing to a memory leak.
+
+Closes: #2471
+---
+ ui/gtk3/emojier.vala | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
+index 097edbda..d899780f 100644
+--- a/ui/gtk3/emojier.vala
++++ b/ui/gtk3/emojier.vala
+@@ -358,7 +358,6 @@ public class IBusEmojier : Gtk.ApplicationWindow {
+ */
+ private bool m_candidate_panel_mode;
+ private IBus.LookupTable m_lookup_table;
+- private Gtk.Label[] m_candidates;
+ private uint m_entry_notify_show_id;
+ private uint m_entry_notify_disable_id;
+ private Gtk.ProgressBar m_unicode_progress_bar;
+@@ -1668,7 +1667,6 @@ public class IBusEmojier : Gtk.ApplicationWindow {
+ 1, 1);
+ n++;
+
+- m_candidates += label;
+ }
+ m_candidate_panel_is_visible = true;
+ if (!m_is_up_side_down) {
+--
+2.54.0
+
+From 5bbe88a1936246185a65f76e58cc85871401e59a Mon Sep 17 00:00:00 2001
+From: Tianhao Chai <cth451@gmail.com>
+Date: Wed, 27 May 2026 13:11:28 +0900
+Subject: [PATCH 13/15] src: make an IBusText own an updated IBusAttrList reference
+
+For all usages of IBusAttrList, the list is an owned reference within a
+IBusText struct. `ibus_panel_convert_text()` and
+`ibus_input_context_convert_text()` violate the invarient by assigning a
+**floating** IBusAttrList reference to anIBusText without sinking it.
+
+When GJS attempts to create a JS representation of an existing GObject,
+it unconditionally sinks the incoming reference.[1] For a non-floating
+reference this up-refs the object.
+
+For this floating IBusAttrLit, `g_object_ref_sink` converts it to a
+strong reference in-place leaving ref-count at 1. At this point the
+`IBusAttrList` is referenced by both the enclosing `IBusText` and the
+newly created GJS wrapper. When one of them is ref-downed the object
+is recycled, leaving the other reference dangling.
+
+To fix this we just need to maintain the list as a non-floating ref.
+We already have a `ibus_text_set_attributes()` that does the intended
+ref sinking, so just use that instead of manually assigning pointers.
+
+[1]: https://gitlab.gnome.org/GNOME/gjs/-/blob/db450465ab0161e131a92992c2509507aa6152aa/gi/object.cpp#L3597
+
+Closes: #2889
+---
+ src/ibusinputcontext.c | 12 ++++--------
+ src/ibuspanelservice.c | 12 ++++--------
+ 2 files changed, 8 insertions(+), 16 deletions(-)
+
+diff --git a/src/ibusinputcontext.c b/src/ibusinputcontext.c
+index 68d12fb5..bdfd166d 100644
+--- a/src/ibusinputcontext.c
++++ b/src/ibusinputcontext.c
+@@ -569,10 +569,8 @@ ibus_input_context_convert_text (IBusInputContext *context,
+ text->text, error->message);
+ g_error_free (error);
+ }
+- if (new_attrs) {
+- g_object_unref (text->attrs);
+- text->attrs = new_attrs;
+- }
++ if (new_attrs)
++ ibus_text_set_attributes (text, new_attrs);
+ break;
+ case IBUS_PREEDIT_FORMAT_HINT:
+ new_attrs = ibus_attr_list_copy_format_to_hint (text->attrs, &error);
+@@ -581,10 +579,8 @@ ibus_input_context_convert_text (IBusInputContext *context,
+ text->text, error->message);
+ g_error_free (error);
+ }
+- if (new_attrs) {
+- g_object_unref (text->attrs);
+- text->attrs = new_attrs;
+- }
++ if (new_attrs)
++ ibus_text_set_attributes (text, new_attrs);
+ break;
+ default:
+ g_assert_not_reached ();
+diff --git a/src/ibuspanelservice.c b/src/ibuspanelservice.c
+index 16229822..f50cea19 100644
+--- a/src/ibuspanelservice.c
++++ b/src/ibuspanelservice.c
+@@ -1203,10 +1203,8 @@ ibus_panel_convert_text (IBusPanelService *panel,
+ text->text, error->message);
+ g_error_free (error);
+ }
+- if (new_attrs) {
+- g_object_unref (text->attrs);
+- text->attrs = new_attrs;
+- }
++ if (new_attrs)
++ ibus_text_set_attributes (text, new_attrs);
+ break;
+ case IBUS_PREEDIT_FORMAT_HINT:
+ new_attrs = ibus_attr_list_copy_format_to_hint (text->attrs, &error);
+@@ -1215,10 +1213,8 @@ ibus_panel_convert_text (IBusPanelService *panel,
+ text->text, error->message);
+ g_error_free (error);
+ }
+- if (new_attrs) {
+- g_object_unref (text->attrs);
+- text->attrs = new_attrs;
+- }
++ if (new_attrs)
++ ibus_text_set_attributes (text, new_attrs);
+ break;
+ default:
+ g_assert_not_reached ();
+--
+2.54.0
+
+From 067de1c2b7fa1d464686cce41331b37c0b9c2886 Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Wed, 27 May 2026 13:26:43 +0900
+Subject: [PATCH 14/15] Add test-deserialize.py
+
+Add a test case to deserialize IBusText
+
+Closes: #2889
+---
+ bindings/pygobject/Makefile.am | 41 ++++----
+ bindings/pygobject/test-deserialize.py | 118 +++++++++++++++++++++++
+ bindings/pygobject/test-override-ibus.py | 11 +--
+ src/ibuspanelservice.c | 9 +-
+ src/tests/runtest | 12 ++-
+ 6 files changed, 167 insertions(+), 28 deletions(-)
+ create mode 100755 bindings/pygobject/test-deserialize.py
+ mode change 100644 => 100755 bindings/pygobject/test-override-ibus.py
+
+diff --git a/bindings/pygobject/Makefile.am b/bindings/pygobject/Makefile.am
+index 84bd37cb..255f5989 100644
+--- a/bindings/pygobject/Makefile.am
++++ b/bindings/pygobject/Makefile.am
+@@ -4,7 +4,7 @@
+ #
+ # Copyright (c) 2012 Daiki Ueno <ueno@unixuser.org>
+ # Copyright (c) 2014-2016 Peng Huang <shawn.p.huang@gmail.com>
+-# Copyright (c) 2018-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
++# Copyright (c) 2018-2026 Takao Fujiwara <takao.fujiwara1@gmail.com>
+ # Copyright (c) 2012-2018 Red Hat, Inc.
+ #
+ # This library is free software; you can redistribute it and/or
+@@ -27,37 +27,40 @@ NULL =
+ if ENABLE_PYTHON2
+ py2_compile = PYTHON=$(PYTHON2) $(SHELL) $(py_compile)
+ overrides2dir = $(py2overridesdir)
+-overrides2_DATA = \
+- gi/overrides/IBus.py \
+- $(NULL)
++overrides2_DATA = \
++ gi/overrides/IBus.py \
++ $(NULL)
+ endif
+
+ overridesdir = $(pyoverridesdir)
+-overrides_PYTHON = \
+- gi/overrides/IBus.py \
+- $(NULL)
++overrides_PYTHON = \
++ gi/overrides/IBus.py \
++ $(NULL)
+
+ TESTS =
+
+ if ENABLE_TESTS
+-TESTS += test-override-ibus.py
++TESTS += test-deserialize.py test-override-ibus.py
+ endif
+
+ # IBus.Keymap() accesses keymap files
+ TESTS_ENVIRONMENT = \
+- PYTHONPATH=$(top_srcdir)/tests:$${PYTHONPATH:+:$$PYTHONPATH} \
+- LD_LIBRARY_PATH=$(top_builddir)/src/.libs:$$LD_LIBRARY_PATH \
+- GI_TYPELIB_PATH=$(top_builddir)/src:$$GI_TYPELIB_PATH \
+- IBUS_KEYMAP_PATH=$(top_srcdir)/data/keymaps \
+- $(NULL)
++ top_srcdir=$(top_srcdir) \
++ PYTHONPATH=$(abs_top_srcdir)/tests:$${PYTHONPATH:+:$$PYTHONPATH} \
++ PYTHONMALLOC=malloc \
++ LD_LIBRARY_PATH=$(abs_top_builddir)/src/.libs:$$LD_LIBRARY_PATH \
++ GI_TYPELIB_PATH=$(abs_top_builddir)/src:$$GI_TYPELIB_PATH \
++ IBUS_KEYMAP_PATH=$(abs_top_srcdir)/data/keymaps \
++ $(NULL)
+
+-LOG_COMPILER = $(PYTHON) -B
++LOG_COMPILER = $(top_srcdir)/src/tests/runtest $(PYTHON)
+
+-EXTRA_DIST = \
+- gi/__init__.py \
+- gi/overrides/__init__.py \
+- test-override-ibus.py \
+- $(NULL)
++EXTRA_DIST = \
++ gi/__init__.py \
++ gi/overrides/__init__.py \
++ test-deserialize.py \
++ test-override-ibus.py \
++ $(NULL)
+
+ install-data-hook:
+ @$(NORMAL_INSTALL)
+diff --git a/bindings/pygobject/test-deserialize.py b/bindings/pygobject/test-deserialize.py
+new file mode 100755
+index 00000000..290914d7
+--- /dev/null
++++ b/bindings/pygobject/test-deserialize.py
+@@ -0,0 +1,118 @@
++#!/usr/bin/python
++# ibus - The Input Bus
++#
++# Copyright © 2026 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
++
++import sys
++import unittest
++from pathlib import Path
++
++# move the script path at the end, so the necessary modules in system
++# pygobject can be loaded first
++tests_builddir = Path(__file__).resolve().parent
++sys.path = [path for path in sys.path if Path(path) != tests_builddir]
++sys.path.append(str(tests_builddir))
++
++from gi import require_versions as gi_require_versions
++
++gi_require_versions({'IBus': '1.0', 'GLib': '2.0', 'Gio': '2.0', })
++from gi.repository import IBus
++from gi.repository import GLib
++from gi.repository import Gio
++
++
++class TestOverride(unittest.TestCase):
++ __bus = None
++ __text = None
++ __attrs = None
++ __invocation = None
++
++ def setUp(self):
++ IBus.init()
++ self.__bus = IBus.Bus()
++
++ def update_preedit_text_cb(self,
++ context,
++ text,
++ cursor,
++ visible):
++ self.update_preedit_text_with_mode_cb(
++ context, text, cursor, visible, 0)
++
++ def update_preedit_text_with_mode_cb(self,
++ context,
++ text,
++ cursor,
++ visible,
++ mode):
++ self.__text = text
++ self.__attrs = self.__text.get_attributes()
++ print('# Got update-preedit-text-with-mode',
++ self.__text.get_text(), cursor, visible, mode)
++
++
++ def test_deserialized_input_context(self):
++ text = IBus.Text.new_from_string('test')
++ text.append_attribute(IBus.AttrType.HINT,
++ IBus.AttrPreedit.WHOLE,
++ 0,
++ text.get_length())
++ text_variant = text.serialize_object()
++ update_preedit_variant = GLib.Variant.new_tuple(
++ GLib.Variant.new_variant(text_variant),
++ GLib.Variant.new_uint32(0),
++ GLib.Variant.new_boolean(True),
++ GLib.Variant.new_uint32(0))
++ context = self.__bus.create_input_context('test')
++ context.connect('update-preedit-text-with-mode',
++ self.update_preedit_text_with_mode_cb)
++ context.do_g_signal(context,
++ 'org.freedesktop.DBus',
++ 'UpdatePreeditTextWithMode',
++ update_preedit_variant)
++ print('# Last', self.__attrs, self.__text.get_text())
++
++ def test_deserialized_panel(self):
++ text = IBus.Text.new_from_string('test')
++ text.append_attribute(IBus.AttrType.HINT,
++ IBus.AttrPreedit.WHOLE,
++ 0,
++ text.get_length())
++ text_variant = text.serialize_object()
++ update_preedit_variant = GLib.Variant.new_tuple(
++ GLib.Variant.new_variant(text_variant),
++ GLib.Variant.new_uint32(0),
++ GLib.Variant.new_boolean(True))
++ panel = IBus.PanelService.new(self.__bus.get_connection())
++ panel.connect('update-preedit-text',
++ self.update_preedit_text_cb)
++ self.__invocation = Gio.DBusMethodInvocation()
++ panel.do_service_method_call(panel,
++ self.__bus.get_connection(),
++ 'org.freedesktop.IBus.NullInvocation',
++ IBus.PATH_PANEL + '/DryTest',
++ IBus.INTERFACE_PANEL,
++ 'UpdatePreeditText',
++ update_preedit_variant.ref(),
++ self.__invocation)
++ print('# Last', self.__attrs, self.__text.get_text())
++
++
++if __name__ == '__main__':
++ GLib.log_set_fatal_mask('GLib', GLib.LogLevelFlags.LEVEL_WARNING)
++ unittest.main()
+diff --git a/bindings/pygobject/test-override-ibus.py b/bindings/pygobject/test-override-ibus.py
+old mode 100644
+new mode 100755
+index 8853ff64..89073a08
+--- a/bindings/pygobject/test-override-ibus.py
++++ b/bindings/pygobject/test-override-ibus.py
+@@ -20,16 +20,15 @@
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ # USA
+
+-import unittest
+-
+-import os
+ import sys
++import unittest
++from pathlib import Path
+
+ # move the script path at the end, so the necessary modules in system
+ # pygobject can be loaded first
+-tests_builddir = os.path.abspath(os.path.dirname(__file__))
+-sys.path = [path for path in sys.path if path != tests_builddir]
+-sys.path.append(tests_builddir)
++tests_builddir = Path(__file__).resolve().parent
++sys.path = [path for path in sys.path if Path(path) != tests_builddir]
++sys.path.append(str(tests_builddir))
+
+ import gi
+ gi.require_versions({'GLib': '2.0', 'IBus': '1.0'})
+diff --git a/src/ibuspanelservice.c b/src/ibuspanelservice.c
+index f50cea19..14cca3ec 100644
+--- a/src/ibuspanelservice.c
++++ b/src/ibuspanelservice.c
+@@ -1255,6 +1255,7 @@ ibus_panel_service_service_method_call (IBusService *service,
+ guint cursor = 0;
+ gboolean visible = FALSE;
+ IBusText *text;
++ gboolean is_dry_test;
+
+ g_variant_get (parameters, "(vub)", &variant, &cursor, &visible);
+ text = IBUS_TEXT (ibus_serializable_deserialize (variant));
+@@ -1263,7 +1264,13 @@ ibus_panel_service_service_method_call (IBusService *service,
+
+ g_signal_emit (panel, panel_signals[UPDATE_PREEDIT_TEXT], 0, text, cursor, visible);
+ _g_object_unref_if_floating (text);
+- g_dbus_method_invocation_return_value (invocation, NULL);
++ is_dry_test = !g_strcmp0 (object_path, IBUS_PATH_PANEL "/DryTest");
++ /* GDBusMethodInvocation does not provide instance methods for Python
++ * gobject-introspection binding so we cannot call
++ * g_dbus_method_invocation_return_value() and g_object_unref().
++ */
++ if (!is_dry_test)
++ g_dbus_method_invocation_return_value (invocation, NULL);
+ return;
+ }
+
+diff --git a/src/tests/runtest b/src/tests/runtest
+index 7bd98575..4e54420f 100755
+--- a/src/tests/runtest
++++ b/src/tests/runtest
+@@ -37,11 +37,13 @@ ibus-engine-switch
+ ibus-compose
+ ibus-keypress
+ test-stress
++test-deserialize.py
+ test-override-ibus.py
+ "
+ IBUS_SCHEMA_FILE='org.freedesktop.ibus.gschema.xml'
+ GTK_QUERY_MODULE=gtk-query-immodules-3.0-32
+ MACHINE=`uname -m`
++PYTHON_TEST_ARGS='-B'
+
+ if test x"$MACHINE" = xx86_64 ; then
+ GTK_QUERY_MODULE=gtk-query-immodules-3.0-64
+@@ -137,6 +139,12 @@ run_test_case()
+ cd $tstdir
+
+ if echo "$tst" | grep -q 'python' ; then
++ # Convert the relative path to the absolute path.
++ if echo "$tst" | grep -q "\./" ; then
++ tst=`realpath $tst`
++ elif ! echo "$tst" | grep -q "/" ; then
++ tst=`command -v $tst`
++ fi
+ name=`func_basename "$1"`
+ else
+ name=`func_basename "$tst"`
+@@ -247,10 +255,10 @@ run_test_case()
+ shift
+ if echo "$tst" | grep -q '^/' ; then
+ # absolute path for Meson
+- "$interpreter" "$tst" ${1+"$@"}
++ "$interpreter" $PYTHON_TEST_ARGS "$tst" ${1+"$@"}
+ else
+ # relative path for autotools
+- "$interpreter" "../$tst" ${1+"$@"}
++ "$interpreter" $PYTHON_TEST_ARGS "../$tst" ${1+"$@"}
+ fi
+ else
+ # absolute path for Meson
+--
+2.54.0
+
+From 26aaf13bd62b972cfee1f4b58ba168d214e99eca Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Tue, 26 May 2026 21:19:43 +0900
+Subject: [PATCH 15/15] client/wayland: Ignore wrong cursor and anchor in surrounding-text
+
+KDE Plasma could send wrong cursor and anchor with surrounding_text()
+signal in `zwp_input_method_context_v1_listener`.
+I'm not sure if it's caused by the compositor or IBus engines but
+ibus-wayland should ignore them.
+
+Closes: rhbz#2444787
+---
+ client/wayland/ibuswaylandim.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/client/wayland/ibuswaylandim.c b/client/wayland/ibuswaylandim.c
+index 37fe4bad..367b07c5 100644
+--- a/client/wayland/ibuswaylandim.c
++++ b/client/wayland/ibuswaylandim.c
+@@ -805,11 +805,21 @@ handle_surrounding_text (void *data,
+ #if ENABLE_SURROUNDING
+ IBusWaylandIM *wlim = data;
+ IBusWaylandIMPrivate *priv;
++ size_t len;
+ IBusText *ibustext;
+
+ g_return_if_fail (IBUS_IS_WAYLAND_IM (wlim));
++ g_return_if_fail (text);
+ priv = ibus_wayland_im_get_instance_private (wlim);
+
++ len = strlen (text);
++ if (G_UNLIKELY (len > G_MAXUINT32 || len < cursor || len < anchor)) {
++ /* Should not show the text as a security reason. */
++ g_warning ("Received a wrong surrounding text length %zu < cursor %u "
++ "anchor %u",
++ len, cursor, anchor);
++ return;
++ }
+ ibustext = ibus_text_new_from_string (text);
+
+ if (priv->surrounding_text)
+--
+2.54.0
+
diff --git a/ibus.spec b/ibus.spec
index c4d3dff..7c44ad6 100644
--- a/ibus.spec
+++ b/ibus.spec
@@ -58,7 +58,7 @@
Name: ibus
Version: 1.5.34
# https://github.com/fedora-infra/rpmautospec/issues/101
-Release: 1%{?dist}
+Release: 2%{?dist}
Summary: Intelligent Input Bus for Linux OS
License: LGPL-2.1-or-later
URL: https://github.com/ibus/%name/wiki
@@ -67,6 +67,7 @@ Source1: https://github.com/ibus/%name/releases/download/%{source_version
Source2: %{name}-xinput
Source3: %{name}.conf.5
# Patch0: %%{name}-HEAD.patch
+Patch0: %{name}-HEAD.patch
# Under testing #1349148 #1385349 #1350291 #1406699 #1432252 #1601577
Patch1: %{name}-1385349-segv-bus-proxy.patch
@@ -583,6 +584,12 @@ dconf update || :
%{_datadir}/installed-tests/ibus
%changelog
+* Wed Jun 03 2026 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.34-2
+- Backport upstream patches
+- Make an IBusText own an updated IBusAttrList reference
+- Resolves: #2444787 SEGV with wrong anchor in surrounding-text in Wayland
+- Updates: #2480408 IBus callbacks in Wayland to clarify SEGVs
+
* Thu Apr 30 2026 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.34-1
- Bump to 1.5.34
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-06-03 3:16 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-03 3:16 [rpms/ibus] f44: Backport upstream patches Takao Fujiwara
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox