GVim UI freezes

Using Fedora Rawhide, I have issues using GVim for a long time, where the UI appears to freeze.

The (unreliable) steps to reproduce are:

  1. Open some file in GVim from terminal, in my case it might be $ gvim rubygem-excon.spec
  2. Do something else in some other windows, typically switch to browser or terminal
  3. Once get back to GVim, the UI is mostly frozen. Moving the mouse above, the mouse cursor changes its direction like from LTR / RTL text.
  4. The only option appears to close the GVim window and start from scratch

I have initially reported the issue here:

but so far, without any luck. What brings me here is that strangely enough, the recently landed initial GVim Wayland support does not suffer this issues, while the changes there (as far as I can judge) were not substantial. But maybe somebody more knowledgeable than me could help the spot the issue or the difference between X11 / Wayland.

Hello @vo.x,

Is GVim based on GTK2 or GTK3?

It would be great to get a first stacktrace and check if the application is polling events or if it’s stuck somewhere (a loop or deadlock). Please, read this first: Providing a Stack Trace :: Fedora Docs

  1. Launch GVim and try to reproduce the issue
  2. When GVim is blocked, open the terminal and attach the debugger: gdb -p <PID of GVim>
  3. If it asks for debug info, say yes
  4. Type thread apply all bt

Checking the Fedora vim.spec, it requires gtk3-devel therefore I assume it is GTK3 app.

I agree that it would be great to have BT, but the problem is that GVim is not frozen. Only the UI is mostly frozen. From GVim, it is even possible to open some dialogs.

IOW all the backtraces I can get are from live responding process, therefore I don’t think they are useful.

One of the symptoms seems to be that this signal is not emitted / handled anymore:

Can you check which input method module is in use by GTK? Launch gvim with the environment variable GTK_DEBUG=interactive, switch to the General tab in the inspector and check for Input Method (although may not be there if GTK3 is not very recent!). That’s to rule out graphical artifacts caused by the XIM input method, see Drawing area freezes upon activating the text tool if XIM enabled (#3664) · Issues · Inkscape / inkscape · GitLab

Speaking of GTK, the inspector actually list the 3.24.41 version

Input method is “ibus”.

Checking the GTK_IM_MODULE is not set as far as I can say:

$ echo $GTK_IM_MODULE

$ cat /proc/1366942/environ | tr '\0' '\n' | grep GTK_IM_MODULE

I might try to experiment with the gtk-im-context-simple

Unfortunately, that doesn’t help and my GVim UI is frozen again:

$ ps -ef |grep gvim
vondruch 1372845    2378  0 09:47 ?        00:00:00 gvim newpackage.spec
vondruch 1377218 1372709  0 10:43 pts/7    00:00:00 grep --color=auto gvim

$ cat /proc/1372845/environ | tr '\0' '\n' | grep GTK_IM_MODULE
GTK_IM_MODULE=gtk-im-context-simple

After a trying e.g. Valgrind, I am back in debugger with a few more ideas.

So there is the configure-event signal, which should be emitted upon size, position or stacking of the widget 's window changes. This calls drawarea_configure_event_cb function. Setting breakpoint there, this is the backtrace:

Thread 1 "gvim" hit Breakpoint 1, drawarea_configure_event_cb (widget=widget@entry=0x555555fa8060, event=0x555556422530, data=0x0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui_gtk_x11.c:2980
2980	{
(gdb) bt
#0  drawarea_configure_event_cb (widget=widget@entry=0x555555fa8060, event=0x555556422530, data=0x0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui_gtk_x11.c:2980
#1  0x00007ffff768d5f4 in _gtk_marshal_BOOLEAN__BOXED (closure=0x555555fa8600, return_value=0x7fffffffb340, param_values=0x7fffffffb3d0, marshal_data=<optimized out>, invocation_hint=<optimized out>, n_param_values=<optimized out>)
    at gtk/gtkmarshalers.c:84
#2  0x00007ffff7dce4da in g_closure_invoke (closure=0x555555fa8600, return_value=0x7fffffffb340, n_param_values=2, param_values=0x7fffffffb3d0, invocation_hint=0x7fffffffb320) at ../gobject/gclosure.c:834
#3  0x00007ffff7dfd903 in signal_emit_unlocked_R.isra.0 (node=node@entry=0x7fffffffb4d0, detail=detail@entry=0, instance=instance@entry=0x555555fa8060, emission_return=emission_return@entry=0x7fffffffb550, 
    instance_and_params=instance_and_params@entry=0x7fffffffb3d0) at ../gobject/gsignal.c:3879
#4  0x00007ffff7dedeb9 in signal_emit_valist_unlocked (instance=instance@entry=0x555555fa8060, signal_id=signal_id@entry=72, detail=detail@entry=0, var_args=var_args@entry=0x7fffffffb640) at ../gobject/gsignal.c:3524
#5  0x00007ffff7dee8b1 in g_signal_emit_valist (instance=0x555555fa8060, signal_id=72, detail=0, var_args=var_args@entry=0x7fffffffb640) at ../gobject/gsignal.c:3254
#6  0x00007ffff7dee973 in g_signal_emit (instance=instance@entry=0x555555fa8060, signal_id=<optimized out>, detail=detail@entry=0) at ../gobject/gsignal.c:3574
#7  0x00007ffff795d314 in gtk_widget_event_internal.part.0.lto_priv.0 (widget=0x555555fa8060, event=0x555556422530) at ../gtk/gtkwidget.c:7812
#8  0x00007ffff77517e0 in gtk_drawing_area_send_configure (darea=0x555555fa8060) at ../gtk/gtkdrawingarea.c:264
#9  0x00007ffff794c4b7 in gtk_widget_size_allocate_with_baseline (widget=0x555555fa8060, allocation=allocation@entry=0x7fffffffb8a0, baseline=<optimized out>, baseline@entry=-1) at ../gtk/gtkwidget.c:6179
#10 0x00007ffff794c80e in gtk_widget_size_allocate (widget=<optimized out>, allocation=allocation@entry=0x7fffffffb8a0) at ../gtk/gtkwidget.c:6260
#11 0x00005555558508ff in form_position_child (form=<optimized out>, child=0x555555fa70a0, force_allocate=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui_gtk_f.c:805
#12 0x00005555558b0a2a in gui_gtk_form_move_resize (h=840, w=1700, y=0, x=0, widget=0x555555fa8060, form=0x555555fa79a0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui_gtk_f.c:840
#13 gui_mch_set_text_area_pos (y=0, h=840, w=1700, x=0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui_gtk.c:845
#14 gui_position_components.isra.0 (total_width=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:1464
#15 0x0000555555846312 in gui_resize_shell (pixel_width=1716, pixel_height=841) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:1579
#16 0x0000555555850c0d in gui_resize_shell (pixel_height=841, pixel_width=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:1557
#17 form_configure_event (widget=widget@entry=0x555555fa79a0, event=0x7fffffffc070, data=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui_gtk_x11.c:4317
#18 0x00007ffff768d5f4 in _gtk_marshal_BOOLEAN__BOXED (closure=0x5555561631b0, return_value=0x7fffffffbb50, param_values=0x7fffffffbbe0, marshal_data=<optimized out>, invocation_hint=<optimized out>, n_param_values=<optimized out>)
    at gtk/gtkmarshalers.c:84
#19 0x00007ffff7dce4da in g_closure_invoke (closure=0x5555561631b0, return_value=0x7fffffffbb50, n_param_values=2, param_values=0x7fffffffbbe0, invocation_hint=0x7fffffffbb30) at ../gobject/gclosure.c:834
#20 0x00007ffff7dfd903 in signal_emit_unlocked_R.isra.0 (node=node@entry=0x7fffffffbce0, detail=detail@entry=0, instance=instance@entry=0x555555fa79a0, emission_return=emission_return@entry=0x7fffffffbd60, 
    instance_and_params=instance_and_params@entry=0x7fffffffbbe0) at ../gobject/gsignal.c:3879
#21 0x00007ffff7dedeb9 in signal_emit_valist_unlocked (instance=instance@entry=0x555555fa79a0, signal_id=signal_id@entry=72, detail=detail@entry=0, var_args=var_args@entry=0x7fffffffbe50) at ../gobject/gsignal.c:3524
#22 0x00007ffff7dee8b1 in g_signal_emit_valist (instance=0x555555fa79a0, signal_id=72, detail=0, var_args=var_args@entry=0x7fffffffbe50) at ../gobject/gsignal.c:3254
#23 0x00007ffff7dee973 in g_signal_emit (instance=instance@entry=0x555555fa79a0, signal_id=<optimized out>, detail=detail@entry=0) at ../gobject/gsignal.c:3574
#24 0x00007ffff795d314 in gtk_widget_event_internal.part.0.lto_priv.0 (widget=0x555555fa79a0, event=0x7fffffffc070) at ../gtk/gtkwidget.c:7812
#25 0x00007ffff77f3f9c in gtk_main_do_event (event=<optimized out>) at ../gtk/gtkmain.c:1861
#26 gtk_main_do_event (event=<optimized out>) at ../gtk/gtkmain.c:1691
#27 0x0000555555850d75 in form_send_configure (form=0x555555fa79a0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui_gtk_f.c:860
#28 form_size_allocate (widget=0x555555fa79a0, allocation=0x7fffffffc160) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui_gtk_f.c:520
#29 0x00007ffff794c4b7 in gtk_widget_size_allocate_with_baseline (widget=0x555555fa79a0, allocation=<optimized out>, baseline=<optimized out>) at ../gtk/gtkwidget.c:6179
#30 0x00007ffff76bef15 in gtk_box_size_allocate_no_center (widget=<optimized out>, allocation=<optimized out>) at ../gtk/gtkbox.c:817
#31 0x00007ffff76bfdad in gtk_box_allocate_contents (gadget=<optimized out>, allocation=<optimized out>, baseline=<optimized out>, out_clip=0x7fffffffc360, unused=<optimized out>) at ../gtk/gtkbox.c:1211
#32 0x00007ffff771865e in gtk_css_gadget_allocate (gadget=0x555555f8e530, allocation=0x7fffffffc4d0, baseline=-1, out_clip=0x7fffffffc400) at ../gtk/gtkcssgadget.c:790
#33 0x00007ffff76bdb0c in gtk_box_size_allocate (widget=0x555555f8dbd0, allocation=0x7fffffffc4d0) at ../gtk/gtkbox.c:1225
#34 0x00007ffff794c4b7 in gtk_widget_size_allocate_with_baseline (widget=0x555555f8dbd0, allocation=<optimized out>, baseline=<optimized out>) at ../gtk/gtkwidget.c:6179
#35 0x00007ffff796c48b in gtk_window_size_allocate (widget=0x555555b7f5d0, allocation=<optimized out>) at ../gtk/gtkwindow.c:7957
#36 0x00007ffff7dce4da in g_closure_invoke (closure=0x5555559f27d0, return_value=0x0, n_param_values=2, param_values=0x7fffffffc760, invocation_hint=0x7fffffffc6b0) at ../gobject/gclosure.c:834
#37 0x00007ffff7dfda30 in signal_emit_unlocked_R.isra.0 (node=node@entry=0x7fffffffc860, detail=detail@entry=0, instance=instance@entry=0x555555b7f5d0, emission_return=emission_return@entry=0x0, 
    instance_and_params=instance_and_params@entry=0x7fffffffc760) at ../gobject/gsignal.c:3712
#38 0x00007ffff7dee654 in signal_emit_valist_unlocked (instance=instance@entry=0x555555b7f5d0, signal_id=signal_id@entry=42, detail=detail@entry=0, var_args=var_args@entry=0x7fffffffc9d0) at ../gobject/gsignal.c:3511
#39 0x00007ffff7dee8b1 in g_signal_emit_valist (instance=0x555555b7f5d0, signal_id=42, detail=0, var_args=var_args@entry=0x7fffffffc9d0) at ../gobject/gsignal.c:3254
#40 0x00007ffff7dee973 in g_signal_emit (instance=instance@entry=0x555555b7f5d0, signal_id=<optimized out>, detail=detail@entry=0) at ../gobject/gsignal.c:3574
#41 0x00007ffff794c696 in gtk_widget_size_allocate_with_baseline (widget=0x555555b7f5d0, allocation=<optimized out>, baseline=<optimized out>) at ../gtk/gtkwidget.c:6177
#42 0x00007ffff796d8f7 in gtk_window_move_resize (window=0x555555b7f5d0) at ../gtk/gtkwindow.c:10052
#43 0x00007ffff7dee7a4 in _g_closure_invoke_va (param_types=0x0, n_params=<optimized out>, args=0x7fffffffcef0, instance=0x555555b7f5d0, return_value=0x0, closure=0x555555a009c0) at ../gobject/gclosure.c:897
#44 signal_emit_valist_unlocked (instance=instance@entry=0x555555b7f5d0, signal_id=signal_id@entry=109, detail=detail@entry=0, var_args=var_args@entry=0x7fffffffcef0) at ../gobject/gsignal.c:3415
#45 0x00007ffff7dee8b1 in g_signal_emit_valist (instance=0x555555b7f5d0, signal_id=109, detail=0, var_args=var_args@entry=0x7fffffffcef0) at ../gobject/gsignal.c:3254
#46 0x00007ffff7dee973 in g_signal_emit (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>) at ../gobject/gsignal.c:3574
#47 0x00007ffff7707b20 in gtk_container_idle_sizer (clock=0x555555b0b120, container=0x555555b7f5d0) at ../gtk/gtkcontainer.c:2066
#48 0x00007ffff7dee7a4 in _g_closure_invoke_va (param_types=0x0, n_params=<optimized out>, args=0x7fffffffd230, instance=0x555555b0b120, return_value=0x0, closure=0x5555564272a0) at ../gobject/gclosure.c:897
#49 signal_emit_valist_unlocked (instance=instance@entry=0x555555b0b120, signal_id=signal_id@entry=31, detail=detail@entry=0, var_args=var_args@entry=0x7fffffffd230) at ../gobject/gsignal.c:3415
#50 0x00007ffff7dee8b1 in g_signal_emit_valist (instance=0x555555b0b120, signal_id=31, detail=0, var_args=var_args@entry=0x7fffffffd230) at ../gobject/gsignal.c:3254
#51 0x00007ffff7dee973 in g_signal_emit (instance=instance@entry=0x555555b0b120, signal_id=<optimized out>, detail=detail@entry=0) at ../gobject/gsignal.c:3574
#52 0x00007ffff7efcb44 in _gdk_frame_clock_emit_layout (frame_clock=0x555555b0b120) at ../gdk/gdkframeclock.c:651
#53 gdk_frame_clock_paint_idle (data=0x555555b0b120) at ../gdk/gdkframeclockidle.c:575
#54 0x00007ffff7ee8cbd in gdk_threads_dispatch (data=data@entry=0x555555f8b7f0) at ../gdk/gdk.c:769
--Type <RET> for more, q to quit, c to continue without paging--c
#55 0x00007ffff72153c9 in g_timeout_dispatch (source=0x555556342500, callback=0x7ffff7ee8c90 <gdk_threads_dispatch>, user_data=0x555555f8b7f0) at ../glib/gmain.c:4989
#56 0x00007ffff720f26c in g_main_dispatch (context=0x5555559ec6c0) at ../glib/gmain.c:3344
#57 g_main_context_dispatch_unlocked (context=0x5555559ec6c0) at ../glib/gmain.c:4152
#58 0x00007ffff72702a8 in g_main_context_iterate_unlocked.isra.0 (context=context@entry=0x5555559ec6c0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/gmain.c:4217
#59 0x00007ffff72106e3 in g_main_context_iteration (context=0x5555559ec6c0, context@entry=0x0, may_block=may_block@entry=1) at ../glib/gmain.c:4282
#60 0x000055555583e90f in gui_mch_wait_for_chars (wtime=4000) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui_gtk_x11.c:6691
#61 gui_wait_for_chars_3 (wtime=wtime@entry=4000, interrupted=interrupted@entry=0x7fffffffd5fc, ignore_input=ignore_input@entry=0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:2957
#62 0x00005555557d78d8 in ui_wait_for_chars_or_timer (wtime=4000, wait_func=0x55555583e830 <gui_wait_for_chars_3>, interrupted=0x7fffffffd5fc, ignore_input=0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/ui.c:488
#63 0x00005555557d82fd in inchar_loop (buf=0x555555982e5a <typebuf_init.lto_priv+90> "", maxlen=58, wtime=-1, tb_change_cnt=301, wait_func=0x55555583ea90 <gui_wait_for_chars_or_timer>, resize_func=<optimized out>)
    at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/ui.c:384
#64 0x0000555555841e49 in gui_wait_for_chars_buf (buf=0x555555982e5a <typebuf_init.lto_priv+90> "", maxlen=58, wtime=-1, tb_change_cnt=301) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:3023
#65 0x00005555557d8ab5 in gui_inchar (tb_change_cnt=<optimized out>, wtime=-1, maxlen=58, buf=0x555555982e5a <typebuf_init.lto_priv+90> "") at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:3056
#66 ui_inchar (buf=0x555555982e5a <typebuf_init.lto_priv+90> "", maxlen=58, wtime=-1, tb_change_cnt=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/ui.c:226
#67 0x0000555555663778 in inchar (buf=0x555555982e5a <typebuf_init.lto_priv+90> "", maxlen=174, wait_time=-1) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/getchar.c:3808
#68 0x0000555555664949 in vgetorpeek (advance=1) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/getchar.c:3593
#69 0x000055555565ffc4 in vgetc () at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/getchar.c:1784
#70 0x00005555556c485e in safe_vgetc () at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/getchar.c:2035
#71 normal_cmd (oap=0x7fffffffdba0, toplevel=1) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/normal.c:761
#72 0x000055555589157b in main_loop (cmdwin=cmdwin@entry=0, noexmode=noexmode@entry=0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/main.c:1562
#73 0x000055555557e0c0 in vim_main2 () at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/main.c:895
#74 main (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/main.c:441

Where there is the gdk_frame_clock_paint_idle function which by its description seems to be responsible for painting the window. It certainly is called every time switching from terminal to GVim. However, the same function is not called when the UI si frozen (but it is still called when trying e.g. the menu).

The question why it is not called. It seems the answer could be in some of the frames bellow the #53

I wonder where are the signals recorded? Where I can put some breakpoint to see why the signal is not emitted anymore?

BTW why I cannot attach links to GH? What is going on here?

Likely because the frame clock is paused waiting for an event from the windowing system, or an update from the UI.

If I remember from last time I saw GVim’s code, the GTK layer in GVim starts and stops the main loop every time an event reaches the GTK widgets, to allow the Vim main loop to run; this of course prevents the frame clock from spinning, which prevents GTK from actually doing its job.

Things might have changed, but that’s an egregious way to break GTK’s own frame rendering.

It’s an anti-spam measure for newly created users. SEO farming is far too common.

Looking around, the gdk_frame_clock_paint_idle seems to be enabled (and later disabled) like this:

#0  maybe_start_idle (clock_idle=0x555556176230, caused_by_thaw=0) at ../gdk/gdkframeclockidle.c:298
#1  0x00007ffff7f0488c in impl_window_add_update_area (region=0x555556345b40, impl_window=0x555555aafa90) at ../gdk/gdkwindow.c:4357
#2  gdk_window_invalidate_maybe_recurse_full (window=0x555555aafa90, region=0x555556345910, child_func=<optimized out>, user_data=0x0) at ../gdk/gdkwindow.c:4486
#3  0x00007ffff79476a6 in gtk_widget_queue_draw_area (widget=0x555555fa8130, x=2, y=933, width=<optimized out>, height=19) at ../gtk/gtkwidget.c:5684
#4  0x00005555558488dd in gui_gtk2_draw_string_ext (force_pango=<optimized out>, flags=<optimized out>, len=<optimized out>, s=0x55555632b910 " ", col=1, row=49) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui_gtk_x11.c:6298
#5  gui_gtk2_draw_string (flags=<optimized out>, len=<optimized out>, s=<optimized out>, col=1, row=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui_gtk_x11.c:6034
#6  gui_outstr_nowrap (s=<optimized out>, s@entry=0x55555632b910 " ", len=<optimized out>, len@entry=1, flags=flags@entry=16, fg=fg@entry=0, bg=bg@entry=0, back=back@entry=1) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:2518
#7  0x000055555584a614 in gui_screenstr (fg=0, bg=0, back=<optimized out>, flags=<optimized out>, len=<optimized out>, off=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:2234
#8  gui_redraw_block (row1=<optimized out>, col1=<optimized out>, row2=<optimized out>, col2=<optimized out>, flags=flags@entry=16) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:2847
#9  0x000055555584a87d in gui_redraw_block (flags=16, col2=<optimized out>, row2=<optimized out>, col1=<optimized out>, row1=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:2753
#10 gui_undraw_cursor () at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:2697
#11 0x000055555583d16d in gui_undraw_cursor () at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:1176
#12 gui_update_cursor (force=<optimized out>, clear_selection=0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:1179
#13 0x00005555557ad7b2 in out_flush_cursor (clear_selection=0, force=1) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/term.c:2780
#14 out_flush_cursor (force=1, clear_selection=0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/term.c:2770
#15 0x0000555555841103 in gui_focus_change (in_focus=1) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:4720
#16 focus_in_event (widget=widget@entry=0x555555f833c0, event=<optimized out>, data=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui_gtk_x11.c:1065
#17 0x00007ffff768d5f4 in _gtk_marshal_BOOLEAN__BOXED (closure=0x555555fa8b40, return_value=0x7fffffffce60, param_values=0x7fffffffcef0, marshal_data=<optimized out>, invocation_hint=<optimized out>, n_param_values=<optimized out>)
    at gtk/gtkmarshalers.c:84
#18 0x00007ffff7dce4da in g_closure_invoke (closure=0x555555fa8b40, return_value=0x7fffffffce60, n_param_values=2, param_values=0x7fffffffcef0, invocation_hint=0x7fffffffce40) at ../gobject/gclosure.c:834
#19 0x00007ffff7dfd903 in signal_emit_unlocked_R.isra.0 (node=node@entry=0x7fffffffcff0, detail=detail@entry=0, instance=instance@entry=0x555555f833c0, emission_return=emission_return@entry=0x7fffffffd070, 
    instance_and_params=instance_and_params@entry=0x7fffffffcef0) at ../gobject/gsignal.c:3879
#20 0x00007ffff7dedeb9 in signal_emit_valist_unlocked (instance=instance@entry=0x555555f833c0, signal_id=signal_id@entry=73, detail=detail@entry=0, var_args=var_args@entry=0x7fffffffd160) at ../gobject/gsignal.c:3524
#21 0x00007ffff7dee8b1 in g_signal_emit_valist (instance=0x555555f833c0, signal_id=73, detail=0, var_args=var_args@entry=0x7fffffffd160) at ../gobject/gsignal.c:3254
#22 0x00007ffff7dee973 in g_signal_emit (instance=instance@entry=0x555555f833c0, signal_id=<optimized out>, detail=detail@entry=0) at ../gobject/gsignal.c:3574
#23 0x00007ffff795d314 in gtk_widget_event_internal.part.0.lto_priv.0 (widget=0x555555f833c0, event=0x555555b714f0) at ../gtk/gtkwidget.c:7812
#24 0x00007ffff77f3f9c in gtk_main_do_event (event=<optimized out>) at ../gtk/gtkmain.c:1861
#25 gtk_main_do_event (event=<optimized out>) at ../gtk/gtkmain.c:1691
#26 0x00007ffff7eef457 in _gdk_event_emit (event=0x555555b714f0) at ../gdk/gdkevents.c:73
#27 _gdk_event_emit (event=0x555555b714f0) at ../gdk/gdkevents.c:67
#28 0x00007ffff7f4934e in gdk_event_source_dispatch.lto_priv () at ../gdk/x11/gdkeventsource.c:354
#29 0x00007ffff720f26c in g_main_dispatch (context=0x5555559ec760) at ../glib/gmain.c:3344
#30 g_main_context_dispatch_unlocked (context=0x5555559ec760) at ../glib/gmain.c:4152
#31 0x00007ffff72702a8 in g_main_context_iterate_unlocked.isra.0 (context=context@entry=0x5555559ec760, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/gmain.c:4217
#32 0x00007ffff72106e3 in g_main_context_iteration (context=0x5555559ec760, context@entry=0x0, may_block=may_block@entry=1) at ../glib/gmain.c:4282
#33 0x000055555583e90f in gui_mch_wait_for_chars (wtime=-481852) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui_gtk_x11.c:6691
#34 gui_wait_for_chars_3 (wtime=wtime@entry=-481852, interrupted=interrupted@entry=0x7fffffffd5fc, ignore_input=ignore_input@entry=0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:2957
#35 0x00005555557d78d8 in ui_wait_for_chars_or_timer (wtime=-481852, wait_func=0x55555583e830 <gui_wait_for_chars_3>, interrupted=0x7fffffffd5fc, ignore_input=0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/ui.c:488
#36 0x00005555557d82fd in inchar_loop (buf=0x555555982e45 <typebuf_init.lto_priv+69> "", maxlen=65, wtime=-1, tb_change_cnt=19, wait_func=0x55555583ea90 <gui_wait_for_chars_or_timer>, resize_func=<optimized out>)
    at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/ui.c:384
#37 0x0000555555841e49 in gui_wait_for_chars_buf (buf=0x555555982e45 <typebuf_init.lto_priv+69> "", maxlen=65, wtime=-1, tb_change_cnt=19) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:3023
#38 0x00005555557d8ab5 in gui_inchar (tb_change_cnt=<optimized out>, wtime=-1, maxlen=65, buf=0x555555982e45 <typebuf_init.lto_priv+69> "") at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:3056
#39 ui_inchar (buf=0x555555982e45 <typebuf_init.lto_priv+69> "", maxlen=65, wtime=-1, tb_change_cnt=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/ui.c:226
#40 0x0000555555663778 in inchar (buf=0x555555982e45 <typebuf_init.lto_priv+69> "", maxlen=195, wait_time=-1) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/getchar.c:3808
#41 0x0000555555664949 in vgetorpeek (advance=1) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/getchar.c:3593
#42 0x000055555565ffc4 in vgetc () at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/getchar.c:1784
#43 0x00005555556c485e in safe_vgetc () at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/getchar.c:2035
#44 normal_cmd (oap=0x7fffffffdba0, toplevel=1) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/normal.c:761
#45 0x000055555589157b in main_loop (cmdwin=cmdwin@entry=0, noexmode=noexmode@entry=0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/main.c:1562
#46 0x000055555557e0c0 in vim_main2 () at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/main.c:895
#47 main (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/main.c:441

So this is handler is instantiated when needed. This is probably not the right path.

But yes, it seems that GVim is driving the clock and calling g_main_context_iteration step by step. So far, I don’t think that is the issue.

Thx for unblocking. However, the notification I have receive was not very helpful to find a way around.

Interestingly, I have executed GVim with the Gnome Inspector. With the frozen GVim UI, the inspector typically continued to behave just fine. However today, coming back to my computer where I left it yesterday (with frozen GVim), the Inspector is frozen similarly to GVim. In the mean time, I have also undocked / docked the computer, therefore windows get resized and repositioned.

These are the current backtraces:

^C
Thread 1 "gvim" received signal SIGINT, Interrupt.
0x00007ffff6d3b73d in __GI___poll (fds=0x555556863fb0, nfds=5, timeout=3993) at ../sysdeps/unix/sysv/linux/poll.c:29
Downloading source file /usr/src/debug/glibc-2.39-2.fc40.x86_64/io/../sysdeps/unix/sysv/linux/poll.c
29        return SYSCALL_CANCEL (poll, fds, nfds, timeout);                                                                                                                                                                                   
(gdb) thread apply all bt

Thread 27 (Thread 0x7ffff4011d40 (LWP 397765) "gvim"):
#0  0x00007ffff6c72398 in __GI___sigtimedwait (set=set@entry=0x7ffff6dd7b00 <sigtimer_set>, info=info@entry=0x7ffff4010e80, timeout=timeout@entry=0x0) at ../sysdeps/unix/sysv/linux/sigtimedwait.c:31
#1  0x00007ffff6c723fb in __GI___sigwaitinfo (set=set@entry=0x7ffff6dd7b00 <sigtimer_set>, info=info@entry=0x7ffff4010e80) at ../sysdeps/unix/sysv/linux/sigwaitinfo.c:25
#2  0x00007ffff6cd2f63 in timer_helper_thread (arg=<optimized out>) at ../sysdeps/unix/sysv/linux/timer_routines.c:70
#3  0x00007ffff6cc71f7 in start_thread (arg=<optimized out>) at pthread_create.c:447
#4  0x00007ffff6d493ac in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

Thread 18 (Thread 0x7fffee0006c0 (LWP 397756) "gvim:sh0"):
#0  0x00007ffff6cc3959 in __futex_abstimed_wait_common64 (private=0, cancel=true, abstime=0x0, op=393, expected=0, futex_word=0x555556339c30) at futex-internal.c:57
#1  __futex_abstimed_wait_common (futex_word=futex_word@entry=0x555556339c30, expected=expected@entry=0, clockid=clockid@entry=0, abstime=abstime@entry=0x0, private=private@entry=0, cancel=cancel@entry=true) at futex-internal.c:87
#2  0x00007ffff6cc39df in __GI___futex_abstimed_wait_cancelable64 (futex_word=futex_word@entry=0x555556339c30, expected=expected@entry=0, clockid=clockid@entry=0, abstime=abstime@entry=0x0, private=private@entry=0) at futex-internal.c:139
#3  0x00007ffff6cc6329 in __pthread_cond_wait_common (abstime=0x0, clockid=0, mutex=<optimized out>, cond=0x555556339c08) at pthread_cond_wait.c:503
#4  ___pthread_cond_wait (cond=0x555556339c08, mutex=<optimized out>) at pthread_cond_wait.c:618
#5  0x00007fffe5a9dddd in cnd_wait (cond=<optimized out>, mtx=<optimized out>) at ../src/c11/impl/threads_posix.c:135
#6  0x00007fffe5a7b9ab in util_queue_thread_func (input=input@entry=0x55555633b950) at ../src/util/u_queue.c:290
#7  0x00007fffe5a9dd0c in impl_thrd_routine (p=<optimized out>) at ../src/c11/impl/threads_posix.c:67
#8  0x00007ffff6cc71f7 in start_thread (arg=<optimized out>) at pthread_create.c:447
#9  0x00007ffff6d493ac in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

Thread 17 (Thread 0x7fffef4006c0 (LWP 397755) "gvim:disk$0"):
#0  0x00007ffff6cc3959 in __futex_abstimed_wait_common64 (private=0, cancel=true, abstime=0x0, op=393, expected=0, futex_word=0x555555c0c468) at futex-internal.c:57
#1  __futex_abstimed_wait_common (futex_word=futex_word@entry=0x555555c0c468, expected=expected@entry=0, clockid=clockid@entry=0, abstime=abstime@entry=0x0, private=private@entry=0, cancel=cancel@entry=true) at futex-internal.c:87
#2  0x00007ffff6cc39df in __GI___futex_abstimed_wait_cancelable64 (futex_word=futex_word@entry=0x555555c0c468, expected=expected@entry=0, clockid=clockid@entry=0, abstime=abstime@entry=0x0, private=private@entry=0) at futex-internal.c:139
#3  0x00007ffff6cc6329 in __pthread_cond_wait_common (abstime=0x0, clockid=0, mutex=<optimized out>, cond=0x555555c0c440) at pthread_cond_wait.c:503
#4  ___pthread_cond_wait (cond=0x555555c0c440, mutex=<optimized out>) at pthread_cond_wait.c:618
#5  0x00007fffe5a9dddd in cnd_wait (cond=<optimized out>, mtx=<optimized out>) at ../src/c11/impl/threads_posix.c:135
#6  0x00007fffe5a7b9ab in util_queue_thread_func (input=input@entry=0x555555dad310) at ../src/util/u_queue.c:290
#7  0x00007fffe5a9dd0c in impl_thrd_routine (p=<optimized out>) at ../src/c11/impl/threads_posix.c:67
#8  0x00007ffff6cc71f7 in start_thread (arg=<optimized out>) at pthread_create.c:447
#9  0x00007ffff6d493ac in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

Thread 4 (Thread 0x7ffff50006c0 (LWP 397741) "gdbus"):
#0  0x00007ffff6d3b73d in __GI___poll (fds=0x7fffe0000b90, nfds=3, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
#1  0x00007ffff7270244 in g_main_context_poll_unlocked (priority=2147483647, n_fds=3, fds=0x7fffe0000b90, timeout=<optimized out>, context=0x555555a3a9c0) at ../glib/gmain.c:4521
#2  g_main_context_iterate_unlocked.isra.0 (context=0x555555a3a9c0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/gmain.c:4212
#3  0x00007ffff7215227 in g_main_loop_run (loop=0x555555a3aac0) at ../glib/gmain.c:4419
#4  0x00007ffff75487d2 in gdbus_shared_thread_func (user_data=0x555555a3a990) at ../gio/gdbusprivate.c:284
#5  0x00007ffff723f453 in g_thread_proxy (data=0x555555a3aae0) at ../glib/gthread.c:835
#6  0x00007ffff6cc71f7 in start_thread (arg=<optimized out>) at pthread_create.c:447
#7  0x00007ffff6d493ac in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

Thread 3 (Thread 0x7fffefe006c0 (LWP 397740) "gmain"):
#0  0x00007ffff6d3b73d in __GI___poll (fds=0x555555a2d2a0, nfds=2, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
#1  0x00007ffff7270244 in g_main_context_poll_unlocked (priority=2147483647, n_fds=2, fds=0x555555a2d2a0, timeout=<optimized out>, context=0x555555a2d000) at ../glib/gmain.c:4521
#2  g_main_context_iterate_unlocked.isra.0 (context=context@entry=0x555555a2d000, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/gmain.c:4212
#3  0x00007ffff72106e3 in g_main_context_iteration (context=0x555555a2d000, may_block=may_block@entry=1) at ../glib/gmain.c:4282
#4  0x00007ffff7210739 in glib_worker_main (data=<optimized out>) at ../glib/gmain.c:6442
#5  0x00007ffff723f453 in g_thread_proxy (data=0x555555a2d240) at ../glib/gthread.c:835
#6  0x00007ffff6cc71f7 in start_thread (arg=<optimized out>) at pthread_create.c:447
#7  0x00007ffff6d493ac in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

Thread 2 (Thread 0x7ffff5a006c0 (LWP 397739) "pool-spawner"):
#0  syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
#1  0x00007ffff7262a2d in g_cond_wait (cond=0x555555a2a558, mutex=0x555555a2a550) at ../glib/gthread-posix.c:1552
#2  0x00007ffff71da52b in g_async_queue_pop_intern_unlocked (queue=0x555555a2a550, wait=1, end_time=-1) at ../glib/gasyncqueue.c:375
#3  0x00007ffff7240643 in g_thread_pool_spawn_thread (data=<optimized out>) at ../glib/gthreadpool.c:297
#4  0x00007ffff723f453 in g_thread_proxy (data=0x555555a29280) at ../glib/gthread.c:835
--Type <RET> for more, q to quit, c to continue without paging--
#5  0x00007ffff6cc71f7 in start_thread (arg=<optimized out>) at pthread_create.c:447
#6  0x00007ffff6d493ac in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

Thread 1 (Thread 0x7ffff5cae1c0 (LWP 397738) "gvim"):
#0  0x00007ffff6d3b73d in __GI___poll (fds=0x555556863fb0, nfds=5, timeout=3993) at ../sysdeps/unix/sysv/linux/poll.c:29
#1  0x00007ffff7270244 in g_main_context_poll_unlocked (priority=2147483647, n_fds=5, fds=0x555556863fb0, timeout=<optimized out>, context=0x5555559e8a00) at ../glib/gmain.c:4521
#2  g_main_context_iterate_unlocked.isra.0 (context=context@entry=0x5555559e8a00, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/gmain.c:4212
#3  0x00007ffff72106e3 in g_main_context_iteration (context=0x5555559e8a00, context@entry=0x0, may_block=may_block@entry=1) at ../glib/gmain.c:4282
#4  0x000055555583e90f in gui_mch_wait_for_chars (wtime=4000) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui_gtk_x11.c:6691
#5  gui_wait_for_chars_3 (wtime=wtime@entry=4000, interrupted=interrupted@entry=0x7fffffffd57c, ignore_input=ignore_input@entry=0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:2957
#6  0x00005555557d78d8 in ui_wait_for_chars_or_timer (wtime=4000, wait_func=0x55555583e830 <gui_wait_for_chars_3>, interrupted=0x7fffffffd57c, ignore_input=0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/ui.c:488
#7  0x00005555557d82fd in inchar_loop (buf=0x555555982e41 <typebuf_init.lto_priv+65> "", maxlen=66, wtime=-1, tb_change_cnt=1918, wait_func=0x55555583ea90 <gui_wait_for_chars_or_timer>, resize_func=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/ui.c:384
#8  0x0000555555841e49 in gui_wait_for_chars_buf (buf=0x555555982e41 <typebuf_init.lto_priv+65> "", maxlen=66, wtime=-1, tb_change_cnt=1918) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:3023
#9  0x00005555557d8ab5 in gui_inchar (tb_change_cnt=<optimized out>, wtime=-1, maxlen=66, buf=0x555555982e41 <typebuf_init.lto_priv+65> "") at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/gui.c:3056
#10 ui_inchar (buf=0x555555982e41 <typebuf_init.lto_priv+65> "", maxlen=66, wtime=-1, tb_change_cnt=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/ui.c:226
#11 0x0000555555663778 in inchar (buf=0x555555982e41 <typebuf_init.lto_priv+65> "", maxlen=199, wait_time=-1) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/getchar.c:3808
#12 0x0000555555664949 in vgetorpeek (advance=1) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/getchar.c:3593
#13 0x000055555565ffc4 in vgetc () at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/getchar.c:1784
#14 0x00005555556c485e in safe_vgetc () at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/getchar.c:2035
#15 normal_cmd (oap=0x7fffffffdb20, toplevel=1) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/normal.c:761
#16 0x000055555589157b in main_loop (cmdwin=cmdwin@entry=0, noexmode=noexmode@entry=0) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/main.c:1562
#17 0x000055555557e0c0 in vim_main2 () at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/main.c:895
#18 main (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/vim-9.1.083-1.fc40.x86_64/src/main.c:441
(gdb) 

Hi, could you try the following? When the main window is frozen, break from gdb with Ctrl+C and replicate the commands

(gdb) p gui
$1 = {in_focus = 0, in_use = 1, starting = 0, shell_created = 1, dying = 0, dofork = 0, dragged_sb = -1, dragged_wp = 0x0, pointer_hidden = 0, col = 0, row = 0, cursor_col = 0, cursor_row = 0, cursor_is_valid = 1 '\001', num_cols = 117, 
  num_rows = 52, scroll_region_top = 0, scroll_region_bot = 51, scroll_region_left = 0, scroll_region_right = 116, highlight_mask = 2049, scrollbar_width = 16, scrollbar_height = 16, left_sbar_x = 0, right_sbar_x = 944, 
  force_redraw = 0, menu_is_active = 1 '\001', bottom_sbar = {ident = 2, wp = 0x0, type = 2, value = 0, size = 1, max = 1, top = 0, height = 0, width = 0, status_height = 0, id = 0x555555c81330, handler_id = 169}, which_scrollbars = {0, 
    1, 0}, prev_wrap = -1, char_width = 8, char_height = 19, char_ascent = 15, border_width = 2, border_offset = 2, norm_font = 0x555555bded10, font_can_bold = 1, wide_font = 0x0, back_pixel = 16777215, norm_pixel = 0, 
  def_back_pixel = 16777215, def_norm_pixel = 0, blank_pointer = 0x555555cc8a10, geom = 0x0, mainwin = 0x555555ae8bd0, formwin = 0x555555bdd800, drawarea = 0x555555bdde80, menubar = 0x555555b51b00, toolbar = 0x555555b2b550, 
  fgcolor = 0x555555a09330, bgcolor = 0x555555c0a330, spcolor = 0x555555b19cf0, surface = 0x555555c79210, text_context = 0x555555ae1080, ascii_font = 0x555555c3cf90, ascii_glyphs = 0x555555be07b0, tabline = 0x555555b14920, 
  accel_group = 0x555555b0a1e0, filedlg = 0x0, browse_fname = 0x0, event_time = 21321295, ligatures_map = '\000' <repeats 255 times>, rsrc_input_method = 0x0, rsrc_preedit_type_name = 0x0}
(gdb) p (const char *)g_type_name_from_instance (gui.mainwin)
$2 = 0x7ffff7a89e9e "GtkWindow"
(gdb) set $gdk_win = (GdkWindow*)gtk_widget_get_window (gui.mainwin)
(gdb) p (const char *)g_type_name_from_instance ($gdk_win)
$3 = 0x7ffff7f94c58 "GdkX11Window"
(gdb) p *$gdk_win
$4 = {parent_instance = {g_type_instance = {g_class = Python Exception <class 'gdb.error'>: No type named TypeNode.
}, ref_count = 17, qdata = 0x555555b9fe40}, impl = 0x555555b276a0, parent = 0x555555a59c90, transient_for = 0x0, visual = 0x555555a58610, user_data = 0x555555ae8bd0, x = 0, y = 69, 
  event_mask = 4456210, window_type = 1 '\001', depth = 24 '\030', resize_count = 0 '\000', toplevel_window_type = -1 '\377', filters = 0x0, children = 0x555555b95340 = {0x555555b952e0, 0x555555c0b600, 0x555555bad0a0, 0x555555b1ac00, 
    0x555555cca8d0}, children_list_node = {data=0x555555bee5b0, next=0x555555a68b80, prev=0x0}, native_children = 0x0, background = 0x555555b64520, current_paint = {surface = 0x0, region = 0x0, flushed_region = 0x0, 
    need_blend_region = 0x0, surface_needs_composite = 0, use_gl = 0}, gl_paint_context = 0x0, update_area = 0x0, update_freeze_count = 0, active_update_area = 0x0, old_updated_area = {0x555555c54fd0, 0x555555c493b0}, 
  old_state = (GDK_WINDOW_STATE_FOCUSED | GDK_WINDOW_STATE_TOP_RESIZABLE | GDK_WINDOW_STATE_RIGHT_RESIZABLE | GDK_WINDOW_STATE_BOTTOM_RESIZABLE | GDK_WINDOW_STATE_LEFT_RESIZABLE), 
  state = (GDK_WINDOW_STATE_TOP_RESIZABLE | GDK_WINDOW_STATE_RIGHT_RESIZABLE | GDK_WINDOW_STATE_BOTTOM_RESIZABLE | GDK_WINDOW_STATE_LEFT_RESIZABLE), synthesized_crossing_event_id = 0, alpha = 255 '\377', fullscreen_mode = 0 '\000', 
  input_only = 0, pass_through = 0, modal_hint = 0, composited = 0, has_alpha_background = 0, destroyed = 0, accept_focus = 1, focus_on_map = 1, shaped = 0, support_multidevice = 0, effective_visibility = 0, visibility = 0, 
  native_visibility = 0, viewable = 1, applied_shape = 0, in_update = 0, geometry_dirty = 0, event_compression = 1, frame_clock_events_paused = 0, impl_window = 0x555555bee5b0, update_and_descendants_freeze_count = 0, abs_x = 0, 
  abs_y = 0, width = 960, height = 1011, shadow_top = 0, shadow_left = 0, shadow_right = 0, shadow_bottom = 0, num_offscreen_children = 0, clip_region = 0x555555c386a0, cursor = 0x0, device_cursor = 0x555555b28850Python Exception <class 'gdb.error'>: There is no member named keys.
, shape = 0x0, 
  input_shape = 0x0, devices_inside = 0x0, device_events = 0x0, source_event_masks = 0x0, device_added_handler_id = 0, device_changed_handler_id = 0, frame_clock = 0x555555b4a330, invalidate_handler = 0x0, drawing_context = 0x0, 
  opaque_region = 0x555555b1a550}
(gdb) p *(GdkX11Window*)$gdk_win
$5 = {parent = {parent_instance = {g_type_instance = {g_class = Python Exception <class 'gdb.error'>: No type named TypeNode.
}, ref_count = 17, qdata = 0x555555b9fe40}, impl = 0x555555b276a0, parent = 0x555555a59c90, transient_for = 0x0, visual = 0x555555a58610, user_data = 0x555555ae8bd0, x = 0, 
    y = 69, event_mask = 4456210, window_type = 1 '\001', depth = 24 '\030', resize_count = 0 '\000', toplevel_window_type = -1 '\377', filters = 0x0, children = 0x555555b95340 = {0x555555b952e0, 0x555555c0b600, 0x555555bad0a0, 
      0x555555b1ac00, 0x555555cca8d0}, children_list_node = {data=0x555555bee5b0, next=0x555555a68b80, prev=0x0}, native_children = 0x0, background = 0x555555b64520, current_paint = {surface = 0x0, region = 0x0, flushed_region = 0x0, 
      need_blend_region = 0x0, surface_needs_composite = 0, use_gl = 0}, gl_paint_context = 0x0, update_area = 0x0, update_freeze_count = 0, active_update_area = 0x0, old_updated_area = {0x555555c54fd0, 0x555555c493b0}, 
    old_state = (GDK_WINDOW_STATE_FOCUSED | GDK_WINDOW_STATE_TOP_RESIZABLE | GDK_WINDOW_STATE_RIGHT_RESIZABLE | GDK_WINDOW_STATE_BOTTOM_RESIZABLE | GDK_WINDOW_STATE_LEFT_RESIZABLE), 
    state = (GDK_WINDOW_STATE_TOP_RESIZABLE | GDK_WINDOW_STATE_RIGHT_RESIZABLE | GDK_WINDOW_STATE_BOTTOM_RESIZABLE | GDK_WINDOW_STATE_LEFT_RESIZABLE), synthesized_crossing_event_id = 0, alpha = 255 '\377', fullscreen_mode = 0 '\000', 
    input_only = 0, pass_through = 0, modal_hint = 0, composited = 0, has_alpha_background = 0, destroyed = 0, accept_focus = 1, focus_on_map = 1, shaped = 0, support_multidevice = 0, effective_visibility = 0, visibility = 0, 
    native_visibility = 0, viewable = 1, applied_shape = 0, in_update = 0, geometry_dirty = 0, event_compression = 1, frame_clock_events_paused = 0, impl_window = 0x555555bee5b0, update_and_descendants_freeze_count = 0, abs_x = 0, 
    abs_y = 0, width = 960, height = 1011, shadow_top = 0, shadow_left = 0, shadow_right = 0, shadow_bottom = 0, num_offscreen_children = 0, clip_region = 0x555555c386a0, cursor = 0x0, device_cursor = 0x555555b28850Python Exception <class 'gdb.error'>: There is no member named keys.
, shape = 0x0, 
    input_shape = 0x0, devices_inside = 0x0, device_events = 0x0, source_event_masks = 0x0, device_added_handler_id = 0, device_changed_handler_id = 0, frame_clock = 0x555555b4a330, invalidate_handler = 0x0, drawing_context = 0x0, 
    opaque_region = 0x555555b1a550}}
(gdb) set $impl = $gdk_win->impl
(gdb) p *$impl
$6 = {parent = {g_type_instance = {g_class = Python Exception <class 'gdb.error'>: No type named TypeNode.
}, ref_count = 12, qdata = 0x0}}
(gdb) p (const char *)g_type_name_from_instance ($impl)
$7 = 0x7ffff7f94c65 "GdkWindowImplX11"
(gdb) p *(GdkWindowImplX11*)$impl
$8 = {parent_instance = {parent = {g_type_instance = {g_class = Python Exception <class 'gdb.error'>: No type named TypeNode.
}, ref_count = 12, qdata = 0x0}}, wrapper = 0x555555bee5b0, xid = 10485763, toplevel = 0x555555a6faa0, cursor = 0x0, device_cursor = 0x555555c2e530Python Exception <class 'gdb.error'>: There is no member named keys.
, no_bg = 0, 
  override_redirect = 0, frame_clock_connected = 1, frame_sync_enabled = 1, tracking_damage = 0, window_scale = 1, unscaled_width = 960, unscaled_height = 1011, cairo_surface = 0x555555a7e930, damage = 0}
(gdb) set $frameclock = gdk_window_get_frame_clock ($gdk_win)
(gdb) p (const char *)g_type_name_from_instance ($frameclock)
$9 = 0x7ffff7f84ae0 "GdkFrameClockIdle"
(gdb) p *$frameclock
$10 = {parent_instance = {g_type_instance = {g_class = Python Exception <class 'gdb.error'>: No type named TypeNode.
}, ref_count = 12, qdata = 0x0}, priv = 0x555555b4a2a0}
(gdb) p *$frameclock->priv
$11 = {frame_counter = 186, n_timings = 16, current = 10, timings = {0x7fffe40034c0, 0x555555c829d0, 0x555555b7fe70, 0x555555b07ef0, 0x7fffe40073f0, 0x555555dc7b70, 0x555555aee1f0, 0x555555b73c20, 0x7fffe40030f0, 0x555555af1700, 
    0x555555bace50, 0x555555c1dff0, 0x555555b8a920, 0x555555afdd60, 0x555555af9940, 0x555555bdec10}}
(gdb) p *(GdkFrameClockIdle*)$frameclock
$12 = {parent_instance = {parent_instance = {g_type_instance = {g_class = Python Exception <class 'gdb.error'>: No type named TypeNode.
}, ref_count = 12, qdata = 0x0}, priv = 0x555555b4a2a0}, priv = 0x555555b4a230}
(gdb) p *((GdkFrameClockIdle*)$frameclock)->priv
$13 = {frame_time = 21322610350, smoothed_frame_time_base = 21322610350, smoothed_frame_time_period = 16667, smoothed_frame_time_reported = 21322610350, smoothed_frame_time_phase = 0, min_next_frame_time = 0, 
  smooth_phase_state = SMOOTH_PHASE_STATE_VALID, sleep_serial = 471, freeze_time = 0, flush_idle_id = 0, paint_idle_id = 0, freeze_count = 0, updating_count = 0, requested = GDK_FRAME_CLOCK_PHASE_NONE, 
  phase = GDK_FRAME_CLOCK_PHASE_NONE, in_paint_idle = 0, paint_is_thaw = 1}
(gdb)

Here we go:

(gdb) p gui
$76 = {in_focus = 0, in_use = 1, starting = 0, shell_created = 1, dying = 0, dofork = 0, dragged_sb = -1, dragged_wp = 0x0, pointer_hidden = 0, col = 2, row = 14, cursor_col = 2, cursor_row = 14, cursor_is_valid = 1 '\001', 
  num_cols = 237, num_rows = 57, scroll_region_top = 0, scroll_region_bot = 56, scroll_region_left = 0, scroll_region_right = 236, highlight_mask = 0, scrollbar_width = 16, scrollbar_height = 16, left_sbar_x = 0, right_sbar_x = 1904, 
  force_redraw = 0, menu_is_active = 1 '\001', bottom_sbar = {ident = 2, wp = 0x0, type = 2, value = 0, size = 1, max = 1, top = 0, height = 0, width = 0, status_height = 0, id = 0x5555568bb9e0, handler_id = 6500}, which_scrollbars = {
    0, 1, 0}, prev_wrap = -1, char_width = 8, char_height = 19, char_ascent = 15, border_width = 2, border_offset = 2, norm_font = 0x55555688c3b0, font_can_bold = 1, wide_font = 0x0, back_pixel = 16777215, norm_pixel = 0, 
  def_back_pixel = 16777215, def_norm_pixel = 0, blank_pointer = 0x555555e87d50, geom = 0x0, mainwin = 0x555555daf870, formwin = 0x555555cc8a70, drawarea = 0x555555cc9150, menubar = 0x555555cc3280, toolbar = 0x555555cc3090, 
  fgcolor = 0x55555683f150, bgcolor = 0x55555683eed0, spcolor = 0x55555683ab90, surface = 0x5555568ba2a0, text_context = 0x555555db02a0, ascii_font = 0x555556890ca0, ascii_glyphs = 0x555555a58910, tabline = 0x5555561d6f10, 
  accel_group = 0x555555daf5e0, filedlg = 0x0, browse_fname = 0x0, event_time = 538591464, ligatures_map = '\000' <repeats 255 times>, rsrc_input_method = 0x0, rsrc_preedit_type_name = 0x0}
(gdb) p (const char *)g_type_name_from_instance (gui.mainwin)
$77 = 0x7ffff7a402d6 "GtkWindow"
(gdb) set $gdk_win = (GdkWindow*)gtk_widget_get_window (gui.mainwin)
(gdb) p (const char *)g_type_name_from_instance ($gdk_win)
$78 = 0x7ffff7f6a77a "GdkX11Window"
(gdb) p *$gdk_win
$79 = {parent_instance = {g_type_instance = {g_class = 0x5555559d13e0}, ref_count = 117, qdata = 0x555556c0b5c0}, impl = 0x555555f95680, parent = 0x5555559d14d0, transient_for = 0x0, visual = 0x5555559d90b0, user_data = 0x555555daf870, 
  x = 1920, y = 37, event_mask = 4456214, window_type = 1 '\001', depth = 24 '\030', resize_count = 0 '\000', toplevel_window_type = -1 '\377', filters = 0x0, children = 0x555556a25870, children_list_node = {data = 0x555555ea1950, 
    next = 0x5555559e87f0, prev = 0x0}, native_children = 0x0, background = 0x555555fe8ed0, current_paint = {surface = 0x0, region = 0x0, flushed_region = 0x0, need_blend_region = 0x0, surface_needs_composite = 0, use_gl = 0}, 
  gl_paint_context = 0x0, update_area = 0x555556c7edc0, update_freeze_count = 0, active_update_area = 0x0, old_updated_area = {0x555556bb9170, 0x555556180f00}, 
  old_state = (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FOCUSED | GDK_WINDOW_STATE_TOP_RESIZABLE | GDK_WINDOW_STATE_RIGHT_RESIZABLE | GDK_WINDOW_STATE_BOTTOM_RESIZABLE | GDK_WINDOW_STATE_LEFT_RESIZABLE), 
  state = (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_TOP_RESIZABLE | GDK_WINDOW_STATE_RIGHT_RESIZABLE | GDK_WINDOW_STATE_BOTTOM_RESIZABLE | GDK_WINDOW_STATE_LEFT_RESIZABLE), synthesized_crossing_event_id = 0, alpha = 255 '\377', 
  fullscreen_mode = 0 '\000', input_only = 0, pass_through = 0, modal_hint = 0, composited = 0, has_alpha_background = 0, destroyed = 0, accept_focus = 1, focus_on_map = 1, shaped = 0, support_multidevice = 0, effective_visibility = 0, 
  visibility = 0, native_visibility = 0, viewable = 1, applied_shape = 0, in_update = 0, geometry_dirty = 0, event_compression = 1, frame_clock_events_paused = 0, impl_window = 0x555555ea1950, update_and_descendants_freeze_count = 0, 
  abs_x = 0, abs_y = 0, width = 1920, height = 1163, shadow_top = 0, shadow_left = 0, shadow_right = 0, shadow_bottom = 0, num_offscreen_children = 0, clip_region = 0x555556be4a90, cursor = 0x0, device_cursor = 0x555555b14450, 
  shape = 0x0, input_shape = 0x0, devices_inside = 0x0, device_events = 0x0, source_event_masks = 0x0, device_added_handler_id = 0, device_changed_handler_id = 0, frame_clock = 0x555555a80710, invalidate_handler = 0x0, 
  drawing_context = 0x0, opaque_region = 0x5555561bbc50}
(gdb) p *(GdkX11Window*)$gdk_win
$80 = {parent = {parent_instance = {g_type_instance = {g_class = 0x5555559d13e0}, ref_count = 117, qdata = 0x555556c0b5c0}, impl = 0x555555f95680, parent = 0x5555559d14d0, transient_for = 0x0, visual = 0x5555559d90b0, 
    user_data = 0x555555daf870, x = 1920, y = 37, event_mask = 4456214, window_type = 1 '\001', depth = 24 '\030', resize_count = 0 '\000', toplevel_window_type = -1 '\377', filters = 0x0, children = 0x555556a25870, 
    children_list_node = {data = 0x555555ea1950, next = 0x5555559e87f0, prev = 0x0}, native_children = 0x0, background = 0x555555fe8ed0, current_paint = {surface = 0x0, region = 0x0, flushed_region = 0x0, need_blend_region = 0x0, 
      surface_needs_composite = 0, use_gl = 0}, gl_paint_context = 0x0, update_area = 0x555556c7edc0, update_freeze_count = 0, active_update_area = 0x0, old_updated_area = {0x555556bb9170, 0x555556180f00}, 
    old_state = (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FOCUSED | GDK_WINDOW_STATE_TOP_RESIZABLE | GDK_WINDOW_STATE_RIGHT_RESIZABLE | GDK_WINDOW_STATE_BOTTOM_RESIZABLE | GDK_WINDOW_STATE_LEFT_RESIZABLE), 
    state = (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_TOP_RESIZABLE | GDK_WINDOW_STATE_RIGHT_RESIZABLE | GDK_WINDOW_STATE_BOTTOM_RESIZABLE | GDK_WINDOW_STATE_LEFT_RESIZABLE), synthesized_crossing_event_id = 0, alpha = 255 '\377', 
    fullscreen_mode = 0 '\000', input_only = 0, pass_through = 0, modal_hint = 0, composited = 0, has_alpha_background = 0, destroyed = 0, accept_focus = 1, focus_on_map = 1, shaped = 0, support_multidevice = 0, 
    effective_visibility = 0, visibility = 0, native_visibility = 0, viewable = 1, applied_shape = 0, in_update = 0, geometry_dirty = 0, event_compression = 1, frame_clock_events_paused = 0, impl_window = 0x555555ea1950, 
    update_and_descendants_freeze_count = 0, abs_x = 0, abs_y = 0, width = 1920, height = 1163, shadow_top = 0, shadow_left = 0, shadow_right = 0, shadow_bottom = 0, num_offscreen_children = 0, clip_region = 0x555556be4a90, 
    cursor = 0x0, device_cursor = 0x555555b14450, shape = 0x0, input_shape = 0x0, devices_inside = 0x0, device_events = 0x0, source_event_masks = 0x0, device_added_handler_id = 0, device_changed_handler_id = 0, 
    frame_clock = 0x555555a80710, invalidate_handler = 0x0, drawing_context = 0x0, opaque_region = 0x5555561bbc50}}
(gdb) set $impl = $gdk_win->impl
(gdb) p *$impl
$81 = {parent = {g_type_instance = {g_class = 0x5555559d1cc0}, ref_count = 45, qdata = 0x0}}
(gdb) p (const char *)g_type_name_from_instance ($impl)
$82 = 0x7ffff7f6a4dd "GdkWindowImplX11"
(gdb) p *(GdkWindowImplX11*)$impl
$83 = {parent_instance = {parent = {g_type_instance = {g_class = 0x5555559d1cc0}, ref_count = 45, qdata = 0x0}}, wrapper = 0x555555ea1950, xid = 20971527, toplevel = 0x555555a9b530, cursor = 0x0, device_cursor = 0x555555f6c5f0, 
  no_bg = 0, override_redirect = 0, frame_clock_connected = 1, frame_sync_enabled = 1, tracking_damage = 0, window_scale = 1, unscaled_width = 1920, unscaled_height = 1163, cairo_surface = 0x555555a9ed10, damage = 0}
(gdb) set $frameclock = gdk_window_get_frame_clock ($gdk_win)
(gdb) p (const char *)g_type_name_from_instance ($frameclock)
$84 = 0x7ffff7f67c0c "GdkFrameClockIdle"
(gdb) p *$frameclock
$85 = {parent_instance = {g_type_instance = {g_class = 0x5555559e8f10}, ref_count = 99, qdata = 0x555556c16ef0}, priv = 0x555555a80680}
(gdb) p *$frameclock->priv
$86 = {frame_counter = 270, n_timings = 16, current = 14, timings = {0x5555563d0ab0, 0x555555ac3d30, 0x55555689d310, 0x55555641c8c0, 0x555556a66a00, 0x5555564816b0, 0x555555c15ed0, 0x555556bc9ed0, 0x555556ae3c10, 0x555555a62b50, 
    0x555556abef20, 0x555555aed400, 0x555555f42400, 0x555555b13e80, 0x5555561e3800, 0x555556bb5f20}}
(gdb) p *(GdkFrameClockIdle*)$frameclock
$87 = {parent_instance = {parent_instance = {g_type_instance = {g_class = 0x5555559e8f10}, ref_count = 99, qdata = 0x555556c16ef0}, priv = 0x555555a80680}, priv = 0x555555a80620}
(gdb) p *((GdkFrameClockIdle*)$frameclock)->priv
$88 = {frame_time = 538586369936, smoothed_frame_time_base = 538586373751, smoothed_frame_time_period = 16681, smoothed_frame_time_reported = 538589960166, smoothed_frame_time_phase = 0, min_next_frame_time = 0, 
  smooth_phase_state = SMOOTH_PHASE_STATE_AWAIT_FIRST, sleep_serial = 2204, flush_idle_id = 0, paint_idle_id = 0, freeze_count = 1, updating_count = 1, 
  requested = (GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS | GDK_FRAME_CLOCK_PHASE_LAYOUT | GDK_FRAME_CLOCK_PHASE_PAINT), phase = GDK_FRAME_CLOCK_PHASE_NONE, in_paint_idle = 0, paint_is_thaw = 0}

I hope I have not missed anything.

I have blindly executed the sequence, now let me try to understand what you are going after :innocent:

1 Like

One thing I have not mentioned here. The freeze is very prominent, when the window is maximized. I think it also happens in normalized state, but just very rarely.

Great!

Ok, the GdkFrameClock is frozen, which explains why nothing happens anymore

Thawing / freezing happens only in two places:

Somehow the calls are not balanced. As this happens only with GNOME (which AFAIK is the only WM implementing _NET_WM_FRAME_DRAWN), most probably it’s the second: the X11 backend.

Yeah, it would be great to have a reason field to track why a frame clock is frozen

Perhaps the event filter installed by gvim is filtering _NET_WM_FRAME_DRAWN events? vim/src/gui_gtk_x11.c at fa37835b8c0ed0f83952978fca4c332335ca7c46 · vim/vim · GitHub

Nice. I have just tried:

(gdb) call _gdk_frame_clock_thaw ($frameclock)
(gdb) c

And it “unfreeze” / thaw the GUI. I’ll try to put a few breakponts / watches around

1 Like

Hmmm, I have set breakpoints at the places you have highlighted. I was running over pairs like this:

Thread 1 "gvim" hit Breakpoint 3, gdk_x11_window_end_frame (window=0x555555e57650) at ../gdk/x11/gdkwindow-x11.c:449
449	          _gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
(gdb) 
Continuing.

Thread 1 "gvim" hit Breakpoint 5, _gdk_wm_protocols_filter (xev=<optimized out>, event=<optimized out>, data=<optimized out>) at ../gdk/x11/gdkdisplay-x11.c:1385
1385	              _gdk_frame_clock_thaw (clock);
(gdb) 

This got quickly boring. So I tried to setup watch on the freeze_count. I can’t say I have succeeded, but soon after the attempt this happened:

(gdb) c
Continuing.
[Detaching after fork from child process 638112]
[Detaching after fork from child process 638145]
[Detaching after fork from child process 638178]
[Detaching after fork from child process 638207]
[Detaching after fork from child process 638226]

Thread 1 "gvim" hit Breakpoint 1, gdk_window_freeze_toplevel_updates (window=0x555556ecfdc0) at ../gdk/gdkwindow.c:4781
4781	  _gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
(gdb) c
Continuing.

Thread 1 "gvim" hit Breakpoint 2, gdk_window_thaw_toplevel_updates (window=0x555556ecfdc0) at ../gdk/gdkwindow.c:4810
4810	  _gdk_frame_clock_thaw (gdk_window_get_frame_clock (window));
(gdb) 
Continuing.

Thread 1 "gvim" hit Breakpoint 1, gdk_window_freeze_toplevel_updates (window=0x555556ecfdc0) at ../gdk/gdkwindow.c:4781
4781	  _gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
(gdb) 
Continuing.
[Detaching after fork from child process 638243]
[Detaching after fork from child process 638297]
^C
Thread 1 "gvim" received signal SIGINT, Interrupt.
0x00007ffff6d3b73d in __GI___poll (fds=0x555556a977a0, nfds=5, timeout=3990) at ../sysdeps/unix/sysv/linux/poll.c:29
29	  return SYSCALL_CANCEL (poll, fds, nfds, timeout);
(gdb) p *((GdkFrameClockIdle*)$frameclock)->priv
$8 = {frame_time = 595319329725, smoothed_frame_time_base = 595319334292, smoothed_frame_time_period = 16681, smoothed_frame_time_reported = 595572702001, smoothed_frame_time_phase = 0, min_next_frame_time = 0, 
  smooth_phase_state = SMOOTH_PHASE_STATE_AWAIT_FIRST, sleep_serial = 7087, flush_idle_id = 0, paint_idle_id = 0, freeze_count = 1, updating_count = 1, 
  requested = (GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS | GDK_FRAME_CLOCK_PHASE_LAYOUT | GDK_FRAME_CLOCK_PHASE_PAINT), phase = GDK_FRAME_CLOCK_PHASE_NONE, in_paint_idle = 0, paint_is_thaw = 0}
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00007ffff7f04483 in gdk_window_freeze_toplevel_updates at ../gdk/gdkwindow.c:4781
	breakpoint already hit 2 times
2       breakpoint     keep y   0x00007ffff7f05d49 in gdk_window_thaw_toplevel_updates at ../gdk/gdkwindow.c:4810
	breakpoint already hit 1 time
3       breakpoint     keep n   0x00007ffff7f5806c in gdk_x11_window_end_frame at ../gdk/x11/gdkwindow-x11.c:449
	breakpoint already hit 27 times
4       breakpoint     keep y   0x00007ffff7f4ad01 in gdk_x11_display_translate_event at ../gdk/x11/gdkdisplay-x11.c:890
5       breakpoint     keep n   0x00007ffff7f44421 in _gdk_wm_protocols_filter at ../gdk/x11/gdkdisplay-x11.c:1385
	breakpoint already hit 27 times

Of course I have no idea where this come from and under what conditions …

But in next run, I have the window frozen without hitting this imbalance :confused:

Yeah, freezing / thawing happens very frequently during animations, e.g when switching applications. Count the breakpoints instead:

Try on a new gvim instance, making sure to start counting when freeze_count is zero

But in next run, I have the window frozen without hitting this imbalance :confused:

What’s the value of freeze_count?

…last but not least, set a breakpoint on the global filter: vim/src/gui_gtk_x11.c at fa37835b8c0ed0f83952978fca4c332335ca7c46 · vim/vim · GitHub That way we know if it handled some events