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

From: Po Lu <[email-masked]>
Date: Wed, 12 Feb 2025 09:24:01 +0800

Pip Cet <[email-masked]> writes:

> But Emacs calls XFilterEvent in conjunction with GDK in a weird way,
> sometimes out of order (and sometimes twice for the same event? I'm not
> sure I understand this), and once in a while such reordering will result
> in the fake time wraparound happening and key presses not being
> filtered.
>
> IOW, Emacs treats XFilterEvent as a pure function, but it has side
> effects which can cause a second return value, or one generated out of
> order, to differ when input methods are in use.
>
> I assume the reason this happens with feature/igc but not with master is
> that handle_one_xevent can have significant (not user-noticeable, but
> enough for the time between keypress and keyrelease, maybe) and
> unexpected latency when GC is happening, but not with the old GC.
>
> I don't have a proper fix, but can you try this patch and see what
> behavior is like with it?
>
>
> diff --git a/src/xterm.c b/src/xterm.c
> index 80108190590..59d1d7fdaa6 100644
> --- a/src/xterm.c
> +++ b/src/xterm.c
> @@ -24131,7 +24131,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
>  		  copy.xkey.window = xev->event;
>  		  copy.xkey.root = xev->root;
>  		  copy.xkey.subwindow = xev->child;
> -		  copy.xkey.time = xev->time;
> +		  fprintf (stderr, "ignoring time %ld\n", (long) xev->time);
> +		  copy.xkey.time = CurrentTime;
>  		  copy.xkey.state = state;
>  		  xi_convert_button_state (&xev->buttons, &copy.xkey.state);
>  
> @@ -24189,7 +24190,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
>  	      xkey.window = xev->event;
>  	      xkey.root = xev->root;
>  	      xkey.subwindow = xev->child;
> -	      xkey.time = xev->time;
> +	      fprintf (stderr, "ignoring time %ld\n", (long) xev->time);
> +	      xkey.time = CurrentTime;
>  	      xkey.state = state;
>  	      xkey.x = lrint (xev->event_x);
>  	      xkey.y = lrint (xev->event_y);
> @@ -24631,7 +24633,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
>  	      xkey.window = xev->event;
>  	      xkey.root = xev->root;
>  	      xkey.subwindow = xev->child;
> -	      xkey.time = xev->time;
> +	      fprintf (stderr, "ignoring time %ld\n", (long) xev->time);
> +	      xkey.time = CurrentTime;
>  	      xkey.state = xi_convert_event_keyboard_state (xev);
>  	      xkey.x = lrint (xev->event_x);
>  	      xkey.y = lrint (xev->event_y);
>
> At least over here (with the imperfect setup described above), I haven't
> been able to reproduce the falsely-unfiltered key issue.

I don't think this is correct, but Emacs is not supposed to hand events
for which XFilterEvent has already been involved over to GDK.  It is for
this reason that all key press events which are registered by Emacs's
input window and filtered are withheld from GDK, as it generates GDK
events in a separate event queue that is polled long after
handle_one_xevent returns (and the time at which GTK's input method
conversion transpires is further away still).  But this is only material
if GTK's XIM input module is enabled, for otherwise only non-key events
are filtered by GTK, as XFilterEvent is not input extension-aware.

Yikai, what is your GTK_IM_MODULE?  You can ascertain this by enabling
the GTK Inspector (I think a web search should provide ample
instructions), starting `gtk3-demo', typing Ctrl+Shift+d, and displaying
the General tab in the inspector window.