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