diff --git a/Containerfile b/Containerfile index 49189910..417a65d7 100644 --- a/Containerfile +++ b/Containerfile @@ -502,7 +502,8 @@ RUN --mount=type=cache,dst=/var/cache/rpm-ostree \ ibus-gtk4 \ ibus-libs \ ibus-panel \ - ibus-setup && \ + ibus-setup \ + ibus-xinit && \ rpm-ostree install \ jupiter-sd-mounting-btrfs \ at-spi2-core.i686 \ diff --git a/spec_files/ibus/ibus-1.5.30.tar.gz.sum b/spec_files/ibus/ibus-1.5.30.tar.gz.sum new file mode 100644 index 00000000..7aa32dac --- /dev/null +++ b/spec_files/ibus/ibus-1.5.30.tar.gz.sum @@ -0,0 +1,4 @@ +cksum 4283112382 4124084 ibus-1.5.30.tar.gz +sha1sum cda03c8622d5817e1a968b38bd05240e2102928d ibus-1.5.30.tar.gz +sha256sum 05b84d4a45139face161596e5ade8e6c5da55cfaf6f194861da66516190f5b96 ibus-1.5.30.tar.gz +sha512sum cbed37bf62e8d8593c838f8ef7fe0b22bf8f4a661b887fc7be2f2768dda912075abdf3070c22b9699def90e7002aaaf7394f5fc590e12ef6ebb2bb5161cc29a0 ibus-1.5.30.tar.gz diff --git a/spec_files/ibus/ibus-1385349-segv-bus-proxy.patch b/spec_files/ibus/ibus-1385349-segv-bus-proxy.patch new file mode 100644 index 00000000..7254d7d1 --- /dev/null +++ b/spec_files/ibus/ibus-1385349-segv-bus-proxy.patch @@ -0,0 +1,650 @@ +From 68996e1430e3478bda1201d8e31a82679b2659a4 Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Sat, 30 Sep 2023 11:50:14 +0900 +Subject: [PATCH] Fix SEGV in bus_panel_proxy_focus_in() + +rhbz#1350291 SEGV in BUS_IS_CONNECTION(skip_connection) in +bus_dbus_impl_dispatch_message_by_rule() +check if dbus_connection is closed in bus_dbus_impl_connection_filter_cb(). + +rhbz#1767976 SEGV in assert(connection != NULL) in +bus_dbus_impl_connection_filter_cb() +call bus_connection_set_filter() in bus_dbus_impl_destroy(). + +rhbz#2213445 SEGV in bus_panel_proxy_new() +WIP: Add a GError. + +rhbz#1601577 rhbz#1797726 SEGV in ibus_engine_desc_get_layout() in +bus_engine_proxy_new_internal() +WIP: Add a GError to get the error message to check why the SEGV happened. + +rhbz#1663528 SEGV in g_mutex_clear() in bus_dbus_impl_destroy() +If the mutex is not unlocked, g_mutex_clear() causes assert. + +rhbz#1767691 SEGV in client/x11/main.c:_sighandler(). +Do not call atexit functions in _sighandler(). + +rhbz#2195895 SEGV in client/x11/main.c:_xim_set_cursor_location() +check if IBusInputContext was disconnected. + +rhbz#1795499 rhbz#1936777 SEGV in ibus_bus_get_bus_address() because of +no _bus->priv. +_changed_cb() should not be called after ibus_bus_destroy() is called. + +rhbz#1771238 SEGV in assert(m_loop == null) in switcher.vala. +Grabbing keyboard could be failed and switcher received the keyboard +events and m_loop was not released. + +rhbz#1797120 SEGV in assert(bus.is_connected()) in panel_binding_construct() +Check m_ibus in extension.vala:bus_name_acquired_cb() + +rhbz#2151344 SEGV with portal_context->owner in name_owner_changed() +Maybe g_object_unref() is called but not finalized yet. + +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#1767691 +BUG=rhbz#1795499 +BUG=rhbz#1771238 +BUG=rhbz#1767976 +BUG=rhbz#1797120 +BUG=rhbz#2151344 +BUG=rhbz#2195895 +BUG=rhbz#2239633 +--- + bus/dbusimpl.c | 47 ++++++++++++++++++++++++--- + bus/engineproxy.c | 44 +++++++++++++++++++------ + bus/panelproxy.c | 9 +++++- + client/x11/main.c | 56 ++++++++++++++++++++++++++++---- + portal/portal.c | 25 ++++++++++++--- + src/ibusbus.c | 6 ++++ + ui/gtk3/extension.vala | 4 +++ + ui/gtk3/switcher.vala | 73 +++++++++++++++++++++++++----------------- + 8 files changed, 208 insertions(+), 56 deletions(-) + +diff --git a/bus/dbusimpl.c b/bus/dbusimpl.c +index 59787a80..af2fbde2 100644 +--- a/bus/dbusimpl.c ++++ b/bus/dbusimpl.c +@@ -610,6 +610,7 @@ static void + bus_dbus_impl_destroy (BusDBusImpl *dbus) + { + GList *p; ++ int i; + + for (p = dbus->objects; p != NULL; p = p->next) { + IBusService *object = (IBusService *) p->data; +@@ -633,6 +634,10 @@ bus_dbus_impl_destroy (BusDBusImpl *dbus) + + for (p = dbus->connections; p != NULL; p = p->next) { + BusConnection *connection = BUS_CONNECTION (p->data); ++ /* rhbz#1767976 Fix connection == NULL in ++ * bus_dbus_impl_connection_filter_cb() ++ */ ++ bus_connection_set_filter (connection, NULL, NULL, NULL); + g_signal_handlers_disconnect_by_func (connection, + bus_dbus_impl_connection_destroy_cb, dbus); + ibus_object_destroy (IBUS_OBJECT (connection)); +@@ -647,12 +652,39 @@ bus_dbus_impl_destroy (BusDBusImpl *dbus) + dbus->unique_names = NULL; + dbus->names = NULL; + ++ for (i = 0; g_idle_remove_by_data (dbus); i++) { ++ if (i > 1000) { ++ g_warning ("Too many idle threads were generated by " \ ++ "bus_dbus_impl_forward_message_idle_cb and " \ ++ "bus_dbus_impl_dispatch_message_by_rule_idle_cb"); ++ break; ++ } ++ } + g_list_free_full (dbus->start_service_calls, + (GDestroyNotify) bus_method_call_free); + dbus->start_service_calls = NULL; + +- g_mutex_clear (&dbus->dispatch_lock); +- g_mutex_clear (&dbus->forward_lock); ++ /* rhbz#1663528 Call g_mutex_trylock() before g_mutex_clear() ++ * because if the mutex is not unlocked, g_mutex_clear() causes assert. ++ */ ++#define BUS_DBUS_MUTEX_SAFE_CLEAR(mtex) { \ ++ int count = 0; \ ++ while (!g_mutex_trylock ((mtex))) { \ ++ g_usleep (1); \ ++ if (count > 60) { \ ++ g_warning (#mtex " is dead lock"); \ ++ break; \ ++ } \ ++ ++count; \ ++ } \ ++ g_mutex_unlock ((mtex)); \ ++ g_mutex_clear ((mtex)); \ ++} ++ ++ BUS_DBUS_MUTEX_SAFE_CLEAR (&dbus->dispatch_lock); ++ BUS_DBUS_MUTEX_SAFE_CLEAR (&dbus->forward_lock); ++ ++#undef BUS_DBUS_MUTEX_SAFE_CLEAR + + /* FIXME destruct _lock and _queue members. */ + IBUS_OBJECT_CLASS(bus_dbus_impl_parent_class)->destroy ((IBusObject *) dbus); +@@ -1483,13 +1515,20 @@ bus_dbus_impl_connection_filter_cb (GDBusConnection *dbus_connection, + gboolean incoming, + gpointer user_data) + { ++ BusDBusImpl *dbus; ++ BusConnection *connection; ++ + g_assert (G_IS_DBUS_CONNECTION (dbus_connection)); + g_assert (G_IS_DBUS_MESSAGE (message)); + g_assert (BUS_IS_DBUS_IMPL (user_data)); + +- BusDBusImpl *dbus = (BusDBusImpl *) user_data; +- BusConnection *connection = bus_connection_lookup (dbus_connection); ++ if (g_dbus_connection_is_closed (dbus_connection)) ++ return NULL; ++ ++ dbus = (BusDBusImpl *) user_data; ++ connection = bus_connection_lookup (dbus_connection); + g_assert (connection != NULL); ++ g_assert (BUS_IS_CONNECTION (connection)); + + if (incoming) { + /* is incoming message */ +diff --git a/bus/engineproxy.c b/bus/engineproxy.c +index b3e16066..ba479b59 100644 +--- a/bus/engineproxy.c ++++ b/bus/engineproxy.c +@@ -693,10 +693,12 @@ bus_engine_proxy_g_signal (GDBusProxy *proxy, + g_return_if_reached (); + } + ++#pragma GCC optimize ("O0") + static BusEngineProxy * + bus_engine_proxy_new_internal (const gchar *path, + IBusEngineDesc *desc, +- GDBusConnection *connection) ++ GDBusConnection *connection, ++ GError **error) + { + GDBusProxyFlags flags; + BusEngineProxy *engine; +@@ -706,12 +708,20 @@ bus_engine_proxy_new_internal (const gchar *path, + g_assert (path); + g_assert (IBUS_IS_ENGINE_DESC (desc)); + g_assert (G_IS_DBUS_CONNECTION (connection)); ++ g_assert (error && *error == NULL); + ++ /* rhbz#1601577 engine == NULL if connection is closed. */ ++ if (g_dbus_connection_is_closed (connection)) { ++ *error = g_error_new (G_DBUS_ERROR, ++ G_DBUS_ERROR_FAILED, ++ "Connection is closed."); ++ return NULL; ++ } + flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START; + engine = (BusEngineProxy *) g_initable_new ( + BUS_TYPE_ENGINE_PROXY, + NULL, +- NULL, ++ error, + "desc", desc, + "g-connection", connection, + "g-interface-name", IBUS_INTERFACE_ENGINE, +@@ -719,6 +729,12 @@ bus_engine_proxy_new_internal (const gchar *path, + "g-default-timeout", g_gdbus_timeout, + "g-flags", flags, + NULL); ++ /* FIXME: rhbz#1601577 */ ++ if (!engine) { ++ /* show abrt local variable */ ++ gchar *message = g_strdup ((*error)->message); ++ g_error ("%s", message); ++ } + const gchar *layout = ibus_engine_desc_get_layout (desc); + if (layout != NULL && layout[0] != '\0') { + engine->keymap = ibus_keymap_get (layout); +@@ -756,6 +772,7 @@ bus_engine_proxy_new_internal (const gchar *path, + + return engine; + } ++#pragma GCC reset_options + + typedef struct { + GTask *task; +@@ -818,23 +835,30 @@ create_engine_ready_cb (BusFactoryProxy *factory, + GAsyncResult *res, + EngineProxyNewData *data) + { ++ GError *error = NULL; ++ gchar *path; ++ BusEngineProxy *engine; ++ + g_return_if_fail (data->task != NULL); + +- GError *error = NULL; +- gchar *path = bus_factory_proxy_create_engine_finish (factory, +- res, +- &error); ++ path = bus_factory_proxy_create_engine_finish (factory, res, &error); + if (path == NULL) { + g_task_return_error (data->task, error); + engine_proxy_new_data_free (data); + return; + } + +- BusEngineProxy *engine = +- bus_engine_proxy_new_internal (path, +- data->desc, +- g_dbus_proxy_get_connection ((GDBusProxy *)data->factory)); ++ engine = bus_engine_proxy_new_internal ( ++ path, ++ data->desc, ++ g_dbus_proxy_get_connection ((GDBusProxy *)data->factory), ++ &error); + g_free (path); ++ if (!engine) { ++ g_task_return_error (data->task, error); ++ engine_proxy_new_data_free (data); ++ return; ++ } + + /* FIXME: set destroy callback ? */ + g_task_return_pointer (data->task, engine, NULL); +diff --git a/bus/panelproxy.c b/bus/panelproxy.c +index e6001ebf..00828fbc 100644 +--- a/bus/panelproxy.c ++++ b/bus/panelproxy.c +@@ -122,6 +122,8 @@ bus_panel_proxy_new (BusConnection *connection, + const gchar *path = NULL; + GObject *obj; + BusPanelProxy *panel; ++ GError *error = NULL; ++ const gchar *message; + + g_assert (BUS_IS_CONNECTION (connection)); + +@@ -138,7 +140,7 @@ bus_panel_proxy_new (BusConnection *connection, + + obj = g_initable_new (BUS_TYPE_PANEL_PROXY, + NULL, +- NULL, ++ &error, + "g-object-path", path, + "g-interface-name", IBUS_INTERFACE_PANEL, + "g-connection", bus_connection_get_dbus_connection (connection), +@@ -146,6 +148,11 @@ bus_panel_proxy_new (BusConnection *connection, + "g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL); + ++ if (error) { ++ /* TODO: rhbz#2213445 Why does this issue happen? */ ++ message = error->message; ++ g_critical ("Failed to generate BusPanelProxy: %s", message); ++ } + panel = BUS_PANEL_PROXY (obj); + panel->panel_type = panel_type; + return panel; +diff --git a/client/x11/main.c b/client/x11/main.c +index b7eb5961..3075d5d0 100644 +--- a/client/x11/main.c ++++ b/client/x11/main.c +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + + #include + +@@ -69,6 +70,7 @@ typedef struct _X11ICONN X11ICONN; + typedef struct _X11IC X11IC; + struct _X11IC { + IBusInputContext *context; ++ gboolean ibus_connected; + Window client_window; + Window focus_window; + gint32 input_style; +@@ -327,6 +329,18 @@ _xim_store_ic_values (X11IC *x11ic, IMChangeICStruct *call_data) + return 1; + } + ++static void ++ibus_ic_connection_closed_cb (GDBusConnection *connection, ++ gboolean remote_peer_vanished, ++ GError *error, ++ X11IC *x11ic) ++{ ++ /* rhbz#2195895 The moment of the IBusBus disconnection would be ++ * different from the moment of XIM_DISCONNECT. ++ */ ++ x11ic->ibus_connected = FALSE; ++} ++ + + static int + xim_create_ic (XIMS xims, IMChangeICStruct *call_data) +@@ -334,6 +348,7 @@ xim_create_ic (XIMS xims, IMChangeICStruct *call_data) + static int base_icid = 1; + X11IC *x11ic; + guint32 capabilities = IBUS_CAP_FOCUS; ++ GDBusConnection *connection; + + call_data->icid = base_icid ++; + +@@ -345,8 +360,9 @@ xim_create_ic (XIMS xims, IMChangeICStruct *call_data) + + x11ic->icid = call_data->icid; + x11ic->connect_id = call_data->connect_id; +- x11ic->conn = (X11ICONN *)g_hash_table_lookup (_connections, +- GINT_TO_POINTER ((gint) call_data->connect_id)); ++ x11ic->conn = (X11ICONN *)g_hash_table_lookup ( ++ _connections, ++ GINT_TO_POINTER ((gint) call_data->connect_id)); + if (x11ic->conn == NULL) { + g_slice_free (X11IC, x11ic); + g_return_val_if_reached (0); +@@ -376,6 +392,10 @@ xim_create_ic (XIMS xims, IMChangeICStruct *call_data) + G_CALLBACK (_context_enabled_cb), x11ic); + g_signal_connect (x11ic->context, "disabled", + G_CALLBACK (_context_disabled_cb), x11ic); ++ connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (x11ic->context)); ++ x11ic->ibus_connected = !g_dbus_connection_is_closed (connection); ++ g_signal_connect (connection, "closed", ++ G_CALLBACK (ibus_ic_connection_closed_cb), x11ic); + + + if (x11ic->input_style & XIMPreeditCallbacks) +@@ -400,11 +420,19 @@ xim_destroy_ic (XIMS xims, IMChangeICStruct *call_data) + LOG (1, "XIM_DESTROY_IC ic=%d connect_id=%d", + call_data->icid, call_data->connect_id); + +- x11ic = (X11IC *)g_hash_table_lookup (_x11_ic_table, +- GINT_TO_POINTER ((gint) call_data->icid)); ++ x11ic = (X11IC *)g_hash_table_lookup ( ++ _x11_ic_table, ++ GINT_TO_POINTER ((gint) call_data->icid)); + g_return_val_if_fail (x11ic != NULL, 0); + + if (x11ic->context) { ++ GDBusConnection *connection = ++ g_dbus_proxy_get_connection (G_DBUS_PROXY (x11ic->context)); ++ x11ic->ibus_connected = FALSE; ++ g_signal_handlers_disconnect_by_func ( ++ connection, ++ (GCallback)ibus_ic_connection_closed_cb, ++ x11ic); + ibus_proxy_destroy ((IBusProxy *)x11ic->context); + g_object_unref (x11ic->context); + x11ic->context = NULL; +@@ -412,7 +440,8 @@ xim_destroy_ic (XIMS xims, IMChangeICStruct *call_data) + + g_hash_table_remove (_x11_ic_table, + GINT_TO_POINTER ((gint) call_data->icid)); +- x11ic->conn->clients = g_list_remove (x11ic->conn->clients, (gconstpointer)x11ic); ++ x11ic->conn->clients = g_list_remove (x11ic->conn->clients, ++ (gconstpointer)x11ic); + + g_free (x11ic->preedit_string); + x11ic->preedit_string = NULL; +@@ -439,6 +468,8 @@ xim_set_ic_focus (XIMS xims, IMChangeFocusStruct *call_data) + x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table, + GINT_TO_POINTER ((gint) call_data->icid)); + g_return_val_if_fail (x11ic != NULL, 0); ++ if (!x11ic->ibus_connected) ++ return 1; + + ibus_input_context_focus_in (x11ic->context); + _xim_set_cursor_location (x11ic); +@@ -458,6 +489,8 @@ xim_unset_ic_focus (XIMS xims, IMChangeFocusStruct *call_data) + x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table, + GINT_TO_POINTER ((gint) call_data->icid)); + g_return_val_if_fail (x11ic != NULL, 0); ++ if (!x11ic->ibus_connected) ++ return 1; + + ibus_input_context_focus_out (x11ic->context); + +@@ -712,6 +745,8 @@ xim_forward_event (XIMS xims, IMForwardEventStruct *call_data) + _x11_ic_table, + GINT_TO_POINTER ((gint) call_data->icid)); + g_return_val_if_fail (x11ic != NULL, 0); ++ if (!x11ic->ibus_connected) ++ return 0; + + xevent = (XKeyEvent*) &(call_data->event); + +@@ -870,6 +905,8 @@ _xim_set_cursor_location (X11IC *x11ic) + } + } + ++ if (!x11ic->ibus_connected) ++ return; + ibus_input_context_set_cursor_location (x11ic->context, + preedit_area.x, + preedit_area.y, +@@ -950,6 +987,8 @@ xim_reset_ic (XIMS xims, IMResetICStruct *call_data) + x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table, + GINT_TO_POINTER ((gint) call_data->icid)); + g_return_val_if_fail (x11ic != NULL, 0); ++ if (!x11ic->ibus_connected) ++ return 1; + + ibus_input_context_reset (x11ic->context); + +@@ -1309,7 +1348,12 @@ _atexit_cb () + static void + _sighandler (int sig) + { +- exit(EXIT_FAILURE); ++ /* rhbz#1767691 _sighandler() is called with SIGTERM ++ * and exit() causes SEGV during calling atexit functions. ++ * _atexit_cb() might be broken. _exit() does not call ++ * atexit functions. ++ */ ++ _exit(EXIT_FAILURE); + } + + static void +diff --git a/portal/portal.c b/portal/portal.c +index c2e4fc7f..76ef4f0a 100644 +--- a/portal/portal.c ++++ b/portal/portal.c +@@ -90,6 +90,11 @@ static void portal_context_g_signal (GDBusProxy *proxy, + GVariant *parameters, + IBusPortalContext *portal_context); + ++#define IBUS_TYPE_PORTAL_CONTEXT \ ++ (ibus_portal_context_get_type ()) ++#define IBUS_IS_PORTAL_CONTEXT(obj) \ ++ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_PORTAL_CONTEXT)) ++ + G_DEFINE_TYPE_WITH_CODE (IBusPortalContext, + ibus_portal_context, + IBUS_DBUS_TYPE_INPUT_CONTEXT_SKELETON, +@@ -449,11 +454,6 @@ ibus_portal_context_new (IBusInputContext *context, + g_strdup_printf (IBUS_PATH_INPUT_CONTEXT, portal_context->id); + portal_context->service = ibus_dbus_service_skeleton_new (); + +- g_signal_connect (portal_context->service, +- "handle-destroy", +- G_CALLBACK (ibus_portal_context_handle_destroy), +- portal_context); +- + if (!g_dbus_interface_skeleton_export ( + G_DBUS_INTERFACE_SKELETON (portal_context->service), + connection, portal_context->object_path, +@@ -466,8 +466,17 @@ ibus_portal_context_new (IBusInputContext *context, + return NULL; + } + ++ /* rhbz#2239633 g_list_prepend() needs to be callsed before ++ * ibus_portal_context_handle_destroy() is connected ++ * for g_list_remove() in ibus_portal_context_finalize(). ++ */ + all_contexts = g_list_prepend (all_contexts, portal_context); + ++ g_signal_connect (portal_context->service, ++ "handle-destroy", ++ G_CALLBACK (ibus_portal_context_handle_destroy), ++ portal_context); ++ + return portal_context; + } + +@@ -624,6 +633,12 @@ name_owner_changed (GDBusConnection *connection, + IBusPortalContext *portal_context = l->data; + next = l->next; + ++ /* rhbz#2151344 portal_context might not be finalized? */ ++ if (!G_LIKELY (IBUS_IS_PORTAL_CONTEXT (portal_context))) { ++ g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, ++ "portal_context is not IBusPortalContext"); ++ continue; ++ } + if (g_strcmp0 (portal_context->owner, name) == 0) { + g_object_unref (portal_context); + } +diff --git a/src/ibusbus.c b/src/ibusbus.c +index 0e6d67f1..fcc742b6 100644 +--- a/src/ibusbus.c ++++ b/src/ibusbus.c +@@ -742,6 +742,12 @@ ibus_bus_destroy (IBusObject *object) + _bus = NULL; + + if (bus->priv->monitor) { ++ /* rhbz#1795499 _changed_cb() causes SEGV because of no bus->priv ++ * after ibus_bus_destroy() is called. ++ */ ++ g_signal_handlers_disconnect_by_func (bus->priv->monitor, ++ (GCallback) _changed_cb, bus); ++ g_file_monitor_cancel (bus->priv->monitor); + g_object_unref (bus->priv->monitor); + bus->priv->monitor = NULL; + } +diff --git a/ui/gtk3/extension.vala b/ui/gtk3/extension.vala +index a6f2e8e6..b7a04081 100644 +--- a/ui/gtk3/extension.vala ++++ b/ui/gtk3/extension.vala +@@ -73,6 +73,10 @@ class ExtensionGtk : Gtk.Application { + string signal_name, + Variant parameters) { + debug("signal_name = %s", signal_name); ++ /* rhbz#1797120 Fix assert(bus.is_connected()) in ++ * panel_binding_construct() ++ */ ++ return_if_fail(m_bus.is_connected()); + m_panel = new PanelBinding(m_bus, this); + m_panel.load_settings(); + } +diff --git a/ui/gtk3/switcher.vala b/ui/gtk3/switcher.vala +index e3fab8d9..a827094f 100644 +--- a/ui/gtk3/switcher.vala ++++ b/ui/gtk3/switcher.vala +@@ -176,8 +176,8 @@ class Switcher : Gtk.Window { + IBus.EngineDesc[] engines, + int index, + string input_context_path) { +- assert (m_loop == null); +- assert (index < engines.length); ++ assert(m_loop == null); ++ assert(index < engines.length); + + if (m_is_running) + return index; +@@ -236,16 +236,18 @@ class Switcher : Gtk.Window { + null, + event, + null); +- if (status != Gdk.GrabStatus.SUCCESS) ++ if (status != Gdk.GrabStatus.SUCCESS) { + warning("Grab keyboard failed! status = %d", status); +- status = seat.grab(get_window(), +- Gdk.SeatCapabilities.POINTER, +- true, +- null, +- event, +- null); +- if (status != Gdk.GrabStatus.SUCCESS) +- warning("Grab pointer failed! status = %d", status); ++ } else { ++ status = seat.grab(get_window(), ++ Gdk.SeatCapabilities.POINTER, ++ true, ++ null, ++ event, ++ null); ++ if (status != Gdk.GrabStatus.SUCCESS) ++ warning("Grab pointer failed! status = %d", status); ++ } + #else + Gdk.Device device = event.get_device(); + if (device == null) { +@@ -281,30 +283,41 @@ class Switcher : Gtk.Window { + Gdk.EventMask.KEY_RELEASE_MASK, + null, + Gdk.CURRENT_TIME); +- if (status != Gdk.GrabStatus.SUCCESS) ++ if (status != Gdk.GrabStatus.SUCCESS) { + warning("Grab keyboard failed! status = %d", status); +- // Grab all pointer events +- status = pointer.grab(get_window(), +- Gdk.GrabOwnership.NONE, +- true, +- Gdk.EventMask.BUTTON_PRESS_MASK | +- Gdk.EventMask.BUTTON_RELEASE_MASK, +- null, +- Gdk.CURRENT_TIME); +- if (status != Gdk.GrabStatus.SUCCESS) +- warning("Grab pointer failed! status = %d", status); ++ } else { ++ // Grab all pointer events ++ status = pointer.grab(get_window(), ++ Gdk.GrabOwnership.NONE, ++ true, ++ Gdk.EventMask.BUTTON_PRESS_MASK | ++ Gdk.EventMask.BUTTON_RELEASE_MASK, ++ null, ++ Gdk.CURRENT_TIME); ++ if (status != Gdk.GrabStatus.SUCCESS) ++ warning("Grab pointer failed! status = %d", status); ++ } + #endif + +- // Probably we can delete m_popup_delay_time in 1.6 +- pointer.get_position_double(null, +- out m_mouse_init_x, +- out m_mouse_init_y); +- m_mouse_moved = false; ++ /* Fix RHBZ #1771238 assert(m_loop == null) ++ * Grabbing keyboard can be failed when the second Super-e is typed ++ * before Switcher dialog is focused. And m_loop could not be released ++ * if the failed Super-e would call m_loop.run() below and could not ++ * call key_release_event(). And m_loop == null would be false in the ++ * third Super-e. ++ */ ++ if (status == Gdk.GrabStatus.SUCCESS) { ++ // Probably we can delete m_popup_delay_time in 1.6 ++ pointer.get_position_double(null, ++ out m_mouse_init_x, ++ out m_mouse_init_y); ++ m_mouse_moved = false; + + +- m_loop = new GLib.MainLoop(); +- m_loop.run(); +- m_loop = null; ++ m_loop = new GLib.MainLoop(); ++ m_loop.run(); ++ m_loop = null; ++ } + + #if VALA_0_34 + seat.ungrab(); +-- +2.41.0 + diff --git a/spec_files/ibus/ibus-HEAD.patch b/spec_files/ibus/ibus-HEAD.patch new file mode 100644 index 00000000..e7a95128 --- /dev/null +++ b/spec_files/ibus/ibus-HEAD.patch @@ -0,0 +1,1621 @@ +From 4059b9f43f4505c855677abde1b59fc13241ca58 Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Tue, 2 Apr 2024 23:34:07 +0900 +Subject: [PATCH 1/6] Makefile: Add check sum file + +--- + Makefile.am | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/Makefile.am b/Makefile.am +index 16548d25..88fdbd48 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -138,6 +138,14 @@ srpm: dist @PACKAGE_NAME@.spec + --define "_specdir `pwd`/rpm" \ + @PACKAGE_NAME@.spec + ++@PACKAGE_NAME@-@PACKAGE_VERSION@.%.sum: @PACKAGE_NAME@-@PACKAGE_VERSION@.% ++ f=`basename $@ .sum`; \ ++ printf "cksum %s %s %s\n" `cksum $$f` > $@; \ ++ printf "sha1sum %s %s\n" `sha1sum $$f` >> $@; \ ++ printf "sha256sum %s %s\n" `sha256sum $$f` >> $@; \ ++ printf "sha512sum %s %s\n" `sha512sum $$f` >> $@; \ ++ $(NULL) ++ + clean-rpm: + -$(RM) -r "`uname -i`" + +-- +2.45.0 + +From e39345af20c1dd9b18cdb6ccb5039b03e4135f73 Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Fri, 24 May 2024 13:18:42 +0900 +Subject: [PATCH 2/6] src/tests: Fix ibus-daemon in ibus-desktop-testing-runner + +Some distributions do not need the IBus panel and gnome-shell also +does not need it. +Add --verbose option to get ibus-daemon error messages. + +Add vala check in autogen.sh since valac changes the source codes. +--- + autogen.sh | 2 +- + src/tests/ibus-desktop-testing-runner.in | 17 ++++++++++++++--- + 2 files changed, 15 insertions(+), 4 deletions(-) + +diff --git a/autogen.sh b/autogen.sh +index d6f8f983..90e126ec 100755 +--- a/autogen.sh ++++ b/autogen.sh +@@ -14,7 +14,7 @@ GCC_VERSION=$(gcc --version | head -1 | awk '{print $3}') + GCC_MAJOR_VERSION=$(echo "$GCC_VERSION" | awk -F. '{print $1}') + FEDORA_PKG1='autoconf automake libtool gettext-devel' + FEDORA_PKG2='glib2-devel gtk2-devel gtk3-devel +- wayland-devel' ++ wayland-devel vala' + FEDORA_PKG3='cldr-emoji-annotation iso-codes-devel unicode-emoji unicode-ucd + xkeyboard-config-devel' + +diff --git a/src/tests/ibus-desktop-testing-runner.in b/src/tests/ibus-desktop-testing-runner.in +index 6b208345..1ac2dfc8 100755 +--- a/src/tests/ibus-desktop-testing-runner.in ++++ b/src/tests/ibus-desktop-testing-runner.in +@@ -45,6 +45,7 @@ TEST_LOG_STDOUT=0 + RESULT_LOG="" + SCREEN_LOG="" + HAVE_GRAPHICS=1 ++VERBOSE=0 + DESKTOP_COMMAND="dbus-launch --exit-with-session gnome-session" + PID_XORG=0 + PID_GNOME_SESSION=0 +@@ -83,6 +84,7 @@ usage() + "-b, --builddir=BUILDDIR Set the BUILDDIR\n" \ + "-s, --srcdir=SOURCEDIR Set the SOURCEDIR\n" \ + "-c, --no-graphics Use Xvfb instead of Xorg\n" \ ++"-V, --verbose Verbose log for ibus-daemon\n" \ + "-d, --desktop=DESKTOP Run DESTKTOP. The default is gnome-session.\n" \ + " Suffix '-with-dbus' can run DESKTOP with dbus session." \ + " E.g. --desktop=mutter-with-dbus" \ +@@ -101,8 +103,8 @@ usage() + parse_args() + { + # This is GNU getopt. "sudo port getopt" in BSD? +- ARGS=`getopt -o hvb:s:cd:t:r:T:o:O:S: --long \ +- help,version,builddir:,srcdir:,no-graphics,desktop:,tests:,runner:,timeout:,output:,result:,screendump:\ ++ ARGS=`getopt -o hvb:s:cVd:t:r:T:o:O:S: --long \ ++ help,version,builddir:,srcdir:,no-graphics,verbose,desktop:,tests:,runner:,timeout:,output:,result:,screendump:\ + -- "$@"`; + eval set -- "$ARGS" + while [ 1 ] ; do +@@ -112,6 +114,7 @@ parse_args() + -b | --builddir ) BUILDDIR="$2"; shift 2;; + -s | --srcdir ) SRCDIR="$2"; shift 2;; + -c | --no-graphics ) HAVE_GRAPHICS=0; shift;; ++ -V | --verbose ) VERBOSE=1; shift;; + -d | --desktop ) DESKTOP_COMMAND="$2"; shift 2;; + -t | --tests ) TESTS="$2"; shift 2;; + -r | --runner ) TESTING_RUNNER="$2"; shift 2;; +@@ -286,6 +289,7 @@ run_desktop() + PID_GNOME_SESSION=$! + sleep 30 + ++ IBUS_ARGS="--verbose --panel disable" + # 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 +@@ -302,8 +306,15 @@ run_desktop() + # 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 ++ if test $VERBOSE -eq 1 ; then ++ ibus-daemon $IBUS_ARGS & ++ else ++ ibus-daemon $IBUS_ARGS --daemonize ++ fi + sleep 3 ++ if test $VERBOSE -eq 1 ; then ++ ps -ef | grep ibus ++ fi + } + + +-- +2.45.0 + +From f190da19b53c267ca1c9730e18f1b53c089c0247 Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Fri, 24 May 2024 15:37:00 +0900 +Subject: [PATCH 3/6] ui/gtk3: Configure initial keymaps with localectl in + Wayland + +`setxkbmap -query` returns US layout with Xwayland and it does not +correspond to the session keymaps so ibus-panel now uses +`localectl status` in Wayland but it does not provide the session +XKB options against `setxkbmap` command in Xorg. +Need to think how to load or set the XKB options in Wayland later. + +BUG=rhbz#2267615 +BUG=https://github.com/ibus/ibus/pull/2624 +--- + src/tests/ibus-keypress.c | 40 +++++++++---- + ui/gtk3/panel.vala | 2 +- + ui/gtk3/xkblayout.vala | 123 ++++++++++++++++++++++++++++---------- + 3 files changed, 119 insertions(+), 46 deletions(-) + +diff --git a/src/tests/ibus-keypress.c b/src/tests/ibus-keypress.c +index bab05398..d44f39b2 100644 +--- a/src/tests/ibus-keypress.c ++++ b/src/tests/ibus-keypress.c +@@ -5,6 +5,14 @@ + #include + #include + ++#ifdef GDK_WINDOWING_WAYLAND ++#if GTK_CHECK_VERSION (3, 98, 4) ++#include ++#else ++#include ++#endif ++#endif ++ + #define GREEN "\033[0;32m" + #define RED "\033[0;31m" + #define NC "\033[0m" +@@ -186,15 +194,8 @@ set_engine_cb (GObject *object, + } + + display = gtk_widget_get_display (entry); +- if (GDK_IS_X11_DISPLAY (display)) { +- xdisplay = gdk_x11_display_get_xdisplay (display); +- } else { +-#if 0 +- xdisplay = XOpenDisplay (NULL); +-#else +- g_critical ("No idea to simulate key events in Wayland\n"); +-#endif +- } ++ g_assert (GDK_IS_X11_DISPLAY (display)); ++ xdisplay = gdk_x11_display_get_xdisplay (display); + g_return_if_fail (xdisplay); + + for (i = 0; test_cases[i][0].keyval; i++) { +@@ -272,12 +273,18 @@ create_window () + static void + test_keypress (void) + { ++ gchar *path; + int status = 0; + GError *error = NULL; + +- g_spawn_command_line_sync ("setxkbmap -layout us", +- NULL, NULL, +- &status, &error); ++ /* localectl does not change the session keymap. */ ++ path = g_find_program_in_path ("setxkbmap"); ++ if (path) { ++ g_spawn_command_line_sync ("setxkbmap -layout us", ++ NULL, NULL, ++ &status, &error); ++ } ++ g_free (path); + g_assert (register_ibus_engine ()); + + create_window (); +@@ -295,6 +302,15 @@ main (int argc, char *argv[]) + g_message ("Failed setenv NO_AT_BRIDGE\n"); + g_test_init (&argc, &argv, NULL); + gtk_init (&argc, &argv); ++#ifdef GDK_WINDOWING_WAYLAND ++ { ++ GdkDisplay *display = gdk_display_get_default (); ++ if (GDK_IS_WAYLAND_DISPLAY (display)) { ++ g_print ("setxkbmap and XTEST do not work in Wayland.\n"); ++ return 0; ++ } ++ } ++#endif + + g_test_add_func ("/ibus/keyrepss", test_keypress); + +diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala +index 678b51f0..d907458e 100644 +--- a/ui/gtk3/panel.vala ++++ b/ui/gtk3/panel.vala +@@ -510,7 +510,7 @@ class Panel : IBus.PanelService { + string layouts; + string variants; + string option; +- XKBLayout.get_layout(out layouts, out variants, out option); ++ m_xkblayout.get_layout(out layouts, out variants, out option); + + GLib.List xkb_engines = + new GLib.List(); +diff --git a/ui/gtk3/xkblayout.vala b/ui/gtk3/xkblayout.vala +index 729b48ce..7812c4bb 100644 +--- a/ui/gtk3/xkblayout.vala ++++ b/ui/gtk3/xkblayout.vala +@@ -4,7 +4,7 @@ + * + * Copyright(c) 2014 Red Hat, Inc. + * Copyright(c) 2014 Peng Huang +- * Copyright(c) 2014 Takao Fujiwara ++ * Copyright(c) 2014-2024 Takao Fujiwara + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -25,11 +25,11 @@ + class XKBLayout + { + private const string XKB_COMMAND = "setxkbmap"; +- private const string XKB_QUERY_ARG = "-query"; + private const string XKB_LAYOUT_ARG = "-layout"; + private const string XMODMAP_COMMAND = "xmodmap"; + private const string[] XMODMAP_KNOWN_FILES = {".xmodmap", ".xmodmaprc", + ".Xmodmap", ".Xmodmaprc"}; ++ private string[] m_get_layout_args = {}; + private string[] m_xkb_latin_layouts = {}; + private string m_default_layout = ""; + private string m_default_variant = ""; +@@ -39,16 +39,23 @@ class XKBLayout + public XKBLayout() { + } + ++ + public void set_latin_layouts(string[] xkb_latin_layouts) { + m_xkb_latin_layouts = xkb_latin_layouts; + } + +- public static void get_layout(out string layout, +- out string variant, +- out string option) { ++ ++ public void get_layout(out string layout, ++ out string variant, ++ out string option) { ++ search_get_layout_program(); ++ if (m_get_layout_args[0] == null) { ++ warning("Not found localectl or setxkbmap command in PATH"); ++ return; ++ } + string[] exec_command = {}; +- exec_command += XKB_COMMAND; +- exec_command += XKB_QUERY_ARG; ++ foreach (unowned string arg in m_get_layout_args) ++ exec_command += arg; + string standard_output = null; + string standard_error = null; + int exit_status = 0; +@@ -69,46 +76,94 @@ class XKBLayout + } catch (GLib.SpawnError err) { + stderr.printf("IBUS_ERROR: %s\n", err.message); + } +- if (exit_status != 0) { ++ if (exit_status != 0) + stderr.printf("IBUS_ERROR: %s\n", standard_error ?? ""); +- } +- if (standard_output == null) { ++ if (standard_output == null) + return; ++ ++ if (exec_command[0] == "localectl") { ++ parse_localectl_status_str(standard_output, ++ out layout, ++ out variant, ++ out option); ++ } else if (exec_command[0] == XKB_COMMAND) { ++ parse_xkbmap_query_str(standard_output, ++ out layout, ++ out variant, ++ out option); + } ++ } ++ + ++ private void search_get_layout_program() { ++ if (m_get_layout_args[0] != null) ++ return; ++ string get_layout_command = null; ++ // setxkbmap can get the session XKB options in Xorg. ++ if (BindingCommon.default_is_xdisplay()) ++ get_layout_command = "setxkbmap -query"; ++ else if (GLib.Environment.find_program_in_path("localectl") != null) ++ get_layout_command = "localectl status"; ++ else if (GLib.Environment.find_program_in_path("setxkbmap") != null) ++ get_layout_command = "setxkbmap -query"; ++ if (get_layout_command != null) ++ m_get_layout_args = get_layout_command.split(" "); ++ } ++ ++ ++ private void parse_localectl_status_str(string standard_output, ++ out string layout, ++ out string variant, ++ out string option) { ++ layout = ""; ++ variant = ""; ++ option = ""; + foreach (string line in standard_output.split("\n")) { +- string element = "layout:"; +- string retval = ""; +- if (line.has_prefix(element)) { +- retval = line[element.length:line.length]; +- if (retval != null) { +- retval = retval.strip(); ++ const string[] elements = { "X11 Layout:", "X11 Variant:" }; ++ foreach (unowned string element in elements) { ++ string retval = ""; ++ int index = line.index_of(element); ++ if (index >= 0) { ++ retval = line[index + element.length:line.length]; ++ if (retval != null) ++ retval = retval.strip(); ++ if (element == elements[0]) ++ layout = retval; ++ else if (element == elements[1]) ++ variant = retval; + } +- layout = retval; + } ++ } ++ } + +- element = "variant:"; +- retval = ""; +- if (line.has_prefix(element)) { +- retval = line[element.length:line.length]; +- if (retval != null) { +- retval = retval.strip(); +- } +- variant = retval; +- } + +- element = "options:"; +- retval = ""; +- if (line.has_prefix(element)) { +- retval = line[element.length:line.length]; +- if (retval != null) { +- retval = retval.strip(); ++ private void parse_xkbmap_query_str(string standard_output, ++ out string layout, ++ out string variant, ++ out string option) { ++ layout = ""; ++ variant = ""; ++ option = ""; ++ foreach (string line in standard_output.split("\n")) { ++ const string[] elements = { "layout:", "variant:", "options:" }; ++ foreach (unowned string element in elements) { ++ string retval = ""; ++ if (line.has_prefix(element)) { ++ retval = line[element.length:line.length]; ++ if (retval != null) ++ retval = retval.strip(); ++ if (element == elements[0]) ++ layout = retval; ++ else if (element == elements[1]) ++ variant = retval; ++ else if (element == elements[2]) ++ option = retval; + } +- option = retval; + } + } + } + ++ + public void set_layout(IBus.EngineDesc engine) { + string layout = engine.get_layout(); + string variant = engine.get_layout_variant(); +@@ -206,6 +261,7 @@ class XKBLayout + run_xmodmap(); + } + ++ + public void run_xmodmap() { + if (!m_use_xmodmap) { + return; +@@ -246,6 +302,7 @@ class XKBLayout + } + } + ++ + public void set_use_xmodmap(bool use_xmodmap) { + m_use_xmodmap = use_xmodmap; + } +-- +2.45.0 + +From 48c4a9c900421b9e77be399a4792974f25a80be6 Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Fri, 24 May 2024 16:17:58 +0900 +Subject: [PATCH 4/6] src/ibusenginesimple: Ignore Super modifier for compose + keys + +Now IBus receives key events prior to the window manager and needs +to ignore Super modifier since Super key has been already ignored +for compose keys. + +BUG=https://gitlab.gnome.org/GNOME/mutter/-/issues/3128 +--- + src/ibusenginesimple.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/ibusenginesimple.c b/src/ibusenginesimple.c +index 4bee8cb3..76dd9eb5 100644 +--- a/src/ibusenginesimple.c ++++ b/src/ibusenginesimple.c +@@ -2,7 +2,7 @@ + /* vim:set et sts=4: */ + /* ibus - The Input Bus + * Copyright (C) 2014 Peng Huang +- * Copyright (C) 2015-2023 Takao Fujiwara ++ * Copyright (C) 2015-2024 Takao Fujiwara + * Copyright (C) 2014-2017 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or +@@ -1017,7 +1017,9 @@ ibus_engine_simple_process_key_event (IBusEngine *engine, + !is_hex_start && !is_hex_end && !is_escape && !is_backspace) || + (priv->in_emoji_sequence && !printable_keyval && + !is_emoji_start && !is_hex_end && !is_escape && !is_backspace)) { +- if (modifiers & (IBUS_MOD1_MASK | IBUS_CONTROL_MASK) || ++ guint no_text_input_mask = IBUS_MOD1_MASK | IBUS_MOD4_MASK \ ++ | IBUS_CONTROL_MASK | IBUS_SUPER_MASK; ++ if (modifiers & no_text_input_mask || + ((priv->in_hex_sequence || priv->in_emoji_sequence) && + priv->modifiers_dropped && + (keyval == IBUS_KEY_Return || +-- +2.45.0 + +From a3a5a20a30f2a8ecee4dc2aaa4fd48c62c91d768 Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Fri, 24 May 2024 16:18:03 +0900 +Subject: [PATCH 5/6] src/ibusenginesimple: Do not update zero length preedit + text + +Several engines can inherit IBusEngieSimple for the compose key support +likes Anthy, Hangul, M17n and it could have the duplicated preedit text +between the engine and the parent IBusEngineSimple and it could update +the preedit text mutually by mistake. + +Then the preedit text should not be hidden for zero length at least. +This update might not be enough but hope to fix the cursor position +reset with hiding the preedit text against the reported issue with +`m17n:sa:itrans` engine. + +BUG=https://github.com/ibus/ibus/issues/2536 +--- + src/ibusenginesimple.c | 41 +++++++++++++++++++++++++++++++++++------ + 1 file changed, 35 insertions(+), 6 deletions(-) + +diff --git a/src/ibusenginesimple.c b/src/ibusenginesimple.c +index 76dd9eb5..ac478855 100644 +--- a/src/ibusenginesimple.c ++++ b/src/ibusenginesimple.c +@@ -83,11 +83,13 @@ struct _IBusEngineSimplePrivate { + IBusEngineDict *emoji_dict; + IBusLookupTable *lookup_table; + gboolean lookup_table_visible; ++ IBusText *updated_preedit; + }; + + guint COMPOSE_BUFFER_SIZE = 20; + G_LOCK_DEFINE_STATIC (global_tables); + static GSList *global_tables; ++static IBusText *updated_preedit_empty; + + /* functions prototype */ + static void ibus_engine_simple_destroy (IBusEngineSimple *simple); +@@ -135,24 +137,29 @@ ibus_engine_simple_class_init (IBusEngineSimpleClass *class) + engine_class->page_up = ibus_engine_simple_page_up; + engine_class->candidate_clicked + = ibus_engine_simple_candidate_clicked; ++ updated_preedit_empty = ibus_text_new_from_string (""); ++ g_object_ref_sink (updated_preedit_empty); + } + + static void + ibus_engine_simple_init (IBusEngineSimple *simple) + { ++ IBusEngineSimplePrivate *priv; + GBytes *data; + GError *error = NULL; + const char *contents; + gsize length = 0; + IBusComposeTableEx *en_compose_table; + +- simple->priv = IBUS_ENGINE_SIMPLE_GET_PRIVATE (simple); +- simple->priv->compose_buffer = g_new0 (guint, COMPOSE_BUFFER_SIZE + 1); +- simple->priv->hex_mode_enabled = ++ priv = simple->priv = IBUS_ENGINE_SIMPLE_GET_PRIVATE (simple); ++ priv->compose_buffer = g_new0 (guint, COMPOSE_BUFFER_SIZE + 1); ++ priv->hex_mode_enabled = + g_getenv("IBUS_ENABLE_CTRL_SHIFT_U") != NULL || + g_getenv("IBUS_ENABLE_CONTROL_SHIFT_U") != NULL; +- simple->priv->tentative_match = g_string_new (""); +- simple->priv->tentative_match_len = 0; ++ priv->tentative_match = g_string_new (""); ++ priv->tentative_match_len = 0; ++ priv->updated_preedit = ++ (IBusText *)g_object_ref_sink (updated_preedit_empty); + data = g_resources_lookup_data ("/org/freedesktop/ibus/compose/sequences", + G_RESOURCE_LOOKUP_FLAGS_NONE, + &error); +@@ -190,6 +197,7 @@ ibus_engine_simple_destroy (IBusEngineSimple *simple) + g_string_free (priv->tentative_match, TRUE); + priv->tentative_match = NULL; + priv->tentative_match_len = 0; ++ g_clear_object (&priv->updated_preedit); + + IBUS_OBJECT_CLASS(ibus_engine_simple_parent_class)->destroy ( + IBUS_OBJECT (simple)); +@@ -228,6 +236,9 @@ ibus_engine_simple_reset (IBusEngine *engine) + priv->tentative_match_len = 0; + } + ibus_engine_hide_preedit_text ((IBusEngine *)simple); ++ g_object_unref (priv->updated_preedit); ++ priv->updated_preedit = ++ (IBusText *)g_object_ref_sink (updated_preedit_empty); + } + + static void +@@ -318,7 +329,10 @@ ibus_engine_simple_update_preedit_text (IBusEngineSimple *simple) + int len = strlen (priv->tentative_emoji); + ibus_text_append_attribute (text, + IBUS_ATTR_TYPE_UNDERLINE, IBUS_ATTR_UNDERLINE_SINGLE, 0, len); ++ g_object_ref_sink (text); + ibus_engine_update_preedit_text ((IBusEngine *)simple, text, len, TRUE); ++ g_object_unref (priv->updated_preedit); ++ priv->updated_preedit = text; + g_string_free (s, TRUE); + return; + } else if (priv->in_compose_sequence) { +@@ -370,7 +384,19 @@ ibus_engine_simple_update_preedit_text (IBusEngineSimple *simple) + } + + if (s->len == 0) { +- ibus_engine_hide_preedit_text ((IBusEngine *)simple); ++ /* #2536 IBusEngine can inherit IBusEngineSimple for comopse keys. ++ * If the previous preedit is zero, the current preedit does not ++ * need to be hidden here at least because ibus-daemon could have ++ * another preedit for the child IBusEnigne likes m17n and caclling ++ * ibus_engine_hide_preedit_text() here could cause a reset of ++ * the cursor position in ibus-daemon. ++ */ ++ if (strlen (priv->updated_preedit->text)) { ++ ibus_engine_hide_preedit_text ((IBusEngine *)simple); ++ g_object_unref (priv->updated_preedit); ++ priv->updated_preedit = ++ (IBusText *)g_object_ref_sink (updated_preedit_empty); ++ } + } else if (s->len >= G_MAXINT) { + g_warning ("%s is too long compose length: %lu", s->str, s->len); + } else { +@@ -378,7 +404,10 @@ ibus_engine_simple_update_preedit_text (IBusEngineSimple *simple) + IBusText *text = ibus_text_new_from_string (s->str); + ibus_text_append_attribute (text, + IBUS_ATTR_TYPE_UNDERLINE, IBUS_ATTR_UNDERLINE_SINGLE, 0, len); ++ g_object_ref_sink (text); + ibus_engine_update_preedit_text ((IBusEngine *)simple, text, len, TRUE); ++ g_object_unref (priv->updated_preedit); ++ priv->updated_preedit = text; + } + g_string_free (s, TRUE); + } +-- +2.45.0 + +From 627e7cc37d3bea4c288c932773f69fcee9ac773e Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Fri, 24 May 2024 16:28:40 +0900 +Subject: [PATCH 6/6] ui/gtk3: Fix to unref GdkDisplay in Wayland + +Panel does not need to allocate the X11 display in Wayland but the check +only. Vala codes need to set the unowned parameter. +Also fixed a memory leak in the update preedit in daemon. + +BUG=rhbz#2252227 +BUG=https://github.com/ibus/ibus/issues/2642 +BUG=https://github.com/ibus/ibus/issues/2644 +--- + bus/inputcontext.c | 1 + + ui/gtk3/application.vala | 2 + + ui/gtk3/bindingcommon.vala | 6 +- + ui/gtk3/handle.vala | 2 + + ui/gtk3/panel.vala | 18 ++++- + 6 files changed, 96 insertions(+), 78 deletions(-) + +diff --git a/bus/inputcontext.c b/bus/inputcontext.c +index c914fbd2..7666f057 100644 +--- a/bus/inputcontext.c ++++ b/bus/inputcontext.c +@@ -3306,6 +3306,7 @@ bus_input_context_update_preedit_text (BusInputContext *context, + pre_data.key = 'm'; + if (bus_input_context_make_post_process_key_event (context, + &pre_data)) { ++ g_variant_unref (variant); + return; + } else if (context->client_commit_preedit) { + bus_input_context_emit_signal ( +diff --git a/ui/gtk3/application.vala b/ui/gtk3/application.vala +index ae67624f..31517c79 100644 +--- a/ui/gtk3/application.vala ++++ b/ui/gtk3/application.vala +@@ -228,6 +228,8 @@ class Application { + } + + private static void make_wayland_im() { ++ if (BindingCommon.default_is_xdisplay()) ++ return; + assert (open_log()); + void *wl_display = null; + ulong i = 0; +diff --git a/ui/gtk3/bindingcommon.vala b/ui/gtk3/bindingcommon.vala +index e32db178..7e6443c5 100644 +--- a/ui/gtk3/bindingcommon.vala ++++ b/ui/gtk3/bindingcommon.vala +@@ -259,11 +259,11 @@ class BindingCommon { + + public static bool default_is_xdisplay() { + if (m_xdisplay == null) +- get_xdisplay(); ++ get_xdisplay(true); + return m_default_is_xdisplay; + } + +- public static Gdk.X11.Display? get_xdisplay() { ++ public static Gdk.X11.Display? get_xdisplay(bool check_only=false) { + if (m_xdisplay != null) + return m_xdisplay; + var display = Gdk.Display.get_default(); +@@ -277,6 +277,8 @@ class BindingCommon { + m_xdisplay = (Gdk.X11.Display)display; + return m_xdisplay; + } ++ if (check_only) ++ return null; + Gdk.set_allowed_backends("x11"); + // Call _gdk_display_manager_add_display() internally. + m_xdisplay = +diff --git a/ui/gtk3/handle.vala b/ui/gtk3/handle.vala +index 65635439..1d0eefe9 100644 +--- a/ui/gtk3/handle.vala ++++ b/ui/gtk3/handle.vala +@@ -62,6 +62,8 @@ class Handle : Gtk.EventBox { + } + + public override bool button_press_event(Gdk.EventButton event) { ++ if (!BindingCommon.default_is_xdisplay()) ++ return false; + if (event.button != 1) + return false; + m_workarea = Gdk.Rectangle(){ +diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala +index d907458e..534a9d37 100644 +--- a/ui/gtk3/panel.vala ++++ b/ui/gtk3/panel.vala +@@ -166,6 +166,9 @@ class Panel : IBus.PanelService { + property_activate(k, s); + }); + ++ set_version(); ++ check_wayland(); ++ + state_changed(); + } + +@@ -443,6 +446,8 @@ class Panel : IBus.PanelService { + } + + private void bind_switch_shortcut() { ++ if (m_is_wayland_im) ++ return; + string[] accelerators = m_settings_hotkey.get_strv("triggers"); + + var keybinding_manager = KeybindingManager.get_instance(); +@@ -874,6 +879,16 @@ class Panel : IBus.PanelService { + message = format.printf(Environment.get_prgname()); + } + } ++ if (!m_is_wayland && m_is_wayland_im) { ++ var format = ++ _("Seems you run %s with '--enable-wayland-im' " + ++ "option but your display server is Xorg so the Wayland " + ++ "feature is disabled. You would be better off running " + ++ "ibus-daemon directly instead or %s without that " + ++ "option."); ++ unowned string prgname = Environment.get_prgname(); ++ message = format.printf(prgname, prgname); ++ } + if (message == null) + return; + #if ENABLE_LIBNOTIFY +@@ -908,9 +923,6 @@ class Panel : IBus.PanelService { + + + public void load_settings() { +- set_version(); +- check_wayland(); +- + init_engines_order(); + + // Update m_use_system_keyboard_layout before update_engines() +-- +2.45.0 + +From aea035a96261f9c3a36f5cd9c30b84b1d7609103 Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Sat, 8 Jun 2024 10:23:31 +0900 +Subject: [PATCH] ui/gtk3: Fix Super-space in Wayland + +ibus_bus_set_global_shortcut_keys_async() was not called in Plasma +Wayland after "Fix to unref GdkDisplay in Wayland" patch is applied. +Now it's called correctly and the event handler is disabled instead. + +BUG=rhbz#2290842 +BUG=https://github.com/ibus/ibus/issues/2644 +Fixes: https://github.com/ibus/ibus/commit/627e7cc +--- + ui/gtk3/keybindingmanager.vala | 9 +++++---- + ui/gtk3/panel.vala | 5 ++--- + 2 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/ui/gtk3/keybindingmanager.vala b/ui/gtk3/keybindingmanager.vala +index 71b4acb2..d4c7636a 100644 +--- a/ui/gtk3/keybindingmanager.vala ++++ b/ui/gtk3/keybindingmanager.vala +@@ -60,8 +60,9 @@ public class KeybindingManager : GLib.Object { + public delegate void KeybindingHandlerFunc(Gdk.Event event); + + +- private KeybindingManager() { +- Gdk.Event.handler_set(event_handler); ++ private KeybindingManager(bool is_wayland_im) { ++ if (!is_wayland_im) ++ Gdk.Event.handler_set(event_handler); + } + + /** +@@ -107,9 +108,9 @@ public class KeybindingManager : GLib.Object { + m_bindings.remove (binding); + } + +- public static KeybindingManager get_instance () { ++ public static KeybindingManager get_instance (bool is_wayland_im=false) { + if (m_instance == null) +- m_instance = new KeybindingManager (); ++ m_instance = new KeybindingManager (is_wayland_im); + return m_instance; + } + +diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala +index 534a9d37..b24c23ac 100644 +--- a/ui/gtk3/panel.vala ++++ b/ui/gtk3/panel.vala +@@ -446,11 +446,10 @@ class Panel : IBus.PanelService { + } + + private void bind_switch_shortcut() { +- if (m_is_wayland_im) +- return; + string[] accelerators = m_settings_hotkey.get_strv("triggers"); + +- var keybinding_manager = KeybindingManager.get_instance(); ++ var keybinding_manager = ++ KeybindingManager.get_instance(m_is_wayland_im); + + BindingCommon.KeyEventFuncType ftype = + BindingCommon.KeyEventFuncType.IME_SWITCHER; +-- +2.45.0 + +From be94b8ddb4c37fe83646860a08c600b98e67fe84 Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Sat, 25 May 2024 18:10:36 +0900 +Subject: [PATCH] src/ibusengine: Hide preedit text with PanelExtensionReceived + signal + +IBusEngineSimple no longer calls to hide the preedit with the zero +length to fix the slurring cursor position but the emoji preedit +becomes not to be hidden with the preedit commit or escape events +as a side effect. +To fix the issue, IBusEngine needs to decide to clear or keep +the preedit when the emoji mode is finished. + +BUG=https://github.com/ibus/ibus/issues/2536 +Fixes: https://github.com/ibus/ibus/commit/a3a5a20a +--- + src/ibusengine.c | 11 +++++++++++ + src/ibusenginesimple.c | 2 +- + 2 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/src/ibusengine.c b/src/ibusengine.c +index eff4992c..0352fd49 100644 +--- a/src/ibusengine.c ++++ b/src/ibusengine.c +@@ -1326,6 +1326,17 @@ ibus_engine_service_method_call (IBusService *service, + return; + } + priv->enable_extension = ibus_extension_event_is_enabled (event); ++ /* IBusEngineSimple no longer calls to hide the preedit with the zero ++ * lenght and this sends the null preedit here when the emojier ++ * commits or escapes the emoji preedit text. ++ * TODO: Do we need a signal for the parent engines to inform this ++ * information because some engines don't wish to hide their preedit ++ * with hiding the emoji preedit? ++ */ ++ if (!priv->enable_extension) { ++ IBusText *text = ibus_text_new_from_static_string (""); ++ ibus_engine_update_preedit_text (engine, text, 0, FALSE); ++ } + g_dbus_method_invocation_return_value (invocation, NULL); + return; + } +diff --git a/src/ibusenginesimple.c b/src/ibusenginesimple.c +index ac478855..e2f96a37 100644 +--- a/src/ibusenginesimple.c ++++ b/src/ibusenginesimple.c +@@ -385,7 +385,7 @@ ibus_engine_simple_update_preedit_text (IBusEngineSimple *simple) + + if (s->len == 0) { + /* #2536 IBusEngine can inherit IBusEngineSimple for comopse keys. +- * If the previous preedit is zero, the current preedit does not ++ * If the previous preedit is zero, the current preedit does not + * need to be hidden here at least because ibus-daemon could have + * another preedit for the child IBusEnigne likes m17n and caclling + * ibus_engine_hide_preedit_text() here could cause a reset of +-- +2.45.0 + +From 759105df1d83ae25d9eea801a7c91e67dca43cb8 Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Sat, 25 May 2024 19:23:23 +0900 +Subject: [PATCH 1/6] bus: Change IBus unique name to :1.0 from IBUS_SERVICE_IBUS +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +According to the D-Bus specification, +`org.freedesktop.DBus.GetNameOwner()` must return a unique name (i.e. +one of the form `:1.23`). The only unique name which is allowed to not +be in this form is `org.freedesktop.DBus`. + +The change in GLib 2.80.1 was to validate that the sender of every +message is either a unique name (according to `g_dbus_is_unique_name()`), +or the special name `org.freedesktop.DBus` to meet the specification. + +In the long term, it might be more robust to rework the code so that the +mapping from `org.freedesktop.IBus` → a unique name is stored in +`dbus->names` (in `dbusimpl.c`) like all the other requested names. +However, handling for the `org.freedesktop.IBus` well-known name is +hardcoded throughout `dbusimpl.c`, so porting this single bit of it to +create a `BusNameService` would probably cause more problems. + +BUG=https://github.com/ibus/ibus/issues/2639 +BUG=https://gitlab.gnome.org/GNOME/glib/-/issues/3268 +BUG=https://github.com/advisories/GHSA-f632-c3rh-r2v2 +--- + bus/connection.h | 3 +++ + bus/dbusimpl.c | 29 +++++++++++++++-------------- + bus/ibusimpl.c | 13 +++++++------ + bus/inputcontext.c | 2 +- + bus/matchrule.c | 10 +++++++++- + bus/matchrule.h | 4 +++- + 6 files changed, 38 insertions(+), 23 deletions(-) + +diff --git a/bus/connection.h b/bus/connection.h +index 440faf1e..8264980e 100644 +--- a/bus/connection.h ++++ b/bus/connection.h +@@ -42,6 +42,9 @@ + #define BUS_CONNECTION_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), BUS_TYPE_CONNECTION, BusConnectionClass)) + ++/* bus_dbus_impl_hello() sets the client unique names ":1.1" or later. */ ++#define IBUS_NAME_OWNER_NAME ":1.0" ++ + G_BEGIN_DECLS + + typedef struct _BusConnection BusConnection; +diff --git a/bus/dbusimpl.c b/bus/dbusimpl.c +index 59787a80..52092e58 100644 +--- a/bus/dbusimpl.c ++++ b/bus/dbusimpl.c +@@ -710,7 +710,8 @@ bus_dbus_impl_list_names (BusDBusImpl *dbus, + + /* FIXME should add them? */ + g_variant_builder_add (&builder, "s", "org.freedesktop.DBus"); +- g_variant_builder_add (&builder, "s", "org.freedesktop.IBus"); ++ g_variant_builder_add (&builder, "s", IBUS_SERVICE_IBUS); ++ g_variant_builder_add (&builder, "s", IBUS_NAME_OWNER_NAME); + + /* append well-known names */ + GList *names, *name; +@@ -785,11 +786,11 @@ bus_dbus_impl_get_name_owner (BusDBusImpl *dbus, + const gchar *name = NULL; + g_variant_get (parameters, "(&s)", &name); + +- if (g_strcmp0 (name, "org.freedesktop.DBus") == 0 || +- g_strcmp0 (name, "org.freedesktop.IBus") == 0) { ++ if (!g_strcmp0 (name, "org.freedesktop.DBus")) { + name_owner = name; +- } +- else { ++ } else if (!g_strcmp0 (name, IBUS_SERVICE_IBUS)) { ++ name_owner = IBUS_NAME_OWNER_NAME; ++ } else { + BusConnection *owner = bus_dbus_impl_get_connection_by_name (dbus, name); + if (owner != NULL) { + name_owner = bus_connection_get_unique_name (owner); +@@ -800,8 +801,7 @@ bus_dbus_impl_get_name_owner (BusDBusImpl *dbus, + g_dbus_method_invocation_return_error (invocation, + G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER, + "Can not get name owner of '%s': no such name", name); +- } +- else { ++ } else { + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(s)", name_owner)); + } +@@ -932,6 +932,9 @@ bus_dbus_impl_add_match (BusDBusImpl *dbus, + "Parse match rule [%s] failed", rule_text); + return; + } ++ /* ibus_bus_watch_ibus_signal() supports IBUS_SERVICE_IBUS sender. */ ++ if (!g_strcmp0 (bus_match_rule_get_sender (rule), IBUS_SERVICE_IBUS)) ++ bus_match_rule_set_sender (rule, IBUS_NAME_OWNER_NAME); + + g_dbus_method_invocation_return_value (invocation, NULL); + GList *p; +@@ -1510,7 +1513,8 @@ bus_dbus_impl_connection_filter_cb (GDBusConnection *dbus_connection, + /* connection unique name as sender of the message*/ + g_dbus_message_set_sender (message, bus_connection_get_unique_name (connection)); + +- if (g_strcmp0 (destination, "org.freedesktop.IBus") == 0) { ++ if (!g_strcmp0 (destination, IBUS_SERVICE_IBUS) || ++ !g_strcmp0 (destination, IBUS_NAME_OWNER_NAME)) { + /* the message is sent to IBus service. messages from ibusbus and ibuscontext may fall into this category. */ + switch (message_type) { + case G_DBUS_MESSAGE_TYPE_METHOD_CALL: +@@ -1528,8 +1532,7 @@ bus_dbus_impl_connection_filter_cb (GDBusConnection *dbus_connection, + g_object_unref (message); + g_return_val_if_reached (NULL); /* return NULL since the service does not handle signals. */ + } +- } +- else if (g_strcmp0 (destination, "org.freedesktop.DBus") == 0) { ++ } else if (!g_strcmp0 (destination, "org.freedesktop.DBus")) { + /* the message is sent to DBus service. messages from ibusbus may fall into this category. */ + switch (message_type) { + case G_DBUS_MESSAGE_TYPE_METHOD_CALL: +@@ -1547,8 +1550,7 @@ bus_dbus_impl_connection_filter_cb (GDBusConnection *dbus_connection, + g_object_unref (message); + g_return_val_if_reached (NULL); /* return NULL since the service does not handle signals. */ + } +- } +- else if (destination == NULL) { ++ } else if (destination == NULL) { + /* the message is sent to the current connection. communications between ibus-daemon and panel/engines may fall into this + * category since the panel/engine proxies created by ibus-daemon does not set bus name. */ + switch (message_type) { +@@ -1570,8 +1572,7 @@ bus_dbus_impl_connection_filter_cb (GDBusConnection *dbus_connection, + g_object_unref (message); + g_return_val_if_reached (NULL); /* return NULL since the service does not handle messages. */ + } +- } +- else { ++ } else { + /* The message is sent to an other service. Forward it. + * For example, the config proxy class in src/ibusconfig.c sets its "g-name" property (i.e. destination) to IBUS_SERVICE_CONFIG. */ + bus_dbus_impl_forward_message (dbus, connection, message); +diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c +index 875cd550..8681c78b 100644 +--- a/bus/ibusimpl.c ++++ b/bus/ibusimpl.c +@@ -2388,19 +2388,20 @@ bus_ibus_impl_property_changed (BusIBusImpl *service, + GVariant *value) + { + GDBusMessage *message = +- g_dbus_message_new_signal ("/org/freedesktop/IBus", ++ g_dbus_message_new_signal (IBUS_PATH_IBUS, + "org.freedesktop.DBus.Properties", + "PropertiesChanged"); + + /* set a non-zero serial to make libdbus happy */ + g_dbus_message_set_serial (message, 1); +- g_dbus_message_set_sender (message, "org.freedesktop.IBus"); ++ g_dbus_message_set_sender (message, IBUS_NAME_OWNER_NAME); ++ + + GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY); + g_variant_builder_add (builder, "{sv}", property_name, value); + g_dbus_message_set_body (message, + g_variant_new ("(sa{sv}as)", +- "org.freedesktop.IBus", ++ IBUS_SERVICE_IBUS, + builder, + NULL)); + g_variant_builder_unref (builder); +@@ -2419,12 +2420,12 @@ bus_ibus_impl_emit_signal (BusIBusImpl *ibus, + const gchar *signal_name, + GVariant *parameters) + { +- GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/IBus", +- "org.freedesktop.IBus", ++ GDBusMessage *message = g_dbus_message_new_signal (IBUS_PATH_IBUS, ++ IBUS_INTERFACE_IBUS, + signal_name); + /* set a non-zero serial to make libdbus happy */ + g_dbus_message_set_serial (message, 1); +- g_dbus_message_set_sender (message, "org.freedesktop.IBus"); ++ g_dbus_message_set_sender (message, IBUS_NAME_OWNER_NAME); + if (parameters) + g_dbus_message_set_body (message, parameters); + bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL); +diff --git a/bus/inputcontext.c b/bus/inputcontext.c +index 7666f057..e0ad0742 100644 +--- a/bus/inputcontext.c ++++ b/bus/inputcontext.c +@@ -755,7 +755,7 @@ bus_input_context_send_signal (BusInputContext *context, + ibus_service_get_object_path ((IBusService *)context), + interface_name, + signal_name); +- g_dbus_message_set_sender (message, "org.freedesktop.IBus"); ++ g_dbus_message_set_sender (message, IBUS_NAME_OWNER_NAME); + g_dbus_message_set_destination ( + message, + bus_connection_get_unique_name (context->connection)); +diff --git a/bus/matchrule.c b/bus/matchrule.c +index 4fb1d902..2381ca9e 100644 +--- a/bus/matchrule.c ++++ b/bus/matchrule.c +@@ -2,7 +2,8 @@ + /* vim:set et sts=4: */ + /* IBus - The Input Bus + * Copyright (C) 2008-2010 Peng Huang +- * Copyright (C) 2008-2010 Red Hat, Inc. ++ * Copyright (C) 2024 Takao Fujiwara ++ * Copyright (C) 2008-2024 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 +@@ -407,6 +408,13 @@ bus_match_rule_set_message_type (BusMatchRule *rule, + return TRUE; + } + ++const gchar * ++bus_match_rule_get_sender (BusMatchRule *rule) ++{ ++ g_return_val_if_fail (rule != NULL, NULL); ++ return rule->sender; ++} ++ + gboolean + bus_match_rule_set_sender (BusMatchRule *rule, + const gchar *sender) +diff --git a/bus/matchrule.h b/bus/matchrule.h +index 1dd304cd..37b6347b 100644 +--- a/bus/matchrule.h ++++ b/bus/matchrule.h +@@ -2,7 +2,8 @@ + /* vim:set et sts=4: */ + /* IBus - The Input Bus + * Copyright (C) 2008-2010 Peng Huang +- * Copyright (C) 2008-2010 Red Hat, Inc. ++ * Copyright (C) 2024 Takao Fujiwara ++ * Copyright (C) 2008-2024 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 +@@ -57,6 +58,7 @@ void bus_match_rule_free (BusMatchRule *rule); + gboolean bus_match_rule_set_message_type + (BusMatchRule *rule, + gint type); ++const gchar * bus_match_rule_get_sender (BusMatchRule *rule); + gboolean bus_match_rule_set_sender (BusMatchRule *rule, + const gchar *sender); + gboolean bus_match_rule_set_interface +-- +2.45.0 + +From a4d58cb859cad4a0c12e2c2a34f440f77cd73bae Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Sat, 1 Jun 2024 20:20:19 +0900 +Subject: [PATCH 2/6] portal: Let Flatpak application accept new IBus unique name + +ibus-portal can accept the connection from IBUS_SERVICE_IBUS only +but now the IBus unique name is changed to IBUS_NAME_OWNER_NAME +as the D-Bus name owner and probably I think the name check is +not needed and just delete it. + +BUG=https://github.com/ibus/ibus/issues/2639 +Fixes: https://github.com/ibus/ibus/commit/759105d +--- + portal/portal.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/portal/portal.c b/portal/portal.c +index c2e4fc7f..34da9679 100644 +--- a/portal/portal.c ++++ b/portal/portal.c +@@ -400,9 +400,6 @@ portal_context_g_signal (GDBusProxy *proxy, + GError *error = NULL; + GDBusConnection *connection; + +- if (g_strcmp0 (sender_name, IBUS_SERVICE_IBUS) != 0) +- return; +- + connection = g_dbus_interface_skeleton_get_connection ( + G_DBUS_INTERFACE_SKELETON (portal_context)); + if (!g_dbus_connection_emit_signal (connection, +-- +2.45.0 + +From 02632ccdd430fdc3d1a58025d31c5ec72d9a7989 Mon Sep 17 00:00:00 2001 +From: fujiwarat +Date: Sat, 1 Jun 2024 20:32:29 +0900 +Subject: [PATCH 3/6] portal: Support new sync ibus_input_context_process_key_event() + +IBus clients have been enhanced with the new synchronous +"ProcessKeyEvent" to fix the long-standing issues and ibus-portal +also needs to support it. + +Fixes: https://github.com/ibus/ibus/commit/38f09c6 +--- + portal/org.freedesktop.IBus.Portal.xml | 7 +++- + portal/portal.c | 54 ++++++++++++++++++++++++-- + 2 files changed, 56 insertions(+), 5 deletions(-) + +diff --git a/portal/org.freedesktop.IBus.Portal.xml b/portal/org.freedesktop.IBus.Portal.xml +index 376ad424..0b3f6864 100644 +--- a/portal/org.freedesktop.IBus.Portal.xml ++++ b/portal/org.freedesktop.IBus.Portal.xml +@@ -1,6 +1,6 @@ + +