Subject: bug#74590: 31.0.50 [scratch/igc branch]; key input sometimes skip fcitx input method preedit box

From: Pip Cet <[email-masked]>
Date: Fri, 28 Feb 2025 16:54:20 +0000

"Yikai Zhao" <[email-masked]> writes:

> On Tue, Feb 25, 2025 at 11:19 PM Yikai Zhao <[email-masked]> wrote:
> Update: after some days of use, I can confirm that this patch fixes
> the issue for me.

Thank you, that is good news!

Po Lu, could you have a look at this patch?  The rationale is we should
always call XFilterEvent for keyboard events, even if they arrive while
current_count is -1 (whatever that means), because they might be
intended for the input method.

>From eaba03a308dce4ed66fb5c3260e90c4f4dc47aa4 Mon Sep 17 00:00:00 2001
From: Pip Cet <[email-masked]>
Subject: [PATCH] Always call XFilterEvent for X11 keyboard events (bug#74590)

* src/xterm.c (event_handler_gdk): Call 'x_filter_event' or
'xg_filter_key' even when 'current_count' is negative.
---
 src/xterm.c | 84 ++++++++++++++++++++++++++---------------------------
 1 file changed, 42 insertions(+), 42 deletions(-)

diff --git a/src/xterm.c b/src/xterm.c
index c3137945ac5..54d8cb0f865 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -17966,59 +17966,59 @@ event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data)
   XEvent *xev = (XEvent *) gxev;
 
   block_input ();
-  if (current_count >= 0)
-    {
-      struct x_display_info *dpyinfo;
+  struct x_display_info *dpyinfo;
 
-      dpyinfo = x_display_info_for_display (xev->xany.display);
+  dpyinfo = x_display_info_for_display (xev->xany.display);
 
 #ifdef HAVE_X_I18N
-      /* Filter events for the current X input method.
-         GTK calls XFilterEvent but not for key press and release,
-         so we do it here.  */
-      if ((xev->type == KeyPress || xev->type == KeyRelease)
-	  && dpyinfo
-	  && x_filter_event (dpyinfo, xev))
-	{
-	  unblock_input ();
-	  return GDK_FILTER_REMOVE;
-	}
+  /* Filter events for the current X input method.
+     GTK calls XFilterEvent but not for key press and release,
+     so we do it here.  */
+  if ((xev->type == KeyPress || xev->type == KeyRelease)
+      && dpyinfo
+      && x_filter_event (dpyinfo, xev))
+    {
+      unblock_input ();
+      return GDK_FILTER_REMOVE;
+    }
 #elif USE_GTK
-      if (dpyinfo && (dpyinfo->prefer_native_input
-		      || x_gtk_use_native_input)
-	  && (xev->type == KeyPress
-#ifdef HAVE_XINPUT2
-	      /* GTK claims cookies for us, so we don't have to claim
-		 them here.  */
-	      || (dpyinfo->supports_xi2
-		  && xev->type == GenericEvent
-		  && (xev->xgeneric.extension
-		      == dpyinfo->xi2_opcode)
-		  && ((xev->xgeneric.evtype
-		       == XI_KeyPress)
-		      || (xev->xgeneric.evtype
-			  == XI_KeyRelease)))
-#endif
-	      ))
-	{
-	  struct frame *f;
+  if (dpyinfo && (dpyinfo->prefer_native_input
+		  || x_gtk_use_native_input)
+      && (xev->type == KeyPress
+	  #ifdef HAVE_XINPUT2
+	  /* GTK claims cookies for us, so we don't have to claim
+	     them here.  */
+	  || (dpyinfo->supports_xi2
+	      && xev->type == GenericEvent
+	      && (xev->xgeneric.extension
+		  == dpyinfo->xi2_opcode)
+	      && ((xev->xgeneric.evtype
+		   == XI_KeyPress)
+		  || (xev->xgeneric.evtype
+		      == XI_KeyRelease)))
+	  #endif
+	 ))
+    {
+      struct frame *f;
 
 #ifdef HAVE_XINPUT2
-	  if (xev->type == GenericEvent)
-	    f = x_any_window_to_frame (dpyinfo,
-				       ((XIDeviceEvent *) xev->xcookie.data)->event);
-	  else
+      if (xev->type == GenericEvent)
+	f = x_any_window_to_frame (dpyinfo,
+				   ((XIDeviceEvent *) xev->xcookie.data)->event);
+      else
 #endif
-	    f = x_any_window_to_frame (dpyinfo, xev->xany.window);
+      f = x_any_window_to_frame (dpyinfo, xev->xany.window);
 
-	  if (f && xg_filter_key (f, xev))
-	    {
-	      unblock_input ();
-	      return GDK_FILTER_REMOVE;
-	    }
+      if (f && xg_filter_key (f, xev))
+	{
+	  unblock_input ();
+	  return GDK_FILTER_REMOVE;
 	}
+    }
 #endif
 
+  if (current_count >= 0)
+    {
       if (! dpyinfo)
         current_finish = X_EVENT_NORMAL;
       else
-- 
2.48.1