public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/ibus] autotool: Fix time lag of CandidatePanel in X11
@ 2026-05-31  2:08 Takao Fujiwara
  0 siblings, 0 replies; only message in thread
From: Takao Fujiwara @ 2026-05-31  2:08 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/ibus
            Branch : autotool
            Commit : b17b2c5349ed16e3b5b7fc67ad7ec3b137102f32
            Author : Takao Fujiwara <tfujiwar@redhat.com>
            Date   : 2025-03-14T21:47:28+09:00
            Stats  : +419/-1 in 2 file(s)
            URL    : https://src.fedoraproject.org/rpms/ibus/c/b17b2c5349ed16e3b5b7fc67ad7ec3b137102f32?branch=autotool

            Log:
            Fix time lag of CandidatePanel in X11

Fix infinite Return key in xterm with Wayalnd input-method protocol V2

---
diff --git a/ibus-HEAD.patch b/ibus-HEAD.patch
index 310739c..eada3fc 100644
--- a/ibus-HEAD.patch
+++ b/ibus-HEAD.patch
@@ -127,3 +127,416 @@ index 20f89cef..fa15d2e7 100644
 -- 
 2.47.0
 
+From 5797150892317a30e37756ee62ae4fd644700dfc Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Fri, 14 Mar 2025 21:00:38 +0900
+Subject: [PATCH] ui/gtk3: Fix time lag of CandidatePanel in X11
+
+The timed `set_lookup_table()` is a workaround with the Wayland
+input-method protocol under the construction to stop the many D-Bus
+methods but it should not affect Xorg UI at least.
+
+Now `m_is_wayland flag` is inherited to the CandidatePanel and Switcher
+and add `m_first_set_lookup_table` flag newly to enhance the lag
+with the Wayland input-method protocol.
+
+Also fix compile warnings with `valac` in `xkblayout.vala`.
+
+Fixes: https://github.com/ibus/ibus/commit/d5e6e71
+BUG=https://github.com/ibus/ibus/issues/2740
+---
+ ui/gtk3/candidatepanel.vala | 63 ++++++++++++++++++++++++++++++++-----
+ ui/gtk3/panel.vala          |  5 +--
+ ui/gtk3/switcher.vala       | 25 ++++++++-------
+ ui/gtk3/xkblayout.vala      | 34 ++++++++++----------
+ 4 files changed, 90 insertions(+), 37 deletions(-)
+
+diff --git a/ui/gtk3/candidatepanel.vala b/ui/gtk3/candidatepanel.vala
+index f2447703..5ba8cf36 100644
+--- a/ui/gtk3/candidatepanel.vala
++++ b/ui/gtk3/candidatepanel.vala
+@@ -36,9 +36,10 @@ public class CandidatePanel : Gtk.Box{
+ 
+     private Pango.Attribute m_language_attribute;
+     private uint m_update_id;
++    private bool m_is_wayland;
++    private bool m_no_wayland_panel;
+ 
+ #if USE_GDK_WAYLAND
+-    private bool m_no_wayland_panel;
+     private bool m_hide_after_show;
+     private uint m_prev_page_size;
+     private uint m_prev_ncandidates;
+@@ -48,6 +49,7 @@ public class CandidatePanel : Gtk.Box{
+     private uint m_set_preedit_text_id;
+     private uint m_set_auxiliary_text_id;
+     private uint m_set_lookup_table_id;
++    private bool m_first_set_lookup_table;
+ #endif
+ 
+     public signal void cursor_up();
+@@ -64,7 +66,8 @@ public class CandidatePanel : Gtk.Box{
+     public signal void realize_surface(void *surface);
+ #endif
+ 
+-    public CandidatePanel(bool no_wayland_panel) {
++    public CandidatePanel(bool is_wayland,
++                          bool no_wayland_panel) {
+         // Call base class constructor
+         GLib.Object(
+             name : "IBusCandidate",
+@@ -72,9 +75,8 @@ public class CandidatePanel : Gtk.Box{
+             visible: true
+         );
+ 
+-#if USE_GDK_WAYLAND
++        m_is_wayland = is_wayland;
+         m_no_wayland_panel = no_wayland_panel;
+-#endif
+         m_toplevel = new Gtk.Window(Gtk.WindowType.POPUP);
+         m_toplevel.add_events(Gdk.EventMask.BUTTON_PRESS_MASK);
+         m_toplevel.button_press_event.connect((w, e) => {
+@@ -87,7 +89,7 @@ public class CandidatePanel : Gtk.Box{
+             adjust_window_position(w);
+         });
+ #if USE_GDK_WAYLAND
+-        if (!BindingCommon.default_is_xdisplay()) {
++        if (m_is_wayland) {
+             m_toplevel.realize.connect((w) => {
+                 realize_window(true);
+             });
+@@ -201,6 +203,10 @@ public class CandidatePanel : Gtk.Box{
+     }
+ 
+     public void set_preedit_text(IBus.Text? text, uint cursor) {
++        if (!m_is_wayland) {
++            set_preedit_text_real(text, cursor);
++            return;
++        }
+ #if USE_GDK_WAYLAND
+         if (m_set_preedit_text_id > 0)
+             GLib.Source.remove(m_set_preedit_text_id);
+@@ -238,6 +244,10 @@ public class CandidatePanel : Gtk.Box{
+     }
+ 
+     public void set_auxiliary_text(IBus.Text? text) {
++        if (!m_is_wayland) {
++            set_auxiliary_text_real(text);
++            return;
++        }
+ #if USE_GDK_WAYLAND
+         if (m_set_auxiliary_text_id > 0)
+             GLib.Source.remove(m_set_auxiliary_text_id);
+@@ -269,6 +279,10 @@ public class CandidatePanel : Gtk.Box{
+     }
+ 
+     public void set_lookup_table(IBus.LookupTable? table) {
++        if (!m_is_wayland) {
++            set_lookup_table_real(table);
++            return;
++        }
+ #if USE_GDK_WAYLAND
+         if (m_set_lookup_table_id > 0) {
+             if (table == null ||
+@@ -282,14 +296,25 @@ public class CandidatePanel : Gtk.Box{
+             }
+         }
+         if (table != null) {
++            if (m_prev_ncandidates == 0)
++                m_first_set_lookup_table = true;
+             m_prev_page_size = table.get_page_size();
+             m_prev_ncandidates = table.get_number_of_candidates();
+             m_prev_cursor = table.get_cursor_pos();
+             m_prev_cursor_in_page = table.get_cursor_in_page();
+             m_prev_show_cursor = table.is_cursor_visible();
++        } else {
++            m_prev_page_size = m_prev_ncandidates = m_prev_cursor =
++                    m_prev_cursor_in_page = 0;
++            m_prev_show_cursor = false;
+         }
+         // FIXME: Too many PreeditText D-Bus signal happens in Wayland.
+         m_set_lookup_table_id = Timeout.add(100,
++                                            // FIXME: If m_set_lookup_table_id
++                                            // == 0, delete the queued timed
++                                            // callbacks to avoid the last
++                                            // reverse cursor move after the
++                                            // key release.
+                                             () => {
+                                                 m_set_lookup_table_id = 0;
+                                                 set_lookup_table_real(table);
+@@ -353,9 +378,33 @@ public class CandidatePanel : Gtk.Box{
+     }
+ 
+     private void update() {
++        if (!m_is_wayland) {
++            update_real();
++            return;
++        }
++#if USE_GDK_WAYLAND
++        // Show the first lookup table immediately with the Wayland
++        // input-method protocol because keeping pressing the space key
++        // causes many update() and the timed update_real() is not called
++        // until the space key is released.
++        if (m_first_set_lookup_table) {
++            m_first_set_lookup_table = false;
++            if (m_update_id > 0) {
++                GLib.Source.remove(m_update_id);
++                m_update_id = 0;
++            }
++            update_real();
++            return;
++        }
++#endif
+         if (m_update_id > 0)
+             GLib.Source.remove(m_update_id);
+-        // set_lookup_table() and set_preedit_text() happens sequentially.
++        // - set_lookup_table() and set_preedit_text() happens sequentially.
++        // - Hide CandidatePanel after a candidate is committed with Emojier
++        // and xterm without the Wayland panel in the Wayland input-method V2.
++        // - Don't show the hidden lookup table unexpectedly again after
++        // a candidate is committed with the Wayland applications in the
++        // Wayland input-method V2.
+         m_update_id = Timeout.add(100,
+                                   () => {
+                                       m_update_id = 0;
+@@ -436,7 +485,7 @@ public class CandidatePanel : Gtk.Box{
+ 
+     public new void hide() {
+ #if USE_GDK_WAYLAND
+-        if (!BindingCommon.default_is_xdisplay())
++        if (m_is_wayland)
+             realize_surface(null);
+ #endif
+         m_toplevel.hide();
+diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
+index 186b3ac9..e42a166e 100644
+--- a/ui/gtk3/panel.vala
++++ b/ui/gtk3/panel.vala
+@@ -173,7 +173,8 @@ class Panel : IBus.PanelService {
+     }
+ 
+     private CandidatePanel candidate_panel_new(bool no_wayland_panel) {
+-        CandidatePanel candidate_panel = new CandidatePanel(no_wayland_panel);
++        CandidatePanel candidate_panel = new CandidatePanel(m_is_wayland,
++                                                            no_wayland_panel);
+         candidate_panel.page_up.connect((w) => this.page_up());
+         candidate_panel.page_down.connect((w) => this.page_down());
+         candidate_panel.cursor_up.connect((w) => this.cursor_up());
+@@ -190,7 +191,7 @@ class Panel : IBus.PanelService {
+     }
+ 
+     private Switcher switcher_new(bool no_wayland_panel) {
+-        Switcher switcher = new Switcher(no_wayland_panel);
++        Switcher switcher = new Switcher(m_is_wayland, no_wayland_panel);
+ #if USE_GDK_WAYLAND
+         switcher.realize_surface.connect(
+                 (w, s) => this.realize_surface(s));
+diff --git a/ui/gtk3/switcher.vala b/ui/gtk3/switcher.vala
+index 13eeb481..99a2fa0b 100644
+--- a/ui/gtk3/switcher.vala
++++ b/ui/gtk3/switcher.vala
+@@ -96,6 +96,7 @@ class Switcher : Gtk.Window {
+     private double m_mouse_init_x;
+     private double m_mouse_init_y;
+     private bool   m_mouse_moved;
++    private bool   m_is_wayland;
+     private bool   m_no_wayland_panel;
+     private GLib.HashTable<string, string> m_xkb_languages =
+             new GLib.HashTable<string, string>(GLib.str_hash,
+@@ -106,16 +107,19 @@ class Switcher : Gtk.Window {
+     public signal void realize_surface(void *surface);
+ #endif
+ 
+-    public Switcher(bool no_wayland_panel) {
++    public Switcher(bool is_wayland,
++                    bool no_wayland_panel) {
+         GLib.Object(
+             type : Gtk.WindowType.POPUP,
+-            events : Gdk.EventMask.KEY_PRESS_MASK | Gdk.EventMask.KEY_RELEASE_MASK,
++            events : Gdk.EventMask.KEY_PRESS_MASK |
++                     Gdk.EventMask.KEY_RELEASE_MASK,
+             window_position : Gtk.WindowPosition.CENTER,
+             accept_focus : true,
+             decorated : false,
+             modal : true,
+             focus_visible : true
+         );
++        m_is_wayland = is_wayland;
+         m_no_wayland_panel = no_wayland_panel;
+         Gtk.Box vbox = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
+         add(vbox);
+@@ -139,7 +143,7 @@ class Switcher : Gtk.Window {
+         vbox.pack_end(m_label, false, false, 0);
+ 
+ #if USE_GDK_WAYLAND
+-        if (!BindingCommon.default_is_xdisplay()) {
++        if (m_is_wayland) {
+             this.realize.connect((w) => {
+                 realize_window(true);
+             });
+@@ -381,12 +385,8 @@ class Switcher : Gtk.Window {
+                     return false;
+                 }
+                 m_mouse_moved = true;
+-#if USE_GDK_WAYLAND
+-                if (BindingCommon.default_is_xdisplay())
++                if (!m_is_wayland)
+                     button.grab_focus();
+-#else
+-                button.grab_focus();
+-#endif
+                 m_selected_engine = index;
+                 return false;
+             });
+@@ -571,7 +571,7 @@ class Switcher : Gtk.Window {
+         // if e.type == Gdk.EventType.KEY_RELEASE, m_loop is already null.
+         // m_loop is always null in Wayland but this signal is not emitted
+         // when the Wayland panel protocol is enabled.
+-        if (m_loop == null && !m_no_wayland_panel)
++        if (m_loop == null && !m_is_wayland)
+             return Gdk.EVENT_PROPAGATE;
+ 
+         if (m_popup_delay_time > 0) {
+@@ -582,9 +582,9 @@ class Switcher : Gtk.Window {
+         }
+ 
+         m_result = (int)m_selected_engine;
+-        if (!m_no_wayland_panel) {
++        if (!m_is_wayland) {
+             m_loop.quit();
+-        } else {
++        } else if (m_no_wayland_panel) {
+             // Switcher without the Wayland panel protocol can return
+             // the m_result_engine immediately in Wayland without waiting
+             // for the focus-in event due to a virtual input context in
+@@ -592,6 +592,9 @@ class Switcher : Gtk.Window {
+             GLib.assert(m_result < m_engines.length);
+             m_result_engine = m_engines[m_result];
+             hide();
++        } else {
++            // Switcher should not get focus with the Wayland panel protocol.
++            GLib.assert_not_reached();
+         }
+         return Gdk.EVENT_STOP;
+     }
+diff --git a/ui/gtk3/xkblayout.vala b/ui/gtk3/xkblayout.vala
+index 874920ee..598431c3 100644
+--- a/ui/gtk3/xkblayout.vala
++++ b/ui/gtk3/xkblayout.vala
+@@ -48,6 +48,11 @@ class XKBLayout
+     public void get_layout(out string layout,
+                            out string variant,
+                            out string option) {
++        layout = "";
++        variant = "";
++        var o = Environment.get_variable("XKB_DEFAULT_OPTIONS");
++        option = o != null ? o : "";
++
+         search_get_layout_program();
+         if (m_get_layout_args[0] == null) {
+             warning("Not found localectl or setxkbmap command in PATH");
+@@ -60,11 +65,6 @@ class XKBLayout
+         string standard_error = null;
+         int exit_status = 0;
+ 
+-        layout = "";
+-        variant = "";
+-        var o = Environment.get_variable("XKB_DEFAULT_OPTIONS");
+-        option = o != null ? o : "";
+-
+         try {
+             GLib.Process.spawn_sync(null,
+                                     exec_command,
+@@ -84,14 +84,14 @@ class XKBLayout
+ 
+         if (exec_command[0] == "localectl") {
+             parse_localectl_status_str(standard_output,
+-                                       out layout,
+-                                       out variant,
+-                                       out option);
++                                       ref layout,
++                                       ref variant,
++                                       ref option);
+         } else if (exec_command[0] == XKB_COMMAND) {
+             parse_xkbmap_query_str(standard_output,
+-                                   out layout,
+-                                   out variant,
+-                                   out option);
++                                   ref layout,
++                                   ref variant,
++                                   ref option);
+         }
+     }
+ 
+@@ -113,9 +113,9 @@ class XKBLayout
+ 
+ 
+     private void parse_localectl_status_str(string standard_output,
+-                                            out string layout,
+-                                            out string variant,
+-                                            out string option) {
++                                            ref string layout,
++                                            ref string variant,
++                                            ref string option) {
+         foreach (string line in standard_output.split("\n")) {
+             const string[] elements = { "X11 Layout:", "X11 Variant:" };
+             foreach (unowned string element in elements) {
+@@ -136,9 +136,9 @@ class XKBLayout
+ 
+ 
+     private void parse_xkbmap_query_str(string standard_output,
+-                                        out string layout,
+-                                        out string variant,
+-                                        out string option) {
++                                        ref string layout,
++                                        ref string variant,
++                                        ref string option) {
+         foreach (string line in standard_output.split("\n")) {
+             const string[] elements = { "layout:", "variant:", "options:" };
+             foreach (unowned string element in elements) {
+-- 
+2.47.0
+
+From 1d56d77b19daf5c8d6f3ee87a0712ae5904293f4 Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Fri, 14 Mar 2025 21:00:52 +0900
+Subject: [PATCH] client/wayland: Fix infinite Return key in xterm
+
+Currently the repeating key feature of IBus is disabled when the focus
+is changed but the feature of the Wayland compositor still happens in
+the Sway desktop session when invoke xterm by manual in foot.
+I think Sway should stop the repeating key feature when the focus is
+changed from the Wayland application to the non-Wayland application.
+
+I add a workaround to call `zwp_virtual_keyboard_v1_key()` with
+the `WL_KEYBOARD_KEY_STATE_RELEASED` flag to stop the feature of
+the Sway compositor after the IBus repeating key timeout.
+---
+ client/wayland/ibuswaylandim.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/client/wayland/ibuswaylandim.c b/client/wayland/ibuswaylandim.c
+index ba392c6b..356cec31 100644
+--- a/client/wayland/ibuswaylandim.c
++++ b/client/wayland/ibuswaylandim.c
+@@ -1332,6 +1332,17 @@ _process_key_event_repeat_delay_cb (gpointer user_data)
+     /* The key release event was sent to non-Wayland apps likes xterm. */
+     if (!priv->ibuscontext) {
+         event->count_cb_id = 0;
++        /* Stop the infinite Return keys in non-Wayland apps likes xterm in
++         * the Sway desktop session.
++         * But priv->context in NULL in the Wayland input-method V1 here.
++         */
++        if (priv->version != INPUT_METHOD_V1) {
++            ibus_wayland_im_key(event->wlim,
++                                event->serial,
++                                event->time + priv->repeat_delay,
++                                event->key,
++                                WL_KEYBOARD_KEY_STATE_RELEASED);
++        }
+         return G_SOURCE_REMOVE;
+     }
+     /* The focus is changed. */
+-- 
+2.47.0
+

diff --git a/ibus.spec b/ibus.spec
index 5caa42d..b1ba38d 100644
--- a/ibus.spec
+++ b/ibus.spec
@@ -63,7 +63,7 @@
 Name:           ibus
 Version:        1.5.32~rc1
 # https://github.com/fedora-infra/rpmautospec/issues/101
-Release:        3%{?dist}
+Release:        4%{?dist}
 Summary:        Intelligent Input Bus for Linux OS
 License:        LGPL-2.1-or-later
 URL:            https://github.com/ibus/%name/wiki
@@ -386,6 +386,7 @@ fi
     --enable-introspection \
     --enable-install-tests \
     %{nil}
+make -C ui/gtk3 maintainer-clean-generic
 
 %make_build
 
@@ -638,6 +639,10 @@ dconf update || :
 %{_datadir}/installed-tests/ibus
 
 %changelog
+* Fri Mar 14 2025 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.32~rc1-4
+- Fix time lag of CandidatePanel in X11
+- Fix infinite Return key in xterm with Wayalnd input-method protocol V2
+
 * Sun Mar 09 2025 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.32~rc1-3
 - Send RequireSurroundingText method with engine active-surrounding-text property
 

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-05-31  2:08 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-31  2:08 [rpms/ibus] autotool: Fix time lag of CandidatePanel in X11 Takao Fujiwara

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox